diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 3eaf2a46..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,3 +0,0 @@ -# Donate to us! - -https://ko-fi.com/souldbminer diff --git a/.gitignore b/.gitignore index 76dc4eee..ccaedb2d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ build Source/hekate dist/* !dist/.gitignore +Status-Monitor-Overlay.ovl* \ No newline at end of file diff --git a/COMPILING.md b/COMPILING.md index 78b7331b..99a062e7 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -5,4 +5,6 @@ Horizon OC Compilation Instructions 3. Clone the Horizon OC develop branch (``git clone https://github.com/Horizon-OC/Horizon-OC.git --recurse-submodules``) 4. Run ``./build.sh`` in the root directory - If you want to compile with extensions, append ``--ext`` + - To skip components, append ``-s``/``--skip`` followed by one or more of: ``ldr`` (loader), ``clk`` (hoc-clk), ``hek`` (hekate), ``btb`` (benchmark toolbox), ``exos`` (exosphere), ``sm`` (status-monitor download), ``zip`` (dist.zip packaging). Example: ``./build.sh --ext -s ldr hek`` + - Building the custom Hekate (``--ext`` without skipping ``hek``) additionally requires devkitARM with ``DEVKITARM`` exported - Installing ``ccache`` is optional; if it is on your PATH it is used automatically to speed up rebuilds diff --git a/README.md b/README.md index 46bd07f8..54efce12 100644 --- a/README.md +++ b/README.md @@ -34,9 +34,9 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to ## Default clocks -* **CPU:** Up to 1963MHz (Mariko) / 1785MHz (Erista) -* **GPU:** Up to 1075MHz (Mariko) / 921MHz (Erista) -* **RAM:** Up to 1866/2133MHz (Mariko) / 1600MHz (Erista) +* **CPU:** 1963MHz (Mariko) / 1785MHz (Erista) +* **GPU:** 1152MHz (Mariko) / 921MHz (Erista) +* **RAM:** 2133MHz (Mariko) / 1600MHz (Erista) * Over/undervolting support * Built-in configurator * Compatible with most homebrew @@ -51,7 +51,7 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to * [Atmosphere](https://github.com/Atmosphere-NX/Atmosphere) * [Ultrahand Overlay](https://github.com/ppkantorski/Ultrahand-Overlay) -2. Download and extract the **Horizon OC Package** to the root of your SD card. +2. Download and extract **Horizon OC** to the root of your SD card. 3. If using **Hekate**, edit `hekate_ipl.ini` to include: ``` @@ -83,13 +83,23 @@ We don't accept donations. Put your spare cash into a charity instead :) Refer to COMPILATION.md --- -## Clock table + +Higher clocks are achievable via undervolting or further configuration, refer to this table for more details. +The averages are only for reference. Each ram is different and must be tuned independently. Refer to the guide for more details! + +
+

Clock table

### MEM clocks (mhz) - -* 3200 → max on mariko, JEDEC. +* 3400 → max on mariko. +* 3366 +* 3333 +* 3300 +* 3266 +* 3233 +* 3200 → JEDEC, Hynix NEE/x267 Average * 3166 -* 3133 +* 3133 → Micron WT:B Average * 3100 * 3066 * 3033 @@ -98,20 +108,20 @@ Refer to COMPILATION.md * 2933 → JEDEC. * 2900 * 2866 -* 2833 +* 2833 → Samsung AA-MGCL Average * 2800 * 2766 -* 2733 +* 2733 → Samsung AM-MGCJ/Micron WT:E Average * 2700 -* 2666 → JEDEC. +* 2666 → JEDEC, Micron WT:F Average * 2633 * 2600 -* 2566 +* 2566 → Samsung AB-MGCL Average * 2533 * 2500 * 2466 * 2433 -* 2400 → max on erista, JEDEC. +* 2400 → max on erista, JEDEC, Hynix NME Average * 2366 * 2333 * 2300 @@ -124,7 +134,7 @@ Refer to COMPILATION.md * 2066 * 2033 * 2000 -* 1996 → JEDEC standard +* 1996 → JEDEC, Erista Average * 1966 * 1933 * 1900 @@ -138,12 +148,18 @@ Refer to COMPILATION.md * 1633 * 1600 → official docked, boost mode, Erista JEDEC standard max (3200 Modules), JEDEC. * 1331 → official handheld, JEDEC. -* 1065 -* 800 -* 665 +* 1065 → Erista only +* 800 → Erista only +* 665 → Erista only +* 408 → Erista only +* 204 → sleep mode +* 102 → Erista only +* 68 → Erista only +* 40 → Erista only ### CPU clocks (mhz) -* 2703 → mariko absolute max, dangerous +* 2805 → mariko absolute max, dangerous +* 2703 * 2601 → unsafe * 2499 * 2397 → mariko safe max with UV (low speedo) @@ -166,9 +182,13 @@ Refer to COMPILATION.md * 612 → sleep mode ### GPU clocks (mhz) -* 1536 → absolute max clock on mariko. Dangerous -* 1497 → max mariko unsafe clock +* 1574 → absolute max clock on mariko. Dangerous +* 1536 +* 1497 → max mariko unsafe clock +* 1459 +* 1420 * 1382 → Max mariko "safe" clock +* 1344 * 1305 * 1267 → NVIDIA T214(mariko) rating * 1228 → mariko High UV safe clock @@ -195,12 +215,15 @@ Refer to COMPILATION.md 3. On Mariko, cap with hiOpt is 614MHz, with hiOpt-15mV it is 691MHz and with High UV it's 768MHz 4. Clocks higher than 768MHz on erista need the official charger is plugged in. +
+ --- ## Credits -* **Lightos's Cat** - Cat +* **Lightos's Cats** - Cats * **Souldbminer** - hoc-clk and loader development * **Lightos** - Loader patches development, hoc-clk development, guides +* **HAZEL** - Perfect DRAM timings help * **TDRR** - HOC Logo Design * **tetetete-ctrl** - Website design * **SciresM** - Atmosphere CFW @@ -217,6 +240,9 @@ Refer to COMPILATION.md * **Dominatorul, Samybigio, Arcdelta, Miki, Happy, Winnerboi77, Blaise, Alvise, agjeococh, frost, letum00, and Xenshen** - Testing * **Samybigio2011, Miki** - Italian translations * **angelblaster** - Korean translations -* **q1332348216-glitch** - Chinese translations +* **q1332348216-glitch, nangongjing1, xinluochenjiang** - Chinese translations * **th3-ne0undr5c0r** - French translations +* **redraz** - Russian translations +* **Wivi** - Portuguese translations +* **Niklas080208** - JSON language support for sysmodule notifications. * **Nvidia** - [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual), soctherm driver, L4T diff --git a/Source/Atmosphere-Patches/diff/README.MD b/Source/Atmosphere-Patches/diff/README.MD new file mode 100644 index 00000000..e43f3005 --- /dev/null +++ b/Source/Atmosphere-Patches/diff/README.MD @@ -0,0 +1 @@ +This contains a diff all modifications done to exosphere diff --git a/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff b/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff new file mode 100644 index 00000000..1cb6ab99 --- /dev/null +++ b/Source/Atmosphere-Patches/diff/secmon_memory_layout.diff @@ -0,0 +1,57 @@ +131,156c131,159 +< #define AMS_SECMON_FOREACH_DEVICE_REGION(HANDLER, ...) \ +< 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(Uart, GicCpuInterface, UINT64_C(0x70006000), 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(Timer, RtcPmc, UINT64_C(0x60005000), 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(SecurityEngine2, SecurityEngine, UINT64_C(0x70412000), UINT64_C(0x2000), 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(FuseKFuse, MemoryController, UINT64_C(0x7000F000), UINT64_C(0x1000), 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(BootloaderParams, FlowController, UINT64_C(0x40000000), 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(I2c1, Gpio, UINT64_C(0x7000C000), 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(MemoryController1, MemoryController0, UINT64_C(0x7001D000), 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(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ +< HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) +--- +> #define AMS_SECMON_FOREACH_DEVICE_REGION(HANDLER, ...) \ +> 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(Uart, GicCpuInterface, UINT64_C(0x70006000), 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(Timer, RtcPmc, UINT64_C(0x60005000), 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(SecurityEngine2, SecurityEngine, UINT64_C(0x70412000), UINT64_C(0x2000), 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(ExternalMemoryController, MemoryController, UINT64_C(0x7001b000), 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(FlowController, ApbMisc, UINT64_C(0x60007000), 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(Gpio, I2c5, UINT64_C(0x6000D000), 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(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ +> HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ +> HANDLER(ExternalMemoryController0, MemoryController1, UINT64_C(0x7001E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ +> HANDLER(ExternalMemoryController1, ExternalMemoryController0, UINT64_C(0x7001F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ +> HANDLER(Sdmmc, ExternalMemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), 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(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ diff --git a/Source/Atmosphere-Patches/diff/secmon_setup.diff b/Source/Atmosphere-Patches/diff/secmon_setup.diff new file mode 100644 index 00000000..5b796e03 --- /dev/null +++ b/Source/Atmosphere-Patches/diff/secmon_setup.diff @@ -0,0 +1,29 @@ +1221c1221 +< const auto target_fw = GetTargetFirmware(); +--- +> // const auto target_fw = GetTargetFirmware(); +1223,1226c1223,1226 +< if (target_fw >= TargetFirmware_2_0_0) { +< /* Set the PMC secure. */ +< reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE)); +< } +--- +> // if (target_fw >= TargetFirmware_2_0_0) { +> // /* Set the PMC secure. */ I REFUSE +> // reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE)); +> // } +1228,1233c1228,1234 +< if (target_fw >= TargetFirmware_4_0_0) { +< /* Set the MC secure. */ +< reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE), +< SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE), +< SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE)); +< } +--- +> // if (target_fw >= TargetFirmware_4_0_0) { +> // /* Set the MC secure. */ I REFUSE +> // reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE), +> // SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE), +> // SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE)); +> // } +> return; diff --git a/Source/Atmosphere-Patches/diff/secmon_smc_handler.diff b/Source/Atmosphere-Patches/diff/secmon_smc_handler.diff new file mode 100644 index 00000000..ee25f585 --- /dev/null +++ b/Source/Atmosphere-Patches/diff/secmon_smc_handler.diff @@ -0,0 +1,2 @@ +154a155 +> { 0xF0000005, Restriction_None, SmcShowError }, diff --git a/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff b/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff new file mode 100644 index 00000000..e4c4375a --- /dev/null +++ b/Source/Atmosphere-Patches/diff/secmon_smc_register_access.diff @@ -0,0 +1,22 @@ +100a101,105 +> #include "secmon_define_emc_access_table.inc" +> #include "secmon_define_emc01_access_table.inc" +> #include "secmon_define_flow_controller_access_table.inc" +> #include "secmon_define_exception_vectors_access_table.inc" +> #include "secmon_define_rtc_pmc_access_table.inc" +104,107c109,118 +< { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, }, +< { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::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, }, +--- +> { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, }, +> { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, }, +> { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, }, +> { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Size, }, +> { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Size, }, +> { FlowControllerAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceFlowController.GetAddress(), FlowControllerAccessTable::Address, FlowControllerAccessTable::Size, }, +> { ExceptionVectorsAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExceptionVectors.GetAddress(), ExceptionVectorsAccessTable::Address, ExceptionVectorsAccessTable::Size, }, +> { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::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, }, diff --git a/Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc b/Source/Atmosphere-Patches/secmon_define_emc01_access_table.inc new file mode 100644 index 00000000..3a34e1dc --- /dev/null +++ b/Source/Atmosphere-Patches/secmon_define_emc01_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 . + */ + +#define __ACCESS_TABLE_NAME__ Emc01AccessTable +#define __ACCESS_TABLE_ADDRESS__ 0 +#define __ACCESS_TABLE_INC__ "secmon_emc01_access_table_data.inc" + +#include "secmon_define_access_table.inc" + +#undef __ACCESS_TABLE_INC__ +#undef __ACCESS_TABLE_ADDRESS__ +#undef __ACCESS_TABLE_NAME__ diff --git a/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc b/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc new file mode 100644 index 00000000..a3718c5e --- /dev/null +++ b/Source/Atmosphere-Patches/secmon_emc01_access_table_data.inc @@ -0,0 +1,1040 @@ +/* + * 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 . + */ + +SetRegisterAllowed(0x0); +SetRegisterAllowed(0x4); +SetRegisterAllowed(0x8); +SetRegisterAllowed(0xC); +SetRegisterAllowed(0x10); +SetRegisterAllowed(0x14); +SetRegisterAllowed(0x18); +SetRegisterAllowed(0x1C); +SetRegisterAllowed(0x20); +SetRegisterAllowed(0x24); +SetRegisterAllowed(0x28); +SetRegisterAllowed(0x2C); +SetRegisterAllowed(0x30); +SetRegisterAllowed(0x34); +SetRegisterAllowed(0x38); +SetRegisterAllowed(0x3C); +SetRegisterAllowed(0x40); +SetRegisterAllowed(0x44); +SetRegisterAllowed(0x48); +SetRegisterAllowed(0x4C); +SetRegisterAllowed(0x50); +SetRegisterAllowed(0x54); +SetRegisterAllowed(0x58); +SetRegisterAllowed(0x5C); +SetRegisterAllowed(0x60); +SetRegisterAllowed(0x64); +SetRegisterAllowed(0x68); +SetRegisterAllowed(0x6C); +SetRegisterAllowed(0x70); +SetRegisterAllowed(0x74); +SetRegisterAllowed(0x78); +SetRegisterAllowed(0x7C); +SetRegisterAllowed(0x80); +SetRegisterAllowed(0x84); +SetRegisterAllowed(0x88); +SetRegisterAllowed(0x8C); +SetRegisterAllowed(0x90); +SetRegisterAllowed(0x94); +SetRegisterAllowed(0x98); +SetRegisterAllowed(0x9C); +SetRegisterAllowed(0xA0); +SetRegisterAllowed(0xA4); +SetRegisterAllowed(0xA8); +SetRegisterAllowed(0xAC); +SetRegisterAllowed(0xB0); +SetRegisterAllowed(0xB4); +SetRegisterAllowed(0xB8); +SetRegisterAllowed(0xBC); +SetRegisterAllowed(0xC0); +SetRegisterAllowed(0xC4); +SetRegisterAllowed(0xC8); +SetRegisterAllowed(0xCC); +SetRegisterAllowed(0xD0); +SetRegisterAllowed(0xD4); +SetRegisterAllowed(0xD8); +SetRegisterAllowed(0xDC); +SetRegisterAllowed(0xE0); +SetRegisterAllowed(0xE4); +SetRegisterAllowed(0xE8); +SetRegisterAllowed(0xEC); +SetRegisterAllowed(0xF0); +SetRegisterAllowed(0xF4); +SetRegisterAllowed(0xF8); +SetRegisterAllowed(0xFC); +SetRegisterAllowed(0x100); +SetRegisterAllowed(0x104); +SetRegisterAllowed(0x108); +SetRegisterAllowed(0x10C); +SetRegisterAllowed(0x110); +SetRegisterAllowed(0x114); +SetRegisterAllowed(0x118); +SetRegisterAllowed(0x11C); +SetRegisterAllowed(0x120); +SetRegisterAllowed(0x124); +SetRegisterAllowed(0x128); +SetRegisterAllowed(0x12C); +SetRegisterAllowed(0x130); +SetRegisterAllowed(0x134); +SetRegisterAllowed(0x138); +SetRegisterAllowed(0x13C); +SetRegisterAllowed(0x140); +SetRegisterAllowed(0x144); +SetRegisterAllowed(0x148); +SetRegisterAllowed(0x14C); +SetRegisterAllowed(0x150); +SetRegisterAllowed(0x154); +SetRegisterAllowed(0x158); +SetRegisterAllowed(0x15C); +SetRegisterAllowed(0x160); +SetRegisterAllowed(0x164); +SetRegisterAllowed(0x168); +SetRegisterAllowed(0x16C); +SetRegisterAllowed(0x170); +SetRegisterAllowed(0x174); +SetRegisterAllowed(0x178); +SetRegisterAllowed(0x17C); +SetRegisterAllowed(0x180); +SetRegisterAllowed(0x184); +SetRegisterAllowed(0x188); +SetRegisterAllowed(0x18C); +SetRegisterAllowed(0x190); +SetRegisterAllowed(0x194); +SetRegisterAllowed(0x198); +SetRegisterAllowed(0x19C); +SetRegisterAllowed(0x1A0); +SetRegisterAllowed(0x1A4); +SetRegisterAllowed(0x1A8); +SetRegisterAllowed(0x1AC); +SetRegisterAllowed(0x1B0); +SetRegisterAllowed(0x1B4); +SetRegisterAllowed(0x1B8); +SetRegisterAllowed(0x1BC); +SetRegisterAllowed(0x1C0); +SetRegisterAllowed(0x1C4); +SetRegisterAllowed(0x1C8); +SetRegisterAllowed(0x1CC); +SetRegisterAllowed(0x1D0); +SetRegisterAllowed(0x1D4); +SetRegisterAllowed(0x1D8); +SetRegisterAllowed(0x1DC); +SetRegisterAllowed(0x1E0); +SetRegisterAllowed(0x1E4); +SetRegisterAllowed(0x1E8); +SetRegisterAllowed(0x1EC); +SetRegisterAllowed(0x1F0); +SetRegisterAllowed(0x1F4); +SetRegisterAllowed(0x1F8); +SetRegisterAllowed(0x1FC); +SetRegisterAllowed(0x200); +SetRegisterAllowed(0x204); +SetRegisterAllowed(0x208); +SetRegisterAllowed(0x20C); +SetRegisterAllowed(0x210); +SetRegisterAllowed(0x214); +SetRegisterAllowed(0x218); +SetRegisterAllowed(0x21C); +SetRegisterAllowed(0x220); +SetRegisterAllowed(0x224); +SetRegisterAllowed(0x228); +SetRegisterAllowed(0x22C); +SetRegisterAllowed(0x230); +SetRegisterAllowed(0x234); +SetRegisterAllowed(0x238); +SetRegisterAllowed(0x23C); +SetRegisterAllowed(0x240); +SetRegisterAllowed(0x244); +SetRegisterAllowed(0x248); +SetRegisterAllowed(0x24C); +SetRegisterAllowed(0x250); +SetRegisterAllowed(0x254); +SetRegisterAllowed(0x258); +SetRegisterAllowed(0x25C); +SetRegisterAllowed(0x260); +SetRegisterAllowed(0x264); +SetRegisterAllowed(0x268); +SetRegisterAllowed(0x26C); +SetRegisterAllowed(0x270); +SetRegisterAllowed(0x274); +SetRegisterAllowed(0x278); +SetRegisterAllowed(0x27C); +SetRegisterAllowed(0x280); +SetRegisterAllowed(0x284); +SetRegisterAllowed(0x288); +SetRegisterAllowed(0x28C); +SetRegisterAllowed(0x290); +SetRegisterAllowed(0x294); +SetRegisterAllowed(0x298); +SetRegisterAllowed(0x29C); +SetRegisterAllowed(0x2A0); +SetRegisterAllowed(0x2A4); +SetRegisterAllowed(0x2A8); +SetRegisterAllowed(0x2AC); +SetRegisterAllowed(0x2B0); +SetRegisterAllowed(0x2B4); +SetRegisterAllowed(0x2B8); +SetRegisterAllowed(0x2BC); +SetRegisterAllowed(0x2C0); +SetRegisterAllowed(0x2C4); +SetRegisterAllowed(0x2C8); +SetRegisterAllowed(0x2CC); +SetRegisterAllowed(0x2D0); +SetRegisterAllowed(0x2D4); +SetRegisterAllowed(0x2D8); +SetRegisterAllowed(0x2DC); +SetRegisterAllowed(0x2E0); +SetRegisterAllowed(0x2E4); +SetRegisterAllowed(0x2E8); +SetRegisterAllowed(0x2EC); +SetRegisterAllowed(0x2F0); +SetRegisterAllowed(0x2F4); +SetRegisterAllowed(0x2F8); +SetRegisterAllowed(0x2FC); +SetRegisterAllowed(0x300); +SetRegisterAllowed(0x304); +SetRegisterAllowed(0x308); +SetRegisterAllowed(0x30C); +SetRegisterAllowed(0x310); +SetRegisterAllowed(0x314); +SetRegisterAllowed(0x318); +SetRegisterAllowed(0x31C); +SetRegisterAllowed(0x320); +SetRegisterAllowed(0x324); +SetRegisterAllowed(0x328); +SetRegisterAllowed(0x32C); +SetRegisterAllowed(0x330); +SetRegisterAllowed(0x334); +SetRegisterAllowed(0x338); +SetRegisterAllowed(0x33C); +SetRegisterAllowed(0x340); +SetRegisterAllowed(0x344); +SetRegisterAllowed(0x348); +SetRegisterAllowed(0x34C); +SetRegisterAllowed(0x350); +SetRegisterAllowed(0x354); +SetRegisterAllowed(0x358); +SetRegisterAllowed(0x35C); +SetRegisterAllowed(0x360); +SetRegisterAllowed(0x364); +SetRegisterAllowed(0x368); +SetRegisterAllowed(0x36C); +SetRegisterAllowed(0x370); +SetRegisterAllowed(0x374); +SetRegisterAllowed(0x378); +SetRegisterAllowed(0x37C); +SetRegisterAllowed(0x380); +SetRegisterAllowed(0x384); +SetRegisterAllowed(0x388); +SetRegisterAllowed(0x38C); +SetRegisterAllowed(0x390); +SetRegisterAllowed(0x394); +SetRegisterAllowed(0x398); +SetRegisterAllowed(0x39C); +SetRegisterAllowed(0x3A0); +SetRegisterAllowed(0x3A4); +SetRegisterAllowed(0x3A8); +SetRegisterAllowed(0x3AC); +SetRegisterAllowed(0x3B0); +SetRegisterAllowed(0x3B4); +SetRegisterAllowed(0x3B8); +SetRegisterAllowed(0x3BC); +SetRegisterAllowed(0x3C0); +SetRegisterAllowed(0x3C4); +SetRegisterAllowed(0x3C8); +SetRegisterAllowed(0x3CC); +SetRegisterAllowed(0x3D0); +SetRegisterAllowed(0x3D4); +SetRegisterAllowed(0x3D8); +SetRegisterAllowed(0x3DC); +SetRegisterAllowed(0x3E0); +SetRegisterAllowed(0x3E4); +SetRegisterAllowed(0x3E8); +SetRegisterAllowed(0x3EC); +SetRegisterAllowed(0x3F0); +SetRegisterAllowed(0x3F4); +SetRegisterAllowed(0x3F8); +SetRegisterAllowed(0x3FC); +SetRegisterAllowed(0x400); +SetRegisterAllowed(0x404); +SetRegisterAllowed(0x408); +SetRegisterAllowed(0x40C); +SetRegisterAllowed(0x410); +SetRegisterAllowed(0x414); +SetRegisterAllowed(0x418); +SetRegisterAllowed(0x41C); +SetRegisterAllowed(0x420); +SetRegisterAllowed(0x424); +SetRegisterAllowed(0x428); +SetRegisterAllowed(0x42C); +SetRegisterAllowed(0x430); +SetRegisterAllowed(0x434); +SetRegisterAllowed(0x438); +SetRegisterAllowed(0x43C); +SetRegisterAllowed(0x440); +SetRegisterAllowed(0x444); +SetRegisterAllowed(0x448); +SetRegisterAllowed(0x44C); +SetRegisterAllowed(0x450); +SetRegisterAllowed(0x454); +SetRegisterAllowed(0x458); +SetRegisterAllowed(0x45C); +SetRegisterAllowed(0x460); +SetRegisterAllowed(0x464); +SetRegisterAllowed(0x468); +SetRegisterAllowed(0x46C); +SetRegisterAllowed(0x470); +SetRegisterAllowed(0x474); +SetRegisterAllowed(0x478); +SetRegisterAllowed(0x47C); +SetRegisterAllowed(0x480); +SetRegisterAllowed(0x484); +SetRegisterAllowed(0x488); +SetRegisterAllowed(0x48C); +SetRegisterAllowed(0x490); +SetRegisterAllowed(0x494); +SetRegisterAllowed(0x498); +SetRegisterAllowed(0x49C); +SetRegisterAllowed(0x4A0); +SetRegisterAllowed(0x4A4); +SetRegisterAllowed(0x4A8); +SetRegisterAllowed(0x4AC); +SetRegisterAllowed(0x4B0); +SetRegisterAllowed(0x4B4); +SetRegisterAllowed(0x4B8); +SetRegisterAllowed(0x4BC); +SetRegisterAllowed(0x4C0); +SetRegisterAllowed(0x4C4); +SetRegisterAllowed(0x4C8); +SetRegisterAllowed(0x4CC); +SetRegisterAllowed(0x4D0); +SetRegisterAllowed(0x4D4); +SetRegisterAllowed(0x4D8); +SetRegisterAllowed(0x4DC); +SetRegisterAllowed(0x4E0); +SetRegisterAllowed(0x4E4); +SetRegisterAllowed(0x4E8); +SetRegisterAllowed(0x4EC); +SetRegisterAllowed(0x4F0); +SetRegisterAllowed(0x4F4); +SetRegisterAllowed(0x4F8); +SetRegisterAllowed(0x4FC); +SetRegisterAllowed(0x500); +SetRegisterAllowed(0x504); +SetRegisterAllowed(0x508); +SetRegisterAllowed(0x50C); +SetRegisterAllowed(0x510); +SetRegisterAllowed(0x514); +SetRegisterAllowed(0x518); +SetRegisterAllowed(0x51C); +SetRegisterAllowed(0x520); +SetRegisterAllowed(0x524); +SetRegisterAllowed(0x528); +SetRegisterAllowed(0x52C); +SetRegisterAllowed(0x530); +SetRegisterAllowed(0x534); +SetRegisterAllowed(0x538); +SetRegisterAllowed(0x53C); +SetRegisterAllowed(0x540); +SetRegisterAllowed(0x544); +SetRegisterAllowed(0x548); +SetRegisterAllowed(0x54C); +SetRegisterAllowed(0x550); +SetRegisterAllowed(0x554); +SetRegisterAllowed(0x558); +SetRegisterAllowed(0x55C); +SetRegisterAllowed(0x560); +SetRegisterAllowed(0x564); +SetRegisterAllowed(0x568); +SetRegisterAllowed(0x56C); +SetRegisterAllowed(0x570); +SetRegisterAllowed(0x574); +SetRegisterAllowed(0x578); +SetRegisterAllowed(0x57C); +SetRegisterAllowed(0x580); +SetRegisterAllowed(0x584); +SetRegisterAllowed(0x588); +SetRegisterAllowed(0x58C); +SetRegisterAllowed(0x590); +SetRegisterAllowed(0x594); +SetRegisterAllowed(0x598); +SetRegisterAllowed(0x59C); +SetRegisterAllowed(0x5A0); +SetRegisterAllowed(0x5A4); +SetRegisterAllowed(0x5A8); +SetRegisterAllowed(0x5AC); +SetRegisterAllowed(0x5B0); +SetRegisterAllowed(0x5B4); +SetRegisterAllowed(0x5B8); +SetRegisterAllowed(0x5BC); +SetRegisterAllowed(0x5C0); +SetRegisterAllowed(0x5C4); +SetRegisterAllowed(0x5C8); +SetRegisterAllowed(0x5CC); +SetRegisterAllowed(0x5D0); +SetRegisterAllowed(0x5D4); +SetRegisterAllowed(0x5D8); +SetRegisterAllowed(0x5DC); +SetRegisterAllowed(0x5E0); +SetRegisterAllowed(0x5E4); +SetRegisterAllowed(0x5E8); +SetRegisterAllowed(0x5EC); +SetRegisterAllowed(0x5F0); +SetRegisterAllowed(0x5F4); +SetRegisterAllowed(0x5F8); +SetRegisterAllowed(0x5FC); +SetRegisterAllowed(0x600); +SetRegisterAllowed(0x604); +SetRegisterAllowed(0x608); +SetRegisterAllowed(0x60C); +SetRegisterAllowed(0x610); +SetRegisterAllowed(0x614); +SetRegisterAllowed(0x618); +SetRegisterAllowed(0x61C); +SetRegisterAllowed(0x620); +SetRegisterAllowed(0x624); +SetRegisterAllowed(0x628); +SetRegisterAllowed(0x62C); +SetRegisterAllowed(0x630); +SetRegisterAllowed(0x634); +SetRegisterAllowed(0x638); +SetRegisterAllowed(0x63C); +SetRegisterAllowed(0x640); +SetRegisterAllowed(0x644); +SetRegisterAllowed(0x648); +SetRegisterAllowed(0x64C); +SetRegisterAllowed(0x650); +SetRegisterAllowed(0x654); +SetRegisterAllowed(0x658); +SetRegisterAllowed(0x65C); +SetRegisterAllowed(0x660); +SetRegisterAllowed(0x664); +SetRegisterAllowed(0x668); +SetRegisterAllowed(0x66C); +SetRegisterAllowed(0x670); +SetRegisterAllowed(0x674); +SetRegisterAllowed(0x678); +SetRegisterAllowed(0x67C); +SetRegisterAllowed(0x680); +SetRegisterAllowed(0x684); +SetRegisterAllowed(0x688); +SetRegisterAllowed(0x68C); +SetRegisterAllowed(0x690); +SetRegisterAllowed(0x694); +SetRegisterAllowed(0x698); +SetRegisterAllowed(0x69C); +SetRegisterAllowed(0x6A0); +SetRegisterAllowed(0x6A4); +SetRegisterAllowed(0x6A8); +SetRegisterAllowed(0x6AC); +SetRegisterAllowed(0x6B0); +SetRegisterAllowed(0x6B4); +SetRegisterAllowed(0x6B8); +SetRegisterAllowed(0x6BC); +SetRegisterAllowed(0x6C0); +SetRegisterAllowed(0x6C4); +SetRegisterAllowed(0x6C8); +SetRegisterAllowed(0x6CC); +SetRegisterAllowed(0x6D0); +SetRegisterAllowed(0x6D4); +SetRegisterAllowed(0x6D8); +SetRegisterAllowed(0x6DC); +SetRegisterAllowed(0x6E0); +SetRegisterAllowed(0x6E4); +SetRegisterAllowed(0x6E8); +SetRegisterAllowed(0x6EC); +SetRegisterAllowed(0x6F0); +SetRegisterAllowed(0x6F4); +SetRegisterAllowed(0x6F8); +SetRegisterAllowed(0x6FC); +SetRegisterAllowed(0x700); +SetRegisterAllowed(0x704); +SetRegisterAllowed(0x708); +SetRegisterAllowed(0x70C); +SetRegisterAllowed(0x710); +SetRegisterAllowed(0x714); +SetRegisterAllowed(0x718); +SetRegisterAllowed(0x71C); +SetRegisterAllowed(0x720); +SetRegisterAllowed(0x724); +SetRegisterAllowed(0x728); +SetRegisterAllowed(0x72C); +SetRegisterAllowed(0x730); +SetRegisterAllowed(0x734); +SetRegisterAllowed(0x738); +SetRegisterAllowed(0x73C); +SetRegisterAllowed(0x740); +SetRegisterAllowed(0x744); +SetRegisterAllowed(0x748); +SetRegisterAllowed(0x74C); +SetRegisterAllowed(0x750); +SetRegisterAllowed(0x754); +SetRegisterAllowed(0x758); +SetRegisterAllowed(0x75C); +SetRegisterAllowed(0x760); +SetRegisterAllowed(0x764); +SetRegisterAllowed(0x768); +SetRegisterAllowed(0x76C); +SetRegisterAllowed(0x770); +SetRegisterAllowed(0x774); +SetRegisterAllowed(0x778); +SetRegisterAllowed(0x77C); +SetRegisterAllowed(0x780); +SetRegisterAllowed(0x784); +SetRegisterAllowed(0x788); +SetRegisterAllowed(0x78C); +SetRegisterAllowed(0x790); +SetRegisterAllowed(0x794); +SetRegisterAllowed(0x798); +SetRegisterAllowed(0x79C); +SetRegisterAllowed(0x7A0); +SetRegisterAllowed(0x7A4); +SetRegisterAllowed(0x7A8); +SetRegisterAllowed(0x7AC); +SetRegisterAllowed(0x7B0); +SetRegisterAllowed(0x7B4); +SetRegisterAllowed(0x7B8); +SetRegisterAllowed(0x7BC); +SetRegisterAllowed(0x7C0); +SetRegisterAllowed(0x7C4); +SetRegisterAllowed(0x7C8); +SetRegisterAllowed(0x7CC); +SetRegisterAllowed(0x7D0); +SetRegisterAllowed(0x7D4); +SetRegisterAllowed(0x7D8); +SetRegisterAllowed(0x7DC); +SetRegisterAllowed(0x7E0); +SetRegisterAllowed(0x7E4); +SetRegisterAllowed(0x7E8); +SetRegisterAllowed(0x7EC); +SetRegisterAllowed(0x7F0); +SetRegisterAllowed(0x7F4); +SetRegisterAllowed(0x7F8); +SetRegisterAllowed(0x7FC); +SetRegisterAllowed(0x800); +SetRegisterAllowed(0x804); +SetRegisterAllowed(0x808); +SetRegisterAllowed(0x80C); +SetRegisterAllowed(0x810); +SetRegisterAllowed(0x814); +SetRegisterAllowed(0x818); +SetRegisterAllowed(0x81C); +SetRegisterAllowed(0x820); +SetRegisterAllowed(0x824); +SetRegisterAllowed(0x828); +SetRegisterAllowed(0x82C); +SetRegisterAllowed(0x830); +SetRegisterAllowed(0x834); +SetRegisterAllowed(0x838); +SetRegisterAllowed(0x83C); +SetRegisterAllowed(0x840); +SetRegisterAllowed(0x844); +SetRegisterAllowed(0x848); +SetRegisterAllowed(0x84C); +SetRegisterAllowed(0x850); +SetRegisterAllowed(0x854); +SetRegisterAllowed(0x858); +SetRegisterAllowed(0x85C); +SetRegisterAllowed(0x860); +SetRegisterAllowed(0x864); +SetRegisterAllowed(0x868); +SetRegisterAllowed(0x86C); +SetRegisterAllowed(0x870); +SetRegisterAllowed(0x874); +SetRegisterAllowed(0x878); +SetRegisterAllowed(0x87C); +SetRegisterAllowed(0x880); +SetRegisterAllowed(0x884); +SetRegisterAllowed(0x888); +SetRegisterAllowed(0x88C); +SetRegisterAllowed(0x890); +SetRegisterAllowed(0x894); +SetRegisterAllowed(0x898); +SetRegisterAllowed(0x89C); +SetRegisterAllowed(0x8A0); +SetRegisterAllowed(0x8A4); +SetRegisterAllowed(0x8A8); +SetRegisterAllowed(0x8AC); +SetRegisterAllowed(0x8B0); +SetRegisterAllowed(0x8B4); +SetRegisterAllowed(0x8B8); +SetRegisterAllowed(0x8BC); +SetRegisterAllowed(0x8C0); +SetRegisterAllowed(0x8C4); +SetRegisterAllowed(0x8C8); +SetRegisterAllowed(0x8CC); +SetRegisterAllowed(0x8D0); +SetRegisterAllowed(0x8D4); +SetRegisterAllowed(0x8D8); +SetRegisterAllowed(0x8DC); +SetRegisterAllowed(0x8E0); +SetRegisterAllowed(0x8E4); +SetRegisterAllowed(0x8E8); +SetRegisterAllowed(0x8EC); +SetRegisterAllowed(0x8F0); +SetRegisterAllowed(0x8F4); +SetRegisterAllowed(0x8F8); +SetRegisterAllowed(0x8FC); +SetRegisterAllowed(0x900); +SetRegisterAllowed(0x904); +SetRegisterAllowed(0x908); +SetRegisterAllowed(0x90C); +SetRegisterAllowed(0x910); +SetRegisterAllowed(0x914); +SetRegisterAllowed(0x918); +SetRegisterAllowed(0x91C); +SetRegisterAllowed(0x920); +SetRegisterAllowed(0x924); +SetRegisterAllowed(0x928); +SetRegisterAllowed(0x92C); +SetRegisterAllowed(0x930); +SetRegisterAllowed(0x934); +SetRegisterAllowed(0x938); +SetRegisterAllowed(0x93C); +SetRegisterAllowed(0x940); +SetRegisterAllowed(0x944); +SetRegisterAllowed(0x948); +SetRegisterAllowed(0x94C); +SetRegisterAllowed(0x950); +SetRegisterAllowed(0x954); +SetRegisterAllowed(0x958); +SetRegisterAllowed(0x95C); +SetRegisterAllowed(0x960); +SetRegisterAllowed(0x964); +SetRegisterAllowed(0x968); +SetRegisterAllowed(0x96C); +SetRegisterAllowed(0x970); +SetRegisterAllowed(0x974); +SetRegisterAllowed(0x978); +SetRegisterAllowed(0x97C); +SetRegisterAllowed(0x980); +SetRegisterAllowed(0x984); +SetRegisterAllowed(0x988); +SetRegisterAllowed(0x98C); +SetRegisterAllowed(0x990); +SetRegisterAllowed(0x994); +SetRegisterAllowed(0x998); +SetRegisterAllowed(0x99C); +SetRegisterAllowed(0x9A0); +SetRegisterAllowed(0x9A4); +SetRegisterAllowed(0x9A8); +SetRegisterAllowed(0x9AC); +SetRegisterAllowed(0x9B0); +SetRegisterAllowed(0x9B4); +SetRegisterAllowed(0x9B8); +SetRegisterAllowed(0x9BC); +SetRegisterAllowed(0x9C0); +SetRegisterAllowed(0x9C4); +SetRegisterAllowed(0x9C8); +SetRegisterAllowed(0x9CC); +SetRegisterAllowed(0x9D0); +SetRegisterAllowed(0x9D4); +SetRegisterAllowed(0x9D8); +SetRegisterAllowed(0x9DC); +SetRegisterAllowed(0x9E0); +SetRegisterAllowed(0x9E4); +SetRegisterAllowed(0x9E8); +SetRegisterAllowed(0x9EC); +SetRegisterAllowed(0x9F0); +SetRegisterAllowed(0x9F4); +SetRegisterAllowed(0x9F8); +SetRegisterAllowed(0x9FC); +SetRegisterAllowed(0xA00); +SetRegisterAllowed(0xA04); +SetRegisterAllowed(0xA08); +SetRegisterAllowed(0xA0C); +SetRegisterAllowed(0xA10); +SetRegisterAllowed(0xA14); +SetRegisterAllowed(0xA18); +SetRegisterAllowed(0xA1C); +SetRegisterAllowed(0xA20); +SetRegisterAllowed(0xA24); +SetRegisterAllowed(0xA28); +SetRegisterAllowed(0xA2C); +SetRegisterAllowed(0xA30); +SetRegisterAllowed(0xA34); +SetRegisterAllowed(0xA38); +SetRegisterAllowed(0xA3C); +SetRegisterAllowed(0xA40); +SetRegisterAllowed(0xA44); +SetRegisterAllowed(0xA48); +SetRegisterAllowed(0xA4C); +SetRegisterAllowed(0xA50); +SetRegisterAllowed(0xA54); +SetRegisterAllowed(0xA58); +SetRegisterAllowed(0xA5C); +SetRegisterAllowed(0xA60); +SetRegisterAllowed(0xA64); +SetRegisterAllowed(0xA68); +SetRegisterAllowed(0xA6C); +SetRegisterAllowed(0xA70); +SetRegisterAllowed(0xA74); +SetRegisterAllowed(0xA78); +SetRegisterAllowed(0xA7C); +SetRegisterAllowed(0xA80); +SetRegisterAllowed(0xA84); +SetRegisterAllowed(0xA88); +SetRegisterAllowed(0xA8C); +SetRegisterAllowed(0xA90); +SetRegisterAllowed(0xA94); +SetRegisterAllowed(0xA98); +SetRegisterAllowed(0xA9C); +SetRegisterAllowed(0xAA0); +SetRegisterAllowed(0xAA4); +SetRegisterAllowed(0xAA8); +SetRegisterAllowed(0xAAC); +SetRegisterAllowed(0xAB0); +SetRegisterAllowed(0xAB4); +SetRegisterAllowed(0xAB8); +SetRegisterAllowed(0xABC); +SetRegisterAllowed(0xAC0); +SetRegisterAllowed(0xAC4); +SetRegisterAllowed(0xAC8); +SetRegisterAllowed(0xACC); +SetRegisterAllowed(0xAD0); +SetRegisterAllowed(0xAD4); +SetRegisterAllowed(0xAD8); +SetRegisterAllowed(0xADC); +SetRegisterAllowed(0xAE0); +SetRegisterAllowed(0xAE4); +SetRegisterAllowed(0xAE8); +SetRegisterAllowed(0xAEC); +SetRegisterAllowed(0xAF0); +SetRegisterAllowed(0xAF4); +SetRegisterAllowed(0xAF8); +SetRegisterAllowed(0xAFC); +SetRegisterAllowed(0xB00); +SetRegisterAllowed(0xB04); +SetRegisterAllowed(0xB08); +SetRegisterAllowed(0xB0C); +SetRegisterAllowed(0xB10); +SetRegisterAllowed(0xB14); +SetRegisterAllowed(0xB18); +SetRegisterAllowed(0xB1C); +SetRegisterAllowed(0xB20); +SetRegisterAllowed(0xB24); +SetRegisterAllowed(0xB28); +SetRegisterAllowed(0xB2C); +SetRegisterAllowed(0xB30); +SetRegisterAllowed(0xB34); +SetRegisterAllowed(0xB38); +SetRegisterAllowed(0xB3C); +SetRegisterAllowed(0xB40); +SetRegisterAllowed(0xB44); +SetRegisterAllowed(0xB48); +SetRegisterAllowed(0xB4C); +SetRegisterAllowed(0xB50); +SetRegisterAllowed(0xB54); +SetRegisterAllowed(0xB58); +SetRegisterAllowed(0xB5C); +SetRegisterAllowed(0xB60); +SetRegisterAllowed(0xB64); +SetRegisterAllowed(0xB68); +SetRegisterAllowed(0xB6C); +SetRegisterAllowed(0xB70); +SetRegisterAllowed(0xB74); +SetRegisterAllowed(0xB78); +SetRegisterAllowed(0xB7C); +SetRegisterAllowed(0xB80); +SetRegisterAllowed(0xB84); +SetRegisterAllowed(0xB88); +SetRegisterAllowed(0xB8C); +SetRegisterAllowed(0xB90); +SetRegisterAllowed(0xB94); +SetRegisterAllowed(0xB98); +SetRegisterAllowed(0xB9C); +SetRegisterAllowed(0xBA0); +SetRegisterAllowed(0xBA4); +SetRegisterAllowed(0xBA8); +SetRegisterAllowed(0xBAC); +SetRegisterAllowed(0xBB0); +SetRegisterAllowed(0xBB4); +SetRegisterAllowed(0xBB8); +SetRegisterAllowed(0xBBC); +SetRegisterAllowed(0xBC0); +SetRegisterAllowed(0xBC4); +SetRegisterAllowed(0xBC8); +SetRegisterAllowed(0xBCC); +SetRegisterAllowed(0xBD0); +SetRegisterAllowed(0xBD4); +SetRegisterAllowed(0xBD8); +SetRegisterAllowed(0xBDC); +SetRegisterAllowed(0xBE0); +SetRegisterAllowed(0xBE4); +SetRegisterAllowed(0xBE8); +SetRegisterAllowed(0xBEC); +SetRegisterAllowed(0xBF0); +SetRegisterAllowed(0xBF4); +SetRegisterAllowed(0xBF8); +SetRegisterAllowed(0xBFC); +SetRegisterAllowed(0xC00); +SetRegisterAllowed(0xC04); +SetRegisterAllowed(0xC08); +SetRegisterAllowed(0xC0C); +SetRegisterAllowed(0xC10); +SetRegisterAllowed(0xC14); +SetRegisterAllowed(0xC18); +SetRegisterAllowed(0xC1C); +SetRegisterAllowed(0xC20); +SetRegisterAllowed(0xC24); +SetRegisterAllowed(0xC28); +SetRegisterAllowed(0xC2C); +SetRegisterAllowed(0xC30); +SetRegisterAllowed(0xC34); +SetRegisterAllowed(0xC38); +SetRegisterAllowed(0xC3C); +SetRegisterAllowed(0xC40); +SetRegisterAllowed(0xC44); +SetRegisterAllowed(0xC48); +SetRegisterAllowed(0xC4C); +SetRegisterAllowed(0xC50); +SetRegisterAllowed(0xC54); +SetRegisterAllowed(0xC58); +SetRegisterAllowed(0xC5C); +SetRegisterAllowed(0xC60); +SetRegisterAllowed(0xC64); +SetRegisterAllowed(0xC68); +SetRegisterAllowed(0xC6C); +SetRegisterAllowed(0xC70); +SetRegisterAllowed(0xC74); +SetRegisterAllowed(0xC78); +SetRegisterAllowed(0xC7C); +SetRegisterAllowed(0xC80); +SetRegisterAllowed(0xC84); +SetRegisterAllowed(0xC88); +SetRegisterAllowed(0xC8C); +SetRegisterAllowed(0xC90); +SetRegisterAllowed(0xC94); +SetRegisterAllowed(0xC98); +SetRegisterAllowed(0xC9C); +SetRegisterAllowed(0xCA0); +SetRegisterAllowed(0xCA4); +SetRegisterAllowed(0xCA8); +SetRegisterAllowed(0xCAC); +SetRegisterAllowed(0xCB0); +SetRegisterAllowed(0xCB4); +SetRegisterAllowed(0xCB8); +SetRegisterAllowed(0xCBC); +SetRegisterAllowed(0xCC0); +SetRegisterAllowed(0xCC4); +SetRegisterAllowed(0xCC8); +SetRegisterAllowed(0xCCC); +SetRegisterAllowed(0xCD0); +SetRegisterAllowed(0xCD4); +SetRegisterAllowed(0xCD8); +SetRegisterAllowed(0xCDC); +SetRegisterAllowed(0xCE0); +SetRegisterAllowed(0xCE4); +SetRegisterAllowed(0xCE8); +SetRegisterAllowed(0xCEC); +SetRegisterAllowed(0xCF0); +SetRegisterAllowed(0xCF4); +SetRegisterAllowed(0xCF8); +SetRegisterAllowed(0xCFC); +SetRegisterAllowed(0xD00); +SetRegisterAllowed(0xD04); +SetRegisterAllowed(0xD08); +SetRegisterAllowed(0xD0C); +SetRegisterAllowed(0xD10); +SetRegisterAllowed(0xD14); +SetRegisterAllowed(0xD18); +SetRegisterAllowed(0xD1C); +SetRegisterAllowed(0xD20); +SetRegisterAllowed(0xD24); +SetRegisterAllowed(0xD28); +SetRegisterAllowed(0xD2C); +SetRegisterAllowed(0xD30); +SetRegisterAllowed(0xD34); +SetRegisterAllowed(0xD38); +SetRegisterAllowed(0xD3C); +SetRegisterAllowed(0xD40); +SetRegisterAllowed(0xD44); +SetRegisterAllowed(0xD48); +SetRegisterAllowed(0xD4C); +SetRegisterAllowed(0xD50); +SetRegisterAllowed(0xD54); +SetRegisterAllowed(0xD58); +SetRegisterAllowed(0xD5C); +SetRegisterAllowed(0xD60); +SetRegisterAllowed(0xD64); +SetRegisterAllowed(0xD68); +SetRegisterAllowed(0xD6C); +SetRegisterAllowed(0xD70); +SetRegisterAllowed(0xD74); +SetRegisterAllowed(0xD78); +SetRegisterAllowed(0xD7C); +SetRegisterAllowed(0xD80); +SetRegisterAllowed(0xD84); +SetRegisterAllowed(0xD88); +SetRegisterAllowed(0xD8C); +SetRegisterAllowed(0xD90); +SetRegisterAllowed(0xD94); +SetRegisterAllowed(0xD98); +SetRegisterAllowed(0xD9C); +SetRegisterAllowed(0xDA0); +SetRegisterAllowed(0xDA4); +SetRegisterAllowed(0xDA8); +SetRegisterAllowed(0xDAC); +SetRegisterAllowed(0xDB0); +SetRegisterAllowed(0xDB4); +SetRegisterAllowed(0xDB8); +SetRegisterAllowed(0xDBC); +SetRegisterAllowed(0xDC0); +SetRegisterAllowed(0xDC4); +SetRegisterAllowed(0xDC8); +SetRegisterAllowed(0xDCC); +SetRegisterAllowed(0xDD0); +SetRegisterAllowed(0xDD4); +SetRegisterAllowed(0xDD8); +SetRegisterAllowed(0xDDC); +SetRegisterAllowed(0xDE0); +SetRegisterAllowed(0xDE4); +SetRegisterAllowed(0xDE8); +SetRegisterAllowed(0xDEC); +SetRegisterAllowed(0xDF0); +SetRegisterAllowed(0xDF4); +SetRegisterAllowed(0xDF8); +SetRegisterAllowed(0xDFC); +SetRegisterAllowed(0xE00); +SetRegisterAllowed(0xE04); +SetRegisterAllowed(0xE08); +SetRegisterAllowed(0xE0C); +SetRegisterAllowed(0xE10); +SetRegisterAllowed(0xE14); +SetRegisterAllowed(0xE18); +SetRegisterAllowed(0xE1C); +SetRegisterAllowed(0xE20); +SetRegisterAllowed(0xE24); +SetRegisterAllowed(0xE28); +SetRegisterAllowed(0xE2C); +SetRegisterAllowed(0xE30); +SetRegisterAllowed(0xE34); +SetRegisterAllowed(0xE38); +SetRegisterAllowed(0xE3C); +SetRegisterAllowed(0xE40); +SetRegisterAllowed(0xE44); +SetRegisterAllowed(0xE48); +SetRegisterAllowed(0xE4C); +SetRegisterAllowed(0xE50); +SetRegisterAllowed(0xE54); +SetRegisterAllowed(0xE58); +SetRegisterAllowed(0xE5C); +SetRegisterAllowed(0xE60); +SetRegisterAllowed(0xE64); +SetRegisterAllowed(0xE68); +SetRegisterAllowed(0xE6C); +SetRegisterAllowed(0xE70); +SetRegisterAllowed(0xE74); +SetRegisterAllowed(0xE78); +SetRegisterAllowed(0xE7C); +SetRegisterAllowed(0xE80); +SetRegisterAllowed(0xE84); +SetRegisterAllowed(0xE88); +SetRegisterAllowed(0xE8C); +SetRegisterAllowed(0xE90); +SetRegisterAllowed(0xE94); +SetRegisterAllowed(0xE98); +SetRegisterAllowed(0xE9C); +SetRegisterAllowed(0xEA0); +SetRegisterAllowed(0xEA4); +SetRegisterAllowed(0xEA8); +SetRegisterAllowed(0xEAC); +SetRegisterAllowed(0xEB0); +SetRegisterAllowed(0xEB4); +SetRegisterAllowed(0xEB8); +SetRegisterAllowed(0xEBC); +SetRegisterAllowed(0xEC0); +SetRegisterAllowed(0xEC4); +SetRegisterAllowed(0xEC8); +SetRegisterAllowed(0xECC); +SetRegisterAllowed(0xED0); +SetRegisterAllowed(0xED4); +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); diff --git a/Source/Atmosphere-Patches/secmon_memory_layout.hpp b/Source/Atmosphere-Patches/secmon_memory_layout.hpp index 7c0e499a..ba3e3ab8 100644 --- a/Source/Atmosphere-Patches/secmon_memory_layout.hpp +++ b/Source/Atmosphere-Patches/secmon_memory_layout.hpp @@ -151,7 +151,9 @@ namespace ams::secmon { 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(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ - HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ + HANDLER(ExternalMemoryController0, MemoryController1, UINT64_C(0x7001E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ + HANDLER(ExternalMemoryController1, ExternalMemoryController0, UINT64_C(0x7001F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ + HANDLER(Sdmmc, ExternalMemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), 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(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) \ diff --git a/Source/Atmosphere-Patches/secmon_setup.cpp b/Source/Atmosphere-Patches/secmon_setup.cpp new file mode 100644 index 00000000..ca761033 --- /dev/null +++ b/Source/Atmosphere-Patches/secmon_setup.cpp @@ -0,0 +1,1226 @@ +/* + * 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 . + */ +#include +#include "secmon_setup.hpp" +#include "secmon_error.hpp" +#include "secmon_map.hpp" +#include "secmon_cpu_context.hpp" +#include "secmon_mariko_fatal_error.hpp" +#include "secmon_interrupt_handler.hpp" +#include "secmon_misc.hpp" +#include "smc/secmon_random_cache.hpp" +#include "smc/secmon_smc_power_management.hpp" +#include "smc/secmon_smc_se_lock.hpp" + +namespace ams::secmon { + + namespace { + + constexpr inline const uintptr_t TIMER = secmon::MemoryRegionVirtualDeviceTimer.GetAddress(); + constexpr inline const uintptr_t SYSTEM = secmon::MemoryRegionVirtualDeviceSystem.GetAddress(); + constexpr inline const uintptr_t APB_MISC = secmon::MemoryRegionVirtualDeviceApbMisc.GetAddress(); + constexpr inline const uintptr_t FLOW_CTLR = secmon::MemoryRegionVirtualDeviceFlowController.GetAddress(); + constexpr inline const uintptr_t PMC = secmon::MemoryRegionVirtualDevicePmc.GetAddress(); + constexpr inline const uintptr_t MC = secmon::MemoryRegionVirtualDeviceMemoryController.GetAddress(); + constexpr inline const uintptr_t EVP = secmon::MemoryRegionVirtualDeviceExceptionVectors.GetAddress(); + constexpr inline const uintptr_t CLK_RST = secmon::MemoryRegionVirtualDeviceClkRst.GetAddress(); + + alignas(8) constinit u8 g_se_aes_key_slot_test_vector[se::AesBlockSize] = {}; + + struct Carveout { + uintptr_t address; + size_t size; + }; + + constinit Carveout g_kernel_carveouts[KernelCarveoutCount] = { + { secmon::MemoryRegionDramDefaultKernelCarveout.GetAddress(), secmon::MemoryRegionDramDefaultKernelCarveout.GetSize(), }, + { 0, 0, }, + }; + + constinit bool g_is_cold_boot = true; + + constinit se::StickyBits ExpectedSeStickyBits = { + .se_security = (1 << 0), /* SE_HARD_SETTING */ + .tzram_security = 0, + .crypto_security_perkey = (1 << pkg1::AesKeySlot_UserEnd) - 1, + .crypto_keytable_access = { + (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 0: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */ + (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 1: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */ + (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 2: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */ + (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 3: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */ + (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 4: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */ + (0 << 7) | (1 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 5: User keyslot. KEY. KEYUSE, UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. UIVREAD, OIVREAD, KEYREAD disabled. */ + (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 6: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */ + (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 7: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */ + (0 << 7) | (0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 8: Temp keyslot. KEY. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */ + (0 << 7) | (0 << 6) | (1 << 5) | (0 << 4) | (1 << 3) | (0 << 2) | (1 << 1) | (0 << 0), /* 9: SmcTemp keyslot. KEY. UIVUPDATE, OIVUPDATE, KEYUPDATE enabled. KEYUSE, UIVREAD, OIVREAD, KEYREAD disabled. */ + (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 10: Wrap1 keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */ + (0 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 11: Wrap2 keyslot. KEY. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */ + (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 12: DMaster keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */ + (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Master keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */ + (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 14: Unused keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */ + (1 << 7) | (0 << 6) | (0 << 5) | (0 << 4) | (0 << 3) | (0 << 2) | (0 << 1) | (0 << 0), /* 13: Device keyslot. KEK. KEYUSE, UIVUPDATE, UIVREAD, OIVUPDATE, OIVREAD, KEYUPDATE, KEYREAD disabled. */ + }, + .rsa_security_perkey = 0, + .rsa_keytable_access = { + (0 << 2) | (1 << 1) | (0 << 0), /* KEYUSE/KEYREAD disabled, KEYUPDATE enabled. */ + (0 << 2) | (1 << 1) | (0 << 0), /* KEYUSE/KEYREAD disabled, KEYUPDATE enabled. */ + }, + }; + + void InitializeConfigurationContext() { + /* Get the global context. */ + auto &ctx = ::ams::secmon::impl::GetConfigurationContext(); + + /* Clear the context to zero. */ + std::memset(std::addressof(ctx), 0, sizeof(ctx)); + + /* If the storage context is valid, we want to copy it to the global context. */ + if (const auto &storage_ctx = *MemoryRegionPhysicalDramMonitorConfiguration.GetPointer(); storage_ctx.IsValid()) { + ctx.secmon_cfg.CopyFrom(storage_ctx); + ctx.emummc_cfg = storage_ctx.emummc_cfg; + } else { + /* If we don't have a valid storage context, we can just use the default one. */ + ctx.secmon_cfg = DefaultSecureMonitorConfiguration; + } + + /* Cache the fuse info for quick access. */ + ctx.secmon_cfg.SetFuseInfo(); + } + + void GenerateSecurityEngineAesKeySlotTestVector(void *dst, size_t size) { + /* Clear the output. */ + AMS_ABORT_UNLESS(size == se::AesBlockSize); + std::memset(dst, 0, se::AesBlockSize); + + /* Ensure output is seen as cleared by the se. */ + hw::FlushDataCache(dst, se::AesBlockSize); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Declare a block. */ + alignas(8) u8 empty_block[se::AesBlockSize]; + + /* Iteratively transform an empty block. */ + #define TRANSFORM_WITH_KEY(key) \ + __builtin_memset(empty_block, 0, sizeof(empty_block)); \ + se::SetEncryptedAesKey256(pkg1::AesKeySlot_Temporary, key, empty_block, sizeof(empty_block)); \ + se::DecryptAes128(dst, se::AesBlockSize, pkg1::AesKeySlot_Temporary, dst, se::AesBlockSize) + + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_RandomForUserWrap); + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_RandomForKeyStorageWrap); + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_Master); + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_DeviceMaster); + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_Device); + + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_RandomForUserWrap); + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_RandomForKeyStorageWrap); + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_Master); + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_DeviceMaster); + TRANSFORM_WITH_KEY(pkg1::AesKeySlot_Device); + + /* Ensure output is seen correctly by the cpu. */ + hw::FlushDataCache(dst, se::AesBlockSize); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Clear the temporary key slot. */ + se::ClearAesKeySlot(pkg1::AesKeySlot_Temporary); + } + + void VerifySecurityEngineStickyBits() { + /* On mariko, an extra sticky bit is set. */ + if (GetSocType() == fuse::SocType_Mariko) { + ExpectedSeStickyBits.se_security |= (1 << 5); + } else /* if (GetSocType() == fuse::SocType_Erista) */ { + /* Erista does not support DST_KEYTABLE_ONLY, and so all keys will have the bit clear. */ + for (size_t i = 0; i < util::size(ExpectedSeStickyBits.crypto_keytable_access); ++i) { + ExpectedSeStickyBits.crypto_keytable_access[i] &= ~(1 << 7); + } + } + + if (!se::ValidateStickyBits(ExpectedSeStickyBits)) { + SetError(pkg1::ErrorInfo_InvalidSecurityEngineStickyBits); + AMS_ABORT("Invalid sticky bits"); + } + } + + void VerifySecurityEngineAesKeySlotTestVector() { + alignas(8) u8 test_vector[se::AesBlockSize]; + GenerateSecurityEngineAesKeySlotTestVector(test_vector, sizeof(test_vector)); + + AMS_ABORT_UNLESS(crypto::IsSameBytes(g_se_aes_key_slot_test_vector, test_vector, se::AesBlockSize)); + } + + void ClearAesKeySlots() { + /* Clear all non-secure monitor keys. */ + for (int i = 0; i < pkg1::AesKeySlot_SecmonStart; ++i) { + se::ClearAesKeySlot(i); + } + + /* Clear the secure-monitor temporary keys. */ + se::ClearAesKeySlot(pkg1::AesKeySlot_Temporary); + se::ClearAesKeySlot(pkg1::AesKeySlot_Smc); + } + + void ClearRsaKeySlots() { + /* Clear all rsa keyslots. */ + for (int i = 0; i < se::RsaKeySlotCount; ++i) { + se::ClearRsaKeySlot(i); + } + } + + void SetupKernelCarveouts() { + #define MC_ENABLE_CLIENT_ACCESS(INDEX, WHICH) MC_REG_BITS_ENUM(CLIENT_ACCESS##INDEX##_##WHICH, ENABLE) + + constexpr u32 ClientAccess0 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(0, PTCR), + MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0A), + MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0AB), + MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0B), + MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0BB), + MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0C), + MC_ENABLE_CLIENT_ACCESS(0, DISPLAY0CB), + MC_ENABLE_CLIENT_ACCESS(0, AFIR), + MC_ENABLE_CLIENT_ACCESS(0, DISPLAYHC), + MC_ENABLE_CLIENT_ACCESS(0, DISPLAYHCB), + MC_ENABLE_CLIENT_ACCESS(0, HDAR), + MC_ENABLE_CLIENT_ACCESS(0, HOST1XDMAR), + MC_ENABLE_CLIENT_ACCESS(0, HOST1XR), + MC_ENABLE_CLIENT_ACCESS(0, NVENCSRD), + MC_ENABLE_CLIENT_ACCESS(0, PPCSAHBDMAR), + MC_ENABLE_CLIENT_ACCESS(0, PPCSAHBSLVR)); + + constexpr u32 ClientAccess1 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(1, MPCORER), + MC_ENABLE_CLIENT_ACCESS(1, NVENCSWR), + MC_ENABLE_CLIENT_ACCESS(1, AFIW), + MC_ENABLE_CLIENT_ACCESS(1, HDAW), + MC_ENABLE_CLIENT_ACCESS(1, HOST1XW), + MC_ENABLE_CLIENT_ACCESS(1, MPCOREW), + MC_ENABLE_CLIENT_ACCESS(1, PPCSAHBDMAW), + MC_ENABLE_CLIENT_ACCESS(1, PPCSAHBSLVW)); + + constexpr u32 ClientAccess2 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(2, XUSB_HOSTR), + MC_ENABLE_CLIENT_ACCESS(2, XUSB_HOSTW), + MC_ENABLE_CLIENT_ACCESS(2, XUSB_DEVR), + MC_ENABLE_CLIENT_ACCESS(2, XUSB_DEVW)); + + constexpr u32 ClientAccess2_100 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(2, XUSB_HOSTR), + MC_ENABLE_CLIENT_ACCESS(2, XUSB_HOSTW), + MC_ENABLE_CLIENT_ACCESS(2, XUSB_DEVR), + MC_ENABLE_CLIENT_ACCESS(2, XUSB_DEVW), + MC_ENABLE_CLIENT_ACCESS(2, TSECSRD), + MC_ENABLE_CLIENT_ACCESS(2, TSECSWR)); + + constexpr u32 ClientAccess3 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(3, SDMMCRA), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCRAA), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCRAB), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCWA), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCWAA), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCWAB), + MC_ENABLE_CLIENT_ACCESS(3, VICSRD), + MC_ENABLE_CLIENT_ACCESS(3, VICSWR), + MC_ENABLE_CLIENT_ACCESS(3, DISPLAYD), + MC_ENABLE_CLIENT_ACCESS(3, APER), + MC_ENABLE_CLIENT_ACCESS(3, APEW), + MC_ENABLE_CLIENT_ACCESS(3, NVJPGSRD), + MC_ENABLE_CLIENT_ACCESS(3, NVJPGSWR)); + + constexpr u32 ClientAccess3_100 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(3, SDMMCRA), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCRAA), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCRAB), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCWA), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCWAA), + MC_ENABLE_CLIENT_ACCESS(3, SDMMCWAB), + MC_ENABLE_CLIENT_ACCESS(3, VICSRD), + MC_ENABLE_CLIENT_ACCESS(3, VICSWR), + MC_ENABLE_CLIENT_ACCESS(3, DISPLAYD), + MC_ENABLE_CLIENT_ACCESS(3, NVDECSRD), + MC_ENABLE_CLIENT_ACCESS(3, NVDECSWR), + MC_ENABLE_CLIENT_ACCESS(3, APER), + MC_ENABLE_CLIENT_ACCESS(3, APEW), + MC_ENABLE_CLIENT_ACCESS(3, NVJPGSRD), + MC_ENABLE_CLIENT_ACCESS(3, NVJPGSWR)); + + constexpr u32 ClientAccess4 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(4, SESRD), + MC_ENABLE_CLIENT_ACCESS(4, SESWR)); + + constexpr u32 ClientAccess4_800 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(4, SESRD), + MC_ENABLE_CLIENT_ACCESS(4, SESWR), + MC_ENABLE_CLIENT_ACCESS(4, TSECRDB), + MC_ENABLE_CLIENT_ACCESS(4, TSECWRB)); + + + constexpr u32 ClientAccess4_100 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(4, SESRD), + MC_ENABLE_CLIENT_ACCESS(4, SESWR)); + + #undef MC_ENABLE_CLIENT_ACCESS + + constexpr u32 ForceInternalAccess0 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS0_AVPCARM7R, ENABLE)); + constexpr u32 ForceInternalAccess0_100 = 0; + + constexpr u32 ForceInternalAccess1 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS1_AVPCARM7W, ENABLE)); + constexpr u32 ForceInternalAccess1_100 = 0; + + constexpr u32 CarveoutConfig = reg::Encode(MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, ANY_ADDRESS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, TZ_SECURE)); + + constexpr u32 CarveoutConfig_100 = reg::Encode(MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, ANY_ADDRESS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, TZ_SECURE)); + + const u32 target_fw = GetTargetFirmware(); + u32 client_access_2; + u32 client_access_3; + u32 client_access_4; + u32 carveout_config; + if (target_fw >= TargetFirmware_8_1_0) { + client_access_2 = ClientAccess2; + client_access_3 = ClientAccess3; + client_access_4 = ClientAccess4; + carveout_config = CarveoutConfig; + } else if (target_fw >= TargetFirmware_8_0_0) { + client_access_2 = ClientAccess2; + client_access_3 = ClientAccess3; + client_access_4 = ClientAccess4_800; + carveout_config = CarveoutConfig; + } else { + client_access_2 = ClientAccess2_100; + client_access_3 = ClientAccess3_100; + client_access_4 = ClientAccess4_100; + carveout_config = CarveoutConfig_100; + } + + /* Configure carveout 4. */ + reg::Write(MC + MC_SECURITY_CARVEOUT4_BOM, g_kernel_carveouts[0].address >> 0); + reg::Write(MC + MC_SECURITY_CARVEOUT4_BOM_HI, g_kernel_carveouts[0].address >> 32); + reg::Write(MC + MC_SECURITY_CARVEOUT4_SIZE_128KB, g_kernel_carveouts[0].size / 128_KB); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS0, ClientAccess0); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS1, ClientAccess1); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS2, client_access_2); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS3, client_access_3); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_ACCESS4, client_access_4); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS0, (target_fw >= TargetFirmware_4_0_0) ? ForceInternalAccess0 : ForceInternalAccess0_100); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS1, (target_fw >= TargetFirmware_4_0_0) ? ForceInternalAccess1 : ForceInternalAccess1_100); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS2, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS3, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CLIENT_FORCE_INTERNAL_ACCESS4, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT4_CFG0, carveout_config); + + /* Configure carveout 5. */ + reg::Write(MC + MC_SECURITY_CARVEOUT5_BOM, g_kernel_carveouts[1].address >> 0); + reg::Write(MC + MC_SECURITY_CARVEOUT5_BOM_HI, g_kernel_carveouts[1].address >> 32); + reg::Write(MC + MC_SECURITY_CARVEOUT5_SIZE_128KB, g_kernel_carveouts[1].size / 128_KB); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS0, ClientAccess0); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS1, ClientAccess1); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS2, client_access_2); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS3, client_access_3); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_ACCESS4, client_access_4); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS0, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS1, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS2, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS3, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CLIENT_FORCE_INTERNAL_ACCESS4, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT5_CFG0, carveout_config); + } + + void ConfigureSlaveSecurity() { + u32 reg0, reg1, reg2; + if (GetTargetFirmware() > TargetFirmware_1_0_0) { + reg0 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(0, SATA_AUX, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, DTV, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, QSPI, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, SE, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, SATA, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, LA, ENABLE)); + + reg1 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, SPI1, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI2, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI3, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI5, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI6, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, I2C6, ENABLE)); + + reg2 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(2, SDMMC3, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(2, DDS, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(2, DP2, ENABLE)); + + const auto hw_type = GetHardwareType(); + + /* Switch Lite can't use HDMI, so set CEC to secure on hoag. */ + if (hw_type == fuse::HardwareType_Hoag) { + reg0 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(0, CEC, ENABLE)); + } + + /* Icosa, Iowa, and Aula all set I2C4 to be secure. */ + if (hw_type == fuse::HardwareType_Icosa && hw_type == fuse::HardwareType_Iowa && hw_type == fuse::HardwareType_Aula) { + reg1 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, I2C4, ENABLE)); + + } + + /* Hoag additionally sets UART_B to secure. */ + if (hw_type == fuse::HardwareType_Hoag) { + reg1 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, UART_B, ENABLE)); + } + + /* Copper and Calcio lack a lot of hardware, so set the corresponding registers to secure for them. */ + if (hw_type == fuse::HardwareType_Calcio || hw_type == fuse::HardwareType_Copper) { + reg1 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, UART_B, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, UART_C, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI4, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, I2C2, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, I2C3, ENABLE)); + + /* Copper/Calcio have no gamecard reader, and thus set SDMMC2 as secure. */ + reg2 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(2, SDMMC2, ENABLE)); + } + + /* Mariko hardware types (not Icosa or Copper) additionally set mariko-only mmio (SE2, PKA1, FEK) as secure. */ + if (hw_type != fuse::HardwareType_Icosa && hw_type != fuse::HardwareType_Copper) { + reg2 |= reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(2, SE2, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(2, PKA1, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(2, FEK, ENABLE)); + } + } else { + reg0 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(0, SATA_AUX, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, DTV, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, QSPI, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, SATA, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(0, LA, ENABLE)); + + reg1 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(1, SPI1, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI2, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI3, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI5, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, SPI6, ENABLE), + SLAVE_SECURITY_REG_BITS_ENUM(1, I2C6, ENABLE)); + + reg2 = reg::Encode(SLAVE_SECURITY_REG_BITS_ENUM(2, DDS, ENABLE), + REG_BITS_VALUE(5, 1, 1), /* Note: Bit 5 is not documented in TRM. */ + REG_BITS_VALUE(4, 1, 1)); /* Note: Bit 4 is not documented in TRM. */ + } + + reg::Write(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, reg0); + reg::Write(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, reg1); + reg::Write(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG2_0, reg2); + } + + void SetupSecureRegisters() { + /* Configure timers 5-8 and watchdog timers 0-3 as secure. */ + reg::Write(TIMER + TIMER_SHARED_TIMER_SECURE_CFG, TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_TMR5, ENABLE), + TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_TMR6, ENABLE), + TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_TMR7, ENABLE), + TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_TMR8, ENABLE), + TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_WDT0, ENABLE), + TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_WDT1, ENABLE), + TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_WDT2, ENABLE), + TIMER_REG_BITS_ENUM(SHARED_TIMER_SECURE_CFG_WDT3, ENABLE)); + + /* Lock cluster switching, to prevent usage of the A53 cores. */ + reg::Write(FLOW_CTLR + FLOW_CTLR_BPMP_CLUSTER_CONTROL, FLOW_REG_BITS_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER_LOCK, ENABLE), + FLOW_REG_BITS_ENUM(BPMP_CLUSTER_CONTROL_CLUSTER_SWITCH_ENABLE, DISABLE), + FLOW_REG_BITS_ENUM(BPMP_CLUSTER_CONTROL_ACTIVE_CLUSTER, FAST)); + + /* Enable flow controller debug qualifier for legacy FIQs. */ + reg::Write(FLOW_CTLR + FLOW_CTLR_FLOW_DBG_QUAL, FLOW_REG_BITS_ENUM(FLOW_DBG_QUAL_FIQ2CCPLEX_ENABLE, ENABLE)); + + /* Configure the PMC to disable deep power-down. */ + reg::Write(PMC + APBDEV_PMC_DPD_ENABLE, PMC_REG_BITS_ENUM(DPD_ENABLE_TSC_MULT_EN, DISABLE), + PMC_REG_BITS_ENUM(DPD_ENABLE_ON, DISABLE)); + + /* Configure the video protect region. */ + reg::Write(MC + MC_VIDEO_PROTECT_GPU_OVERRIDE_0, 1); + reg::Write(MC + MC_VIDEO_PROTECT_GPU_OVERRIDE_1, 0); + reg::Write(MC + MC_VIDEO_PROTECT_BOM, 0); + reg::Write(MC + MC_VIDEO_PROTECT_SIZE_MB, 0); + reg::Write(MC + MC_VIDEO_PROTECT_REG_CTRL, MC_REG_BITS_ENUM(VIDEO_PROTECT_REG_CTRL_VIDEO_PROTECT_ALLOW_TZ_WRITE, DISABLED), + MC_REG_BITS_ENUM(VIDEO_PROTECT_REG_CTRL_VIDEO_PROTECT_WRITE_ACCESS, DISABLED)); + + /* Configure the SEC carveout. */ + reg::Write(MC + MC_SEC_CARVEOUT_BOM, 0); + reg::Write(MC + MC_SEC_CARVEOUT_SIZE_MB, 0); + reg::Write(MC + MC_SEC_CARVEOUT_REG_CTRL, MC_REG_BITS_ENUM(SEC_CARVEOUT_REG_CTRL_SEC_CARVEOUT_WRITE_ACCESS, DISABLED)); + + /* Configure the MTS carveout. */ + reg::Write(MC + MC_MTS_CARVEOUT_BOM, 0); + reg::Write(MC + MC_MTS_CARVEOUT_SIZE_MB, 0); + reg::Write(MC + MC_MTS_CARVEOUT_ADR_HI, 0); + reg::Write(MC + MC_MTS_CARVEOUT_REG_CTRL, MC_REG_BITS_ENUM(MTS_CARVEOUT_REG_CTRL_MTS_CARVEOUT_WRITE_ACCESS, DISABLED)); + + /* Configure the security carveout. */ + reg::Write(MC + MC_SECURITY_CFG0, MC_REG_BITS_VALUE(SECURITY_CFG0_SECURITY_BOM, 0)); + reg::Write(MC + MC_SECURITY_CFG1, MC_REG_BITS_VALUE(SECURITY_CFG1_SECURITY_SIZE, 0)); + reg::Write(MC + MC_SECURITY_CFG3, MC_REG_BITS_VALUE(SECURITY_CFG3_SECURITY_BOM_HI, 3)); + + /* Configure security carveout 1. */ + reg::Write(MC + MC_SECURITY_CARVEOUT1_BOM, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_BOM_HI, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_SIZE_128KB, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS0, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS1, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS2, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS3, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_ACCESS4, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS0, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS1, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS2, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS3, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CLIENT_FORCE_INTERNAL_ACCESS4, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT1_CFG0, MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, UNTRANSLATED_ONLY), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE)); + + /* Security carveout 2 will be configured later by SetupGpuCarveout, after magic values are written to configure gpu/tsec. */ + + /* Configure carveout 3. */ + reg::Write(MC + MC_SECURITY_CARVEOUT3_BOM, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_BOM_HI, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_SIZE_128KB, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS0, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS1, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS2, MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSRD, ENABLE), + MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSWR, ENABLE)); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS3, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_ACCESS4, MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSRD2, ENABLE), + MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSWR2, ENABLE)); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS0, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS1, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS2, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS3, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CLIENT_FORCE_INTERNAL_ACCESS4, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT3_CFG0, MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 3), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, UNTRANSLATED_ONLY), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE)); + + /* If we're cold-booting and on 1.0.0, alter the default carveout size. */ + if (g_is_cold_boot && GetTargetFirmware() <= TargetFirmware_1_0_0) { + g_kernel_carveouts[0].size = 200 * 128_KB; + } + + /* NOTE: Here Nintendo configures the two kernel carveouts; we will do this later, to allow fusee to continue using AVP_CACHE. */ + /* SetupKernelCarveouts(); */ + + /* Configure slave register security. */ + ConfigureSlaveSecurity(); + } + + void SetupSmmu() { + /* Turn on SMMU translation for all devices. */ + reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_0, ~0u); + reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_1, ~0u); + reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_2, ~0u); + reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_3, ~0u); + reg::Write(MC + MC_SMMU_TRANSLATION_ENABLE_4, ~0u); + + /* On modern firmware, configure ASIDs 1-3 as secure, and all others as non-secure. */ + if (GetTargetFirmware() >= TargetFirmware_4_0_0) { + reg::Write(MC + MC_SMMU_ASID_SECURITY, MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_1, SECURE), + MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_2, SECURE), + MC_REG_BITS_ENUM(SMMU_ASID_SECURITY_SECURE_ASIDS_3, SECURE)); + } else { + /* Legacy firmware accesses the MC directly, though, and so correspondingly we must allow ASIDs to be edited by non-secure world. */ + reg::Write(MC + MC_SMMU_ASID_SECURITY, 0); + } + + reg::Write(MC + MC_SMMU_ASID_SECURITY_1, 0); + reg::Write(MC + MC_SMMU_ASID_SECURITY_2, 0); + reg::Write(MC + MC_SMMU_ASID_SECURITY_3, 0); + reg::Write(MC + MC_SMMU_ASID_SECURITY_4, 0); + reg::Write(MC + MC_SMMU_ASID_SECURITY_5, 0); + reg::Write(MC + MC_SMMU_ASID_SECURITY_6, 0); + reg::Write(MC + MC_SMMU_ASID_SECURITY_7, 0); + + /* Initialize the PTB registers to zero .*/ + reg::Write(MC + MC_SMMU_PTB_ASID, 0); + reg::Write(MC + MC_SMMU_PTB_DATA, 0); + + /* Configure the TLB and PTC, then read TLB_CONFIG to ensure configuration takes. */ + reg::Write(MC + MC_SMMU_TLB_CONFIG, MC_REG_BITS_ENUM (SMMU_TLB_CONFIG_TLB_HIT_UNDER_MISS, ENABLE), + MC_REG_BITS_ENUM (SMMU_TLB_CONFIG_TLB_ROUND_ROBIN_ARBITRATION, ENABLE), + MC_REG_BITS_VALUE(SMMU_TLB_CONFIG_TLB_ACTIVE_LINES, 0x30)); + + reg::Write(MC + MC_SMMU_PTC_CONFIG, MC_REG_BITS_ENUM (SMMU_PTC_CONFIG_PTC_CACHE_ENABLE, ENABLE), + MC_REG_BITS_VALUE(SMMU_PTC_CONFIG_PTC_REQ_LIMIT, 8), + MC_REG_BITS_VALUE(SMMU_PTC_CONFIG_PTC_INDEX_MAP, 0x3F)); + + reg::Read (MC + MC_SMMU_TLB_CONFIG); + + /* Flush the entire page table cache, and read TLB_CONFIG to ensure the flush takes. */ + reg::Write(MC + MC_SMMU_PTC_FLUSH_0, 0); + reg::Read (MC + MC_SMMU_TLB_CONFIG); + + /* Flush the entire translation lookaside buffer, and read TLB_CONFIG to ensure the flush takes. */ + reg::Write(MC + MC_SMMU_TLB_FLUSH, 0); + reg::Read (MC + MC_SMMU_TLB_CONFIG); + + /* Enable the SMMU, and read TLB_CONFIG to ensure the enable takes. */ + reg::Write(MC + MC_SMMU_CONFIG, MC_REG_BITS_ENUM (SMMU_CONFIG_SMMU_ENABLE, ENABLE)); + reg::Read (MC + MC_SMMU_TLB_CONFIG); + } + + void SetupSecureEl2AndEl1SystemRegisters() { + /* Setup actlr_el2 and actlr_el3. */ + { + util::BitPack32 actlr = {}; + + actlr.Set(1); /* Enable access to cpuactlr from lower EL. */ + actlr.Set(1); /* Enable access to cpuectlr from lower EL. */ + actlr.Set(1); /* Enable access to l2ctlr from lower EL. */ + actlr.Set(1); /* Enable access to l2actlr from lower EL. */ + actlr.Set(1); /* Enable access to l2ectlr from lower EL. */ + + HW_CPU_SET_ACTLR_EL3(actlr); + HW_CPU_SET_ACTLR_EL2(actlr); + } + + /* Setup hcr_el2. */ + { + util::BitPack64 hcr = {}; + + hcr.Set(1); /* EL1 is aarch64 mode. */ + + HW_CPU_SET_HCR_EL2(hcr); + } + + /* Configure all domain access permissions as manager. */ + HW_CPU_SET_DACR32_EL2(~0u); + + /* Setup sctlr_el1. */ + { + util::BitPack64 sctlr = { hw::SctlrEl1::Res1 }; + + sctlr.Set(0); /* Globally disable the MMU. */ + sctlr.Set(0); /* Disable alignment fault checking. */ + sctlr.Set(0); /* Globally disable the data and unified caches. */ + sctlr.Set(1); /* Enable stack alignment checking. */ + sctlr.Set(1); /* Enable el0 stack alignment checking. */ + sctlr.Set(1); /* Enable cp15 barrier operations. */ + sctlr.Set(0); /* Disable ThumbEE. */ + sctlr.Set(0); /* Enable itd instructions. */ + sctlr.Set(0); /* Enable setend instruction. */ + sctlr.Set(0); /* Disable el0 interrupt mask access. */ + sctlr.Set(0); /* Globally disable the instruction cache. */ + sctlr.Set(0); /* Disable el0 access to dc zva instruction. */ + sctlr.Set(1); /* wfi instructions in el0 trap. */ + sctlr.Set(1); /* wfe instructions in el0 trap. */ + sctlr.Set(0); /* Do not force writable pages to be ExecuteNever. */ + sctlr.Set(0); /* Data accesses in el0 are little endian. */ + sctlr.Set(0); /* Exceptions should be little endian. */ + sctlr.Set(0); /* Disable el0 access to dc cvau, dc civac, dc cvac, ic ivau. */ + + HW_CPU_SET_SCTLR_EL1(sctlr); + } + + /* Setup sctlr_el2. */ + { + util::BitPack64 sctlr = { hw::SctlrEl2::Res1 }; + + sctlr.Set(0); /* Globally disable the MMU. */ + sctlr.Set(0); /* Disable alignment fault checking. */ + sctlr.Set(0); /* Globally disable the data and unified caches. */ + sctlr.Set(1); /* Enable stack alignment checking. */ + sctlr.Set(0); /* Globally disable the instruction cache. */ + sctlr.Set(0); /* Do not force writable pages to be ExecuteNever. */ + sctlr.Set(0); /* Exceptions should be little endian. */ + + HW_CPU_SET_SCTLR_EL2(sctlr); + } + + /* Ensure instruction consistency. */ + hw::InstructionSynchronizationBarrier(); + } + + void SetupNonSecureSystemRegisters(u32 tsc_frequency) { + /* Set cntfrq_el0. */ + HW_CPU_SET_CNTFRQ_EL0(tsc_frequency); + + /* Set cnthctl_el2. */ + { + util::BitPack32 cnthctl = {}; + + cnthctl.Set(1); /* Do not trap accesses to cntpct_el0. */ + cnthctl.Set(1); /* Do not trap accesses to cntp_ctl_el0, cntp_cval_el0, and cntp_tval_el0. */ + cnthctl.Set(0); /* Disable the event stream. */ + cnthctl.Set(0); /* Trigger events on 0 -> 1 transition. */ + cnthctl.Set(0); /* Select bit0 of cntpct_el0 as the event stream trigger. */ + + HW_CPU_SET_CNTHCTL_EL2(cnthctl); + } + + /* Ensure instruction consistency. */ + hw::InstructionSynchronizationBarrier(); + } + + void SetupGpuCarveout() { + /* Configure carveout 2. */ + reg::Write(MC + MC_SECURITY_CARVEOUT2_BOM, static_cast(MemoryRegionDramGpuCarveout.GetAddress() >> 0)); + reg::Write(MC + MC_SECURITY_CARVEOUT2_BOM_HI, static_cast(MemoryRegionDramGpuCarveout.GetAddress() >> BITSIZEOF(u32))); + reg::Write(MC + MC_SECURITY_CARVEOUT2_SIZE_128KB, MemoryRegionDramGpuCarveout.GetSize() / 128_KB); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS0, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS1, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS2, MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSRD, ENABLE), + MC_REG_BITS_ENUM (CLIENT_ACCESS2_GPUSWR, ENABLE), + MC_REG_BITS_ENUM (CLIENT_ACCESS2_TSECSRD, ENABLE)); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS3, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_ACCESS4, MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSRD2, ENABLE), + MC_REG_BITS_ENUM (CLIENT_ACCESS4_GPUSWR2, ENABLE)); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS0, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS1, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS2, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS3, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CLIENT_FORCE_INTERNAL_ACCESS4, 0); + reg::Write(MC + MC_SECURITY_CARVEOUT2_CFG0, MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 2), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, UNTRANSLATED_ONLY), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, LOCKED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE)); + } + + void DisableArc() { + /* Configure IRAM top/bottom to point to memory ends (disabling redirection). */ + reg::Write(MC + MC_IRAM_BOM, MC_REG_BITS_VALUE(IRAM_BOM_IRAM_BOM, (~0u))); + reg::Write(MC + MC_IRAM_TOM, MC_REG_BITS_VALUE(IRAM_TOM_IRAM_TOM, ( 0u))); + + /* Lock the IRAM aperture. */ + reg::ReadWrite(MC + MC_IRAM_REG_CTRL, MC_REG_BITS_ENUM(IRAM_REG_CTRL_IRAM_CFG_WRITE_ACCESS, DISABLED)); + + /* Disable the ARC clock gate override. */ + reg::ReadWrite(CLK_RST + CLK_RST_CONTROLLER_LVL2_CLK_GATE_OVRD, CLK_RST_REG_BITS_ENUM(LVL2_CLK_GATE_OVRD_ARC_CLK_OVR_ON, OFF)); + + /* Read IRAM REG CTRL to make sure our writes take. */ + reg::Read(MC + MC_IRAM_REG_CTRL); + } + + void DisableUntranslatedDeviceMemoryAccess() { + /* If we can (mariko only), disable GMMU accesses that bypass the SMMU. */ + /* Additionally, force all untranslated acccesses to hit one of the carveouts. */ + if (GetSocType() == fuse::SocType_Mariko) { + reg::Write(MC + MC_UNTRANSLATED_REGION_CHECK, MC_REG_BITS_ENUM(UNTRANSLATED_REGION_CHECK_UNTRANSLATED_REGION_CHECK_ACCESS, DISABLED), + MC_REG_BITS_ENUM(UNTRANSLATED_REGION_CHECK_REQUIRE_UNTRANSLATED_CLIENTS_HIT_CARVEOUT, ENABLED), + MC_REG_BITS_ENUM(UNTRANSLATED_REGION_CHECK_REQUIRE_UNTRANSLATED_GPU_HIT_CARVEOUT, ENABLED)); + } + } + + void FinalizeCarveoutSecureScratchRegisters() { + /* Define carveout scratch values. */ + constexpr uintptr_t WarmbootCarveoutAddress = MemoryRegionDram.GetAddress(); + constexpr size_t WarmbootCarveoutSize = 128_KB; + + #define MC_ENABLE_CLIENT_ACCESS(INDEX, WHICH) MC_REG_BITS_ENUM(CLIENT_ACCESS##INDEX##_##WHICH, ENABLE) + + constexpr u32 WarmbootCarveoutClientAccess0 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(0, AVPCARM7R), + MC_ENABLE_CLIENT_ACCESS(0, PPCSAHBSLVR)); + + constexpr u32 WarmbootCarveoutClientAccess1 = reg::Encode(MC_ENABLE_CLIENT_ACCESS(1, AVPCARM7W)); + + #undef MC_ENABLE_CLIENT_ACCESS + + constexpr u32 WarmbootCarveoutForceInternalAccess0 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS0_AVPCARM7R, ENABLE), + MC_REG_BITS_ENUM(CLIENT_ACCESS0_PPCSAHBSLVR, ENABLE)); + + constexpr u32 WarmbootCarveoutForceInternalAccess1 = reg::Encode(MC_REG_BITS_ENUM(CLIENT_ACCESS1_AVPCARM7W, ENABLE)); + + constexpr u32 WarmbootCarveoutConfig = reg::Encode(MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_IS_WPR, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_FORCE_APERTURE_ID_MATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ALLOW_APERTURE_ID_MISMATCH, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_RD_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_TZ_GLOBAL_WR_EN, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_SEND_CFG_TO_GPU, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_WRITE_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL3, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL2, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL1, ENABLE_CHECKS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_DISABLE_READ_CHECK_ACCESS_LEVEL0, ENABLE_CHECKS), + MC_REG_BITS_VALUE(SECURITY_CARVEOUT_CFG0_APERTURE_ID, 0), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL3, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL2, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_WRITE_ACCESS_LEVEL0, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL3, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL2, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL1, DISABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_READ_ACCESS_LEVEL0, ENABLED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_ADDRESS_TYPE, ANY_ADDRESS), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_LOCK_MODE, UNLOCKED), + MC_REG_BITS_ENUM (SECURITY_CARVEOUT_CFG0_PROTECT_MODE, LOCKBIT_SECURE)); + + /* Save the carveout values into secure scratch. */ + + /* Save MC_SECURITY_CARVEOUT4_BOM. */ + reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH51, REG_BITS_VALUE( 0, 15, WarmbootCarveoutAddress >> 17)); + + /* Save MC_SECURITY_CARVEOUT4_BOM_HI. */ + reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH16, REG_BITS_VALUE(30, 2, WarmbootCarveoutAddress >> 32)); + + /* Save MC_SECURITY_CARVEOUT4_SIZE_128KB. */ + reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH55, REG_BITS_VALUE(12, 12, WarmbootCarveoutSize / 128_KB)); + + /* Save MC_SECURITY_CARVEOUT4_CLIENT_ACCESS. */ + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH74, WarmbootCarveoutClientAccess0); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH75, WarmbootCarveoutClientAccess1); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH76, 0); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH77, 0); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH78, 0); + + /* Save MC_SECURITY_CARVEOUT4_FORCE_INTERNAL_ACCESS. */ + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH99, WarmbootCarveoutForceInternalAccess0); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH100, WarmbootCarveoutForceInternalAccess1); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH101, 0); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH102, 0); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH103, 0); + + /* Save MC_SECURITY_CARVEOUT4_CFG0. */ + reg::ReadWrite(PMC + APBDEV_PMC_SECURE_SCRATCH39, REG_BITS_VALUE(0, 27, WarmbootCarveoutConfig)); + } + + void ValidateResetExpected() { + /* We're coming out of reset, so check that we expected to come out of reset. */ + if (!IsResetExpected()) { + secmon::SetError(pkg1::ErrorInfo_UnexpectedReset); + AMS_ABORT("unexpected reset"); + } + SetResetExpected(false); + } + + void ExitChargerHiZMode() { + /* Setup I2c-1. */ + pinmux::SetupI2c1(); + clkrst::EnableI2c1Clock(); + + /* Initialize I2c-1. */ + i2c::Initialize(i2c::Port_1); + + /* Exit Hi-Z mode. */ + charger::ExitHiZMode(); + + /* Disable clock to I2c-1. */ + clkrst::DisableI2c1Clock(); + } + + bool IsExitLp0() { + return reg::Read(MC + MC_SECURITY_CFG3) == 0; + } + + void SetupLogForBoot() { + log::Initialize(secmon::GetLogPort(), secmon::GetLogBaudRate(), secmon::GetLogFlags()); + log::SendText("OHAYO\n", 6); + log::Flush(); + } + + void LogExitLp0() { + /* NOTE: Nintendo only does this on dev, but we will always do it. */ + if (true /* !pkg1::IsProduction() */) { + SetupLogForBoot(); + } + } + + void SetupForLp0Exit() { + /* Exit HiZ mode in charger, if we need to. */ + const auto target_fw = GetTargetFirmware(); + const bool force_exit_hiz_mode = (target_fw < TargetFirmware_4_0_0) || (target_fw < TargetFirmware_8_0_0 && fuse::GetHardwareType() == fuse::HardwareType_Icosa); + if (force_exit_hiz_mode || smc::IsChargerHiZModeEnabled()) { + ExitChargerHiZMode(); + } + + /* Refill the random cache, which is volatile and thus wiped on warmboot. */ + smc::FillRandomCache(); + + /* Unlock the security engine. */ + secmon::smc::UnlockSecurityEngine(); + } + + } + + void Setup1() { + /* Load the global configuration context. */ + InitializeConfigurationContext(); + + /* Initialize uart for logging. */ + SetupLogForBoot(); + + /* Initialize the security engine. */ + se::Initialize(); + + /* Initialize the gic. */ + gic::InitializeCommon(); + } + + void Setup1ForWarmboot() { + /* Initialize the security engine. */ + se::Initialize(); + + /* Initialize the gic. */ + gic::InitializeCommon(); + } + + void SaveSecurityEngineAesKeySlotTestVector() { + GenerateSecurityEngineAesKeySlotTestVector(g_se_aes_key_slot_test_vector, sizeof(g_se_aes_key_slot_test_vector)); + } + + void SetupSocSecurity() { + /* Set the fuse visibility. */ + clkrst::SetFuseVisibility(true); + + /* Set fuses as only secure-writable. */ + fuse::SetWriteSecureOnly(); + + /* Lockout the fuses. */ + fuse::Lockout(); + + /* Set the security engine to secure mode. */ + se::SetSecure(true); + + /* Verify the security engine's sticky bits. */ + VerifySecurityEngineStickyBits(); + + /* Verify the security engine's Aes slots contain correct contents. */ + VerifySecurityEngineAesKeySlotTestVector(); + + /* Clear aes keyslots. */ + ClearAesKeySlots(); + + /* Clear rsa keyslots. */ + ClearRsaKeySlots(); + + /* Overwrite keys that we want to be random with random contents. */ + se::InitializeRandom(); + se::ConfigureAutomaticContextSave(); + se::SetRandomKey(pkg1::AesKeySlot_Temporary); + se::GenerateSrk(); + se::SetRandomKey(pkg1::AesKeySlot_TzramSaveKek); + + /* Initialize pmc secure scratch. */ + if (GetSocType() == fuse::SocType_Erista) { + pmc::InitializeRandomScratch(); + } + pmc::LockSecureRegister(pmc::SecureRegister_Srk); + + /* Setup secure registers. */ + SetupSecureRegisters(); + + /* Setup the smmu. */ + SetupSmmu(); + + /* Clear the cpu reset vector. */ + reg::Write(EVP + EVP_CPU_RESET_VECTOR, 0); + + /* Configure the SB registers to our start address. */ + constexpr u32 ResetVectorLow = static_cast((PhysicalTzramProgramResetVector >> 0)); + constexpr u32 ResetVectorHigh = static_cast((PhysicalTzramProgramResetVector >> BITSIZEOF(u32))); + + /* Write our reset vector to the secure boot registers. */ + reg::Write(secmon::MemoryRegionVirtualDeviceSystem.GetAddress() + SB_AA64_RESET_LOW, ResetVectorLow | 1); + reg::Write(secmon::MemoryRegionVirtualDeviceSystem.GetAddress() + SB_AA64_RESET_HIGH, ResetVectorHigh); + + /* Disable non-secure writes to the reset vector. */ + reg::Write(secmon::MemoryRegionVirtualDeviceSystem.GetAddress() + SB_CSR, SB_REG_BITS_ENUM(CSR_NS_RST_VEC_WR_DIS, DISABLE)); + + /* Read back SB_CSR to make sure our non-secure write disable takes. */ + reg::Read(secmon::MemoryRegionVirtualDeviceSystem.GetAddress() + SB_CSR); + + /* Write our reset vector to scratch registers used by warmboot, and lock those scratch registers. */ + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH34, ResetVectorLow); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH35, ResetVectorHigh); + pmc::LockSecureRegister(pmc::SecureRegister_ResetVector); + + /* Setup the security engine interrupt. */ + constexpr int SecurityEngineInterruptId = 90; + constexpr u8 SecurityEngineInterruptCoreMask = (1 << 3); + gic::SetPriority (SecurityEngineInterruptId, gic::HighestPriority); + gic::SetInterruptGroup(SecurityEngineInterruptId, 0); + gic::SetEnable (SecurityEngineInterruptId, true); + gic::SetSpiTargetCpu (SecurityEngineInterruptId, SecurityEngineInterruptCoreMask); + gic::SetSpiMode (SecurityEngineInterruptId, gic::InterruptMode_Level); + + /* Setup the activity monitor interrupt. */ + constexpr int ActivityMonitorInterruptId = 77; + constexpr u8 ActivityMonitorInterruptCoreMask = (1 << 3); + gic::SetPriority (ActivityMonitorInterruptId, gic::HighestPriority); + gic::SetInterruptGroup(ActivityMonitorInterruptId, 0); + gic::SetEnable (ActivityMonitorInterruptId, true); + gic::SetSpiTargetCpu (ActivityMonitorInterruptId, ActivityMonitorInterruptCoreMask); + gic::SetSpiMode (ActivityMonitorInterruptId, gic::InterruptMode_Level); + + /* Setup the mariko fatal error interrupt. */ + constexpr u8 MarikoFatalInterruptCoreMask = 0b1111; + gic::SetPriority (MarikoFatalErrorInterruptId, gic::HighestPriority); + gic::SetInterruptGroup(MarikoFatalErrorInterruptId, 0); + gic::SetEnable (MarikoFatalErrorInterruptId, true); + gic::SetSpiTargetCpu (MarikoFatalErrorInterruptId, 0); + gic::SetSpiMode (MarikoFatalErrorInterruptId, gic::InterruptMode_Level); + + /* If we're coldboot, perform one-time setup. */ + if (g_is_cold_boot) { + /* Register all interrupt handlers. */ + SetInterruptHandler(SecurityEngineInterruptId, SecurityEngineInterruptCoreMask, se::HandleInterrupt); + SetInterruptHandler(ActivityMonitorInterruptId, ActivityMonitorInterruptCoreMask, actmon::HandleInterrupt); + SetInterruptHandler(MarikoFatalErrorInterruptId, MarikoFatalInterruptCoreMask, secmon::HandleMarikoFatalErrorInterrupt); + + /* We're expecting the other cores to come out of reset. */ + for (int i = 1; i < NumCores; ++i) { + SetResetExpected(i, true); + } + + /* We only coldboot once. */ + g_is_cold_boot = false; + } + } + + void SetupSocSecurityWarmboot() { + /* Check that we're allowed to continue. */ + ValidateResetExpected(); + + /* Unmap the tzram identity mapping. */ + UnmapTzram(); + + /* If we're exiting LP0, there's a little more work for us to do. */ + if (IsExitLp0()) { + /* Log that we're exiting LP0. */ + LogExitLp0(); + + /* Perform initial setup. */ + Setup1ForWarmboot(); + + /* Generate a random srk. */ + se::GenerateSrk(); + + /* Setup the Soc security. */ + SetupSocSecurity(); + + /* Set the PMC and MC as secure-only. */ + SetupPmcAndMcSecure(); + + /* Perform Lp0-exit specific init. */ + SetupForLp0Exit(); + + /* Setup the Soc protections. */ + SetupSocProtections(); + } + + /* Perform remaining CPU initialization. */ + SetupCpuCoreContext(); + SetupCpuSErrorDebug(); + } + + void SetupSocProtections() { + /* Setup the GPU carveout. */ + SetupGpuCarveout(); + + /* Configure the two kernel carveouts. */ + SetupKernelCarveouts(); + + /* Disable the ARC. */ + DisableArc(); + + /* Disable untranslated memory accesses by devices. */ + DisableUntranslatedDeviceMemoryAccess(); + + /* Further protections aren't applied on <= 1.0.0. */ + if (GetTargetFirmware() <= TargetFirmware_1_0_0) { + return; + } + + /* Finalize and lock the carveout scratch registers. */ + FinalizeCarveoutSecureScratchRegisters(); + pmc::LockSecureRegister(pmc::SecureRegister_Carveout); + + } + + void SetupPmcAndMcSecure() { + // const auto target_fw = GetTargetFirmware(); + + // if (target_fw >= TargetFirmware_2_0_0) { + // /* Set the PMC secure. */ I REFUSE + // reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, ENABLE)); + // } + + // if (target_fw >= TargetFirmware_4_0_0) { + // /* Set the MC secure. */ I REFUSE + // reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG1_0, SLAVE_SECURITY_REG_BITS_ENUM(1, MC0, ENABLE), + // SLAVE_SECURITY_REG_BITS_ENUM(1, MC1, ENABLE), + // SLAVE_SECURITY_REG_BITS_ENUM(1, MCB, ENABLE)); + // } + return; + } + + void SetupCpuCoreContext() { + /* Get the tsc frequency. */ + const u32 tsc_frequency = reg::Read(MemoryRegionVirtualDeviceSysCtr0.GetAddress() + SYSCTR0_CNTFID0); + + /* Setup the secure EL2/EL1 system registers. */ + SetupSecureEl2AndEl1SystemRegisters(); + + /* Setup the non-secure system registers. */ + SetupNonSecureSystemRegisters(tsc_frequency); + + /* Reset the cpu flow controller registers. */ + flow::ResetCpuRegisters(hw::GetCurrentCoreId()); + + /* Initialize the core unique gic registers. */ + gic::InitializeCoreUnique(); + + /* Configure cpu fiq. */ + constexpr int FiqInterruptId = 28; + gic::SetPriority (FiqInterruptId, gic::HighestPriority); + gic::SetInterruptGroup(FiqInterruptId, 0); + gic::SetEnable (FiqInterruptId, true); + + /* Restore the cpu's debug registers. */ + RestoreDebugRegisters(); + } + + void SetupCpuSErrorDebug() { + /* Get whether we should enable SError debug. */ + const auto &bc_data = secmon::GetBootConfig().data; + const bool enabled = bc_data.IsDevelopmentFunctionEnabled() && bc_data.IsSErrorDebugEnabled(); + + /* Get and set scr_el3. */ + { + util::BitPack32 scr; + HW_CPU_GET_SCR_EL3(scr); + + scr.Set(enabled ? 0 : 1); + HW_CPU_SET_SCR_EL3(scr); + } + + /* Prevent reordering instructions around this call. */ + hw::InstructionSynchronizationBarrier(); + } + + void SetKernelCarveoutRegion(int index, uintptr_t address, size_t size) { + /* Configure the carveout. */ + auto &carveout = g_kernel_carveouts[index]; + carveout.address = address; + carveout.size = size; + + SetupKernelCarveouts(); + } + +} \ No newline at end of file diff --git a/Source/Atmosphere-Patches/secmon_smc_power_management.cpp b/Source/Atmosphere-Patches/secmon_smc_power_management.cpp new file mode 100644 index 00000000..7747bb09 --- /dev/null +++ b/Source/Atmosphere-Patches/secmon_smc_power_management.cpp @@ -0,0 +1,567 @@ +/* + * 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 . + */ +#include +#include "../secmon_cache.hpp" +#include "../secmon_cpu_context.hpp" +#include "../secmon_error.hpp" +#include "../secmon_misc.hpp" +#include "secmon_smc_power_management.hpp" +#include "secmon_smc_se_lock.hpp" + +#include "sc7fw_bin.h" + +namespace ams::secmon { + + /* Declare assembly functionality. */ + void *GetCoreExceptionStackVirtual(); + +} + +namespace ams::secmon::smc { + + /* Declare assembly power-management functionality. */ + void PivotStackAndInvoke(void *stack, void (*function)()); + void FinalizePowerOff(); + + namespace { + + constexpr inline const uintptr_t PMC = MemoryRegionVirtualDevicePmc.GetAddress(); + constexpr inline const uintptr_t APB_MISC = MemoryRegionVirtualDeviceApbMisc.GetAddress(); + constexpr inline const uintptr_t GPIO = MemoryRegionVirtualDeviceGpio.GetAddress(); + constexpr inline const uintptr_t CLK_RST = MemoryRegionVirtualDeviceClkRst.GetAddress(); + constexpr inline const uintptr_t EVP = secmon::MemoryRegionVirtualDeviceExceptionVectors.GetAddress(); + constexpr inline const uintptr_t FLOW_CTLR = MemoryRegionVirtualDeviceFlowController.GetAddress(); + constexpr inline const uintptr_t AHB_ARBC = MemoryRegionVirtualDeviceSystem.GetAddress(); + + constexpr inline uintptr_t CommonSmcStackTop = MemoryRegionVirtualTzramVolatileData.GetEndAddress() - (0x80 * (NumCores - 1)); + + enum PowerStateType { + PowerStateType_StandBy = 0, + PowerStateType_PowerDown = 1, + }; + + enum PowerStateId { + PowerStateId_Sc7 = 27, + }; + + /* http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf Page 46 */ + struct SuspendCpuPowerState { + using StateId = util::BitPack32::Field< 0, 16, PowerStateId>; + using StateType = util::BitPack32::Field<16, 1, PowerStateType>; + using PowerLevel = util::BitPack32::Field<24, 2, u32>; + }; + + constinit bool g_charger_hi_z_mode_enabled = false; + + constinit const reg::BitsMask CpuPowerGateStatusMasks[NumCores] = { + PMC_REG_BITS_MASK(PWRGATE_STATUS_CE0), + PMC_REG_BITS_MASK(PWRGATE_STATUS_CE1), + PMC_REG_BITS_MASK(PWRGATE_STATUS_CE2), + PMC_REG_BITS_MASK(PWRGATE_STATUS_CE3), + }; + + constinit const APBDEV_PMC_PWRGATE_TOGGLE_PARTID CpuPowerGateTogglePartitionIds[NumCores] = { + APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE0, + APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE1, + APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE2, + APBDEV_PMC_PWRGATE_TOGGLE_PARTID_CE3, + }; + + bool IsCpuPoweredOn(const reg::BitsMask mask) { + return reg::HasValue(PMC + APBDEV_PMC_PWRGATE_STATUS, REG_BITS_VALUE_FROM_MASK(mask, APBDEV_PMC_PWRGATE_STATUS_STATUS_ON)); + } + + void PowerOnCpu(const reg::BitsMask mask, u32 toggle_partid) { + /* If the cpu is already on, we have nothing to do. */ + if (IsCpuPoweredOn(mask)) { + return; + } + + /* Wait until nothing is being powergated. */ + int timeout = 5000; + while (true) { + if (reg::HasValue(PMC + APBDEV_PMC_PWRGATE_TOGGLE, PMC_REG_BITS_ENUM(PWRGATE_TOGGLE_START, DISABLE))) { + break; + } + + util::WaitMicroSeconds(1); + if ((--timeout) < 0) { + /* NOTE: Nintendo doesn't do any error handling here... */ + return; + } + } + + /* Toggle on the cpu partition. */ + reg::Write(PMC + APBDEV_PMC_PWRGATE_TOGGLE, PMC_REG_BITS_ENUM (PWRGATE_TOGGLE_START, ENABLE), + PMC_REG_BITS_VALUE(PWRGATE_TOGGLE_PARTID, toggle_partid)); + + /* Wait up to 5000 us for the powergate to complete. */ + timeout = 5000; + while (true) { + if (IsCpuPoweredOn(mask)) { + break; + } + + util::WaitMicroSeconds(1); + if ((--timeout) < 0) { + /* NOTE: Nintendo doesn't do any error handling here... */ + return; + } + } + } + + void ResetCpu(int which_core) { + reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_SET, REG_BITS_VALUE(which_core + 0x00, 1, 1), /* CPURESETn */ + REG_BITS_VALUE(which_core + 0x10, 1, 1)); /* CORERESETn */ + } + + void StartCpu(int which_core) { + reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_CPUG_CMPLX_CLR, REG_BITS_VALUE(which_core + 0x00, 1, 1), /* CPURESETn */ + REG_BITS_VALUE(which_core + 0x10, 1, 1)); /* CORERESETn */ + } + + void PowerOffCpuImpl() { + /* Get the current core id. */ + const auto core_id = hw::GetCurrentCoreId(); + + /* Configure the flow controller to prepare for shutting down the current core. */ + flow::SetCpuCsr(core_id, FLOW_CTLR_CPUN_CSR_ENABLE_EXT_POWERGATE_CPU_ONLY); + flow::SetHaltCpuEvents(core_id, false); + flow::SetCc4Ctrl(core_id, 0); + + /* Save the core's context for restoration on next power-on. */ + SaveDebugRegisters(); + SetCoreOff(); + + /* Ensure there are no pending memory transactions prior to our power-down. */ + FlushEntireDataCache(); + + /* Finalize our powerdown and wait for an interrupt. */ + FinalizePowerOff(); + } + + void ValidateSocStateForSuspend() { + /* Validate that all other cores are off. */ + AMS_ABORT_UNLESS(reg::HasValue(PMC + APBDEV_PMC_PWRGATE_STATUS, PMC_REG_BITS_VALUE(PWRGATE_STATUS_CE123, 0))); + + /* Validate that the bpmp is appropriately halted. */ + const bool jtag = IsJtagEnabled(); + AMS_ABORT_UNLESS(reg::Read(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS) == reg::Encode(FLOW_REG_BITS_ENUM (HALT_COP_EVENTS_MODE, FLOW_MODE_STOP), + FLOW_REG_BITS_ENUM_SEL(HALT_COP_EVENTS_JTAG, jtag, ENABLED, DISABLED))); + + /* Further validations aren't guaranteed on < 6.0.0. */ + if (GetTargetFirmware() < TargetFirmware_6_0_0) { + return; + } + + /* Validate that USB2, APB-DMA, AHB-DMA are held in reset. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_RST_DEVICES_H, CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_USB2_RST, ENABLE), + CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_APBDMA_RST, ENABLE), + CLK_RST_REG_BITS_ENUM(RST_DEVICES_H_SWR_AHBDMA_RST, ENABLE))); + + /* Validate that USBD is held in reset. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_RST_DEVICES_L, CLK_RST_REG_BITS_ENUM(RST_DEVICES_L_SWR_USBD_RST, ENABLE))); + + /* Validate that AHB-DMA, USB, USB2, COP are not allowed to arbitrate on the AHB. */ + AMS_ABORT_UNLESS(reg::HasValue(AHB_ARBC + AHB_ARBITRATION_DISABLE, AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_COP, DISABLE), + AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_AHBDMA, DISABLE), + AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_USB, DISABLE), + AHB_REG_BITS_ENUM(ARBITRATION_DISABLE_USB2, DISABLE))); + + /* Validate that the GPIO controller has clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_L, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_L_CLK_ENB_GPIO, ENABLE))); + + /* Validate that both FUSE and KFUSE have clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_H, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_H_CLK_ENB_FUSE, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_H_CLK_ENB_KFUSE, ENABLE))); + + /* Validate that all of IRAM has clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_U, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMA, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMB, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMC, ENABLE), + CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_U_CLK_ENB_IRAMD, ENABLE))); + + /* Validate that ACTMON has clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_V, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_V_CLK_ENB_ACTMON, ENABLE))); + + /* Validate that ENTROPY has clock enabled. */ + AMS_ABORT_UNLESS(reg::HasValue(CLK_RST + CLK_RST_CONTROLLER_CLK_OUT_ENB_W, CLK_RST_REG_BITS_ENUM(CLK_OUT_ENB_W_CLK_ENB_ENTROPY, ENABLE))); + } + + void GenerateCryptographicallyRandomBytes(void * const dst, int size) { + /* Flush the region we're about to fill to ensure consistency with the SE. */ + hw::FlushDataCache(dst, size); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Generate random bytes. */ + se::GenerateRandomBytes(dst, size); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Flush to ensure the CPU sees consistent data for the region. */ + hw::FlushDataCache(dst, size); + hw::DataSynchronizationBarrierInnerShareable(); + } + + void SaveSecureContextForErista() { + /* Generate a random key source. */ + util::AlignedBuffer key_source; + GenerateCryptographicallyRandomBytes(key_source, se::AesBlockSize); + + const u32 * const key_source_32 = reinterpret_cast(static_cast(key_source)); + + /* Ensure that the key source registers are not locked. */ + AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_KeySourceReadWrite) != pmc::LockState::Locked); + + /* Write the key source, lock writes to the key source, and verify that the key source is write-locked. */ + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH24, key_source_32[0]); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH25, key_source_32[1]); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH26, key_source_32[2]); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH27, key_source_32[3]); + pmc::LockSecureRegister(pmc::SecureRegister_KeySourceWrite); + AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_KeySourceWrite) == pmc::LockState::Locked); + + /* Verify the key source is correct in registers, and read-lock the key source registers. */ + AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH24) == key_source_32[0]); + AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH25) == key_source_32[1]); + AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH26) == key_source_32[2]); + AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH27) == key_source_32[3]); + pmc::LockSecureRegister(pmc::SecureRegister_KeySourceRead); + + /* Ensure that the key source registers are locked. */ + AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_KeySourceReadWrite) == pmc::LockState::Locked); + + /* Generate a random kek into keyslot 2. */ + se::SetRandomKey(pkg1::AesKeySlot_TzramSaveKek); + + /* Verify that the se is in a validate state, context save, and validate again. */ + { + se::ValidateErrStatus(); + ON_SCOPE_EXIT { se::ValidateErrStatus(); }; + + { + /* Transition to non-secure mode for the duration of the context save operation. */ + se::SetSecure(false); + ON_SCOPE_EXIT { se::SetSecure(true); }; + + /* Get a pointer to the context storage. */ + se::Context * const context = MemoryRegionVirtualDramSecureDataStoreSecurityEngineState.GetPointer(); + static_assert(MemoryRegionVirtualDramSecureDataStoreSecurityEngineState.GetSize() == sizeof(*context)); + + /* Save the context. */ + se::SaveContext(context); + + /* Ensure that the cpu sees consistent data. */ + hw::FlushDataCache(context, sizeof(*context)); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Write the context pointer to pmc scratch, so that the bootrom will restore it on wake. */ + reg::Write(PMC + APBDEV_PMC_SCRATCH43, MemoryRegionPhysicalDramSecureDataStoreSecurityEngineState.GetAddress()); + } + } + + /* Clear keyslot 3, and then derive the save key. */ + se::ClearAesKeySlot(pkg1::AesKeySlot_TzramSaveKey); + se::SetEncryptedAesKey256(pkg1::AesKeySlot_TzramSaveKey, pkg1::AesKeySlot_TzramSaveKek, key_source, se::AesBlockSize); + + /* Declare a temporary block to be used as both iv and mac. */ + u32 temp_block[se::AesBlockSize / sizeof(u32)] = {}; + + /* Ensure that the SE sees consistent data for tzram. */ + const void * const tzram_save_src = MemoryRegionVirtualTzramReadOnlyAlias.GetPointer() + MemoryRegionVirtualTzramVolatileData.GetSize() + MemoryRegionVirtualTzramVolatileStack.GetSize(); + void * const tzram_save_dst = MemoryRegionVirtualIramSc7Work.GetPointer(); + constexpr size_t TzramSaveSize = MemoryRegionVirtualDramSecureDataStoreTzram.GetSize(); + + hw::FlushDataCache(tzram_save_src, TzramSaveSize); + hw::FlushDataCache(tzram_save_dst, TzramSaveSize); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Encrypt tzram using our random key. */ + se::EncryptAes256Cbc(tzram_save_dst, TzramSaveSize, pkg1::AesKeySlot_TzramSaveKey, tzram_save_src, TzramSaveSize, temp_block, se::AesBlockSize); + hw::FlushDataCache(tzram_save_dst, TzramSaveSize); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Copy the data from work space to the secure storage destination. */ + void * const tzram_store_dst = MemoryRegionVirtualDramSecureDataStoreTzram.GetPointer(); + std::memcpy(tzram_store_dst, tzram_save_dst, TzramSaveSize); + hw::FlushDataCache(tzram_store_dst, TzramSaveSize); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Compute cmac of tzram into our temporary block. */ + se::ComputeAes256Cmac(temp_block, se::AesBlockSize, pkg1::AesKeySlot_TzramSaveKey, tzram_save_src, TzramSaveSize); + + /* Ensure that the cmac registers are not locked. */ + AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_CmacReadWrite) != pmc::LockState::Locked); + + /* Write the cmac, lock writes to the cmac, and verify that the cmac is write-locked. */ + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH112, temp_block[0]); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH113, temp_block[1]); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH114, temp_block[2]); + reg::Write(PMC + APBDEV_PMC_SECURE_SCRATCH115, temp_block[3]); + pmc::LockSecureRegister(pmc::SecureRegister_CmacWrite); + AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_CmacWrite) == pmc::LockState::Locked); + + /* Verify the key source is correct in registers, and read-lock the key source registers. */ + AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH112) == temp_block[0]); + AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH113) == temp_block[1]); + AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH114) == temp_block[2]); + AMS_ABORT_UNLESS(reg::Read(PMC + APBDEV_PMC_SECURE_SCRATCH115) == temp_block[3]); + pmc::LockSecureRegister(pmc::SecureRegister_CmacRead); + + /* Ensure that the key source registers are locked. */ + AMS_ABORT_UNLESS(pmc::GetSecureRegisterLockState(pmc::SecureRegister_CmacReadWrite) == pmc::LockState::Locked); + } + + void SaveSecureContextForMariko() { + /* Save security engine context to TZRAM SE carveout (inaccessible to cpu). */ + se::SaveContextAutomatic(); + + /* Save TZRAM to shadow-TZRAM in always-on power domain. */ + se::SaveTzramAutomatic(); + } + + void SaveSecureContext() { + /* Save the appropriate secure context. */ + const auto soc_type = GetSocType(); + if (soc_type == fuse::SocType_Erista) { + SaveSecureContextForErista(); + } else /* if (soc_type == fuse::SocType_Mariko) */ { + SaveSecureContextForMariko(); + } + + /* Save the debug code. */ + #if defined(AMS_BUILD_FOR_DEBUGGING) || defined(AMS_BUILD_FOR_AUDITING) + { + const void * const debug_code_src = MemoryRegionVirtualDebugCode.GetPointer(); + void * const debug_code_dst = MemoryRegionVirtualDramDebugDataStore.GetPointer(); + std::memcpy(debug_code_dst, debug_code_src, MemoryRegionVirtualDebugCode.GetSize()); + hw::FlushDataCache(debug_code_dst, MemoryRegionVirtualDebugCode.GetSize()); + hw::DataSynchronizationBarrierInnerShareable(); + } + #endif + } + + void LoadAndStartSc7BpmpFirmware() { + /* Set BPMP reset. */ + reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_DEV_L_SET, CLK_RST_REG_BITS_ENUM(RST_DEV_L_SET_SET_COP_RST, ENABLE)); + + /* Set the PMC as insecure, so that the BPMP firmware can access it. */ + reg::ReadWrite(APB_MISC + APB_MISC_SECURE_REGS_APB_SLAVE_SECURITY_ENABLE_REG0_0, SLAVE_SECURITY_REG_BITS_ENUM(0, PMC, DISABLE)); + + /* Set the exception vectors for the bpmp. RESET should point to RESET, all others should point to generic exception/panic. */ + constexpr const u32 Sc7FirmwareResetVector = static_cast(MemoryRegionPhysicalIramSc7Firmware.GetAddress() + 0x0); + constexpr const u32 Sc7FirmwarePanicVector = static_cast(MemoryRegionPhysicalIramSc7Firmware.GetAddress() + 0x4); + + reg::Write(EVP + EVP_COP_RESET_VECTOR, Sc7FirmwareResetVector); + reg::Write(EVP + EVP_COP_UNDEF_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_SWI_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_PREFETCH_ABORT_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_DATA_ABORT_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_RSVD_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_IRQ_VECTOR, Sc7FirmwarePanicVector); + reg::Write(EVP + EVP_COP_FIQ_VECTOR, Sc7FirmwarePanicVector); + + /* Disable activity monitor bpmp monitoring, so that we don't panic upon bpmp wake. */ + actmon::StopMonitoringBpmp(); + + /* Load the bpmp firmware. */ + void * const sc7fw_load_address = MemoryRegionVirtualIramSc7Firmware.GetPointer(); + std::memcpy(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size); + hw::FlushDataCache(sc7fw_load_address, sc7fw_bin_size); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Ensure that the bpmp firmware was loaded. */ + AMS_ABORT_UNLESS(crypto::IsSameBytes(sc7fw_load_address, sc7fw_bin, sc7fw_bin_size)); + + /* Clear BPMP reset. */ + reg::Write(CLK_RST + CLK_RST_CONTROLLER_RST_DEV_L_CLR, CLK_RST_REG_BITS_ENUM(RST_DEV_L_CLR_CLR_COP_RST, ENABLE)); + + /* Start the bpmp. */ + reg::Write(FLOW_CTLR + FLOW_CTLR_HALT_COP_EVENTS, FLOW_REG_BITS_ENUM(HALT_COP_EVENTS_MODE, FLOW_MODE_NONE)); + } + + void SaveSecureContextAndSuspend() { + /* Ensure there are no pending memory transactions before we continue */ + FlushEntireDataCache(); + hw::DataSynchronizationBarrierInnerShareable(); + + /* Save all secure context (security engine state + tzram). */ + SaveSecureContext(); + + /* Load and start the sc7 firmware on the bpmp. */ + if (GetTargetFirmware() >= TargetFirmware_2_0_0) { + LoadAndStartSc7BpmpFirmware(); + } + + /* Log our suspension. */ + /* NOTE: Nintendo only does this on dev, but we will always do it. */ + if (true /* !pkg1::IsProduction() */) { + log::Initialize(secmon::GetLogPort(), secmon::GetLogBaudRate(), secmon::GetLogFlags()); + log::SendText("OYASUMI\n", 8); + log::Flush(); + } + + /* If we're on erista, configure the bootrom to allow our custom warmboot firmware. */ + if (GetSocType() == fuse::SocType_Erista) { + reg::Write(PMC + APBDEV_PMC_SCRATCH31, 0x2202E012); + reg::Write(PMC + APBDEV_PMC_SCRATCH32, 0x6001DC28); + } + + /* Finalize our powerdown and wait for an interrupt. */ + FinalizePowerOff(); + } + + SmcResult SuspendCpuImpl(SmcArguments &args) { + /* Decode arguments. */ + const util::BitPack32 power_state = { static_cast(args.r[1]) }; + const uintptr_t entry_point = args.r[2]; + const uintptr_t context_id = args.r[3]; + + const auto state_type = power_state.Get(); + const auto state_id = power_state.Get(); + + const auto core_id = hw::GetCurrentCoreId(); + + /* Validate arguments. */ + SMC_R_UNLESS(state_type == PowerStateType_PowerDown, PsciDenied); + SMC_R_UNLESS(state_id == PowerStateId_Sc7, PsciDenied); + + /* Orchestrate charger transition to Hi-Z mode if needed. */ + if (IsChargerHiZModeEnabled()) { + /* Ensure we can do comms over i2c-1. */ + clkrst::EnableI2c1Clock(); + + /* If the charger isn't in hi-z mode, perform a transition. */ + if (!charger::IsHiZMode()) { + charger::EnterHiZMode(); + + /* Wait up to 50ms for the transition to complete. */ + const auto start_time = util::GetMicroSeconds(); + auto current_time = start_time; + while ((current_time - start_time) <= 50'000) { + if (auto intr_status = reg::Read(GPIO + 0x634); (intr_status & 1) == 0) { + /* Wait 256 us to ensure the transition completes. */ + util::WaitMicroSeconds(256); + break; + } + current_time = util::GetMicroSeconds(); + } + } + + /* Disable i2c-1, since we're done communicating over it. */ + clkrst::DisableI2c1Clock(); + } + + /* Enable wake event detection. */ + pmc::EnableWakeEventDetection(); + + /* Ensure that i2c-5 is usable for communicating with the pmic. */ + clkrst::EnableI2c5Clock(); + i2c::Initialize(i2c::Port_5); + + /* Orchestrate sleep entry with the pmic. */ + pmic::EnableSleep(); + + /* Ensure that the soc is in a state valid for us to suspend. */ + if (GetTargetFirmware() >= TargetFirmware_2_0_0) { + ValidateSocStateForSuspend(); + } + + /* Configure the pmc for sc7 entry. */ + pmc::ConfigureForSc7Entry(); + + /* Configure the flow controller for sc7 entry. */ + flow::SetCc4Ctrl(core_id, 0); + flow::SetHaltCpuEvents(core_id, false); + flow::ClearL2FlushControl(); + flow::SetCpuCsr(core_id, FLOW_CTLR_CPUN_CSR_ENABLE_EXT_POWERGATE_CPU_TURNOFF_CPURAIL); + + /* Save the entry context. */ + SetEntryContext(core_id, entry_point, context_id); + + /* Configure the cpu context for reset. */ + SaveDebugRegisters(); + SetCoreOff(); + SetResetExpected(true); + + /* Switch to use the common smc stack (all other cores are off), and perform suspension. */ + PivotStackAndInvoke(reinterpret_cast(CommonSmcStackTop), SaveSecureContextAndSuspend); + + /* This code will never be reached. */ + __builtin_unreachable(); + } + + } + + void PowerOffCpu() { + /* Get the current core id. */ + const auto core_id = hw::GetCurrentCoreId(); + + /* Note that we're expecting a reset for the current core. */ + SetResetExpected(true); + + /* If we're on the final core, shut down directly. Otherwise, invoke with special stack. */ + if (core_id == NumCores - 1) { + PowerOffCpuImpl(); + } else { + PivotStackAndInvoke(GetCoreExceptionStackVirtual(), PowerOffCpuImpl); + } + + /* This code will never be reached. */ + __builtin_unreachable(); + } + + SmcResult SmcPowerOffCpu(SmcArguments &args) { + AMS_UNUSED(args); + + PowerOffCpu(); + } + + SmcResult SmcPowerOnCpu(SmcArguments &args) { + /* Get and validate the core to power on. */ + const int which_core = args.r[1]; + SMC_R_UNLESS(0 <= which_core && which_core < NumCores, PsciInvalidParameters); + + /* Ensure the core isn't already on. */ + SMC_R_UNLESS(!IsCoreOn(which_core), PsciAlreadyOn); + + /* Save the entry context. */ + SetEntryContext(which_core, args.r[2], args.r[3]); + + /* Reset the cpu. */ + ResetCpu(which_core); + + /* Turn on the core. */ + PowerOnCpu(CpuPowerGateStatusMasks[which_core], CpuPowerGateTogglePartitionIds[which_core]); + + /* Start the core. */ + StartCpu(which_core); + + return SmcResult::PsciSuccess; + } + + SmcResult SmcSuspendCpu(SmcArguments &args) { + return LockSecurityEngineAndInvoke(args, SuspendCpuImpl); + } + + bool IsChargerHiZModeEnabled() { + return g_charger_hi_z_mode_enabled; + } + + void SetChargerHiZModeEnabled(bool en) { + g_charger_hi_z_mode_enabled = en; + } + +} diff --git a/Source/Atmosphere-Patches/secmon_smc_register_access.cpp b/Source/Atmosphere-Patches/secmon_smc_register_access.cpp index 88757041..4bd7c47e 100644 --- a/Source/Atmosphere-Patches/secmon_smc_register_access.cpp +++ b/Source/Atmosphere-Patches/secmon_smc_register_access.cpp @@ -99,16 +99,19 @@ namespace ams::secmon::smc { #include "secmon_define_pmc_access_table.inc" #include "secmon_define_mc_access_table.inc" #include "secmon_define_emc_access_table.inc" + #include "secmon_define_emc01_access_table.inc" #include "secmon_define_rtc_pmc_access_table.inc" #include "secmon_define_mc01_access_table.inc" constexpr const AccessTableEntry AccessTables[] = { - { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, }, - { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, }, - { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, }, - { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::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, }, + { PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, }, + { McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, }, + { EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, }, + { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController0.GetAddress(), Emc01AccessTable::Size, }, + { Emc01AccessTable::ReducedAccessTable.data(), Emc01AccessTable::Address + MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Address + MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress(), Emc01AccessTable::Size, }, + { RtcPmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceRtcPmc.GetAddress(), RtcPmcAccessTable::Address, RtcPmcAccessTable::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, }, }; constexpr bool IsAccessAllowed(const AccessTableEntry &entry, uintptr_t address) { @@ -170,12 +173,12 @@ namespace ams::secmon::smc { /* This is "probably" to fuck with hackers who got access to the SMC and are trying to get control of the */ /* BPMP to exploit jamais vu, deja vu, or other related DMA/wake-from-sleep vulnerabilities. */ constexpr uintptr_t MC = MemoryRegionPhysicalDeviceMemoryController.GetAddress(); - SMC_R_UNLESS((address == (MC + MC_SMMU_AVPC_ASID) || address == (MC + MC_SMMU_PPCS1_ASID)), InvalidArgument); + // SMC_R_UNLESS((address == (MC + MC_SMMU_AVPC_ASID) || address == (MC + MC_SMMU_PPCS1_ASID)), InvalidArgument); - /* For backwards compatibility, we'll allow access to these devices on 1.0.0. */ - if (GetTargetFirmware() < TargetFirmware_2_0_0) { + // /* For backwards compatibility, we'll allow access to these devices on 1.0.0. */ + // if (GetTargetFirmware() < TargetFirmware_2_0_0) { virtual_address = MemoryRegionVirtualDeviceMemoryController.GetAddress() + (address - MC); - } + // } } /* Perform the read or write, if we should. */ diff --git a/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp b/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp index 0baf0b56..fd96684e 100644 --- a/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/ldr_process_creation.cpp @@ -13,6 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + #include #include "ldr_capabilities.hpp" #include "ldr_content_management.hpp" @@ -126,8 +127,7 @@ namespace ams::ldr { bool g_is_ptm; /* Global Zstd decompression context. */ - constexpr size_t ZstdDctxWorkspaceSize = 0x176E8; - alignas(8) u8 g_zstd_dctx_workspace[ZstdDctxWorkspaceSize]; + alignas(8) u8 g_zstd_dctx_workspace[util::DecompressZstdWithBicWorkBufferSizeDefault]; Result ValidateProgramVersion(ncm::ProgramId program_id, u32 version) { /* No version verification is done before 8.1.0. */ @@ -181,8 +181,8 @@ namespace ams::ldr { return (MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Application; } - Npdm::AddressSpaceType GetAddressSpaceType(const Meta *meta) { - return static_cast((meta->npdm->flags & Npdm::MetaFlag_AddressSpaceTypeMask) >> Npdm::MetaFlag_AddressSpaceTypeShift); + Npdm::ProcessAddressSpace GetProcessAddressSpace(const Meta *meta) { + return static_cast((meta->npdm->flags0 & Npdm::MetaFlag0_ProcessAddressSpaceMask) >> Npdm::MetaFlag0_ProcessAddressSpaceShift); } Acid::PoolPartition GetPoolPartition(const Meta *meta) { @@ -225,7 +225,7 @@ namespace ams::ldr { /* Read NSO header. */ size_t read_size; R_TRY(fs::ReadFile(std::addressof(read_size), file, 0, g_nso_headers + ctx.nso_count, sizeof(NsoHeader))); - R_UNLESS(read_size == sizeof(NsoHeader), ldr::ResultInvalidNso()); + R_UNLESS_LOG(read_size == sizeof(NsoHeader), ldr::ResultInvalidNso(), "[ldr] NSO header truncated!\n"); /* Note nso is present. */ switch (i) { @@ -264,7 +264,7 @@ namespace ams::ldr { Result CheckAutoLoad(const AutoLoadModuleContext &ctx, u32 acid_flags) { /* We must always have a main. */ - R_UNLESS(ctx.ali.has_main, ldr::ResultInvalidNso()); + R_UNLESS_LOG(ctx.ali.has_main, ldr::ResultInvalidNso(), "[ldr] Missing main!\n"); /* Validate flags and extents for all present NSOs. */ for (int i = 0; i < ctx.nso_count; ++i) { @@ -272,11 +272,11 @@ namespace ams::ldr { /* All NSOs must not be --X. */ /* This is "probably" not checked on Ounce? */ - R_UNLESS((hdr.flags & NsoHeader::Flag_PreventCodeReads) == 0, ldr::ResultInvalidNso()); + R_UNLESS_LOG((hdr.flags & NsoHeader::Flag_PreventCodeReads) == 0, ldr::ResultInvalidNso(), "[ldr] NSO[%d] --x not allowed!\n", i); /* Zstd compression only allowed on main, and only when both rtld+sdk are present. */ if (i != ctx.main_nso_idx || ctx.rtld_idx < 0 || ctx.sdk_nso_idx < 0) { - R_UNLESS((hdr.flags & NsoHeader::Flag_UseZbicCompression) == 0, ldr::ResultInvalidNso()); + R_UNLESS_LOG((hdr.flags & NsoHeader::Flag_UseZbicCompression) == 0, ldr::ResultInvalidNso(), "[ldr] NSO[%d] zbic not allowed!\n", i); } /* NSOs must have page-aligned segments. */ @@ -299,13 +299,13 @@ namespace ams::ldr { const bool has_browser_dll = (acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) != 0; if (ctx.ali.has_rtld || ctx.ali.has_sdk) { /* If we have sdk we must have rtld. */ - R_UNLESS(ctx.ali.has_rtld, ldr::ResultInvalidNso()); + R_UNLESS_LOG(ctx.ali.has_rtld, ldr::ResultInvalidNso(), "[ldr] Missing rtld!\n"); /* If we have rtld, we must not have browser core dll. */ - R_UNLESS(!has_browser_dll, ldr::ResultInvalidNso()); + R_UNLESS_LOG(!has_browser_dll, ldr::ResultInvalidNso(), "[ldr] BrowserCoreDll must not be present!\n"); } else { /* We must not have both subsdk and browser dll. */ - R_UNLESS(!(ctx.ali.has_subsdk && has_browser_dll), ldr::ResultInvalidNso()); + R_UNLESS_LOG(!(ctx.ali.has_subsdk && has_browser_dll), ldr::ResultInvalidNso(), "[ldr] Can't have both subsdk and BrowserCoreDll!\n"); } R_SUCCEED(); @@ -394,6 +394,8 @@ namespace ams::ldr { /* If the signature check fails, we need to check if this is allowable. */ if (!is_signature_valid) { + AMS_LOG("[ldr] invalid signature!\n"); + /* We have to enforce signature checks on prod and when we have a signature to check on dev. */ R_UNLESS(IsDevelopmentForAcidProductionCheck(), ldr::ResultInvalidNcaSignature()); R_UNLESS(!code_verification_data.has_data, ldr::ResultInvalidNcaSignature()); @@ -407,52 +409,56 @@ namespace ams::ldr { R_SUCCEED(); } - Result GetCreateProcessFlags(u32 *out, const Meta *meta, const u32 ldr_flags) { - const u8 meta_flags = meta->npdm->flags; + Result GetCreateProcessParameterFlags(u32 *out, const Meta *meta, const u32 ldr_flags) { + const u8 meta_flags0 = meta->npdm->flags0; + const u8 meta_flags1 = meta->npdm->flags1; u32 flags = 0; /* Set Is64Bit. */ - if (meta_flags & Npdm::MetaFlag_Is64Bit) { - flags |= svc::CreateProcessFlag_Is64Bit; + if (meta_flags0 & Npdm::MetaFlag0_Is64BitInstruction) { + flags |= svc::CreateProcessParameterFlag_64Bit; } - /* Set AddressSpaceType. */ - switch (GetAddressSpaceType(meta)) { - case Npdm::AddressSpaceType_32Bit: - flags |= svc::CreateProcessFlag_AddressSpace32Bit; + /* Set ProcessAddressSpace. */ + switch (GetProcessAddressSpace(meta)) { + case Npdm::ProcessAddressSpace_32Bit: + flags |= svc::CreateProcessParameterFlag_AddressSpace32Bit; break; - case Npdm::AddressSpaceType_64BitDeprecated: - flags |= svc::CreateProcessFlag_AddressSpace64BitDeprecated; + case Npdm::ProcessAddressSpace_64Bit36: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit36; break; - case Npdm::AddressSpaceType_32BitWithoutAlias: - flags |= svc::CreateProcessFlag_AddressSpace32BitWithoutAlias; + case Npdm::ProcessAddressSpace_32BitNoReserved: + flags |= svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved; break; - case Npdm::AddressSpaceType_64Bit: - flags |= svc::CreateProcessFlag_AddressSpace64Bit; + case Npdm::ProcessAddressSpace_64Bit39: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit39; + break; + case Npdm::ProcessAddressSpace_64Bit42: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit42; break; default: R_THROW(ldr::ResultInvalidMeta()); } /* Set Enable Debug. */ - if (ldr_flags & CreateProcessFlag_EnableDebug) { - flags |= svc::CreateProcessFlag_EnableDebug; + if (ldr_flags & CreateProcessParameterFlag_EnableJitDebug) { + flags |= svc::CreateProcessParameterFlag_EnableJitDebug; } /* Set Enable ASLR. */ - if (!(ldr_flags & CreateProcessFlag_DisableAslr)) { - flags |= svc::CreateProcessFlag_EnableAslr; + if (!(ldr_flags & CreateProcessParameterFlag_DisableAslr)) { + flags |= svc::CreateProcessParameterFlag_EnableAslr; } /* Set Is Application. */ if (IsApplication(meta)) { - flags |= svc::CreateProcessFlag_IsApplication; + flags |= svc::CreateProcessParameterFlag_IsApplication; /* 7.0.0+: Set OptimizeMemoryAllocation if relevant. */ if (hos::GetVersion() >= hos::Version_7_0_0) { - if (meta_flags & Npdm::MetaFlag_OptimizeMemoryAllocation) { - flags |= svc::CreateProcessFlag_OptimizeMemoryAllocation; + if (meta_flags0 & Npdm::MetaFlag0_OptimizeMemoryAllocation) { + flags |= svc::CreateProcessParameterFlag_OptimizeMemoryAllocation; } } } @@ -464,19 +470,19 @@ namespace ams::ldr { switch (GetPoolPartition(meta)) { case Acid::PoolPartition_Application: if (IsApplet(meta)) { - flags |= svc::CreateProcessFlag_PoolPartitionApplet; + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplet; } else { - flags |= svc::CreateProcessFlag_PoolPartitionApplication; + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplication; } break; case Acid::PoolPartition_Applet: - flags |= svc::CreateProcessFlag_PoolPartitionApplet; + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplet; break; case Acid::PoolPartition_System: - flags |= svc::CreateProcessFlag_PoolPartitionSystem; + flags |= svc::CreateProcessParameterFlag_PoolPartitionSystem; break; case Acid::PoolPartition_SystemNonSecure: - flags |= svc::CreateProcessFlag_PoolPartitionSystemNonSecure; + flags |= svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure; break; default: R_THROW(ldr::ResultInvalidMeta()); @@ -484,18 +490,23 @@ namespace ams::ldr { } else if (hos::GetVersion() >= hos::Version_4_0_0) { /* On 4.0.0+, the corresponding bit was simply "UseSecureMemory". */ if (meta->acid->flags & Acid::AcidFlag_DeprecatedUseSecureMemory) { - flags |= svc::CreateProcessFlag_DeprecatedUseSecureMemory; + flags |= svc::CreateProcessParameterFlag_DeprecatedUseSecureMemory; } } - /* 11.0.0+/meso Set Disable DAS merge. */ - if (meta_flags & Npdm::MetaFlag_DisableDeviceAddressSpaceMerge) { - flags |= svc::CreateProcessFlag_DisableDeviceAddressSpaceMerge; + /* 11.0.0+/meso Set Disable DAS Merge. */ + if (meta_flags0 & Npdm::MetaFlag0_DisableDeviceAddressSpaceMerge) { + flags |= svc::CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge; } - /* 18.0.0+/meso Set Alias region extra size. */ - if (meta_flags & Npdm::MetaFlag_EnableAliasRegionExtraSize) { - flags |= svc::CreateProcessFlag_EnableAliasRegionExtraSize; + /* 18.0.0+/meso Set Enable Address Sanitizer . */ + if (meta_flags0 & Npdm::MetaFlag0_EnableAddressSanitizer) { + flags |= svc::CreateProcessParameterFlag_EnableAddressSanitizer; + } + + /* 23.0.0+/meso Set Enable Shadow Stack. */ + if (meta_flags1 & Npdm::MetaFlag1_EnableShadowStack) { + flags |= svc::CreateProcessParameterFlag_EnableShadowStack; } *out = flags; @@ -513,7 +524,7 @@ namespace ams::ldr { out->reslimit = resource_limit; /* Set flags. */ - R_TRY(GetCreateProcessFlags(std::addressof(out->flags), meta, flags)); + R_TRY(GetCreateProcessParameterFlags(std::addressof(out->flags), meta, flags)); /* 3.0.0+ System Resource Size. */ if (hos::GetVersion() >= hos::Version_3_0_0) { @@ -523,7 +534,7 @@ namespace ams::ldr { /* Validate system resource usage. */ if (meta->npdm->system_resource_size) { /* Process must be 64-bit. */ - R_UNLESS((out->flags & svc::CreateProcessFlag_AddressSpace64Bit), ldr::ResultInvalidMeta()); + R_UNLESS((out->flags & svc::CreateProcessParameterFlag_AddressSpace64Bit39), ldr::ResultInvalidMeta()); /* Process must be application or applet. */ R_UNLESS(IsApplication(meta) || IsApplet(meta), ldr::ResultInvalidMeta()); @@ -596,25 +607,29 @@ namespace ams::ldr { uintptr_t aslr_start = 0; size_t aslr_size = 0; if (hos::GetVersion() >= hos::Version_2_0_0) { - switch (out_param->flags & svc::CreateProcessFlag_AddressSpaceMask) { - case svc::CreateProcessFlag_AddressSpace32Bit: - case svc::CreateProcessFlag_AddressSpace32BitWithoutAlias: + switch (out_param->flags & svc::CreateProcessParameterFlag_AddressSpaceMask) { + case svc::CreateProcessParameterFlag_AddressSpace32Bit: + case svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved: aslr_start = svc::AddressSmallMap32Start; aslr_size = svc::AddressSmallMap32Size; break; - case svc::CreateProcessFlag_AddressSpace64BitDeprecated: + case svc::CreateProcessParameterFlag_AddressSpace64Bit36: aslr_start = svc::AddressSmallMap36Start; aslr_size = svc::AddressSmallMap36Size; break; - case svc::CreateProcessFlag_AddressSpace64Bit: + case svc::CreateProcessParameterFlag_AddressSpace64Bit39: aslr_start = svc::AddressMap39Start; aslr_size = svc::AddressMap39Size; break; + case svc::CreateProcessParameterFlag_AddressSpace64Bit42: + aslr_start = svc::AddressMap42Start; + aslr_size = svc::AddressMap42Size; + break; AMS_UNREACHABLE_DEFAULT_CASE(); } } else { /* On 1.0.0, only 2 address space types existed. */ - if (out_param->flags & svc::CreateProcessFlag_AddressSpace64BitDeprecated) { + if (out_param->flags & svc::CreateProcessParameterFlag_AddressSpace64Bit36) { aslr_start = svc::AddressSmallMap36Start; aslr_size = svc::AddressSmallMap36Size; } else { @@ -627,7 +642,7 @@ namespace ams::ldr { /* Set Create Process output. */ uintptr_t aslr_slide = 0; size_t free_size = (aslr_size - total_size); - if (out_param->flags & svc::CreateProcessFlag_EnableAslr) { + if (out_param->flags & svc::CreateProcessParameterFlag_EnableAslr) { aslr_slide = GenerateSecureRandom(free_size / os::MemoryBlockUnitSize) * os::MemoryBlockUnitSize; } @@ -649,10 +664,13 @@ namespace ams::ldr { R_SUCCEED(); } - Result LoadAutoLoadModuleSegment(fs::FileHandle file, size_t file_offset, size_t compressed_size, size_t segment_size, bool is_compressed, bool is_zstd, uintptr_t map_base, uintptr_t map_end) { + Result LoadAutoLoadModuleSegment(fs::FileHandle file, size_t file_offset, size_t compressed_size, size_t segment_size, bool is_compressed, bool is_zbic, uintptr_t map_base, uintptr_t map_end) { /* Select read size based on compression. */ size_t file_size = is_compressed ? compressed_size : segment_size; + AMS_LOG("[ldr] Loading segment @ 0x%016lx: compressed=%d, file_size=0x%08lx, compressed_size=0x%08lx, segment_size=0x%08lx\n", + map_base, is_compressed, file_size, compressed_size, segment_size); + /* Validate size. */ R_UNLESS(file_size <= segment_size, ldr::ResultInvalidNso()); R_UNLESS(file_size <= std::numeric_limits::max(), ldr::ResultInvalidNso()); @@ -662,19 +680,19 @@ namespace ams::ldr { uintptr_t load_address = is_compressed ? map_end - compressed_size : map_base; size_t read_size; R_TRY(fs::ReadFile(std::addressof(read_size), file, file_offset, reinterpret_cast(load_address), file_size)); - R_UNLESS(read_size == file_size, ldr::ResultInvalidNso()); + R_UNLESS_LOG(read_size == file_size, ldr::ResultInvalidNso(), "[ldr] Couldn't read segment from file!\n"); /* Uncompress if necessary. */ R_SUCCEED_IF(!is_compressed); auto compressed_data_buf = reinterpret_cast(load_address); - if (is_zstd) { - bool decompressed = util::DecompressZstdForLoader(reinterpret_cast(g_zstd_dctx_workspace), ZstdDctxWorkspaceSize, reinterpret_cast(map_base), static_cast(map_end - map_base), segment_size, compressed_data_buf, file_size); - R_UNLESS(decompressed, ldr::ResultInvalidNso()); + if (is_zbic) { + bool decompressed = util::DecompressZstdWithBic(reinterpret_cast(g_zstd_dctx_workspace), sizeof(g_zstd_dctx_workspace), reinterpret_cast(map_base), static_cast(map_end - map_base), segment_size, compressed_data_buf, file_size); + R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with zbic!\n"); } else { bool decompressed = (util::DecompressLZ4(reinterpret_cast(map_base), segment_size, compressed_data_buf, file_size) == static_cast(segment_size)); - R_UNLESS(decompressed, ldr::ResultInvalidNso()); + R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with lz4!\n"); } R_SUCCEED(); @@ -689,12 +707,12 @@ namespace ams::ldr { crypto::GenerateSha256(hash, sizeof(hash), reinterpret_cast(map_address + nso_header->segments[segment].dst_offset), nso_header->segments[segment].size); - R_UNLESS(std::memcmp(hash, nso_header->segment_hashes[segment], sizeof(hash)) == 0, ldr::ResultInvalidNso()); + R_UNLESS_LOG(std::memcmp(hash, nso_header->segment_hashes[segment], sizeof(hash)) == 0, ldr::ResultInvalidNso(), "[ldr] Invalid segment hash!\n"); R_SUCCEED(); } Result LoadAutoLoadModule(os::NativeHandle process_handle, fs::FileHandle file, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size, size_t map_size) { - const bool is_zstd = (nso_header->flags & NsoHeader::Flag_UseZbicCompression) != 0; + const bool is_zbic = (nso_header->flags & NsoHeader::Flag_UseZbicCompression) != 0; const size_t module_size = static_cast(nso_header->rw_dst_offset) + util::AlignUp(nso_header->rw_size + nso_header->bss_size, os::MemoryPageSize); const size_t arena_size = (nso_size > module_size) ? (nso_size - module_size) : 0; @@ -711,11 +729,11 @@ namespace ams::ldr { /* Load NSO segments. */ R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Text].file_offset, nso_header->text_compressed_size, nso_header->text_size, - (nso_header->flags & NsoHeader::Flag_CompressedText) != 0, is_zstd, map_address + nso_header->text_dst_offset, map_end)); + (nso_header->flags & NsoHeader::Flag_CompressedText) != 0, is_zbic, map_address + nso_header->text_dst_offset, map_end)); R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Ro].file_offset, nso_header->ro_compressed_size, nso_header->ro_size, - (nso_header->flags & NsoHeader::Flag_CompressedRo) != 0, is_zstd, map_address + nso_header->ro_dst_offset, map_end)); + (nso_header->flags & NsoHeader::Flag_CompressedRo) != 0, is_zbic, map_address + nso_header->ro_dst_offset, map_end)); R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Rw].file_offset, nso_header->rw_compressed_size, nso_header->rw_size, - (nso_header->flags & NsoHeader::Flag_CompressedRw) != 0, is_zstd, map_address + nso_header->rw_dst_offset, map_end)); + (nso_header->flags & NsoHeader::Flag_CompressedRw) != 0, is_zbic, map_address + nso_header->rw_dst_offset, map_end)); /* Clear unused space to zero. */ const size_t text_end = static_cast(nso_header->text_dst_offset) + static_cast(nso_header->text_size); @@ -778,15 +796,17 @@ namespace ams::ldr { for (int i = 0; i < ctx.nso_count; i++) { const NsoIndex nso_idx = static_cast(ctx.ali.nso_indices[i]); + const bool is_zbic = (ctx.headers[i].flags & NsoHeader::Flag_UseZbicCompression) != 0; + const size_t map_size = is_zbic ? (total_end - process_info->nso_address[i]) : process_info->nso_size[i]; + + AMS_LOG("[ldr] module[%d]: idx=%d, path='%s', zbic=%d\n", i, (int)nso_idx, GetNsoPath(nso_idx), is_zbic); fs::FileHandle file; R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(nso_idx), fs::OpenMode_Read)); ON_SCOPE_EXIT { fs::CloseFile(file); }; - const bool is_zstd = (ctx.headers[i].flags & NsoHeader::Flag_UseZbicCompression) != 0; - const size_t map_size = is_zstd ? (total_end - process_info->nso_address[i]) : process_info->nso_size[i]; - - R_TRY(LoadAutoLoadModule(process_info->process_handle, file, ctx.headers + i, process_info->nso_address[i], process_info->nso_size[i], map_size)); + R_TRY(LoadAutoLoadModule(process_info->process_handle, file, ctx.headers + i, + process_info->nso_address[i], process_info->nso_size[i], map_size)); } /* Load arguments, if present. */ @@ -813,12 +833,6 @@ namespace ams::ldr { } Result CreateProcessAndLoadAutoLoadModules(ProcessInfo *out, const Meta *meta, const AutoLoadModuleContext &ctx, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) { - /* Append extra .bss for 64LUT */ - /* TODO: REMOVE THIS. */ - if (g_is_pcv && ctx.main_nso_idx >= 0) { - g_nso_headers[ctx.main_nso_idx].bss_size += static_cast(hoc::pcv::HocPcvScratchSize); - } - /* Get CreateProcessParameter. */ svc::CreateProcessParameter param; R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, resource_limit)); @@ -833,7 +847,7 @@ namespace ams::ldr { /* Set the output handle, and ensure that if we fail after this point we clean it up. */ out->process_handle = process_handle; out->code_address = param.code_address; - ON_RESULT_FAILURE { svc::CloseHandle(process_handle); }; + ON_RESULT_FAILURE { R_DISCARD(svc::CloseHandle(process_handle)); }; /* Load all auto load modules. */ R_RETURN(LoadAutoLoadModules(out, ctx, argument)); @@ -891,8 +905,8 @@ namespace ams::ldr { os::ProcessId process_id = os::GetProcessId(info.process_handle); /* Register new process. */ - const auto as_type = GetAddressSpaceType(std::addressof(meta)); - RoManager::GetInstance().RegisterProcess(pin_id, process_id, meta.aci->program_id, as_type == Npdm::AddressSpaceType_64Bit || as_type == Npdm::AddressSpaceType_64BitDeprecated); + const auto as_type = GetProcessAddressSpace(std::addressof(meta)); + RoManager::GetInstance().RegisterProcess(pin_id, process_id, meta.aci->program_id, as_type == Npdm::ProcessAddressSpace_64Bit39 || as_type == Npdm::ProcessAddressSpace_64Bit36); /* Register all NSOs. */ for (int i = 0; i < ctx.nso_count; i++) { @@ -903,7 +917,7 @@ namespace ams::ldr { /* If we're overriding for HBL, perform HTML document redirection. */ if (override_status.IsHbl()) { /* Don't validate result, failure is okay. */ - RedirectHtmlDocumentPathForHbl(loc); + R_DISCARD(RedirectHtmlDocumentPathForHbl(loc)); } /* Clear the external code for the program. */ diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp index 5ba70a8f..423ee84f 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.cpp @@ -26,7 +26,7 @@ #define DISABLED 0 #define DEACTIVATED_GPU_FREQ 2000 #define GPU_MIN_MIN_VOLT 480000 -#define CPU_MAX_MAX_VOLT 1200000 +#define CPU_MAX_MAX_VOLT 1235000 namespace ams::ldr::hoc { @@ -36,14 +36,14 @@ volatile CustomizeTable C = { .hpMode = DISABLED, .commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */ -.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */ +.eristaEmcMaxClock = 1600000, /* Erista ram rating*/ /* Available: 33MHz step rate, 66MHz step rate, 100MHz step rate, 133MHz step rate and jedec. */ /* Jedec freqs are 1333MHz, 1600MHz, 1866MHz, 2133MHz, 2400MHz, 2666MHz, 2933MHz, 3200MHz. */ -.stepMode = StepMode_33MHz, +.stepMode = StepMode_Jedec, -.marikoEmcMaxClock = 2133000, /* Requires the EMC DVFS 63-entry patches (EMC DVFS Count / EMC SoC LUT). */ -.marikoEmcVddqVolt = 600000, +.marikoEmcMaxClock = 2133000, /* Should work for every ram*/ +.marikoEmcVddqVolt = 640000, /* Optimal for DRAM OC */ .emcDvbShift = 0, .marikoSocVmax = 0, /* 0 = stock limits (1450 - 1597 is 1050mV, 1598-1708 is 1025mV, 1709+ is 1000mV). */ @@ -100,13 +100,14 @@ volatile CustomizeTable C = { /* 1120mV is NVIDIA rating */ .marikoCpuMaxVolt = 1120, -/* Supported values: 1963500, 2091000, 2193000, 2295000, 2397000, 2499000, 2601000, 2703000. */ -/* 1963500 is official rating of T214/Mariko, fully safe. */ -/* 2091000-2295000 is a slight OC which should work on all units, but no guarantees. */ -/* 2397000 is the max safe OC for most average units with tuned undervolt. */ -/* 2499000 should be used with caution. */ -/* 2601000 exceeds pmic limit on most consoles. */ -/* 2703000 is potentially dangerous and not advised. */ +/* Supported values: 1963500, 2091000, 2193000, 2295000, 2397000, 2499000, 2601000, 2703000, 2805000. */ +/* 1963500 is official rating of T214/Mariko, fully safe. */ +/* 2091000-2295000 is a slight OC which should work on all units, but no guarantees. */ +/* 2397000 is the max safe OC for most average units with tuned undervolt. */ +/* 2499000 should be used with caution. */ +/* 2601000 exceeds pmic limit on most consoles. */ +/* 2703000 is potentially dangerous and not advised. */ +/* 2805000 can only be ran on the best of consoles and may be dangerous due to the voltage requirement */ .marikoCpuMaxClock = 1963500, .eristaCpuBoostClock = 1785000, /* Default boost clock */ @@ -132,7 +133,7 @@ volatile CustomizeTable C = { AUTO /* 153 */, AUTO /* 192 */, AUTO /* 230 */, - AUTO /* 269 */, + AUTO /* 268 */, AUTO /* 307 */, AUTO /* 346 */, AUTO /* 384 */, @@ -181,6 +182,7 @@ volatile CustomizeTable C = { DEACTIVATED_GPU_FREQ /* 1459 (Disabled by default) */, DEACTIVATED_GPU_FREQ /* 1497 (Disabled by default) */, DEACTIVATED_GPU_FREQ /* 1536 (Disabled by default) */, + DEACTIVATED_GPU_FREQ /* 1574 (Disabled by default) */, }, /* Override soc voltage brackets. */ @@ -219,6 +221,16 @@ volatile CustomizeTable C = { .fineTune_t6_tRTW = 0, .fineTune_t7_tWTR = 0, +/* Debugging options */ + +/* PCV Log Verbosity */ +/* 0xFF: Nothing */ +/* 0: Basic logging */ +/* 1: More advanced logging */ +/* 2: All logging excluding MMIO */ +/* 3: All logging including MMIO */ +.pcvLogVerbosity = 2, + /* You shouldn't have to anything past here. */ .eristaCpuDvfsTable = { { 204000, { 721094, }, { } }, @@ -318,6 +330,7 @@ volatile CustomizeTable C = { { 2499000, { 1580725, -35815, 113, }, { CPU_MAX_MAX_VOLT, } }, { 2601000, { 1702903, -36675, 113, }, { CPU_MAX_MAX_VOLT, } }, { 2703000, { 1770375, -37515, 113, }, { CPU_MAX_MAX_VOLT, } }, + { 2805000, { 1838820, -37707, 113, }, { CPU_MAX_MAX_VOLT, } }, }, .marikoCpuDvfsTable1581Tbreak { @@ -346,6 +359,7 @@ volatile CustomizeTable C = { { 2499000, { 1736856, -35286, 113, }, { CPU_MAX_MAX_VOLT, } }, { 2601000, { 1787838, -35967, 113, }, { CPU_MAX_MAX_VOLT, } }, { 2703000, { 1838820, -36648, 113, }, { CPU_MAX_MAX_VOLT, } }, + { 2805000, { 1908891, -37707, 113, }, { CPU_MAX_MAX_VOLT, } }, }, .marikoCpuDvfsTable1683Tbreak { @@ -374,6 +388,7 @@ volatile CustomizeTable C = { { 2499000, { 1736856, -35286, 113, }, { CPU_MAX_MAX_VOLT, } }, { 2601000, { 1787838, -35967, 113, }, { CPU_MAX_MAX_VOLT, } }, { 2703000, { 1838820, -36648, 113, }, { CPU_MAX_MAX_VOLT, } }, + { 2805000, { 1908891, -37707, 113, }, { CPU_MAX_MAX_VOLT, } }, }, .marikoCpuDvfsTableExtreme { @@ -402,6 +417,7 @@ volatile CustomizeTable C = { { 2499000, { 1580725, -35815, 113, }, { CPU_MAX_MAX_VOLT, } }, { 2601000, { 1702903, -36675, 113, }, { CPU_MAX_MAX_VOLT, } }, { 2703000, { 1775375, -37515, 113, }, { CPU_MAX_MAX_VOLT, } }, + { 2805000, { 1838820, -37707, 113, }, { CPU_MAX_MAX_VOLT, } }, }, .eristaGpuDvfsTable = { @@ -571,13 +587,14 @@ volatile CustomizeTable C = { { 1152000, { }, { 1180029, -14534, -830, 0, 1469, 110 } }, { 1228800, { }, { 1238293, -16383, -859, 0, 3722, 313 } }, { 1267200, { }, { 1276399, -17475, -867, 0, 3681, 559 } }, - { 1305600, { }, { } }, - { 1344000, { }, { } }, - { 1382400, { }, { } }, - { 1420800, { }, { } }, - { 1459200, { }, { } }, - { 1497600, { }, { } }, - { 1536000, { }, { } }, + { 1305600, { }, { 0, 0, 0, 0, 0, 0 } }, + { 1344000, { }, { 0, 0, 0, 0, 0, 0 } }, + { 1382400, { }, { 0, 0, 0, 0, 0, 0 } }, + { 1420800, { }, { 0, 0, 0, 0, 0, 0 } }, + { 1459200, { }, { 0, 0, 0, 0, 0, 0 } }, + { 1497600, { }, { 0, 0, 0, 0, 0, 0 } }, + { 1536000, { }, { 0, 0, 0, 0, 0, 0 } }, + { 1574400, { }, { 0, 0, 0, 0, 0, 0 } }, }, .marikoGpuDvfsTableHighUV = { @@ -605,6 +622,7 @@ volatile CustomizeTable C = { { 1459200, { }, { 0, 0, 0, 0, 0, 0 } }, { 1497600, { }, { 0, 0, 0, 0, 0, 0 } }, { 1536000, { }, { 0, 0, 0, 0, 0, 0 } }, + { 1574400, { }, { 0, 0, 0, 0, 0, 0 } }, }, }; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp index a898e20b..e5e9051e 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/customize.hpp @@ -47,14 +47,14 @@ enum ReadLatency: u32 { RL_2133 = 40, RL_1866 = 36, RL_1600 = 32, - RL_1331 = 28, + RL_1333 = 28, }; enum WriteLatency: u32 { WL_2133 = 18, WL_1866 = 16, WL_1600 = 14, - WL_1331 = 12, + WL_1333 = 12, }; using CustomizeCpuDvfsTable = pcv::cvb_entry_t[pcv::DvfsTableEntryLimit]; @@ -126,13 +126,15 @@ struct CustomizeTable { s32 commonGpuVoltOffset; u32 eristaGpuVoltArray[27]; - u32 marikoGpuVoltArray[24]; + u32 marikoGpuVoltArray[25]; s32 marikoSocVoltArray[28]; u32 fineTune_t6_tRTW; u32 fineTune_t7_tWTR; - u32 reserved[60]; + u32 pcvLogVerbosity; + + u32 reserved[57]; CustomizeCpuDvfsTable eristaCpuDvfsTable; CustomizeCpuDvfsTable eristaCpuDvfsTableSLT; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp index 7b23d587..9ec9f726 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/mtc_timing_value.hpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2023 hanai3Bi * - * Copyright (c) 2025 Lightos_ + * 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, @@ -20,7 +20,7 @@ #include "oc_common.hpp" -namespace ams::ldr::hoc { +namespace ams::ldr::hoc::pcv { #define MAX(A, B) std::max(A, B) #define MIN(A, B) std::min(A, B) #define CEIL(A) std::ceil(A) @@ -30,6 +30,9 @@ namespace ams::ldr::hoc { #define PACK_U32(high, low) ((static_cast(high) << 16) | (static_cast(low) & 0xFFFF)) #define PACK_U32_NIBBLE_HIGH_BYTE_LOW(high, low) ((static_cast(high & 0xF) << 28) | (static_cast(low) & 0xFF)) + #define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) + #define GET_CYCLE_FLOOR(PARAM) u32(FLOOR(double(PARAM) / tCK_avg)) + /* Burst latency, not to be confused with base latency (tWRL). */ const u32 BL = 16; @@ -38,6 +41,10 @@ namespace ams::ldr::hoc { /* DQS output access time from CK_t/CK_c. */ const double tDQSCK_max = 3.5; + + /* Turn-around time RDQS to WDQS for WDQS control case. */ + const double tDQSTA = 0.25; + /* Write preamble. (tCK) */ const u32 tWPRE = 2; @@ -56,10 +63,24 @@ namespace ams::ldr::hoc { /* DQ-to-DQS offset(max) (ns) */ const double tDQS2DQ_max = 0.8; + /* Internal READ to PRECHARGE command delay */ + const double tRTP = 7.5; + /* Write recovery time. */ const u32 tWR = 18; - namespace pcv::erista { + /* Write-to-Read delay. */ + const u32 tWTRStock = 10; + + /* Round trace routing delay(?) Guessed based on tK1 (ns) */ + const double roundTripDelay = 0.5; + + const double tODTon = 1.5; + + inline u32 RL; + inline u32 WL; + + namespace erista { const std::array tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 }; const std::array tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 }; const std::array tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 }; @@ -83,13 +104,20 @@ namespace ams::ldr::hoc { const u32 tFAW = static_cast(tRRD * 4.0); const double tRPab = tRPpb + 3; - inline u32 RL; - inline u32 WL; - inline u32 tR2P; inline u32 tR2W; inline u32 rext; + inline u32 rdv; + inline u32 qpop; + inline u32 quse_width; + inline u32 quse; + inline u32 einput_duration; + inline u32 einput; + inline u32 qrst; + inline u32 ibdly; + inline u32 qsafe; + inline u32 tW2P; inline u32 tWTPDEN; inline u32 tW2R; @@ -107,9 +135,17 @@ namespace ams::ldr::hoc { inline double pdex2mrr; inline u8 mrw2; + + namespace { + /* Delay of entering soc? Guessed based on tK1. (ns) */ + double chipDelay = 1.655; + } + + /* Soc->dram->soc delay(?) */ + const double flyByTime = chipDelay + roundTripDelay; } - namespace pcv::mariko { + namespace mariko { const std::array tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 }; const std::array tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 }; const std::array tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 }; @@ -132,9 +168,6 @@ namespace ams::ldr::hoc { inline u32 refresh_raw; - inline u32 RL; - inline u32 WL; - inline u32 tR2P; inline u32 tR2W; inline u32 tRTM; @@ -167,9 +200,17 @@ namespace ams::ldr::hoc { inline u32 tCLKSTOP; - inline u32 pdex2mrr; + inline double pdex2mrr; inline u8 mrw2; + + namespace { + /* Delay of entering soc? Guessed based on tK1. (ns) */ + const double chipDelay = 1.109; + } + + /* Soc->dram->soc delay(?) */ + const double flyByTime = chipDelay + roundTripDelay; } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/nvsrv/nvsrv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/nvsrv/nvsrv.cpp new file mode 100644 index 00000000..274e47e3 --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/nvsrv/nvsrv.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) Souldbminer, Lightos and Horizon OC Contributors + * + * 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 . + */ + +#include "nvsrv.hpp" + +namespace ams::ldr::hoc::nvsrv { + + namespace { + + /* NvServices device names */ + constexpr char DbgGpuPath[] = "/dev/nvhost-dbg-gpu"; + constexpr char ProfGpuPath[] = "/dev/nvhost-prof-gpu"; + + /* Permission offset to patch */ + constexpr size_t DevTablePermOffset = 0x68; + + uintptr_t FindBytes(uintptr_t start, uintptr_t end, const void *needle, size_t len) { + const u8 *pat = reinterpret_cast(needle); + for (uintptr_t addr = start; addr + len <= end; ++addr) { + if (std::memcmp(reinterpret_cast(addr), pat, len) == 0) { + return addr; + } + } + return 0; + } + + /* Unlock the devices */ + Result UnlockDevicePermission(uintptr_t mapped_nso, size_t nso_size, uintptr_t nso_address, const char *path, [[maybe_unused]] const char *description) { + const size_t path_len = std::strlen(path) + 1; + + const uintptr_t str_addr = FindBytes(mapped_nso, mapped_nso + nso_size, path, path_len); + if (str_addr == 0) { + LOGGING("nvsrv: %s path string not found (nso_size=%lx)", description, static_cast(nso_size)); + R_THROW(ldr::ResultInvalidNvsrvDevTable()); + } + + const uintptr_t str_offset = str_addr - mapped_nso; + const uintptr_t candidates[] = { str_offset, nso_address + str_offset }; + + uintptr_t entry_addr = 0; + for (uintptr_t ptr = mapped_nso; entry_addr == 0 && ptr + sizeof(uintptr_t) <= mapped_nso + nso_size; ptr += sizeof(uintptr_t)) { + const uintptr_t val = *reinterpret_cast(ptr); + for (uintptr_t cand : candidates) { + if (val == cand) { + entry_addr = ptr; + break; + } + } + } + if (entry_addr == 0) { + LOGGING("nvsrv: %s str@+%lx has no referencing table entry", description, + static_cast(str_offset)); + R_THROW(ldr::ResultInvalidNvsrvDevTable()); + } + + const uintptr_t perm_addr = entry_addr + DevTablePermOffset; + if (perm_addr + sizeof(uintptr_t) > mapped_nso + nso_size) { + LOGGING("nvsrv: %s entry@+%lx perm field out of bounds", description, static_cast(entry_addr - mapped_nso)); + R_THROW(ldr::ResultInvalidNvsrvDevTable()); + } + + uintptr_t *perm = reinterpret_cast(perm_addr); + LOGGING("nvsrv: %s entry@+%lx perm@+%lx was %lx", description, + static_cast(entry_addr - mapped_nso), + static_cast(perm_addr - mapped_nso), + static_cast(*perm)); + + PATCH_OFFSET(perm, static_cast(0)); + R_SUCCEED(); + } + + } + + void Patch(uintptr_t mapped_nso, size_t nso_size, uintptr_t nso_address) { + struct { + const char *path; + const char *description; + } targets[] = { + { DbgGpuPath, "dbg-gpu" }, + { ProfGpuPath, "prof-gpu" }, + }; + + for (auto &t : targets) { + [[maybe_unused]] const Result res = UnlockDevicePermission(mapped_nso, nso_size, nso_address, t.path, t.description); + LOGGING("nvsrv: %s unlock%s", t.description, R_SUCCEEDED(res) ? "ed" : " skipped"); + } + } + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/nvsrv/nvsrv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/nvsrv/nvsrv.hpp new file mode 100644 index 00000000..4c551a33 --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/nvsrv/nvsrv.hpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 . + */ + +#pragma once + +#include "../oc_common.hpp" + +namespace ams::ldr::hoc::nvsrv { + void Patch(uintptr_t mapped_nso, size_t nso_size, uintptr_t nso_address); +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp index 9440aaf8..566cf14b 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_common.hpp @@ -31,9 +31,6 @@ #define HOC_UART_LOG 0 #endif -#define HOC_PCV_NVLOG_PATCH 1 -#define HOC_PCV_FORCE_VERBOSITY 1 - #include "customize.hpp" #include "oc_log.hpp" @@ -63,37 +60,45 @@ *(offset) = value; namespace ams::ldr { - R_DEFINE_ERROR_RESULT(OutOfRange, 1000); - R_DEFINE_ERROR_RESULT(InvalidMemPllmEntry, 1001); - R_DEFINE_ERROR_RESULT(InvalidMtcMagic, 1002); - R_DEFINE_ERROR_RESULT(InvalidMtcTable, 1003); - R_DEFINE_ERROR_RESULT(InvalidDvbTable, 1004); - R_DEFINE_ERROR_RESULT(InvalidCpuFreqVddEntry, 1005); - R_DEFINE_ERROR_RESULT(InvalidCpuVoltDfllEntry, 1006); - R_DEFINE_ERROR_RESULT(InvalidCpuDvfs, 1007); - R_DEFINE_ERROR_RESULT(InvalidCpuMinVolt, 1008); - R_DEFINE_ERROR_RESULT(InvalidGpuDvfs, 1009); - R_DEFINE_ERROR_RESULT(InvalidGpuFreqMaxPattern, 1010); - R_DEFINE_ERROR_RESULT(InvalidGpuPllEntry, 1011); - R_DEFINE_ERROR_RESULT(InvalidRegulatorEntry, 1012); - R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1013); - R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014); - R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015); - R_DEFINE_ERROR_RESULT(InvalidMtcTablePattern, 1016); - R_DEFINE_ERROR_RESULT(InvalidSocVoltPattern, 1017); - R_DEFINE_ERROR_RESULT(InvalidSocVoltLimit, 1018); - R_DEFINE_ERROR_RESULT(InvalidEmcDvfsCount, 1019); - R_DEFINE_ERROR_RESULT(InvalidEmcSocLut, 1020); - R_DEFINE_ERROR_RESULT(InvalidEmcRateList, 1021); - R_DEFINE_ERROR_RESULT(InvalidNvLogRedirect, 1022); - R_DEFINE_ERROR_RESULT(InvalidBusFreqReloc, 1023); - R_DEFINE_ERROR_RESULT(HookArenaOutOfMemory, 1024); - R_DEFINE_ERROR_RESULT(HookPayloadTooLarge, 1025); - R_DEFINE_ERROR_RESULT(HookRelocationUnsupported, 1026); - R_DEFINE_ERROR_RESULT(HookSiteInvalid, 1027); - R_DEFINE_ERROR_RESULT(HookPayloadEscapes, 1028); - R_DEFINE_ERROR_RESULT(HookDataOutOfMemory, 1029); - R_DEFINE_ERROR_RESULT(HookUnavailable, 1030); + R_DEFINE_ERROR_RESULT(OutOfRange, 1000); + R_DEFINE_ERROR_RESULT(InvalidMemPllmEntry, 1001); + R_DEFINE_ERROR_RESULT(InvalidMtcMagic, 1002); + R_DEFINE_ERROR_RESULT(InvalidMtcTable, 1003); + R_DEFINE_ERROR_RESULT(InvalidDvbTable, 1004); + R_DEFINE_ERROR_RESULT(InvalidCpuFreqVddEntry, 1005); + R_DEFINE_ERROR_RESULT(InvalidCpuVoltDfllEntry, 1006); + R_DEFINE_ERROR_RESULT(InvalidCpuDvfs, 1007); + R_DEFINE_ERROR_RESULT(InvalidCpuMinVolt, 1008); + R_DEFINE_ERROR_RESULT(InvalidGpuDvfs, 1009); + R_DEFINE_ERROR_RESULT(InvalidGpuFreqMaxPattern, 1010); + R_DEFINE_ERROR_RESULT(InvalidGpuPllEntry, 1011); + R_DEFINE_ERROR_RESULT(InvalidRegulatorEntry, 1012); + R_DEFINE_ERROR_RESULT(UninitializedPatcher, 1013); + R_DEFINE_ERROR_RESULT(UnsuccessfulPatcher, 1014); + R_DEFINE_ERROR_RESULT(SafetyCheckFailure, 1015); + R_DEFINE_ERROR_RESULT(InvalidMtcTablePattern, 1016); + R_DEFINE_ERROR_RESULT(InvalidSocVoltPattern, 1017); + R_DEFINE_ERROR_RESULT(InvalidSocVoltLimit, 1018); + R_DEFINE_ERROR_RESULT(InvalidEmcDvfsCount, 1019); + R_DEFINE_ERROR_RESULT(InvalidEmcSocLut, 1020); + R_DEFINE_ERROR_RESULT(InvalidEmcRateList, 1021); + R_DEFINE_ERROR_RESULT(InvalidNvLogRedirect, 1022); + R_DEFINE_ERROR_RESULT(InvalidBusFreqReloc, 1023); + R_DEFINE_ERROR_RESULT(HookArenaOutOfMemory, 1024); + R_DEFINE_ERROR_RESULT(HookPayloadTooLarge, 1025); + R_DEFINE_ERROR_RESULT(HookRelocationUnsupported, 1026); + R_DEFINE_ERROR_RESULT(HookSiteInvalid, 1027); + R_DEFINE_ERROR_RESULT(HookPayloadEscapes, 1028); + R_DEFINE_ERROR_RESULT(HookDataOutOfMemory, 1029); + R_DEFINE_ERROR_RESULT(HookUnavailable, 1030); + R_DEFINE_ERROR_RESULT(InvalidNvsrvDevTable, 1031); + R_DEFINE_ERROR_RESULT(InvalidForceVerbosityPattern, 1032); + R_DEFINE_ERROR_RESULT(InvalidCpuLutMaxAsmPattern, 1033); + R_DEFINE_ERROR_RESULT(InvalidCpuLutHook, 1034); + R_DEFINE_ERROR_RESULT(InvalidDvcoRateConfig, 1035); + R_DEFINE_ERROR_RESULT(InvalidVoltCode, 1036); + R_DEFINE_ERROR_RESULT(InvalidVoltLutIndex, 1037); + R_DEFINE_ERROR_RESULT(InvalidHookCave, 1038); } namespace ams::ldr::hoc { diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp index 4396226a..717f95bb 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_loader.hpp @@ -21,3 +21,4 @@ #include "oc_common.hpp" #include "pcv/pcv.hpp" #include "ptm/ptm.hpp" +#include "nvsrv/nvsrv.hpp" \ No newline at end of file diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_log.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_log.cpp index 6fccc8e4..1335f1a6 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_log.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_log.cpp @@ -155,4 +155,63 @@ namespace ams::ldr::hoc { while(true) { } #endif } + + namespace { + constexpr size_t SdLogBufferSize = 0x1000; + char sdLogBuffer[SdLogBufferSize]; + size_t workingLength = 0; + } + + void SdLog(const char *data, ...) { + if (workingLength >= SdLogBufferSize - 1) { + return; + } + + va_list args; + va_start(args, data); + s32 res = vsnprintf(sdLogBuffer + workingLength, SdLogBufferSize - workingLength, data, args); + va_end(args); + + if (res < 0) { + return; + } + + workingLength = std::min(workingLength + static_cast(res), SdLogBufferSize - 1); + } + + void SaveLog() { + static bool saved = false; + if (workingLength == 0 || saved) { + return; + } + + if (!cfg::IsSdCardInitialized()) { + return; + } + + if (R_FAILED(fs::MountSdCard("sdmc"))) { + return; + } + + ON_SCOPE_EXIT { fs::Unmount("sdmc"); }; + + constexpr const char *Path = "sdmc:/config/horizon-oc/ldr_log.txt"; + + R_DISCARD(fs::DeleteFile(Path)); + if (R_FAILED(fs::CreateFile(Path, workingLength))) { + return; + } + + fs::FileHandle file; + if (R_FAILED(fs::OpenFile(std::addressof(file), Path, fs::OpenMode_Write))) { + return; + } + ON_SCOPE_EXIT { fs::CloseFile(file); }; + + if (R_FAILED(fs::WriteFile(file, 0, sdLogBuffer, workingLength, fs::WriteOption::Flush))) { + return; + } + saved = true; + } + } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/oc_log.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/oc_log.hpp index 6522ee13..8a1ed243 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/oc_log.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/oc_log.hpp @@ -23,6 +23,8 @@ namespace ams::ldr::hoc { Result SmcCopyToIram(uintptr_t dest, const void *src, u32 size); void Log(const char *data, ...); + void SdLog(const char *data, ...); + void SaveLog(); void ViewLog(); /* Emit a formatted line over the kernel debug UART via svcOutputDebugString. diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/common/calculate_timings_common.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/common/calculate_timings_common.cpp new file mode 100644 index 00000000..e55a0520 --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/common/calculate_timings_common.cpp @@ -0,0 +1,185 @@ +/* + * 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 . + */ + +#include "../../oc_common.hpp" +#include "../../mtc_timing_value.hpp" + +namespace ams::ldr::hoc::pcv { + + namespace { + void SwitchLatency(volatile u32 &latency, u32 index, u32 latencyStep) { + latency += index * latencyStep; + } + + void AutoLatency(volatile u32 &latency, u32 freq, u32 latencyStep) { + if (freq > 1600'000 && freq <= 1866'000) { /* 1866tRWL */ + latency += latencyStep * 2; + } else { /* 2133tRWL */ + latency += latencyStep * 3; + } + } + + static s32 GetMaxLatencyIndex(volatile u32 *latencyArray, u32 latencySize) { + s32 maxIndex = -1; + for (u32 i = 0; i < latencySize; ++i) { + if (latencyArray[i]) { + maxIndex = i; + } + } + + return maxIndex; + } + + void HandleLatency(u32 freq, volatile u32 &latency, volatile u32 *latencyArray, u32 indexMax, u32 latencyStep) { + for (u32 i = 0; i <= indexMax; ++i) { + if (latencyArray[i] != 0 && freq <= latencyArray[i]) { + SwitchLatency(latency, i, latencyStep); + return; + } + } + + SwitchLatency(latency, indexMax, latencyStep); + } + + u32 RoundUpToEven(u32 value) { + return value + (value % 2); + } + + double GetTckAvg(u32 khz) { + return 1000'000.0 / static_cast(khz); + } + } + + void HandleLatency(u32 freq) { + static s32 rlIndexMax = GetMaxLatencyIndex(C.readLatency, std::size(C.readLatency)); + static s32 wlIndexMax = GetMaxLatencyIndex(C.writeLatency, std::size(C.writeLatency)); + constexpr u32 ReadLatencyStep = 4; + constexpr u32 WriteLatencyStep = 2; + bool autoLatencyRead = false, autoLatencyWrite = false; + + if (rlIndexMax == -1) { + AutoLatency(RL, freq, ReadLatencyStep); + autoLatencyRead = true; + } + + if (wlIndexMax == -1) { + AutoLatency(WL, freq, WriteLatencyStep); + autoLatencyWrite = true; + } + + if (autoLatencyRead && autoLatencyWrite) { + return; + } + + if (!autoLatencyRead) { + HandleLatency(freq, RL, C.readLatency, rlIndexMax, ReadLatencyStep); + } + + if (!autoLatencyWrite) { + HandleLatency(freq, WL, C.writeLatency, wlIndexMax, WriteLatencyStep); + } + } + + u32 GetRlFrequency() { + switch (RL) { + case RL_1333: + return 1333'000; + case RL_1600: + return 1600'000; + case RL_1866: + return 1866'000; + case RL_2133: + return 2133'000; + default: + return 2133'000; + } + } + + u32 GetWlFrequency() { + switch (WL) { + case WL_1333: + return 1333'000; + case WL_1600: + return 1600'000; + case WL_1866: + return 1866'000; + case WL_2133: + return 2133'000; + default: + return 2133'000; + } + } + + u32 GetOdtLon() { + /* Set A. */ + switch (WL) { + case WL_1333: + return 4; + case WL_1600: + case WL_1866: + return 6; + case WL_2133: + return 8; + default: + return 8; + } + } + + u32 CalculateNWr() { + const u32 latencyFrequency = GetWlFrequency(); + const double tCK = GetTckAvg(latencyFrequency); + const u32 nWr = CEIL(tWR / tCK); + + return RoundUpToEven(nWr); + } + + u32 CalculateNTRTP() { + const u32 latencyFrequency = GetRlFrequency(); + const double tCK = GetTckAvg(latencyFrequency); + + return CEIL(tRTP / tCK); + } + + u8 CalculateMrw2() { + static const u8 rlMapDBI[8] = { + 6, 12, 16, 22, 28, 32, 36, 40 + }; + + static const u8 wlMapSetA[8] = { + 4, 6, 8, 10, 12, 14, 16, 18 + }; + + u32 rlIndex = 0; + u32 wlIndex = 0; + + for (u32 i = 0; i < std::size(rlMapDBI); ++i) { + if (rlMapDBI[i] == RL) { + rlIndex = i; + break; + } + } + + for (u32 i = 0; i < std::size(wlMapSetA); ++i) { + if (wlMapSetA[i] == WL) { + wlIndex = i; + break; + } + } + + /* DBI is always enabled. */ + return static_cast(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6))); + } +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/timing_tables.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/common/calculate_timings_common.hpp similarity index 74% rename from Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/timing_tables.hpp rename to Source/Atmosphere/stratosphere/loader/source/oc/pcv/common/calculate_timings_common.hpp index d682000e..76bda88e 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/timing_tables.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/common/calculate_timings_common.hpp @@ -15,17 +15,20 @@ */ #pragma once -#include -namespace ams::ldr::hoc::pcv::mariko { +namespace ams::ldr::hoc::pcv { - struct ReplacePatch { + struct RextPatch { u32 freq; u32 rext; }; - extern const ReplacePatch g_rext_table[]; - extern const u32 g_rext_table_size; - const ReplacePatch *FindRext(); + void HandleLatency(u32 freq); + u32 GetRlFrequency(); + u32 GetWlFrequency(); + u32 GetOdtLon(); + u32 CalculateNWr(); + u32 CalculateNTRTP(); + u8 CalculateMrw2(); } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/calculate_timings_erista.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/calculate_timings_erista.cpp index fc6ae8f8..e10a5fea 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/calculate_timings_erista.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/calculate_timings_erista.cpp @@ -15,130 +15,172 @@ */ #include "../../mtc_timing_value.hpp" +#include "../common/calculate_timings_common.hpp" namespace ams::ldr::hoc::pcv::erista { - void SwitchLatency(volatile u32 &latency, u32 index, u32 latencyStep) { - latency += index * latencyStep; - } + namespace { + /* Dumped from bpmp fw mtc table (l4t). */ + const RextPatch gRextTable[] = { + {1'633'000, 0x17}, {1'728'000, 0x17}, {1'795'200, 0x19}, + {1'862'400, 0x1A}, {1'894'400, 0x1A}, {1'932'800, 0x1A}, + {1'958'400, 0x1A}, {1'996'800, 0x1A}, {2'035'200, 0x1A}, + {2'064'000, 0x19}, {2'099'200, 0x19}, {2'131'200, 0x1A}, + {2'163'200, 0x1A}, {2'188'800, 0x1A}, {2'227'200, 0x1A}, + {2'265'600, 0x1B}, {2'291'200, 0x1B}, {2'329'600, 0x1A}, + {2'361'600, 0x1A}, + }; - static s32 GetMaxLatencyIndex(volatile u32 *latencyArray, u32 latencySize) { - s32 maxIndex = -1; - for (u32 i = 0; i < latencySize; ++i) { - if (latencyArray[i]) { - maxIndex = i; + const RextPatch *LookupRext(u32 freq) { + for (u32 i = 0; i < std::size(gRextTable); i++) { + if (gRextTable[i].freq >= freq) { + return &gRextTable[i]; + } } + return nullptr; } - return maxIndex; - } - - void AutoLatency(volatile u32 &latency, u32 freq, u32 latencyStep) { - if (freq > 1600'000 && freq <= 1866'000) { /* 1866tRWL */ - latency += latencyStep * 2; - } else { /* 2133tRWL */ - latency += latencyStep * 3; - } - } - - void HandleLatency(u32 freq, volatile u32 &latency, volatile u32 *latencyArray, u32 indexMax, u32 latencyStep) { - for (u32 i = 0; i <= indexMax; ++i) { - if (latencyArray[i] != 0 && freq <= latencyArray[i]) { - SwitchLatency(latency, i, latencyStep); + void GetRext(u32 freq) { + if (auto r = LookupRext(freq)) { + rext = r->rext; return; } + + /* Fallback */ + rext = 0x1A; } - SwitchLatency(latency, indexMax, latencyStep); - } + void CalculateReadTimings(u32 freq, double tCK_avg) { + tR2P = CalculateNTRTP(); - void HandleLatency(u32 freq) { - static s32 rlIndexMax = GetMaxLatencyIndex(C.readLatency, std::size(C.readLatency)); - static s32 wlIndexMax = GetMaxLatencyIndex(C.writeLatency, std::size(C.writeLatency)); - constexpr u32 ReadLatencyStep = 4; - constexpr u32 WriteLatencyStep = 2; - bool autoLatencyRead = false, autoLatencyWrite = false; + double fullRoundDelay = flyByTime + tDQSCK_max; - if (rlIndexMax == -1) { - AutoLatency(RL, freq, ReadLatencyStep); - autoLatencyRead = true; + /* Read to write turnaround. */ + /* Switch seemingly uses odt. */ + tR2W = RL + (BL / 2) + CEIL((fullRoundDelay / tCK_avg) + tDQSTA) - GET_CYCLE_FLOOR(tODTon) - GetOdtLon() + tWPRE - (C.t6_tRTW * 3) + finetRTW; + + /* Read data valid: Read command -> data ready to be latched into the registers. */ + rdv = RL + GET_CYCLE_CEIL(fullRoundDelay) + 18; + + /* Read command -> data poppable at the pad macros, 16 cycles ahead of rdv. */ + qpop = rdv - 16; + + constexpr double TrimmerStepPs = 3.0; + constexpr double MaxTrimmerSteps = 95.0; + + double tCkAvgPs = tCK_avg * 1000.0; + double tckDerated = tCkAvgPs * 0.85; + u32 derateStepCount = MIN(FLOOR(tckDerated / TrimmerStepPs), MaxTrimmerSteps); + double deratedNsDelay = (derateStepCount * TrimmerStepPs) / 1000.0; + + /* readEyeEndDerated, nv call this quseExtra. */ + u32 quseExtra = GET_CYCLE_CEIL(fullRoundDelay - deratedNsDelay); + + /* The amount of deration from the perspective of a full round trip. */ + u32 readEyeEndDerateMargin = GET_CYCLE_CEIL(fullRoundDelay) - quseExtra; + + u32 tQuse = FLOOR((flyByTime + 0.94) / tCK_avg); + u32 readEyeStart = tQuse + RL + 1; + + u32 einputMinimal = readEyeStart + readEyeEndDerateMargin - 2; + + /* Data valid window, quse aligns with the start of the read eye (probably). */ + /* DQS needs to be logically and'ed with quse in order to be valid. */ + /* einputMinimal satisfies this. */ + quse = einputMinimal; + + /* Difference between the two eye edges. */ + quse_width = quseExtra - tQuse + 4; + + /* input receiver takes time to enable. */ + u32 einputLatency = GET_CYCLE_CEIL(10.0); + + /* Enable input receiver. */ + einput = einputMinimal - einputLatency; + + /* Duration of input receiver being enabled? */ + einput_duration = einputLatency + quse_width + 4; + + /* qrst_duration is CEIL(a / tCK_avg + b) */ + /* a and b were derived through a brute forcer. */ + u32 qrst_duration = CEIL(1.4 / tCK_avg + 3.5); + u32 qrstLow = MAX(static_cast(einput - qrst_duration - 2), static_cast(0)); + + /* quse reset? */ + qrst = PACK_U32(qrst_duration, qrstLow); + + /* Qsafe, safe to reset quse? */ + qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput); + + /* Input buffer delay? */ + ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0); + + GetRext(freq); } - if (wlIndexMax == -1) { - AutoLatency(WL, freq, WriteLatencyStep); - autoLatencyWrite = true; + void CalculateWriteTimings(double tCK_avg) { + /* Write to read turnaround. */ + /* According to jedec specifications: nWR >= tWTR + nRTP */ + /* Therefore tWTR >= nWR - tRTP. */ + const u32 nTWTR = GET_CYCLE_CEIL(tWTRStock); + const u32 nWr = CalculateNWr(); + u32 autoPrecharcetWTRMin = nWr - tR2P; + + /* tWTR reduction is applied in a weird way to not break existing setups. */ + tW2R = WL + 1 + MAX(autoPrecharcetWTRMin, nTWTR) - GET_CYCLE_CEIL(tWTR) + finetWTR; + tW2P = (CEIL(WL * 1.7303) * 2) - 5; + tWTPDEN = CEIL(((1.8 / tCK_avg) + MAX(RL + (2.7 / tCK_avg), static_cast(tW2P))) + (BL / 2)); + + wdv = WL; + wsv = WL - 2; + wev = WL - 4; + + /* Output buffer delay? */ + u32 obdlyHigh = 3 / FLOOR(MIN(static_cast(2), tCK_avg * (WL - 7))); + u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0); + obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow); } - if (autoLatencyRead && autoLatencyWrite) { - return; - } + void CalculatePowerDownTimings(double tCK_avg) { + 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; - if (!autoLatencyRead) { - HandleLatency(freq, RL, C.readLatency, rlIndexMax, ReadLatencyStep); - } - - if (!autoLatencyWrite) { - HandleLatency(freq, WL, C.writeLatency, wlIndexMax, WriteLatencyStep); + const double tMMRI = tRCD + (tCK_avg * 3); + pdex2mrr = tMMRI + 10; } } - void CalculateMrw2() { - static const u8 rlMapDBI[8] = { - 6, 12, 16, 22, 28, 32, 36, 40 + u8 GetNWrIndex() { + static const u8 nWrMap[8] = { + 6, 10, 16, 20, 24, 30, 34, 40 }; - static const u8 wlMapSetA[8] = { - 4, 6, 8, 10, 12, 14, 16, 18 - }; + const u32 nWr = CalculateNWr(); - u32 rlIndex = 0; - u32 wlIndex = 0; - - for (u32 i = 0; i < std::size(rlMapDBI); ++i) { - if (rlMapDBI[i] == 32) { - rlIndex = i; - break; + for (u8 i = 0; i < std::size(nWrMap); ++i) { + if (nWrMap[i] >= nWr) { + return i; } } - for (u32 i = 0; i < std::size(wlMapSetA); ++i) { - if (wlMapSetA[i] == WL) { - wlIndex = i; - break; - } - } - - /* DBI is always enabled. */ - mrw2 = static_cast(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6))); + return static_cast(std::size(nWrMap) - 1); } void CalculateTimings(double tCK_avg, u32 freq) { - RL = RL_1331; - WL = WL_1331; + RL = RL_1333; + WL = WL_1333; + /* I don't understand why, I don't want to know why, but for some fucking reason erista doesn't handle RL 40. */ + /* This should not be required but for these fuck damn reasons any type of dram oc will crash instantly with RL 40. */ + /* But it works fine in l4t? Even when copying the tables it still doesn't work??? WTF */ + C.readLatency[std::size(C.readLatency) - 1] = 0; HandleLatency(freq); - CalculateMrw2(); + RL = std::min(static_cast(RL_1866), RL); - tR2P = CEIL((RL * 0.426) - 2.0); - tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW; - - tW2P = (CEIL(WL * 1.7303) * 2) - 5; - tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast(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; - - wdv = WL; - wsv = WL - 2; - wev = 0xA + (WL - 14); - - u32 obdlyHigh = 3 / FLOOR(MIN(static_cast(2), tCK_avg * (WL - 7))); - u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0); - obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow); - - 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; + CalculateReadTimings(freq, tCK_avg); + CalculateWriteTimings(tCK_avg); + CalculatePowerDownTimings(tCK_avg); + mrw2 = CalculateMrw2(); } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/calculate_timings_erista.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/calculate_timings_erista.hpp index 7a61386d..668f44fc 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/calculate_timings_erista.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/calculate_timings_erista.hpp @@ -18,6 +18,7 @@ namespace ams::ldr::hoc::pcv::erista { + u8 GetNWrIndex(); void CalculateTimings(double tCK_avg, u32 freq); } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_gpu.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_gpu.cpp index 937af7d7..bb17e547 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_gpu.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_gpu.cpp @@ -56,13 +56,13 @@ namespace ams::ldr::hoc::pcv::erista { Result GpuFreqMaxAsm(u32 *ptr32) { // Check if both two instructions match the pattern u32 ins1 = *ptr32, ins2 = *(ptr32 + 1); - if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1]))) { + if (!(_asm::Ignoring(ins1, GpuAsmPattern[0], _asm::field::Rd) && _asm::Ignoring(ins2, GpuAsmPattern[1], _asm::field::Rd))) { R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); } // Both instructions should operate on the same register - u8 rd = asm_get_rd(ins1); - if (rd != asm_get_rd(ins2)) { + u8 rd = _asm::Get(ins1, _asm::field::Rd); + if (rd != _asm::Get(ins2, _asm::field::Rd)) { R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); } @@ -83,8 +83,8 @@ namespace ams::ldr::hoc::pcv::erista { } u32 asm_patch[2] = { - asm_set_rd(asm_set_imm16(GpuAsmPattern[0], max_clock), rd), - asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd) + _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, rd}, {_asm::field::Imm16, max_clock}), + _asm::Encode(_asm::op::MovkW, {_asm::field::Rd, rd}, {_asm::field::Imm16, max_clock >> 16}, {_asm::field::Hw, 1}) }; PATCH_OFFSET(ptr32, asm_patch[0]); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_gpu.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_gpu.hpp index cc964628..9decf0db 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_gpu.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_gpu.hpp @@ -51,7 +51,7 @@ namespace ams::ldr::hoc::pcv::erista { inline constexpr u32 GpuAsmPattern[] = { 0x52820000, 0x72A001C0 }; inline bool GpuMaxClockPatternFn(u32 *ptr32) { - return asm_compare_no_rd(*ptr32, GpuAsmPattern[0]); + return _asm::Ignoring(*ptr32, GpuAsmPattern[0], _asm::field::Rd); }; constexpr cvb_entry_t GpuCvbTableDefault[] = { diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_mtc.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_mtc.cpp index 6b2d4321..12dd90a3 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_mtc.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_mtc.cpp @@ -46,10 +46,9 @@ namespace ams::ldr::hoc::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_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) - /* Ram power down */ /* B31: DRAM_CLKSTOP_PD */ /* B30: DRAM_CLKSTOP_SR */ @@ -66,14 +65,6 @@ namespace ams::ldr::hoc::pcv::erista { refresh_raw = MIN(refresh_raw, static_cast(0xFFFF)); } - if (table->rate_khz > 3200000) { - rext = 30; - } else if (table->rate_khz >= 2133001) { - rext = 28; - } else { - rext = 26; - } - u32 trefbw = refresh_raw + 0x40; trefbw = MIN(trefbw, static_cast(0x3FFF)); @@ -112,37 +103,37 @@ namespace ams::ldr::hoc::pcv::erista { 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_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(1.75)); WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(8.499)); WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(pdex2mrr)); WRITE_PARAM_ALL_REG(table, emc_rw2pden, tWTPDEN); /* Accept imperfection or prepare for suffering. */ // #if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING) - // WRITE_PARAM_ALL_REG(table, emc_einput, einput); - // WRITE_PARAM_ALL_REG(table, emc_einput_duration, einput_duration); + 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_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); + 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); table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast(mrw2); - // table->dram_timings.rl = RL; + table->dram_timings.rl = RL; // #endif constexpr double MC_ARB_DIV = 4.0; @@ -233,8 +224,7 @@ namespace ams::ldr::hoc::pcv::erista { const u32 tRFCabStock = tRFC_values[0] * 2; table->dram_timings.t_rfc = tRFCabStock; - table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast(mrw2); - table->emc_mrw = (table->emc_mrw & ~0x70u) | 0x40; /* nWR */ + table->emc_mrw = (table->emc_mrw & ~0x70u) | (GetNWrIndex() << 4); table->emc_cfg_2 = 0x11083D; table->min_volt = std::clamp(900 + (C.emcDvbShift * 25), 900, 1050); } @@ -447,27 +437,28 @@ namespace ams::ldr::hoc::pcv::erista { R_UNLESS(ptr - MovOffset >= nsoStart, ldr::ResultInvalidMtcTablePattern()); u32 adrp = *(ptr - AddrpOffset); - R_UNLESS(AsmCompareAdrpNoImm(adrp, MtcAdrpAsm), ldr::ResultInvalidMtcTablePattern()); + R_UNLESS(_asm::Ignoring(adrp, MtcAdrpAsm, _asm::field::ImmAdrpHi, _asm::field::ImmAdrpLo), ldr::ResultInvalidMtcTablePattern()); - /* Check for the branch instruction above the cbz to ensure we are patching the right location*/ + /* Check for the branch instruction above the cbz to ensure we are patching the right location. */ + /* Only the opcode is checked; the call target varies by firmware (0x97ffae64 on one build). */ u32 bl = *(ptr - BlOffset); - R_UNLESS(AsmBlCompareOpcodeOnly(bl, MtcBlIns), ldr::ResultInvalidMtcTablePattern()); + R_UNLESS(_asm::IsOp(bl, _asm::op::Bl, _asm::field::Imm26), ldr::ResultInvalidMtcTablePattern()); /* Check for the mov that actually sets the mtc table count. */ u32 mov = *(ptr - MovOffset); bool foundMov = false; - foundMov = asm_compare_no_rd(mov, MtcMovAsm); + foundMov = _asm::Ignoring(mov, MtcMovAsm, _asm::field::Rd); if (!foundMov) { mov = *(ptr + MovOffsetOld); /* Check old firmware offset. */ - foundMov = asm_compare_no_rd(mov, MtcMovAsm); + foundMov = _asm::Ignoring(mov, MtcMovAsm, _asm::field::Rd); } R_UNLESS(foundMov, ldr::ResultInvalidMtcTablePattern()); constexpr u32 PrologueWindow = 140; - u32 *functionPrologue = FindFnPrologue(ptr, PrologueWindow, nsoStart); + u32 *functionPrologue = _asm::FindFnPrologue(ptr, PrologueWindow, nsoStart); R_UNLESS(functionPrologue != nullptr, ldr::ResultInvalidMtcTablePattern()); getMtcTableCache.getEristaMtcTableFnSite = functionPrologue; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_mtc.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_mtc.hpp index 5c1c5100..fa2a2bba 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_mtc.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/erista/pcv_erista_mtc.hpp @@ -73,12 +73,11 @@ namespace ams::ldr::hoc::pcv::erista { constexpr u32 MtcBrAsm = 0xD61F0140; constexpr u32 MtcMovAsm = 0x52800148; constexpr u32 MtcAdrpAsm = 0xD0000081; - constexpr u32 MtcBlIns = 0x97ffae64; constexpr u32 MtcAddAsm = 0x91131821; ALWAYS_INLINE bool MemMtcGetGetTablePatternFn(u32 *ptr) { /* This builds an address that gets returned, so the register must be x0 by convention. */ - return AsmCompareAddNoImm12(*ptr, MtcAddAsm); + return _asm::Ignoring(*ptr, MtcAddAsm, _asm::field::Imm12); } Result MemFreqMtcTable(u32 *ptr); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/calculate_timings_mariko.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/calculate_timings_mariko.cpp index fab24dbf..4b433ce7 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/calculate_timings_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/calculate_timings_mariko.cpp @@ -14,191 +14,207 @@ * along with this program. If not, see . */ -#include #include "../../mtc_timing_value.hpp" -#include "timing_tables.hpp" +#include "../common/calculate_timings_common.hpp" namespace ams::ldr::hoc::pcv::mariko { - void GetRext() { - if (auto r = FindRext()) { - rext = r->rext; - return; - } + namespace { + const RextPatch gRextTable[] = { + {1'633'000, 0x17}, {1'666'000, 0x18}, {1'700'000, 0x18}, + {1'733'000, 0x18}, {1'766'000, 0x18}, {1'800'000, 0x1A}, + {1'833'000, 0x1A}, {1'866'000, 0x1A}, {1'900'000, 0x19}, + {1'933'000, 0x19}, {1'966'000, 0x19}, {2'100'000, 0x1A}, + {2'133'000, 0x1A}, {2'166'000, 0x19}, {2'200'000, 0x19}, + {2'233'000, 0x19}, {2'266'000, 0x1A}, {2'300'000, 0x1B}, + {2'333'000, 0x1B}, {2'366'000, 0x1B}, {2'400'000, 0x1B}, + {2'433'000, 0x1B}, {2'466'000, 0x1B}, {2'500'000, 0x1A}, + {2'533'000, 0x1C}, {2'566'000, 0x1B}, {2'600'000, 0x1B}, + {2'633'000, 0x1B}, {2'666'000, 0x1B}, {2'700'000, 0x1C}, + {2'733'000, 0x1C}, {2'766'000, 0x1D}, {2'800'000, 0x1D}, + {2'833'000, 0x1D}, {2'866'000, 0x1D}, {2'900'000, 0x1D}, + {2'933'000, 0x1C}, {2'966'000, 0x1D}, {3'000'000, 0x1D}, + {3'033'000, 0x1D}, {3'066'000, 0x1D}, {3'100'000, 0x1D}, + {3'133'000, 0x1D}, {3'166'000, 0x1C}, {3'200'000, 0x1C}, + {3'233'000, 0x1E}, {3'266'000, 0x1F}, {3'300'000, 0x1E}, + {3'333'000, 0x1F}, {3'366'000, 0x1F}, {3'400'000, 0x1F}, + {3'433'000, 0x1F}, {3'466'000, 0x1F}, {3'500'000, 0x1E}, + {3'533'000, 0x1E}, {3'566'000, 0x1E}, {3'600'000, 0x1E}, + {3'633'000, 0x1E}, {3'666'000, 0x1E}, {3'700'000, 0x1F}, + }; - /* > 3200 */ - rext = 0x1E; - } - - void SwitchLatency(volatile u32 &latency, u32 index, u32 latencyStep) { - latency += index * latencyStep; - } - - static s32 GetMaxLatencyIndex(volatile u32 *latencyArray, u32 latencySize) { - s32 maxIndex = -1; - for (u32 i = 0; i < latencySize; ++i) { - if (latencyArray[i]) { - maxIndex = i; + const RextPatch *LookupRext(u32 freq) { + for (u32 i = 0; i < std::size(gRextTable); i++) { + if (gRextTable[i].freq >= freq) { + return &gRextTable[i]; + } } + return nullptr; } - return maxIndex; - } - - void AutoLatency(volatile u32 &latency, u32 freq, u32 latencyStep) { - if (freq > 1600'000 && freq <= 1862'400) { /* 1866tRWL */ - latency += latencyStep * 2; - } else { /* 2133tRWL */ - latency += latencyStep * 3; - } - } - - void HandleLatency(u32 freq, volatile u32 &latency, volatile u32 *latencyArray, u32 indexMax, u32 latencyStep) { - for (u32 i = 0; i <= indexMax; ++i) { - if (latencyArray[i] != 0 && freq <= latencyArray[i]) { - SwitchLatency(latency, i, latencyStep); + void GetRext(u32 freq) { + if (auto r = LookupRext(freq)) { + rext = r->rext; return; } + + /* Fallback */ + rext = 0x1E; } - SwitchLatency(latency, indexMax, latencyStep); - } + void CalculateActivatePrechargeTimings(bool lowFreq) { + tRCD = tRCD_values[lowFreq ? C.low_t1_tRCD : C.t1_tRCD]; + tRPpb = tRP_values[lowFreq ? C.low_t2_tRP : C.t2_tRP]; + tRAS = tRAS_values[lowFreq ? C.low_t3_tRAS : C.t3_tRAS]; - void HandleLatency(u32 freq) { - static s32 rlIndexMax = GetMaxLatencyIndex(C.readLatency, std::size(C.readLatency)); - static s32 wlIndexMax = GetMaxLatencyIndex(C.writeLatency, std::size(C.writeLatency)); - constexpr u32 ReadLatencyStep = 4; - constexpr u32 WriteLatencyStep = 2; - bool autoLatencyRead = false, autoLatencyWrite = false; - - if (rlIndexMax == -1) { - AutoLatency(RL, freq, ReadLatencyStep); - autoLatencyRead = true; + tRC = tRAS + tRPpb; + tRPab = tRPpb + 3; } - if (wlIndexMax == -1) { - AutoLatency(WL, freq, WriteLatencyStep); - autoLatencyWrite = true; + void CalculateActivateWindowTimings(bool lowFreq) { + tRRD = tRRD_values[lowFreq ? C.low_t4_tRRD : C.t4_tRRD]; + tFAW = static_cast(tRRD * 4.0); } - if (autoLatencyRead && autoLatencyWrite) { - return; + void CalculateReadTimings(u32 freq, double tCK_avg, bool lowFreq) { + u32 tRTW = lowFreq ? C.low_t6_tRTW : C.t6_tRTW; + s32 finetRTW = C.fineTune_t6_tRTW; + + double fullRoundDelay = flyByTime + tDQSCK_max; + + /* Read to precharge delay. */ + tR2P = CalculateNTRTP(); + + /* Read to write turnaround. */ + /* Switch seemingly uses odt. */ + tR2W = RL + (BL / 2) + CEIL((fullRoundDelay / tCK_avg) + tDQSTA) - GET_CYCLE_FLOOR(tODTon) - GetOdtLon() - (tRTW * 3) + finetRTW; + tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + GET_CYCLE_FLOOR(7.489); + tRATM = CEIL((tRTM - 10.0) + (RL * 0.426)); + + /* Read data valid: Read command -> data ready to be latched into the registers. */ + rdv = RL + GET_CYCLE_CEIL(fullRoundDelay) + 16; + + /* Read command -> data poppable at the pad macros, 14 cycles ahead of rdv. */ + qpop = rdv - 14; + + constexpr double TrimmerStepPs = 3.0; + constexpr double MaxTrimmerSteps = 96.0; + + double tCkAvgPs = tCK_avg * 1000.0; + double tckDerated = tCkAvgPs * 0.85; + u32 derateStepCount = MIN(FLOOR(tckDerated / TrimmerStepPs), MaxTrimmerSteps); + double deratedNsDelay = (derateStepCount * TrimmerStepPs) / 1000.0; + /* readEyeEndDerated, nv call this quseExtra. */ + u32 quseExtra = GET_CYCLE_CEIL(fullRoundDelay - deratedNsDelay); + + /* The amount of deration from the perspective of a full round trip. */ + u32 readEyeEndDerateMargin = GET_CYCLE_CEIL(fullRoundDelay) - quseExtra; + + u32 tQuse = FLOOR((flyByTime + 0.94) / tCK_avg); + u32 readEyeStart = tQuse + RL + 1; + + u32 einputMinimal = readEyeStart + readEyeEndDerateMargin - 2; + + /* Data valid window, quse aligns with the start of the read eye (probably). */ + /* DQS needs to be logically and'ed with quse in order to be valid. */ + /* einputMinimal satisfies this. */ + quse = einputMinimal; + + /* input receiver takes time to enable. */ + u32 einputLatency = GET_CYCLE_CEIL(10.0); + + /* Enable input receiver. */ + einput = einputMinimal - einputLatency; + + /* Difference between the two eye edges. */ + quse_width = quseExtra - tQuse + 4; + + /* Duration of input receiver being enabled? */ + einput_duration = einputLatency + quse_width + 4; + + /* qrst_duration is CEIL(a / tCK_avg + b) */ + /* a and b were derived through a brute forcer. */ + u32 qrst_duration = CEIL(1.4 / tCK_avg + 3.5); + u32 qrstLow = MAX(static_cast(einput - qrst_duration - 2), static_cast(0)); + + /* quse reset? */ + qrst = PACK_U32(qrst_duration, qrstLow); + + /* Input buffer delay? */ + ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0); + + /* Qsafe, safe to reset quse? */ + qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput); + + GetRext(freq); } - if (!autoLatencyRead) { - HandleLatency(freq, RL, C.readLatency, rlIndexMax, ReadLatencyStep); + void CalculateWriteTimings(double tCK_avg, bool lowFreq) { + u32 tWTR = 10 - tWTR_values[lowFreq ? C.low_t7_tWTR : C.t7_tWTR]; + s32 finetWTR = C.fineTune_t7_tWTR; + + /* Write to read turnaround. */ + /* According to jedec specifications: nWR >= tWTR + nRTP */ + /* Therefore tWTR >= nWR - tRTP. */ + const u32 nTWTR = GET_CYCLE_CEIL(tWTRStock); + const u32 nWr = CalculateNWr(); + u32 autoPrecharcetWTRMin = nWr - tR2P; + + /* tWTR reduction is applied in a weird way to not break existing setups. */ + tW2R = WL + 1 + MAX(autoPrecharcetWTRMin, nTWTR) - GET_CYCLE_CEIL(tWTR) + finetWTR; + tW2P = (CEIL(WL * 1.7303) * 2) - 5; + tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753)); + tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0; + + wdv = WL; + wsv = WL - 2; + wev = WL - 4; + + /* Output buffer delay? */ + u32 obdlyHigh = 3 / FLOOR(MIN(static_cast(2), tCK_avg * (WL - 7))); + u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0); + obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow); } - if (!autoLatencyWrite) { - HandleLatency(freq, WL, C.writeLatency, wlIndexMax, WriteLatencyStep); - } - } + void CalculateRefreshTimings(double tCK_avg, bool lowFreq) { + tRFCpb = tRFC_values[lowFreq ? C.low_t5_tRFC : C.t5_tRFC]; + tRFCab = tRFCpb * 2; + tXSR = static_cast(tRFCab + 7.5); - void CalculateMrw2() { - static const u8 rlMapDBI[8] = { - 6, 12, 16, 22, 28, 32, 36, 40 - }; - - static const u8 wlMapSetA[8] = { - 4, 6, 8, 10, 12, 14, 16, 18 - }; - - u32 rlIndex = 0; - u32 wlIndex = 0; - - for (u32 i = 0; i < std::size(rlMapDBI); ++i) { - if (rlMapDBI[i] == RL) { - rlIndex = i; - break; + u32 tREFI = lowFreq ? C.low_t8_tREFI : C.t8_tREFI; + refresh_raw = 0xFFFF; + if (tREFI != 6) { + refresh_raw = GET_CYCLE_CEIL(tREFpb_values[tREFI]) - 0x40; + refresh_raw = MIN(refresh_raw, static_cast(0xFFFF)); } } - for (u32 i = 0; i < std::size(wlMapSetA); ++i) { - if (wlMapSetA[i] == WL) { - wlIndex = i; - break; - } - } + void CalculatePowerDownTimings(double tCK_avg) { + tWTPDEN = CEIL(((1.8 / tCK_avg) + MAX(RL + (2.7 / tCK_avg), static_cast(tW2P))) + (BL / 2)); + pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361))); - /* DBI is always enabled. */ - mrw2 = static_cast(((rlIndex & 0x7) | ((wlIndex & 0x7) << 3) | ((0 & 0x1) << 6))); + tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0; + + double tMMRI = tRCD + (tCK_avg * 3); + pdex2mrr = tMMRI + 10; + } } void CalculateTimings(double tCK_avg, u32 freq) { - RL = RL_1331; - WL = WL_1331; + RL = RL_1333; + WL = WL_1333; HandleLatency(freq); - GetRext(); - - /* At 1333WL, for some reason (incorrect ram timing config in mtc table?), tRP causes crashes at high reductions - 2 seems to be the most common limit. */ - /* This is a lazy workaround until I find the issue... */ const bool lowFreq = freq < C.timingEmcTbreak; - tRCD = tRCD_values[lowFreq ? C.low_t1_tRCD : C.t1_tRCD]; - tRPpb = tRP_values[lowFreq ? C.low_t2_tRP : C.t2_tRP]; - tRAS = tRAS_values[lowFreq ? C.low_t3_tRAS : C.t3_tRAS]; - tRRD = tRRD_values[lowFreq ? C.low_t4_tRRD : C.t4_tRRD]; - tRFCpb = tRFC_values[lowFreq ? C.low_t5_tRFC : C.t5_tRFC]; - - u32 tRTW = lowFreq ? C.low_t6_tRTW : C.t6_tRTW; - u32 tWTR = 10 - tWTR_values[lowFreq ? C.low_t7_tWTR : C.t7_tWTR]; - - s32 finetRTW = C.fineTune_t6_tRTW; - s32 finetWTR = C.fineTune_t7_tWTR; - - u32 tREFI = lowFreq ? C.low_t8_tREFI : C.t8_tREFI; - refresh_raw = 0xFFFF; - if (tREFI != 6) { - refresh_raw = CEIL(tREFpb_values[tREFI] / tCK_avg) - 0x40; - refresh_raw = MIN(refresh_raw, static_cast(0xFFFF)); - } - - tRC = tRAS + tRPpb; - tRFCab = tRFCpb * 2; - tXSR = static_cast(tRFCab + 7.5); - tFAW = static_cast(tRRD * 4.0); - tRPab = tRPpb + 3; - - tR2P = CEIL((RL * 0.426) - 2.0); - tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (tRTW * 3) + finetRTW; - tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg); - tRATM = CEIL((tRTM - 10.0) + (RL * 0.426)); - - rdv = RL + FLOOR((5.105 / tCK_avg) + 17.017); - qpop = rdv - 14; - quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782); - quse = FLOOR(RL + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg); - einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width; - einput = quse - CEIL(9.928 / tCK_avg); - u32 qrst_duration = FLOOR(8.399 - tCK_avg); - u32 qrstLow = MAX(static_cast(einput - qrst_duration - 2), static_cast(0)); - qrst = PACK_U32(qrst_duration, qrstLow); - ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0); - qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput); - tW2P = (CEIL(WL * 1.7303) * 2) - 5; - tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast(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; - tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753)); - tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0; - - wdv = WL; - wsv = WL - 2; - wev = 0xA + (WL - 14); - - u32 obdlyHigh = 3 / FLOOR(MIN(static_cast(2), tCK_avg * (WL - 7))); - u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0); - obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow); - - 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; - - u32 tMMRI = tRCD + (tCK_avg * 3); - pdex2mrr = tMMRI + 10; - - CalculateMrw2(); + CalculateActivatePrechargeTimings(lowFreq); + CalculateActivateWindowTimings(lowFreq); + CalculateReadTimings(freq, tCK_avg, lowFreq); + CalculateWriteTimings(tCK_avg, lowFreq); + CalculateRefreshTimings(tCK_avg, lowFreq); + CalculatePowerDownTimings(tCK_avg); + mrw2 = CalculateMrw2(); } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/calculate_timings_mariko.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/calculate_timings_mariko.hpp index 8659d3f2..c908a220 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/calculate_timings_mariko.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/calculate_timings_mariko.hpp @@ -21,4 +21,3 @@ namespace ams::ldr::hoc::pcv::mariko { void CalculateTimings(double tCK_avg, u32 freq); } - diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko.cpp index c2644620..253e0707 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko.cpp @@ -5,7 +5,7 @@ * * Copyright (c) B3711 * - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -27,506 +27,42 @@ #include "pcv_mariko_cpu.hpp" #include "pcv_mariko_gpu.hpp" #include "pcv_mariko_mtc.hpp" +#include "pcv_mariko_soc.hpp" +#include "pcv_mariko_log.hpp" +#include "pcv_mariko_cave.hpp" #include "calculate_timings_mariko.hpp" namespace ams::ldr::hoc::pcv::mariko { u32 *nsoStart; + size_t g_nso_size = 0; - namespace { - size_t g_nso_size = 0; - uintptr_t g_cave_cursor = 0; - } + DEFINE_HOOK_PAYLOAD_PTR(HookPayloadData, m_HookPayloadData); - static uintptr_t CaveReserve(size_t count) { - if (g_pcv_cave == 0 || g_cave_cursor == 0) { - return 0; - } - if (g_cave_cursor + count * sizeof(u32) > g_pcv_cave + g_pcv_cave_size) { - return 0; - } - const uintptr_t entry = g_cave_cursor; - g_cave_cursor += count * sizeof(u32); - return entry; - } + Result InstallHooks() { + R_TRY(CaveInstall()); - #if HOC_UART_LOG - /* Redirect pcv's NvLog() calls to UART */ - Result NvLogUartRedirect(u32 *ptr) { - const uintptr_t mapped_nso = reinterpret_cast(nsoStart); - const size_t nso_size = g_nso_size; - const uintptr_t textEnd = g_pcv_cave; /* .text ends where the cave begins */ - const uintptr_t vsnprintf_addr = reinterpret_cast(ptr); + R_TRY(Hooks().CheckEnabled()); - /* NvLog via the VDD_SOC log */ - static const char Fmt[] = "%s(%s): DVFS request VDD_SOC %d mV\n"; - constexpr size_t FmtLen = sizeof(Fmt) - 1; - uintptr_t strAddr = 0; - { - const char *hay = reinterpret_cast(mapped_nso); - for (size_t i = 0; i + FmtLen <= nso_size; ++i) { - if (std::memcmp(hay + i, Fmt, FmtLen) == 0) { strAddr = mapped_nso + i; break; } - } - } - if (strAddr == 0) { - LOGGING("NvLogRedirect: fmt string not found (vsnprintf@+%lx)", vsnprintf_addr - mapped_nso); - R_THROW(ldr::ResultInvalidNvLogRedirect()); - } + R_TRY(Hooks().CopyPayload()); - uintptr_t nvlog_addr = 0; - for (u32 *p = nsoStart; reinterpret_cast(p + 2) <= textEnd; ++p) { - const uintptr_t pc = reinterpret_cast(p); - if (!AsmIsAdrp(p[0])) { - continue; - } - const uintptr_t adrpPage = (pc & ~static_cast(0xFFFu)) + static_cast(AsmAdrpPageOffset(p[0])); - if (adrpPage != (strAddr & ~static_cast(0xFFFu))) { - continue; - } - const u32 reg = asm_get_rd(p[0]); - if (!(AsmIsAddImm64(p[1]) && asm_get_rd(p[1]) == reg && AsmGetRn(p[1]) == reg && AsmGetImm12(p[1]) == (strAddr & 0xFFFu))) { - continue; - } - for (u32 k = 2; k <= 12 && (pc + (k + 1) * 4) <= textEnd; ++k) { - if (AsmIsBl(p[k])) { nvlog_addr = AsmBranchTarget(p[k], pc + k * 4); break; } - } - if (nvlog_addr != 0) { - break; - } - } - if (nvlog_addr == 0 || nvlog_addr < mapped_nso || nvlog_addr >= textEnd) { - LOGGING("NvLogRedirect: NvLog entry not found (fmt@+%lx)", strAddr - mapped_nso); - R_THROW(ldr::ResultInvalidNvLogRedirect()); - } + auto *data = Hooks().BindData(m_HookPayloadData); + R_UNLESS(data != nullptr, ldr::ResultHookDataOutOfMemory()); - const uintptr_t helper = CaveReserve(40); - if (helper == 0) { - LOGGING("NvLogRedirect: cave unavailable (cave=%lx size=%lx)", - static_cast(g_pcv_cave), static_cast(g_pcv_cave_size)); - R_THROW(ldr::ResultInvalidNvLogRedirect()); - } - u32 *t = reinterpret_cast(helper); - size_t n = 0; - auto emit = [&](u32 ins) { t[n] = ins; ++n; }; + R_TRY(SharedClkBusInstallHooks(data)); - emit(AsmMakeSubImm64(31, 31, 0x200)); - emit(AsmMakeStpImm64(0, 1, 31, 0x100)); - emit(AsmMakeStpImm64(2, 3, 31, 0x110)); - emit(AsmMakeStpImm64(4, 5, 31, 0x120)); - emit(AsmMakeStpImm64(6, 7, 31, 0x130)); - emit(AsmMakeStpqImm(0, 1, 31, 0x140)); - emit(AsmMakeStpqImm(2, 3, 31, 0x160)); - emit(AsmMakeStpqImm(4, 5, 31, 0x180)); - emit(AsmMakeStpqImm(6, 7, 31, 0x1A0)); - emit(AsmMakeStrImm64(30, 31, 0x1E0)); - emit(AsmMakeAddImm64(9, 31, 0x200)); emit(AsmMakeStrImm64(9, 31, 0x1C0)); /* __stack */ - emit(AsmMakeAddImm64(9, 31, 0x140)); emit(AsmMakeStrImm64(9, 31, 0x1C8)); /* __gr_top */ - emit(AsmMakeAddImm64(9, 31, 0x1C0)); emit(AsmMakeStrImm64(9, 31, 0x1D0)); /* __vr_top */ - emit(AsmMakeMovnW(9, 0x37)); emit(AsmMakeStrImm32(9, 31, 0x1D8)); /* __gr_offs = -56 */ - emit(AsmMakeMovnW(9, 0x7F)); emit(AsmMakeStrImm32(9, 31, 0x1DC)); /* __vr_offs = -128 */ - emit(AsmMakeAddImm64(0, 31, 0x00)); /* mov x0,sp (buf) */ - emit(AsmMakeMovzW(1, 0x100)); /* size = 0x100 */ - emit(AsmMakeLdrImm64(2, 31, 0x100)); /* fmt (saved x0) */ - emit(AsmMakeAddImm64(3, 31, 0x1C0)); /* ap */ - emit(AsmMakeBl(helper + n * 4, vsnprintf_addr)); - emit(AsmMakeMovReg(1, 0)); /* len = retval */ - emit(AsmMakeCmpImm32(1, 0x100)); - { const size_t at = n; emit(AsmMakeBCond(helper + at * 4, helper + (at + 2) * 4, 0x3u)); } /* b.lo +2 */ - emit(AsmMakeMovzW(1, 0xFF)); /* clamp len */ - emit(AsmMakeAddImm64(0, 31, 0x00)); /* mov x0,sp (str) */ - emit(AsmMakeSvc(0x27)); /* svcOutputDebugString */ - emit(AsmMakeLdrImm64(30, 31, 0x1E0)); - emit(AsmMakeAddImm64(31, 31, 0x200)); - emit(RetIns); + R_TRY(LutWriterInstallHooks(data)); - /* Redirect the call sites as patching the actual function causes crash */ - const uintptr_t roStart = g_pcv_cave + g_pcv_cave_size; /* module .rodata start */ - size_t patchedSites = 0; - if (HOC_PCV_NVLOG_PATCH) { - for (u32 *p = nsoStart; reinterpret_cast(p + 1) <= textEnd; ++p) { - if (!AsmIsBl(*p)) { - continue; - } - const uintptr_t pc = reinterpret_cast(p); - if (AsmBranchTarget(*p, pc) != nvlog_addr) { - continue; - } - bool isFmtCall = false; - for (u32 j = 1; j <= 8 && reinterpret_cast(p - j) >= reinterpret_cast(nsoStart); ++j) { - const u32 w = *(p - j); - if (AsmIsAdrp(w) && asm_get_rd(w) == 0) { /* adrp x0, */ - const uintptr_t wpc = pc - j * 4; - const uintptr_t tgtPage = (wpc & ~static_cast(0xFFFu)) + static_cast(AsmAdrpPageOffset(w)); - if (tgtPage >= (roStart & ~static_cast(0xFFFu))) { isFmtCall = true; break; } - } - } - if (isFmtCall) { - PATCH_OFFSET(p, AsmMakeBl(pc, helper)); - ++patchedSites; - } - } - } +#if HOC_UART_LOG + R_TRY(ForceVebosityInstallHooks(data)); +#endif - LOGGING("NvLogRedirect: stub@+%lx vsnprintf@+%lx helper@+%lx instr=%zu sites=%zu", - nvlog_addr - mapped_nso, vsnprintf_addr - mapped_nso, helper - mapped_nso, n, patchedSites); - R_SUCCEED(); - } - #endif - - /* Relocate C2/C3Bus to avoid issues*/ - Result BusFreqReloc(u32 *ptr) { - const u32 busReg = AsmGetRn(ptr[0]); /* ldr Xbuf,[Xbus,#0x10] : bus struct pointer */ - const u32 bufReg = asm_get_rd(ptr[0]); /* : freq-buffer arg */ - const u32 bufOff = AsmGetLdStImm64Off(ptr[0]); /* : bus->freqBuf offset */ - const u32 cntReg = asm_get_rd(ptr[1]); /* add Xcnt,Xbus,#0x18 : arg2 (&count) */ - const u32 railReg = asm_get_rd(ptr[2]); /* str Xrail,[Xbus,#0x50]: arg0 (rail) */ - u32 *call = ptr + 3; /* the bl to relocate */ - const uintptr_t realFn = AsmBranchTarget(*call, reinterpret_cast(call)); - - /* Pick 3 scratch registers */ - u32 s[3], sc = 0; - for (u32 r = 9; r <= 15 && sc < 3; ++r) { - if (r != busReg && r != bufReg && r != cntReg && r != railReg) { - s[sc++] = r; - } - } - R_UNLESS(sc == 3, ldr::ResultInvalidBusFreqReloc()); - - const uintptr_t tramp = CaveReserve(9); - R_UNLESS(tramp != 0, ldr::ResultInvalidBusFreqReloc()); - - const uintptr_t region = g_pcv_scratch + HocBusFreqBufOffset; /* [0]=counter, +0x10 + i*0x400 = bufs */ - u32 *t = reinterpret_cast(tramp); - size_t n = 0; - auto emit = [&](u32 ins) { t[n] = ins; ++n; }; - emit(AsmMakeAdrp(tramp + n * 4, region, s[0])); /* adrp s0, */ - emit(AsmMakeAddImm64(s[0], s[0], region & 0xFFFu)); /* add s0,s0,#lo */ - emit(AsmMakeLdrImm32(s[1], s[0], 0x00)); /* s1 = counter */ - emit(AsmMakeAddImm64(s[2], s[1], 1)); /* s2 = counter+1 */ - emit(AsmMakeStrImm32(s[2], s[0], 0x00)); /* counter++ */ - emit(AsmMakeAddImm64(s[0], s[0], 0x10)); /* s0 = region+0x10 (buffers) */ - emit(AsmMakeAddShiftedReg64(bufReg, s[0], s[1], 10)); /* Xbuf = s0 + counter*0x400 */ - emit(AsmMakeStrImm64(bufReg, busReg, bufOff)); /* bus[freqBuf] = Xbuf */ - emit(AsmMakeB(tramp + n * 4, realFn)); /* tail-call the real function */ - - PATCH_OFFSET(call, AsmMakeBl(reinterpret_cast(call), tramp)); - const uintptr_t base = reinterpret_cast(nsoStart); - (void) base; - LOGGING("BusFreqReloc: call@+%lx -> tramp@+%lx realfn@+%lx (bus=x%u buf=x%u off=0x%x scratch=x%u,x%u,x%u)", - reinterpret_cast(call) - base, tramp - base, realFn - base, busReg, bufReg, bufOff, s[0], s[1], s[2]); - R_SUCCEED(); - } - - - #if HOC_UART_LOG - /* Force GetEffectiveVerbosityLevel to return a non-zero level so all NvLog runs. */ - Result ForceVerbosity(u32 *ptr) { - PATCH_OFFSET(&ptr[0], AsmMakeMovzW(0, static_cast(HOC_PCV_FORCE_VERBOSITY))); /* movz w0,#level */ - PATCH_OFFSET(&ptr[1], RetIns); /* ret */ - R_SUCCEED(); - } - #endif - - /* Widen InitDram for a >32-entry EMC DVFS list. Freq array can be dropped to free 264 bytes, relocate the Soc LUT to that space */ - Result EmcSocLutReloc(u32 *ptr) { - constexpr u32 Window = 48; - - u32 *freqStore = ScanAssembly(ptr - Window, Window, EmcSocFreqStoreAsm, asm_compare_no_rd); /* str x?,[x8,#0x18] */ - u32 *voltStore = ScanAssembly(ptr - Window, Window, EmcSocVoltStoreAsm, asm_compare_no_rd); /* str w?,[x8,#0x48] */ - u32 *readLoad = ScanAssembly(ptr - Window, Window, EmcSocReadLoadAsm, asm_compare_no_rd); /* ldr w?,[x9,#0x48] */ - R_UNLESS(freqStore && voltStore && readLoad, ldr::ResultInvalidEmcSocLut()); - - u32 *voltBase = voltStore - 2; /* `add Xb,Xsrc,Xi,LSL#2` (a cmn sits between it and store) */ - R_UNLESS(AsmIsAddShiftedReg64(*voltBase) && asm_get_rd(*voltBase) == AsmGetRn(*voltStore), - ldr::ResultInvalidEmcSocLut()); - - /* adrp Xl ; add Xl,Xl,#off ; ... ; str Xl,[rail,#0x120] */ - const u32 lutReg = asm_get_rd(ptr[0]); - const u32 railReg = AsmGetRn(ptr[0]); - R_UNLESS(AsmIsAdrp(ptr[-3]) && asm_get_rd(ptr[-3]) == lutReg, ldr::ResultInvalidEmcSocLut()); - R_UNLESS(AsmIsAddImm64(ptr[-2]) && asm_get_rd(ptr[-2]) == lutReg && AsmGetRn(ptr[-2]) == lutReg, - ldr::ResultInvalidEmcSocLut()); - - const u32 srcBase = AsmGetRn(*voltBase); /* rail ptr at +0x20 */ - const u32 wBase = asm_get_rd(*voltBase); /* base reg */ - const u32 wIdx = AsmGetRm(*voltBase); /* loop index */ - - PATCH_OFFSET(freqStore, NopIns); /* Unneeded */ - PATCH_OFFSET(voltBase, AsmMakeLdrImm64(wBase, srcBase, 0x20)); /* ldr Xb,[Xsrc,#0x20] (rail) */ - PATCH_OFFSET(voltStore - 1, AsmMakeAddImm64(wBase, wBase, 0x18)); /* add Xb,Xb,#0x18 (was cmn) */ - PATCH_OFFSET(voltStore, AsmSetLdStRegOffset(*voltStore, wIdx)); /* str Wv,[Xb,Xi,LSL#2] -> rail+0x18+i*4 */ - PATCH_OFFSET(voltStore + 1, NopIns); /* Unneeded */ - - /* rail+0x18 as the socMinLut pointer. */ - PATCH_OFFSET(ptr - 3, NopIns); - PATCH_OFFSET(ptr - 2, AsmMakeAddImm64(lutReg, railReg, 0x18));/* add Xl,rail,#0x18 */ - - /* Drop the abort branch in case of a bad read */ - for (u32 i = 1; i <= 4; ++i) { - if (AsmIsBCond(readLoad[i])) { - PATCH_OFFSET(&readLoad[i], NopIns); - break; - } - } - R_SUCCEED(); - } - - Result EmcDvfsCountLimit(u32 *ptr) { - R_UNLESS(EmcDvfsCountPatternFn(ptr), ldr::ResultInvalidEmcDvfsCount()); - - /* cmp w?,#0x21 -> cmp w?,#EmcDvfsTableEntryCount */ - PATCH_OFFSET(ptr, AsmSubsSetImm12(*ptr, static_cast(EmcDvfsTableEntryCount))); - R_SUCCEED(); - } - - Result EmcRateListLimit(u32 *ptr) { - /* ptr = cmp w?,#0x20 ; ptr[1] = csel w?,w?,w?,lt (w? = min(maxCount, 32)) ; ptr[2] = bl */ - R_UNLESS(EmcRateListPatternFn(ptr), ldr::ResultInvalidEmcRateList()); - - /* The csel's Rm holds the 32 cap. */ - const u32 capReg = AsmGetRm(ptr[1]); - const u32 capMov = AsmMakeMovzW(capReg, 0x20); /* movz w,#0x20 */ - - u32 *movPtr = nullptr; - for (u32 i = 1; i <= 16; ++i) { - if (*(ptr - i) == capMov) { - movPtr = ptr - i; - break; - } - } - R_UNLESS(movPtr, ldr::ResultInvalidEmcRateList()); - - /* min(maxCount, 32) -> min(maxCount, EmcDvfsTableEntryCount). */ - PATCH_OFFSET(ptr, AsmSubsSetImm12(*ptr, static_cast(EmcDvfsTableEntryCount))); /* cmp w?,#64 */ - PATCH_OFFSET(movPtr, asm_set_imm16(*movPtr, static_cast(EmcDvfsTableEntryCount))); /* movz w?,#64 */ - R_SUCCEED(); - } - - Result I2cSet_U8(I2cDevice dev, u8 reg, u8 val) { - struct { - u8 reg; - u8 val; - } __attribute__((packed)) cmd; - - I2cSession _session; - R_TRY(i2cOpenSession(&_session, dev)); - - cmd.reg = reg; - cmd.val = val; - Result res = i2csessionSendAuto(&_session, &cmd, sizeof(cmd), I2cTransactionOption_All); - i2csessionClose(&_session); - return res; - } - - Result EmcVddqVolt(u32 *ptr) { - regulator *entry = reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_2_3.default_uv)); - - constexpr u32 uv_step = 5'000; - constexpr u32 uv_min = 250'000; - - auto validator = [entry]() { - R_UNLESS(entry->id == 2, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type == 3, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type_2_3.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry()); - R_UNLESS(entry->type_2_3.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); - R_SUCCEED(); - }; - - R_TRY(validator()); - - u32 emc_uv = C.marikoEmcVddqVolt; - - if (!emc_uv) { - R_SKIP(); - } - - if (emc_uv % uv_step) { - emc_uv = (emc_uv + uv_step - 1) / uv_step * uv_step; // rounding - } - - PATCH_OFFSET(ptr, emc_uv); - - i2cInitialize(); - Result resultI2C = I2cSet_U8(I2cDevice_Max77812_2, 0x25, (emc_uv - uv_min) / uv_step); - i2cExit(); - - R_SUCCEED(); - - return resultI2C; - } - - Result GetSocSpeedo(u32 &socSpeedo) { - constexpr u64 FusePhysicalAddress = 0x7000F000; - u64 virtualAddress = 0; - constexpr u64 Size = 0x1000; - - u64 outSize; - /* TODO: use svc::QueryMemoryMapping instead. */ - R_TRY(svcQueryMemoryMapping(&virtualAddress, &outSize, FusePhysicalAddress, Size)); - - constexpr u32 FuseOffset = 2048; - constexpr u32 SocSpeedoOffset = 308; - socSpeedo = *reinterpret_cast(virtualAddress + FuseOffset + SocSpeedoOffset); - - R_SUCCEED(); - } - - u32 GetSocProcessId(u32 socSpeedo) { - if (socSpeedo <= 1597) { - return 0; - } - - if (socSpeedo <= 1708) { - return 1; - } - - /* >= 1709. */ - return 2; - } - - Result SocVoltAsm(u32 *compareSpeedos) { - constexpr u32 VoltageScanLimit = 10; - /* Might actually be speedo id. */ - u32 *writeProcessId = ScanAssembly(compareSpeedos, VoltageScanLimit, SocVoltWriteProcessIdAsm, asm_compare_no_rd); - R_UNLESS(writeProcessId != nullptr, ldr::ResultInvalidSocVoltPattern()); - u8 writeProcessIdRd = asm_get_rd(*writeProcessId); - - /* This writes 1050mV. */ - u32 *writeVoltage = ScanAssembly(writeProcessId, VoltageScanLimit, SocVoltWriteVoltageAsm, asm_compare_no_rd); - R_UNLESS(writeVoltage != nullptr, ldr::ResultInvalidSocVoltPattern()); - u8 writeVoltageRd = asm_get_rd(*writeVoltage); - - /* A csel instruction is used to select the soc voltage limit register. */ - /* We care about its destination register since that is used for verification. */ - constexpr u32 VoltageSelectScanLimit = 24; - u32 *selectVoltage = ScanAssembly(writeVoltage, VoltageSelectScanLimit, SocVoltSelectRegisterAsm, AsmCompareCselNoReg); - R_UNLESS(selectVoltage != nullptr, ldr::ResultInvalidSocVoltPattern()); - /* Todo: check rm and rn? */ - u8 selectVoltageRd = asm_get_rd(*selectVoltage); - - /* rdCsel is then multiplied by 1000 to convert to uV. */ - /* This is pretty far down the function. */ - constexpr u32 MultiplierScanLimit = 200; - u32 *multiplier = ScanAssembly(selectVoltage, MultiplierScanLimit, SocVoltMultiplyVoltsAsm, AsmCompareMullNoReg); - R_UNLESS(multiplier != nullptr, ldr::ResultInvalidSocVoltPattern()); - u8 multiplierRn = AsmGetMullRn(*multiplier); - u8 multiplierRm = AsmGetMullRm(*multiplier); - /* One of the two registers has to be rdCsel. */ - R_UNLESS((multiplierRn == selectVoltageRd) || (multiplierRm == selectVoltageRd), ldr::ResultInvalidSocVoltPattern()); - u8 multiplierRd = asm_get_rd(*multiplier); - - /* Subs instruction is then used to verify against absolute limit. */ - u32 limitValidationPattern = AsmSubsSetRn(SocVoltValidateLimitAsm, multiplierRd); - u32 *limitValidation = ScanAssembly(multiplier, VoltageScanLimit, limitValidationPattern, AsmSubsCompareNoReg); - R_UNLESS(limitValidation != nullptr, ldr::ResultInvalidSocVoltPattern()); - - /* There is a b.gt instruction right after (checks for socVoltageCap < socVoltageMax). */ - u32 *branchToAbort = limitValidation + 1; - R_UNLESS(AsmCompareBrConNoImm19(*branchToAbort, SocVoltBranchToAbortAsm), ldr::ResultInvalidSocVoltPattern()); - - if (!C.marikoSocVmax || C.marikoSocVmax <= 1000) { - R_SKIP(); - } - - /* Adjust 1598 speedo minimum to ensure it always goes down process id 0 branch. */ - /* 2200 should be high enough :D */ - u32 compareSpeedosPatch = AsmSubsSetImm12(*compareSpeedos, 2200); - PATCH_OFFSET(compareSpeedos, compareSpeedosPatch); - - u32 socSpeedo = 0; - R_TRY(GetSocSpeedo(socSpeedo)); - - /* Adjust processId from 0 to [process id of switch booting this]. */ - /* We're overwriting the orr instruction entirly. */ - u32 processId = GetSocProcessId(socSpeedo); - u32 writeProcessIdPatch = asm_set_rd(asm_set_imm16(SocVoltWriteVoltageAsm, processId), writeProcessIdRd); - PATCH_OFFSET(writeProcessId, writeProcessIdPatch); - - /* Adjust voltage limit. */ - u32 voltageLimitPatch = asm_set_rd(asm_set_imm16(SocVoltWriteVoltageAsm, C.marikoSocVmax), writeVoltageRd); - PATCH_OFFSET(writeVoltage, voltageLimitPatch); - - /* Branches to an abort if limits are invalid -- we patch the branch instruction with NOP. */ - PATCH_OFFSET(branchToAbort, NopIns); - - R_SUCCEED(); - } - - Result SocVoltLimit(u32 *ptr) { - R_UNLESS(!std::memcmp(ptr - SocVoltLimitMaxDefaultIndex, socVoltLimitArray, sizeof(socVoltLimitArray)), ldr::ResultInvalidSocVoltLimit()); - if (!C.marikoSocVmax || C.marikoSocVmax <= SocVoltLimitOfficial) { - R_SKIP(); - } - - constexpr u32 Step = 25; - u32 maxVolt = C.marikoSocVmax; - if (maxVolt % Step) { - maxVolt = maxVolt / Step * Step; /* Round. */ - } - - u32 volt = SocVoltLimitOfficial; - for (u32 i = 1; i < DvfsTableEntryCount - SocVoltLimitMaxDefaultIndex && volt < maxVolt; ++i) { - volt += Step; - PATCH_OFFSET(ptr + i, volt); - } - - R_SUCCEED(); - } - - Result EmcRateSessLimit(u32 *ptr) { - u32 movzI = 0; - R_UNLESS(EmcRateSessFindClamp(ptr, nullptr, nullptr, &movzI), ldr::ResultInvalidEmcRateList()); - - /* Reject cmd11 GetDvfsTable. */ - for (u32 i = 1; i <= 24; ++i) { - const u32 w = ptr[i]; - if (AsmIsSubX29Imm(w) && AsmGetImm12(w) >= 0x20u) { /* sub x?,x29,#>=0x20 */ - R_THROW(ldr::ResultInvalidEmcRateList()); - } - } - - /* mov x,x2 */ - u32 descReg = 0xFFu; - for (u32 i = 1; i <= 24; ++i) { - if (AsmIsMovReg(ptr[i], 2)) { descReg = asm_get_rd(ptr[i]); break; } - } - R_UNLESS(descReg != 0xFFu, ldr::ResultInvalidEmcRateList()); - - /* Repoint the duplicated-imm pair */ - u32 *adds[8]; u32 addImm[8]; u32 nAdds = 0; - for (u32 i = 1; i <= 24 && nAdds < 8; ++i) { - const u32 w = ptr[i]; - if (AsmIsAddSpImm(w)) { /* add x?,sp,#imm12 (shift 0) */ - adds[nAdds] = ptr + i; - addImm[nAdds] = AsmGetImm12(w); - ++nAdds; - } - } - u32 patched = 0; - for (u32 a = 0; a < nAdds; ++a) { - bool dup = false; - for (u32 b = 0; b < nAdds; ++b) { - if (a != b && addImm[a] == addImm[b]) { dup = true; break; } - } - if (dup) { - PATCH_OFFSET(adds[a], AsmMakeLdrImm64(asm_get_rd(*adds[a]), descReg, 0)); /* ldr x?,[x] */ - ++patched; - } - } - R_UNLESS(patched == 2, ldr::ResultInvalidEmcRateList()); - - /* min(maxCount, 32) -> min(maxCount, EmcDvfsTableEntryCount) */ - PATCH_OFFSET(ptr, AsmSubsSetImm12(*ptr, static_cast(EmcDvfsTableEntryCount))); /* cmp w?,#64 */ - PATCH_OFFSET(ptr + movzI, asm_set_imm16(*(ptr + movzI), static_cast(EmcDvfsTableEntryCount))); /* movz w?,#64 */ R_SUCCEED(); } void Patch(uintptr_t mapped_nso, size_t nso_size) { - nsoStart = reinterpret_cast(mapped_nso); - - g_pcv_scratch = mapped_nso + nso_size - HocPcvScratchSize; - g_nso_size = nso_size; - g_cave_cursor = g_pcv_cave; /* start the .text-cave bump allocator (0 if unavailable) */ + nsoStart = reinterpret_cast(mapped_nso); + g_nso_size = nso_size; MtcGenerateFreqTables(); @@ -559,6 +95,12 @@ namespace ams::ldr::hoc::pcv::mariko { { "Bus Freq Reloc", &BusFreqReloc, 1, &BusFreqRelocPatternFn }, { "SOC Volt Asm", &SocVoltAsm, 1, &SocVoltPatternFn }, { "SOC Volt Limit", &SocVoltLimit, 1, nullptr, SocVoltLimitOfficial }, + { "CPU Lut Max Asm", &CpuLutMaxAsm, 1, &CpuLutAsmPatternFn }, + { "CPU Lut Max Asm2", &CpuLutMaxAsm2, 1, &CpuLutAsmPatternFn2 }, + { "CPU Lut Writer", &LutWriterFind, 1, &LutWriterPatternFn }, + { "CPU Dvco Rate Cfg", &CpuLutDvcoRateCfg, 1, &CpuLutDvcoRateCfgPatternFn }, + { "Hook Cave", &DeadDestructorCaveFind, 0, &CaveFlagRunPatternFn, 0, 0, true }, + /* Debugging patches */ #if HOC_UART_LOG { "NvLog Redirect", &NvLogUartRedirect, 1, &NvLogVsnprintfPatternFn, 0, 0, true }, @@ -583,6 +125,10 @@ namespace ams::ldr::hoc::pcv::mariko { CRASH(entry.description); } } + + if (R_FAILED(InstallHooks())) { + panic::SmcError(panic::Patch); + } } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko.hpp index 33b7ed09..d94273ca 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko.hpp @@ -23,408 +23,27 @@ #include "../../oc_common.hpp" #include "../pcv_common.hpp" #include "../pcv_asm.hpp" +#include "../pcv_hook.hpp" namespace ams::ldr::hoc::pcv::mariko { - extern u32 *nsoStart; + constexpr u32 BusFreqTableCount = 2; - constexpr cvb_entry_t CpuCvbTableDefault[] = { - { 204000, { 721589, -12695, 27 }, { } }, - { 306000, { 747134, -14195, 27 }, { } }, - { 408000, { 776324, -15705, 27 }, { } }, - { 510000, { 809160, -17205, 27 }, { } }, - { 612000, { 845641, -18715, 27 }, { } }, - { 714000, { 885768, -20215, 27 }, { } }, - { 816000, { 929540, -21725, 27 }, { } }, - { 918000, { 976958, -23225, 27 }, { } }, - { 1020000, { 1028021, -24725, 27 }, { 1120000 } }, - { 1122000, { 1082730, -26235, 27 }, { 1120000 } }, - { 1224000, { 1141084, -27735, 27 }, { 1120000 } }, - { 1326000, { 1203084, -29245, 27 }, { 1120000 } }, - { 1428000, { 1268729, -30745, 27 }, { 1120000 } }, - { 1581000, { 1374032, -33005, 27 }, { 1120000 } }, - { 1683000, { 1448791, -34505, 27 }, { 1120000 } }, - { 1785000, { 1527196, -36015, 27 }, { 1120000 } }, - { 1887000, { 1609246, -37515, 27 }, { 1120000 } }, - { 1963500, { 1675751, -38635, 27 }, { 1120000 } }, - { }, + struct HookPayloadData { + struct { + u32 *next; /* Save the bytes. */ + uintptr_t originalFnCallback; + u32 table[BusFreqTableCount][EmcDvfsTableEntryCount]; /* Original bus table size: 32. */ + } busData; + struct { + uintptr_t orig; /* ClDvfsLut64ExpandImpl to CLDVFS LUT writer trampoline. */ + u32 table[ClDvfsLutSize]; + } lut64; +#if HOC_UART_LOG + u32 verbosityLevel; +#endif }; - - constexpr u32 CpuClkOfficial = 1963'500; - constexpr u32 CpuVoltOfficial = 1120; - constexpr u32 CpuHighVminOfficial = 850; - constexpr u32 CpuVminOfficial = 620; - constexpr u32 CpuTune0Low = 0xFFCF; - - static const u32 cpuVoltagePatchValues[] = { 850, 38, 1120, 1000, 100, 1000, 0 }; - static const s32 cpuVoltagePatchOffsets[] = { -2, -1, 5, 6, 7, 8, 9 }; - static_assert(sizeof(cpuVoltagePatchValues) == sizeof(cpuVoltagePatchOffsets), "Invalid cpuVoltagePatch size"); - - static const u32 cpuVoltThermalData[] = { 620, 1120, 20000, 620, 1120, 70000, 950, 1132, 0, 950, 1227, 0 }; - - static const u32 allowedCpuMaxFrequencies[] = { 1'963'500, 2'091'000, 2'193'000, 2'295'000, 2'397'000, 2'499'000, 2'601'000, 2'703'000, }; - - constexpr cvb_entry_t GpuCvbTableDefault[] = { - // GPUB01_NA_CVB_TABLE - { 76800, {}, { 610000, } }, - { 153600, {}, { 610000, } }, - { 230400, {}, { 610000, } }, - { 307200, {}, { 610000, } }, - { 384000, {}, { 610000, } }, - { 460800, {}, { 610000, } }, - { 537600, {}, { 801688, -10900, -163, 298, -10599, 162, } }, - { 614400, {}, { 824214, -5743, -452, 238, -6325, 81, } }, - { 691200, {}, { 848830, -3903, -552, 119, -4030, -2, } }, - { 768000, {}, { 891575, -4409, -584, 0, -2849, 39, } }, - { 844800, {}, { 940071, -5367, -602, -60, -63, -93, } }, - { 921600, {}, { 986765, -6637, -614, -179, 1905, -13, } }, - { 998400, {}, { 1098475, -13529, -497, -179, 3626, 9, } }, - { 1075200, {}, { 1163644, -12688, -648, 0, 1077, 40, } }, - { 1152000, {}, { 1204812, -9908, -830, 0, 1469, 110, } }, - { 1228800, {}, { 1277303, -11675, -859, 0, 3722, 313, } }, - { 1267200, {}, { 1335531, -12567, -867, 0, 3681, 559, } }, - { }, - }; - - constexpr u32 GpuClkPllMax = 1300'000'000; - constexpr u32 GpuClkPllLimit = 2'600'000; - constexpr u32 GpuVminOfficial = 610; - - static const u32 gpuDVFSPattern[] = { 1050, 1000, 100, 1000, 10, }; - static const u32 gpuVoltThermalPattern[] = { 800, 1120, 0, 610, 1120, 20000, 610, 1120, 30000, 610, 1120, 50000, 610, 1120, 70000, 610, 1120, 90000, }; - static_assert(sizeof(gpuVoltThermalPattern) == 72, "Invalid gpuVoltThermalPattern"); - - /* GPU Max Clock asm Pattern: - * - * MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11) - * sf | opc | | hw | imm16 | Rd - * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 - * 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1 - * - * MOVK W11, #0xE, LSL#16 16 0xE 0xB (11) - * sf | opc | | hw | imm16 | Rd - * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 - * 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1 - */ - inline constexpr u32 GpuAsmPattern[] = { 0x52820000, 0x72A001C0 }; - - inline bool GpuMaxClockPatternFn(u32 *ptr32) { - return asm_compare_no_rd(*ptr32, GpuAsmPattern[0]); - } - - struct DvbEntry { - u64 freq; - u32 volt[4] = {}; - }; - - constexpr DvbEntry EmcDvbTableDefault[] = { - { 204000, { 637, 637, 637, } }, - { 408000, { 637, 637, 637, } }, - { 800000, { 637, 637, 637, } }, - { 1065600, { 637, 637, 637, } }, - { 1331200, { 650, 637, 637, } }, - { 1600000, { 675, 650, 637, } }, - }; - - /* Movz */ - /* - SF | OPC | HW | Imm16 | RD - 31 | 30 29 28 27 26 25 24 23 | 22 21 | 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0 - */ - constexpr u32 SocVoltCompareSpeedoAsm = 0x7118FAFF; /* subs imm, compares to >=1598 max speedo and then goes down process id 1 route. */ - constexpr u32 SocVoltWriteProcessIdAsm = 0x2A1F03F4; /* orr, writes id 0. */ - constexpr u32 SocVoltWriteVoltageAsm = 0x52808358; /* Movz imm, writes 1050mV. */ - constexpr u32 SocVoltSelectRegisterAsm = 0x1A9A3118; /* Csel, selects the voltage -- we need the register of this. */ - constexpr u32 SocVoltMultiplyVoltsAsm = 0x1B1A7F0B; /* Mul, converts from mV -> uV */ - constexpr u32 SocVoltValidateLimitAsm = 0x6B0A017F; /* Subs, checks limits */ - constexpr u32 SocVoltBranchToAbortAsm = 0x540020AC; /* B.ge Branches to abort if limits are invalid. */ - - ALWAYS_INLINE bool SocVoltPatternFn(u32 *ptr) { - return asm_compare_no_rd(*ptr, SocVoltCompareSpeedoAsm); - } - - constexpr u32 SocVoltLimitOfficial = 1050; - constexpr u32 SocVoltLimitMaxDefaultIndex = 17; - static const u32 socVoltLimitArray[DvfsTableEntryCount] = { 637, 650, 675, 700, 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, }; - - constexpr u32 EmcListDefault[] = { 204000, 1331200, 1600000, }; - constexpr u32 EmcListSizeDefault = std::size(EmcListDefault); - constexpr u32 EmcListEndDefault = EmcListSizeDefault - 1; - - constexpr u32 EmcClkOSAlt = 1331'200; - constexpr u32 EmcClkPllmLimit = 2133'000'000; - constexpr u32 EmcVddqDefault = 600'000; - constexpr u32 MemVdd2Default = 1100'000; - - constexpr u32 MTC_TABLE_REV = 3; - constexpr u32 MtcTableCountDefault = 3; - - constexpr size_t MtcFullTableSize = sizeof(MarikoMtcTable) * MtcTableCountDefault; - constexpr u32 MtcFullTableCount = 17; - - /* These dramids were copied from Hekate -- see /bdk/mem/sdram.h */ - enum DramId : u64 { - HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 3, - AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 5, - IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 6, - - IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, - IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, - IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, - IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, - - HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, - HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, - HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, - HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, - - IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, - IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, - HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, - - IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 20, - HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 21, - AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 22, - - HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, - AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, - - IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, - HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, - AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, - - AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, - - IOWA_4GB_HYNIX_H54G46CYRBX267 = 29, - HOAG_4GB_HYNIX_H54G46CYRBX267 = 30, - AULA_4GB_HYNIX_H54G46CYRBX267 = 31, - - IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 32, - HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB = 33, - AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 34, - }; - - enum MtcTableIndex { - T210b0SdevEmcDvfsTableS4gb01 = 0, /* (Unused) Samsung 4Gb */ - T210b0SdevEmcDvfsTableS4gb03 = 1, /* Samsung AM-MGCJ 4Gb */ - T210b0SdevEmcDvfsTableS8gb03 = 2, /* (Unused) Samsung 4Gb */ - T210b0SdevEmcDvfsTableH4gb03 = 3, /* Hynix NME 4Gb */ - T210b0SdevEmcDvfsTableM4gb03 = 4, /* Micron WT:F 4Gb */ - T210b0SdevEmcDvfsTableS4gbY01 = 5, /* (Unused) Samsung 4Gb */ - T210b0SdevEmcDvfsTableS1y4gbY01 = 6, /* (Unused) Samsung 4Gb */ - T210b0SdevEmcDvfsTableS1y8gbY01 = 7, /* (Unused) Samsung 4Gb */ - T210b0SdevEmcDvfsTableS1y4gbX03 = 8, /* Samsung AA-MGCL 4Gb */ - T210b0SdevEmcDvfsTableS1y8gbX03 = 9, /* Samsung AA-MGCL 8Gb */ - T210b0SdevEmcDvfsTableS1y4gb01 = 10, /* (Unused) Samsung 4Gb */ - T210b0SdevEmcDvfsTableM1y4gb01 = 11, /* Micron WT:E 4Gb */ - T210b0SdevEmcDvfsTableH1y4gb01 = 12, /* Hynix NEE 4Gb */ - T210b0SdevEmcDvfsTableS1y8gb04 = 13, /* Samsung AM-MGCJ 8Gb */ - T210b0SdevEmcDvfsTableS1z4gb01 = 14, /* Samsung AB-MGCL 4Gb */ - T210b0SdevEmcDvfsTableH1a4gb01 = 15, /* Hynix x267 4Gb */ - T210b0SdevEmcDvfsTableM1a4gb01 = 16, /* Micron WT:B 8Gb */ - MtcTableIndex_Invalid = 17, - }; - - struct MtcDramIndex { - DramId dramId; - MtcTableIndex index; - }; - - const inline MtcDramIndex mtcIndexTable[] = { - { HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, }, - { AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, }, - { IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, }, - { IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ, T210b0SdevEmcDvfsTableS4gb03, }, - { IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, T210b0SdevEmcDvfsTableS1y8gb04, }, - { IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME, T210b0SdevEmcDvfsTableH4gb03, }, - { IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE, T210b0SdevEmcDvfsTableM1y4gb01, }, - { HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ, T210b0SdevEmcDvfsTableS4gb03, }, - { HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, T210b0SdevEmcDvfsTableS1y8gb04, }, - { HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME, T210b0SdevEmcDvfsTableH4gb03, }, - { HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE, T210b0SdevEmcDvfsTableM1y4gb01, }, - { IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, }, - { IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, }, - { HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, }, - { IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1z4gb01, }, - { HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1y8gb04, }, - { AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1y8gb04, }, - { HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, }, - { AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, }, - { IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, }, - { HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, }, - { AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, }, - { AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, }, - { IOWA_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, }, - { HOAG_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, }, - { AULA_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, }, - { IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, }, - { HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, }, - { AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, }, - }; - - /* - 710006abfc 40 01 1f d6 br x10 - */ - - /* - 710006ac28 a0 03 00 90 adrp x0,0x71000de000 - 710006ac2c 00 80 16 91 add x0=>SdevEmcDvfsTableS4gb01,x0,#0x5a0 - */ - - /* Br */ - /* - | Z | OP | Fixed | A | M | RN | RM - 31 30 29 28 27 26 25 | 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 |11 | 10 | 9 8 7 6 5 | 4 3 2 1 0 - 1 1 0 1 0 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 Rn 0 0 0 0 0 - Z op A M Rm - */ - - /* Adrp */ - /* - OP | ImmLow | | ImmHigh | RD - 31 | 30 29 | 28 27 26 25 24 | 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0 - */ - - /* ADD (immediate) */ - /* - SF | OP | S | Fixed value | Sh | Imm12 | RN | RD - 31 | 30 | 29 | 28 27 26 25 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0 - */ - - constexpr u32 MtcBrAsm = 0xD61F0140; - constexpr u32 MtcMovAsm = 0x52800068; - constexpr u32 MtcAdrpAsm = 0x900003A0; - constexpr u32 MtcAddAsm = 0x91168000; - - ALWAYS_INLINE bool MemMtcGetGetTablePatternFn(u32 *ptr) { - /* This builds an address that gets returned, so the register must be x0 by convention. */ - return AsmCompareAddNoImm12(*ptr, MtcAddAsm); - } - - constexpr u32 EmcCountCmpAsm = 0x7100851F; /* cmp w?,#0x21 (subs wzr,w?,#0x21) */ - - /* - str ,[,#0x120] ; volt-array pointer - str w?, [,#0x154] ; num_freqs - */ - constexpr u32 EmcSocLutPtrStoreAsm = 0xF9009009; /* str x?,[x0,#0x120] (anchor) */ - constexpr u32 EmcSocLutCountStoreAsm = 0xB9015408; /* str w?,[x0,#0x154] (anchor) */ - constexpr u32 EmcSocFreqStoreAsm = 0xF9000D00; /* str x?,[x8,#0x18] */ - constexpr u32 EmcSocVoltStoreAsm = 0xB9004900; /* str w?,[x8,#0x48] (socMinLut[i]) */ - constexpr u32 EmcSocReadLoadAsm = 0xB9404929; /* ldr w?,[x9,#0x48] (socMinLut readback) */ - - inline bool EmcDvfsCountPatternFn(u32 *ptr) { - /* Local context: cbz w?, ; cmp w?,#0x21 ; b.cs */ - return asm_compare_no_rd(*ptr, EmcCountCmpAsm) && AsmCompareBrConNoImm19(*(ptr + 1), 0x54000002) /* b.cs */ - && AsmCbzCompareOpcodeOnly(*(ptr - 1), 0x34000000); /* cbz */ - } - - inline bool EmcSocLutPatternFn(u32 *ptr) { - return asm_compare_no_rd(*ptr, EmcSocLutPtrStoreAsm) /* str x?,[x0,#0x120] */ - && asm_compare_no_rd(*(ptr + 1), EmcSocLutCountStoreAsm); /* str w?,[x0,#0x154] */ - } - - /* - mov w?,#0x20 ; the 32 cap - cmp w?,#0x20 - csel w?,w?,w?,lt ; w? = min(maxCount, 32) - bl TegraGetEmcDvfsFreqTable - - cmp w?,#0x20 ; (maxCount) - csel w?,,,lt ; min(maxCount, 32) - bl - */ - constexpr u32 EmcRateCapCmpAsm = 0x710082FF; /* cmp w?,#0x20 */ - constexpr u32 EmcRateCapCselAsm = 0x1A80B000; /* csel w?,w?,w?,lt */ - - inline bool EmcRateListPatternFn(u32 *ptr) { - return AsmSubsCompareNoReg(*ptr, EmcRateCapCmpAsm) /* cmp w?,#0x20 */ - && AsmCompareCselNoReg(*(ptr + 1), EmcRateCapCselAsm) /* csel w?,w?,w?,lt */ - && (AsmGetRn(*ptr) == AsmGetRn(*(ptr + 1))) /* min(reg, 0x20) */ - && AsmBlCompareOpcodeOnly(*(ptr + 2), 0x94000000); /* bl */ - } - - constexpr u32 EmcRateSessCmpAsm = 0x710082FF; /* cmp w?,#0x20 */ - constexpr u32 EmcRateSessMovAsm = 0x52800400; /* movz w?,#0x20 */ - constexpr u32 EmcRateSessCselAsm = 0x1A80B000; /* csel w?,w?,w?,lt (opcode + cond) */ - - inline bool EmcRateSessFindClamp(u32 *ptr, u32 *out_c, u32 *out_cap, u32 *out_movz_i) { - if (!AsmSubsCompareNoReg(ptr[0], EmcRateSessCmpAsm)) return false; /* cmp w,#0x20 */ - const u32 c = AsmGetRn(ptr[0]); - for (u32 i = 1; i <= 14; ++i) { - const u32 w = ptr[i]; - if (AsmCompareCselNoReg(w, EmcRateSessCselAsm) && AsmGetRn(w) == c && asm_get_rd(w) == c) { - const u32 cap = AsmGetRm(w); - for (u32 j = 1; j < i; ++j) { - if ((ptr[j] & 0xFFFFFFE0u) == EmcRateSessMovAsm && asm_get_rd(ptr[j]) == cap) { - if (out_c) *out_c = c; - if (out_cap) *out_cap = cap; - if (out_movz_i) *out_movz_i = j; - return true; - } - } - return false; - } - } - return false; - } - - inline bool EmcRateSessPatternFn(u32 *ptr) { - return EmcRateSessFindClamp(ptr, nullptr, nullptr, nullptr); - } - - inline bool BusFreqRelocPatternFn(u32 *ptr) { - if (g_pcv_scratch == 0 || g_pcv_cave == 0) { - return false; - } - if (reinterpret_cast(ptr + 4) > g_pcv_cave) { /* the call site lives in .text */ - return false; - } - if (!(AsmIsLdrImm64(ptr[0]) && AsmGetLdStImm64Off(ptr[0]) == 0x10)) return false; /* ldr Xbuf,[Xbus,#0x10] */ - if (!(AsmIsAddImm64(ptr[1]) && AsmGetImm12(ptr[1]) == 0x18)) return false; /* add Xcnt,Xbus,#0x18 */ - if (!(AsmIsStrImm64(ptr[2]) && AsmGetLdStImm64Off(ptr[2]) == 0x50)) return false; /* str Xrail,[Xbus,#0x50]*/ - if (!AsmIsBl(ptr[3])) return false; /* bl GetDvfsRailUnique */ - const u32 bus = AsmGetRn(ptr[0]); - return AsmGetRn(ptr[1]) == bus && AsmGetRn(ptr[2]) == bus; - } - - inline bool ForceVerbosityPatternFn(u32 *ptr) { - if (HOC_PCV_FORCE_VERBOSITY == 0 || g_pcv_cave == 0) { - return false; - } - if (reinterpret_cast(ptr + 11) > g_pcv_cave) { /* .text only */ - return false; - } - if (ptr[0] != 0xA9BE7BFDu || ptr[1] != 0xF9000BF3u || ptr[2] != 0x910003FDu) return false; /* stp/str/mov x29,sp */ - if (!(AsmIsAddImm64(ptr[3]) && asm_get_rd(ptr[3]) == 0 && AsmGetRn(ptr[3]) == 29)) return false; /* add x0,x29,#imm */ - if (!(AsmIsAddImm64(ptr[4]) && asm_get_rd(ptr[4]) == 19 && AsmGetRn(ptr[4]) == 29)) return false; /* add x19,x29,#imm */ - if (AsmGetImm12(ptr[3]) != AsmGetImm12(ptr[4]) || !AsmIsBl(ptr[5])) return false; - for (u32 j = 6; j <= 10; ++j) { - if (ptr[j] == 0x7100001Fu) { /* cmp w0,#0 */ - return true; - } - } - return false; - } - - /* vsnprintf(buf,size,fmt,va_list) prologue */ - inline constexpr u32 NvLogVsnSig[] = { 0xD10483FFu, 0xA9107BFDu, 0xF9008BFCu, 0x910403FDu, 0xF100003Fu }; - - inline bool NvLogVsnprintfPatternFn(u32 *ptr) { - if (HOC_UART_LOG == 0 || g_pcv_cave == 0) { - return false; - } - if (reinterpret_cast(ptr + std::size(NvLogVsnSig)) > g_pcv_cave) { /* must sit in .text */ - return false; - } - for (size_t k = 0; k < std::size(NvLogVsnSig); ++k) { - if (ptr[k] != NvLogVsnSig[k]) { - return false; - } - } - return true; - } - + DECLARE_HOOK_PAYLOAD_PTR(HookPayloadData, m_HookPayloadData); void Patch(uintptr_t mapped_nso, size_t nso_size); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cave.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cave.cpp new file mode 100644 index 00000000..e468d64b --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cave.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 . + */ + +#include "pcv_mariko_cave.hpp" + +namespace ams::ldr::hoc::pcv::mariko { + + namespace { + + struct { + u32 *site = nullptr; + u32 *end = nullptr; + } caveCache; + + bool HasDirectCaller(const u32 *target, const u32 *begin, const u32 *end) { + for (const u32 *ptr = begin; ptr < end; ++ptr) { + const u32 top6 = *ptr & 0xFC000000u; + if (top6 != _asm::op::B && top6 != _asm::op::Bl) { + continue; + } + + if (_asm::Target26(*ptr, reinterpret_cast(ptr)) == reinterpret_cast(target)) { + return true; + } + } + + return false; + } + + } + + Result DeadDestructorCaveFind(u32 *ptr) { + u32 *textEnd = reinterpret_cast(g_pcv_cave); + + u32 *site = _asm::FindFnPrologue(ptr, CavePrologueMargin, nsoStart); + R_UNLESS(site != nullptr, ldr::ResultInvalidHookCave()); + + u32 *end = _asm::FindFnEnd(site, textEnd); + R_UNLESS(end != nullptr, ldr::ResultInvalidHookCave()); + + /* Ensure this function is never called. */ + R_UNLESS(!HasDirectCaller(site, nsoStart, textEnd), ldr::ResultInvalidHookCave()); + + caveCache.site = site; + caveCache.end = end; + R_SUCCEED(); + } + + Result CaveInstall() { + if (Hooks().CaveFree() >= HookContext::RequiredCaveSize()) { + R_SUCCEED(); + } + + R_UNLESS(caveCache.site != nullptr, ldr::ResultInvalidHookCave()); + + const uintptr_t start = util::AlignUp(reinterpret_cast(caveCache.site + 1), sizeof(u64)); + const uintptr_t end = reinterpret_cast(caveCache.end); + R_UNLESS(start < end && end - start >= HookContext::RequiredCaveSize(), ldr::ResultHookPayloadTooLarge()); + + /* Insert a break in case this function gets called for whatever reason. */ + *caveCache.site = _asm::BrkIns; + + Hooks().SetCave(start, end - start); + R_SUCCEED(); + } + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cave.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cave.hpp new file mode 100644 index 00000000..7d177b49 --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cave.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 . + */ + +#pragma once + +#include "../pcv.hpp" +#include "../pcv_asm.hpp" +#include "../pcv_hook.hpp" + +namespace ams::ldr::hoc::pcv::mariko { + + extern u32 *nsoStart; + + constexpr u32 CaveFlagChunkCount = 4; + constexpr u32 CaveFlagChunkInsCount = 4; + constexpr u32 CaveFlagLdrbDelta = 0x30; + constexpr u32 CavePrologueMargin = 8; + + /* This function consists of multiple chunks. */ + /* Each chunk does a load, a comparison and a conditional branch. The next chunk's address setup (adrp) follows right after it. */ + inline bool IsFlagCheckChunk(const u32 *ptr) { + return _asm::IsOp(ptr[0], _asm::op::LdrbImm, _asm::field::Rt, _asm::field::Rn, _asm::field::Off1) + && _asm::Ignoring(ptr[1], _asm::CmpImm32(0, 1), _asm::field::Rn) + && _asm::Ignoring(ptr[2], _asm::Encode(_asm::op::BCond, {_asm::field::BCond, _asm::cond::Eq}), _asm::field::Imm19); + } + + inline bool IsChunkDeltaValid(const u32 *prev, const u32 *next) { + return IsFlagCheckChunk(next) && _asm::Get(*next, _asm::field::Off1) == _asm::Get(*prev, _asm::field::Off1) + CaveFlagLdrbDelta; + } + + inline bool ValidateChunkConsistency(const u32 *first) { + for (u32 i = 1; i < CaveFlagChunkCount; ++i) { + if (!IsChunkDeltaValid(first + (i - 1) * CaveFlagChunkInsCount, first + i * CaveFlagChunkInsCount)) { + return false; + } + } + + return true; + } + + inline bool CaveFlagRunPatternFn(u32 *ptr) { + if (Hooks().CaveFree() >= HookContext::RequiredCaveSize()) { + return false; + } + /* In case we don't have enough cave memory, we need to commit this warcrime. */ + + /* Ensure we don't dereference invalid memory. */ + u32 *textEnd = reinterpret_cast(g_pcv_cave); + if (ptr - CaveFlagChunkInsCount < nsoStart || ptr + CaveFlagChunkCount * CaveFlagChunkInsCount > textEnd) { + return false; + } + + /* Validate the current chunk and the previous chunk and ensure the delta of the ldrb instructions is consistent. */ + if (!IsFlagCheckChunk(ptr) || IsChunkDeltaValid(ptr - CaveFlagChunkInsCount, ptr)) { + return false; + } + + return ValidateChunkConsistency(ptr); + } + + Result DeadDestructorCaveFind(u32 *ptr); + Result CaveInstall(); + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cpu.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cpu.cpp index 01400c9d..d106668a 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cpu.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cpu.cpp @@ -5,7 +5,7 @@ * * Copyright (c) B3711 * - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -21,20 +21,187 @@ */ #include "../pcv.hpp" +#include "pcv_mariko_cpu.hpp" namespace ams::ldr::hoc::pcv::mariko { - u32 CapCpuClock() { - u32 cpuCap = allowedCpuMaxFrequencies[0]; + namespace { + u32 CapCpuClock() { + u32 cpuCap = allowedCpuMaxFrequencies[0]; - for (u32 freq : allowedCpuMaxFrequencies) { - if (C.marikoCpuMaxClock >= freq) { - cpuCap = freq; - } else { - break; + for (u32 freq : allowedCpuMaxFrequencies) { + if (C.marikoCpuMaxClock >= freq) { + cpuCap = freq; + } else { + break; + } + } + return cpuCap; + } + + /* TODO: Reduce code duplication. */ + cvb_entry_t *GetDvfsTable() { + switch (C.tableConf) { + case TBREAK_1683: return const_cast(C.marikoCpuDvfsTable1683Tbreak); + case TBREAK_1581: return const_cast(C.marikoCpuDvfsTable1581Tbreak); + case EXTREME_TABLE: return const_cast(C.marikoCpuDvfsTableExtreme); + case DEFAULT_TABLE: + default: + return const_cast(mariko::CpuCvbTableDefault); } } - return cpuCap; + + /* Todo: Reduce code duplication of this. */ + Result GetCpuSpeedo(u32 &cpuSpeedo) { + constexpr u64 FusePhysicalAddress = 0x7000F000; + u64 virtualAddress = 0; + constexpr u64 Size = 0x1000; + + u64 outSize; + /* TODO: use svc::QueryMemoryMapping instead. */ + R_TRY(svcQueryMemoryMapping(&virtualAddress, &outSize, FusePhysicalAddress, Size)); + + constexpr u32 FuseOffset = 2048; + constexpr u32 CpuSpeedoOffset = 0x114; + cpuSpeedo = *reinterpret_cast(virtualAddress + FuseOffset + CpuSpeedoOffset); + + R_SUCCEED(); + } + + u32 CalculateCvbVoltage(cvb_entry_t *entry, u32 speedo, u32 speedoScale) { + float speedDiv = static_cast(speedo) / speedoScale; + return ((entry->cvb_dfll_param.c2 * speedDiv + entry->cvb_dfll_param.c1) * speedDiv + entry->cvb_dfll_param.c0); + } + + u32 DivRoundUp(u32 n, u32 d) { + return (n + d - 1) / d; + } + + u32 RoundCvbVoltage(u32 mv, u32 vScale, u32 stepUv) { + u32 step = (stepUv ? stepUv : 1000) * vScale; + + u32 uv = mv * 1000; + uv = DivRoundUp(uv, step) * stepUv; + return uv / 1000; + } + + u32 EffVmin() { return C.marikoCpuLowVmin ? C.marikoCpuLowVmin : CpuVminOfficial; } + u32 EffVmax() { return C.marikoCpuMaxVolt ? C.marikoCpuMaxVolt : CpuVoltOfficial; } + + u32 ClampVoltage(u32 mv) { + return std::clamp(mv, EffVmin(), EffVmax()); + } + + constexpr u32 PmicBaseMv = 250; + constexpr u32 PmicStepMv = 5; + constexpr u32 PmicVoltCount = 256; + + u32 GetExactVoltCode(u32 mv) { + u32 alignMult = mv / PmicStepMv; + + for (u32 i = 0; i < PmicVoltCount; ++i) { + u32 regMult = (PmicBaseMv + i * PmicStepMv) / PmicStepMv; + if (alignMult == regMult) { + return i; + } + } + + return UINT32_MAX; + } + + u32 GetVoltCode(u32 mv) { + u32 alignMult = DivRoundUp(mv, PmicStepMv); + + for (u32 i = 0; i < PmicVoltCount; i++) { + u32 regMult = (PmicBaseMv + i * PmicStepMv) / PmicStepMv; + if (alignMult <= regMult) { + return i; + } + } + + return UINT32_MAX; + } + + Result BuildLut(u32 *lut, const u32 *voltArray) { + const u32 vMin = EffVmin(); + const u32 vMax = *std::max_element(voltArray, voltArray + ClDvfsLutSize); + R_UNLESS(vMin <= vMax, ldr::ResultInvalidCpuMinVolt()); + + u32 voltage = vMin; + u32 code = GetExactVoltCode(voltage); + R_UNLESS(code != UINT32_MAX, ldr::ResultInvalidVoltCode()); + lut[0] = code; + + u32 j = 1; + for (u32 i = 0; i < ClDvfsLutSize; ++i) { + for (;;) { + R_UNLESS(j < ClDvfsLutSize, ldr::ResultInvalidVoltLutIndex()); + + voltage += std::max(1u, (vMax - voltage) / (ClDvfsLutSize - j)); + if (voltage >= voltArray[i]) { + break; + } + + code = GetVoltCode(voltage); + R_UNLESS(code != UINT32_MAX, ldr::ResultInvalidVoltCode()); + if (code != lut[j - 1]) { + lut[j++] = code; + } + } + + voltage = (j == ClDvfsLutSize - 1) ? vMax : voltArray[i]; + code = GetExactVoltCode(voltage); + R_UNLESS(code != UINT32_MAX, ldr::ResultInvalidVoltCode()); + + if (code != lut[j - 1]) { + R_UNLESS(j < ClDvfsLutSize, ldr::ResultInvalidVoltLutIndex()); + lut[j++] = code; + } + + if (voltage >= vMax) { + break; + } + } + + for (u32 k = j; k < ClDvfsLutSize; ++k) { + lut[k] = lut[j - 1]; + } + + R_SUCCEED(); + } + + /* Since doing the proper lut creation in pcv is wasteful, we'll do it ourselves */ + Result FillLutTable(HookPayloadData *data) { + /* Step 1: Get the speedo. */ + u32 cpuSpeedo = 0; + R_TRY(GetCpuSpeedo(cpuSpeedo)); + + /* Step 2: Select the appropriate table. */ + cvb_entry_t *table = GetDvfsTable(); + constexpr u32 SpeedoScale = 100; + constexpr u32 VoltageScale = 1000; + constexpr u32 StepUv = 5000; + + /* Step 3: Fill the voltage array. */ + u32 voltArray[ClDvfsLutSize] = {}; + for (u32 i = 0; i < DvfsTableEntryLimit; ++i) { + u32 voltage = CalculateCvbVoltage(&table[i], cpuSpeedo, SpeedoScale); + voltage = RoundCvbVoltage(voltage, VoltageScale, StepUv); + voltage = ClampVoltage(voltage); + + voltArray[i] = voltage; + } + + /* Step 4: Build the lut table. */ + u32 lut[ClDvfsLutSize] = {}; + R_TRY(BuildLut(lut, voltArray)); + + /* Step 5: Copy it. */ + std::memcpy(data->lut64.table, lut, sizeof(lut)); + + /* Step 6: Finally done. */ + R_SUCCEED(); + } } Result CpuFreqVdd(u32 *ptr) { @@ -227,6 +394,10 @@ namespace ams::ldr::hoc::pcv::mariko { PATCH_OFFSET(&(entry->tune0_high), 0xdfff); PATCH_OFFSET(&(entry->tune1_high), 0x27f07ff); break; + case 13: + PATCH_OFFSET(&(entry->tune0_high), 0xdfff); + PATCH_OFFSET(&(entry->tune1_high), 0x27FF7FF); + break; default: break; } @@ -234,4 +405,213 @@ namespace ams::ldr::hoc::pcv::mariko { R_SUCCEED(); } + /* Little helper for ORR:LSL pairs which are found in here */ + inline bool IsOrrLsl(u32 w) { + if (!_asm::IsOp(w, _asm::op::OrrShifted32, _asm::field::Rd, _asm::field::Rn, _asm::field::Rm, _asm::field::Shift, _asm::field::Imm6)) + return false; + return _asm::Get(w, _asm::field::Shift) == 0; /* 0=LSL, 1=LSR, 2=ASR, 3=ROR */ + } + + /* Probably overcomplicated but I wanted to have a rock-solid way to do this regardless of FW version */ + Result CpuLutMaxAsm(u32* ptr) { + /* Check for the dual ORR-LSL pairs*/ + R_UNLESS(IsOrrLsl(ptr[2]), ldr::ResultInvalidCpuLutMaxAsmPattern()); + R_UNLESS(IsOrrLsl(ptr[3]), ldr::ResultInvalidCpuLutMaxAsmPattern()); + /* We can safely assume that we are in the right place now */ + + /* Safety check */ + R_UNLESS(ptr - 10 >= nsoStart, ldr::ResultInvalidCpuLutMaxAsmPattern()); + + /* Search for the STRB */ + u32* strb = _asm::ScanAssembly(ptr - 10, 10, _asm::Encode(_asm::op::StrbImm, + {_asm::field::Rt, 0}, {_asm::field::Rn, 0}, {_asm::field::Off1, 0x25D}), _asm::field::Rt, + _asm::field::Rn); + R_UNLESS(strb != nullptr, ldr::ResultInvalidCpuLutMaxAsmPattern()); + + /* Probably a cleaner way to do this?*/ + u32 *prod = strb + 2; + const u32 rd = _asm::Get(*prod, _asm::field::Rd); + if (_asm::IsOp(*prod, _asm::op::Ubfm32, _asm::field::Rd, _asm::field::Rn, _asm::field::Immr, _asm::field::Imm6)) { + /* replacement must carry LSL#16 to make up for ubfiz's remoal */ + const u32 nw = _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, rd}, {_asm::field::Imm16, 0x3F}, {_asm::field::Hw, 1}); + PATCH_OFFSET(prod, nw); /* movz wD,#0x3F,LSL#16 */ + } else { + /* Imm12 is 7 for 0xff*/ + R_UNLESS(_asm::IsOp(*prod, _asm::op::AndImm32, _asm::field::Rd, _asm::field::Rn, _asm::field::Imm12) && _asm::Get(*prod, _asm::field::Imm12) == 7, ldr::ResultInvalidCpuLutMaxAsmPattern()); + /* No need to do the lsl */ + const u32 nw = _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, rd}, {_asm::field::Imm16, 0x3F}); + PATCH_OFFSET(prod, nw); /* movz wD,#0x3F */ + } + + /* Set SAFE to entry 32 */ + PATCH_OFFSET(ptr + 1, _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, _asm::Get(ptr[1], _asm::field::Rd)}, {_asm::field::Imm16, 32})); + + R_SUCCEED(); + } + + namespace { + struct { + u32 *site = nullptr; /* LUT writer prologue. */ + } lutWriterCache; + } + + HOOK_PAYLOAD_FN void CpuLutWriterExpandImpl(u64 param) { + HookPayloadData *data = HOOK_PAYLOAD_PTR(HookPayloadData, m_HookPayloadData); + reinterpret_cast(data->lut64.orig)(param); + + /* *(param+8) = CLDVFS mapping */ + const u64 base = *reinterpret_cast(param + 8); + u32 *lut = reinterpret_cast(base + 0x200); + + for (u32 i = 0; i < ClDvfsLutSize; ++i) { + lut[i] = data->lut64.table[i]; + } + __asm__ volatile("dsb st" ::: "memory"); + } + + Result LutWriterFind(u32 *ptr) { + R_UNLESS(LutWriterPatternFn(ptr), ldr::ResultInvalidCpuLutHook()); + + u32 *prog = _asm::FindFnPrologue(ptr, 140, nsoStart); + R_UNLESS(prog != nullptr, ldr::ResultInvalidCpuLutHook()); + + /* Prolouge must hold MMIO base, so obtain it. */ + bool ok = false; + for (u32 i = 0; i < 8; ++i) { + if (_asm::IsOp(prog[i], _asm::op::LdrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8) + && _asm::Get(prog[i], _asm::field::Rn) == 0 + && _asm::Get(prog[i], _asm::field::Off8) == 0x8) { + ok = true; + break; + } + } + + R_UNLESS(ok, ldr::ResultInvalidCpuLutHook()); + lutWriterCache.site = prog; + + R_SUCCEED(); + } + + Result LutWriterInstallHooks(HookPayloadData *data) { + R_UNLESS(lutWriterCache.site != nullptr, ldr::ResultInvalidCpuLutHook()); + + R_TRY(FillLutTable(data)); + + uintptr_t orig = 0; + R_TRY(INSTALL_IMPL_HOOK_ORIG(lutWriterCache.site, CpuLutWriterExpandImpl, &orig)); + data->lut64.orig = orig; + + R_SUCCEED(); + } + + Result CpuLutMaxAsm2(u32* ptr) { + /* movk w?,#0xFFC0,LSL#16 */ + R_UNLESS(_asm::IsOp(ptr[1], _asm::op::MovkW, _asm::field::Rd, _asm::field::Imm16, _asm::field::Hw) + && _asm::Get(ptr[1], _asm::field::Imm16) == 0xFFC0 + && _asm::Get(ptr[1], _asm::field::Hw) == 1, ldr::ResultInvalidCpuLutMaxAsmPattern()); + + /* and x, x, #0xff */ + R_UNLESS(_asm::IsOp(ptr[2], _asm::op::AndImm32, _asm::field::Rd, _asm::field::Rn, _asm::field::Imm12) || + _asm::Get(ptr[2], _asm::field::Imm12) != 7, ldr::ResultInvalidCpuLutMaxAsmPattern()); + + const u32 rd = _asm::Get(ptr[2], _asm::field::Rd); + PATCH_OFFSET(ptr + 2, _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, rd}, {_asm::field::Imm16, 0x3F})); /* movz wD,#0x3F */ + + R_SUCCEED(); + } + + + /* FW 20.4.0 + 71000571dc 01 01 00 d0 adrp param_2=>aCldvfssetdvcor,aSSRequestedDKh+0x1f = "ClDvfsSetDvcoRateMin" + = " %s divider %#x diff %d\n" + 71000571e0 21 40 27 91 add param_2=>aCldvfssetdvcor,param_2,#0x9d0 = "ClDvfsSetDvcoRateMin" + 71000571e4 c3 9f ff 97 bl nn::pcv::NvLog undefined NvLog(char * fmt, ...) + loc_71000571E8 XREF[1]: 71000571b4(j) + 71000571e8 69 aa 42 a9 ldp x9,x10,[x19, #0x28] + 71000571ec 4a fd 41 d3 lsr x10,x10,#0x1 + 71000571f0 68 26 41 f9 ldr x8,[x19, #0x248] Anchor + 71000571f4 0b 0d 0a cb sub x11,x8,x10, LSL #0x3 Target + 71000571f8 6b 4e 01 f9 str x11,[x19, #0x298] Verify1 + 71000571fc 2c 0d 40 f9 ldr x12,[x9, #0x18] Verify2 + 7100057200 7f 01 0c eb cmp x11,x12 + 7100057204 6b 81 8c 9a csel x11,x11,x12,hi + 7100057208 6b 4e 01 f9 str x11,[x19, #0x298] + 710005720c 2b c9 40 f9 ldr x11,[x9, #0x190] + 7100057210 6b 52 01 f9 str x11,[x19, #0x2a0] + 7100057214 8b 00 00 b4 cbz x11,loc_7100057224 + 7100057218 f4 4f 41 a9 ldp x20,x19,[sp, #local_10] + 710005721c fd 7b c2 a8 ldp x29=>local_20,x30,[sp], #0x20 + 7100057220 c0 03 5f d6 ret + loc_7100057224 XREF[1]: 7100057214(j) + 7100057224 08 15 0a 8b add x8,x8,x10, LSL #0x5 Target + 7100057228 2a 55 81 b9 ldrsw x10,[x9, #0x154] Anchor + 710005722c 68 52 01 f9 str x8,[x19, #0x2a0] Verify1 + + */ + + Result CpuLutDvcoRateCfg(u32* ptr) { + /* Anchor via scanning to prevent ordering issues */ + u32 *sub = _asm::ScanAssembly(ptr + 1, 4, + _asm::Encode(_asm::op::SubShifted64, {_asm::field::Rd, 0}, {_asm::field::Rn, 0}, {_asm::field::Rm, 0}, + {_asm::field::Shift, 0}, {_asm::field::Imm6, 3}), + _asm::field::Rd, _asm::field::Rn, _asm::field::Rm); + R_UNLESS(sub != nullptr, ldr::ResultInvalidDvcoRateConfig()); + + /* Verify */ + R_UNLESS(_asm::IsOp(sub[1], _asm::op::StrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8) + && _asm::Get(sub[1], _asm::field::Off8) == 0x298, ldr::ResultInvalidDvcoRateConfig()); + + /* 22.x uses pre-index ldr x?,[x?,#0x18]! here (0xF8418D6D class). */ + const bool isLdr18 = _asm::IsOp(sub[2], _asm::op::LdrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8) + && _asm::Get(sub[2], _asm::field::Off8) == 0x18; + const bool isLdrPre18 = _asm::IsOp(sub[2], _asm::op::LdrPreImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Imm9) + && _asm::Get(sub[2], _asm::field::Imm9) == 0x18; + R_UNLESS(isLdr18 || isLdrPre18, ldr::ResultInvalidDvcoRateConfig()); + + /* Patch the target */ + PATCH_OFFSET(sub, _asm::Encode(_asm::op::SubShifted64, + {_asm::field::Rd, _asm::Get(*sub, _asm::field::Rd)}, + {_asm::field::Rn, _asm::Get(*sub, _asm::field::Rn)}, + {_asm::field::Rm, _asm::Get(*sub, _asm::field::Rm)}, + {_asm::field::Shift, 0}, {_asm::field::Imm6, 4})); + + /* Search for the second anchor */ + u32* ldrsw = _asm::ScanAssembly(sub, 20, + _asm::Encode(_asm::op::LdrsWImm64, {_asm::field::Rt, 0}, {_asm::field::Rn, 0}, {_asm::field::Off4, 0x154}), + _asm::field::Rt, _asm::field::Rn); + + R_UNLESS(ldrsw != nullptr, ldr::ResultInvalidDvcoRateConfig()); + + /* Validate the str #0x2a0 */ + auto isCorrectStr = [](u32 w) { + return _asm::IsOp(w, _asm::op::StrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8) + && _asm::Get(w, _asm::field::Off8) == 0x2a0; + }; + R_UNLESS(isCorrectStr(ldrsw[1]) || isCorrectStr(ldrsw[2]), ldr::ResultInvalidDvcoRateConfig()); + + /* Validate the target in both directuins */ + /* Due to codegen difference */ + u32 *add = nullptr; + if (_asm::IsOp(ldrsw[-1], _asm::op::AddShifted64, _asm::field::Rd, _asm::field::Rn, _asm::field::Rm, _asm::field::Shift, _asm::field::Imm6) + && _asm::Get(ldrsw[-1], _asm::field::Shift) == 0 + && _asm::Get(ldrsw[-1], _asm::field::Imm6) == 5) { + add = ldrsw - 1; + } + else if (_asm::IsOp(ldrsw[1], _asm::op::AddShifted64, _asm::field::Rd, _asm::field::Rn, _asm::field::Rm, _asm::field::Shift, _asm::field::Imm6) + && _asm::Get(ldrsw[1], _asm::field::Shift) == 0 + && _asm::Get(ldrsw[1], _asm::field::Imm6) == 5) { + add = ldrsw + 1; + } + + R_UNLESS(add != nullptr, ldr::ResultInvalidDvcoRateConfig()); + + /* Patch the second target */ + PATCH_OFFSET(add, _asm::Encode(_asm::op::AddShifted64, + {_asm::field::Rd, _asm::Get(*add, _asm::field::Rd)}, + {_asm::field::Rn, _asm::Get(*add, _asm::field::Rn)}, + {_asm::field::Rm, _asm::Get(*add, _asm::field::Rm)}, + {_asm::field::Shift, 0}, {_asm::field::Imm6, 6})); + + R_SUCCEED(); + } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cpu.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cpu.hpp index f6a570d4..52a400cf 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cpu.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_cpu.hpp @@ -5,7 +5,7 @@ * * Copyright (c) B3711 * - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -23,12 +23,89 @@ #pragma once #include "../pcv.hpp" +#include "../pcv_asm.hpp" +#include "../pcv_hook.hpp" namespace ams::ldr::hoc::pcv::mariko { + extern u32 *nsoStart; + + /* Maybe a cleaner way to do this? */ + inline bool LutWriterPatternFn(u32 *ptr) { + if (_asm::IsOp(*ptr, _asm::op::AndImm64, _asm::field::Rd, _asm::field::Rn, _asm::field::Immr, _asm::field::Imm6) + && _asm::Get(*ptr, _asm::field::Immr) == 61 && _asm::Get(*ptr, _asm::field::Imm6) == 7) + return true; + if (_asm::IsOp(*ptr, _asm::op::AndImm32, _asm::field::Rd, _asm::field::Rn, _asm::field::Imm12) + && _asm::Get(*ptr, _asm::field::Imm12) == 0x747) + return true; + return false; + } + + HOOK_PAYLOAD_FN void CpuLutWriterExpandImpl(u64 param); + Result LutWriterFind(u32 *ptr); + Result LutWriterInstallHooks(HookPayloadData *data); + + constexpr cvb_entry_t CpuCvbTableDefault[] = { + { 204000, { 721589, -12695, 27 }, { } }, + { 306000, { 747134, -14195, 27 }, { } }, + { 408000, { 776324, -15705, 27 }, { } }, + { 510000, { 809160, -17205, 27 }, { } }, + { 612000, { 845641, -18715, 27 }, { } }, + { 714000, { 885768, -20215, 27 }, { } }, + { 816000, { 929540, -21725, 27 }, { } }, + { 918000, { 976958, -23225, 27 }, { } }, + { 1020000, { 1028021, -24725, 27 }, { 1120000 } }, + { 1122000, { 1082730, -26235, 27 }, { 1120000 } }, + { 1224000, { 1141084, -27735, 27 }, { 1120000 } }, + { 1326000, { 1203084, -29245, 27 }, { 1120000 } }, + { 1428000, { 1268729, -30745, 27 }, { 1120000 } }, + { 1581000, { 1374032, -33005, 27 }, { 1120000 } }, + { 1683000, { 1448791, -34505, 27 }, { 1120000 } }, + { 1785000, { 1527196, -36015, 27 }, { 1120000 } }, + { 1887000, { 1609246, -37515, 27 }, { 1120000 } }, + { 1963500, { 1675751, -38635, 27 }, { 1120000 } }, + { }, + }; + + constexpr u32 CpuClkOfficial = 1963'500; + constexpr u32 CpuVoltOfficial = 1120; + constexpr u32 CpuHighVminOfficial = 850; + constexpr u32 CpuVminOfficial = 620; + constexpr u32 CpuTune0Low = 0xFFCF; + + static const u32 cpuVoltagePatchValues[] = { 850, 38, 1120, 1000, 100, 1000, 0 }; + static const s32 cpuVoltagePatchOffsets[] = { -2, -1, 5, 6, 7, 8, 9 }; + static_assert(sizeof(cpuVoltagePatchValues) == sizeof(cpuVoltagePatchOffsets), "Invalid cpuVoltagePatch size"); + + static const u32 cpuVoltThermalData[] = { 620, 1120, 20000, 620, 1120, 70000, 950, 1132, 0, 950, 1227, 0 }; + + /* Refer to customize.cpp for more information */ + static const u32 allowedCpuMaxFrequencies[] = { 1'963'500, 2'091'000, 2'193'000, 2'295'000, 2'397'000, 2'499'000, 2'601'000, 2'703'000, 2'805'000 }; + Result CpuFreqVdd(u32 *ptr); Result CpuVoltDVFS(u32 *ptr); Result CpuVoltThermals(u32 *ptr); Result CpuVoltDfll(u32 *ptr); + Result CpuLutMaxAsm(u32* ptr); + Result CpuLutMaxAsm2(u32* ptr); + Result CpuLutDvcoRateCfg(u32* ptr); + + ALWAYS_INLINE bool CpuLutAsmPatternFn(u32* ptr) { + /* Check if it is a DSB ST, a common indication of CL-DVFS related functions */ + return *ptr == _asm::Dsb(_asm::barrier::St); + } + + ALWAYS_INLINE bool CpuLutAsmPatternFn2(u32* ptr) { + /* Note: We are doing multiple checks here as it is the cleanest method */ + return _asm::IsOp(*ptr, _asm::op::MovzW, _asm::field::Rd, _asm::field::Imm16, _asm::field::Hw) + && _asm::Get(*ptr, _asm::field::Imm16) == 0xC0FF + && _asm::Get(*ptr, _asm::field::Hw) == 0; + } + + ALWAYS_INLINE bool CpuLutDvcoRateCfgPatternFn(u32* ptr) { + /* Again, cleaner to ensure we are on the correct instruction here */ + return _asm::IsOp(*ptr, _asm::op::LdrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8) + && _asm::Get(*ptr, _asm::field::Off8) == 0x248; + } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_gpu.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_gpu.cpp index 5b6c1286..2826f485 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_gpu.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_gpu.cpp @@ -5,7 +5,7 @@ * * Copyright (c) B3711 * - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -22,6 +22,7 @@ #include "../pcv.hpp" #include "../pcv_asm.hpp" +#include "pcv_mariko_gpu.hpp" namespace ams::ldr::hoc::pcv::mariko { @@ -62,19 +63,28 @@ namespace ams::ldr::hoc::pcv::mariko { PATCH_OFFSET(ptr + 12, C.marikoGpuVmin); } + // if (C.marikoGpuVmax) { + // PATCH_OFFSET(ptr - 2, C.marikoGpuVmax); + // PATCH_OFFSET(ptr + 1, C.marikoGpuVmax); + // PATCH_OFFSET(ptr + 4, C.marikoGpuVmax); + // PATCH_OFFSET(ptr + 7, C.marikoGpuVmax); + // PATCH_OFFSET(ptr + 10, C.marikoGpuVmax); + // PATCH_OFFSET(ptr + 13, C.marikoGpuVmax); + // } + R_SUCCEED(); } Result GpuFreqMaxAsm(u32 *ptr32) { // Check if both two instructions match the pattern u32 ins1 = *ptr32, ins2 = *(ptr32 + 1); - if (!(asm_compare_no_rd(ins1, GpuAsmPattern[0]) && asm_compare_no_rd(ins2, GpuAsmPattern[1]))) { + if (!(_asm::Ignoring(ins1, GpuAsmPattern[0], _asm::field::Rd) && _asm::Ignoring(ins2, GpuAsmPattern[1], _asm::field::Rd))) { R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); } // Both instructions should operate on the same register - u8 rd = asm_get_rd(ins1); - if (rd != asm_get_rd(ins2)) { + u8 rd = _asm::Get(ins1, _asm::field::Rd); + if (rd != _asm::Get(ins2, _asm::field::Rd)) { R_THROW(ldr::ResultInvalidGpuFreqMaxPattern()); } @@ -101,8 +111,8 @@ namespace ams::ldr::hoc::pcv::mariko { } u32 asm_patch[2] = { - asm_set_rd(asm_set_imm16(GpuAsmPattern[0], max_clock), rd), - asm_set_rd(asm_set_imm16(GpuAsmPattern[1], max_clock >> 16), rd) + _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, rd}, {_asm::field::Imm16, max_clock}), + _asm::Encode(_asm::op::MovkW, {_asm::field::Rd, rd}, {_asm::field::Imm16, max_clock >> 16}, {_asm::field::Hw, 1}) }; PATCH_OFFSET(ptr32, asm_patch[0]); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_gpu.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_gpu.hpp index f5e4c33f..4f87b6ab 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_gpu.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_gpu.hpp @@ -5,7 +5,7 @@ * * Copyright (c) B3711 * - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -26,6 +26,54 @@ namespace ams::ldr::hoc::pcv::mariko { + constexpr cvb_entry_t GpuCvbTableDefault[] = { + // GPUB01_NA_CVB_TABLE + { 76800, {}, { 610000, } }, + { 153600, {}, { 610000, } }, + { 230400, {}, { 610000, } }, + { 307200, {}, { 610000, } }, + { 384000, {}, { 610000, } }, + { 460800, {}, { 610000, } }, + { 537600, {}, { 801688, -10900, -163, 298, -10599, 162, } }, + { 614400, {}, { 824214, -5743, -452, 238, -6325, 81, } }, + { 691200, {}, { 848830, -3903, -552, 119, -4030, -2, } }, + { 768000, {}, { 891575, -4409, -584, 0, -2849, 39, } }, + { 844800, {}, { 940071, -5367, -602, -60, -63, -93, } }, + { 921600, {}, { 986765, -6637, -614, -179, 1905, -13, } }, + { 998400, {}, { 1098475, -13529, -497, -179, 3626, 9, } }, + { 1075200, {}, { 1163644, -12688, -648, 0, 1077, 40, } }, + { 1152000, {}, { 1204812, -9908, -830, 0, 1469, 110, } }, + { 1228800, {}, { 1277303, -11675, -859, 0, 3722, 313, } }, + { 1267200, {}, { 1335531, -12567, -867, 0, 3681, 559, } }, + { }, + }; + + constexpr u32 GpuClkPllMax = 1300'000'000; + constexpr u32 GpuClkPllLimit = 2'600'000; + constexpr u32 GpuVminOfficial = 610; + + static const u32 gpuDVFSPattern[] = { 1050, 1000, 100, 1000, 10, }; + static const u32 gpuVoltThermalPattern[] = { 800, 1120, 0, 610, 1120, 20000, 610, 1120, 30000, 610, 1120, 50000, 610, 1120, 70000, 610, 1120, 90000, }; + static_assert(sizeof(gpuVoltThermalPattern) == 72, "Invalid gpuVoltThermalPattern"); + + /* GPU Max Clock asm Pattern: + * + * MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11) + * sf | opc | | hw | imm16 | Rd + * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 + * 0 | 1 0 | 1 0 0 1 0 1| 0 0| 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 |0 1 0 1 1 + * + * MOVK W11, #0xE, LSL#16 16 0xE 0xB (11) + * sf | opc | | hw | imm16 | Rd + * #31 |30 29|28 27 26 25 24 23|22 21|20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 |4 3 2 1 0 + * 0 | 1 1 | 1 0 0 1 0 1| 0 1| 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 |0 1 0 1 1 + */ + inline constexpr u32 GpuAsmPattern[] = { 0x52820000, 0x72A001C0 }; + + inline bool GpuMaxClockPatternFn(u32 *ptr32) { + return _asm::Ignoring(*ptr32, GpuAsmPattern[0], _asm::field::Rd); + } + Result GpuVoltDVFS(u32 *ptr); Result GpuVoltThermals(u32 *ptr); Result GpuFreqMaxAsm(u32 *ptr32); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_log.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_log.cpp new file mode 100644 index 00000000..0377aade --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_log.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) Souldbminer, Lightos and Horizon OC Contributors + * + * 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 . + */ + +#include "../pcv.hpp" +#include "pcv_mariko_log.hpp" + +namespace ams::ldr::hoc::pcv::mariko { + + /* Todo: Remove this bs. */ + [[maybe_unused]] static uintptr_t CaveReserve(size_t count) { + return reinterpret_cast(Hooks().Reserve(count)); + } + + #if HOC_UART_LOG + namespace { + struct { + uintptr_t vsnprintf_addr = 0; + uintptr_t nvlog_addr = 0; + } nvLogCache; + } + + Result NvLogUartRedirect(u32 *ptr) { + const uintptr_t mapped_nso = reinterpret_cast(nsoStart); + const size_t nso_size = g_nso_size; + const uintptr_t textEnd = g_pcv_cave; /* .text ends where the cave begins */ + const uintptr_t vsnprintf_addr = reinterpret_cast(ptr); + + { + using namespace _asm::field; + R_UNLESS(_asm::Ignoring(ptr[1], NvLogStpFpLrAsm, PairOff8), ldr::ResultInvalidNvLogRedirect()); /* stp x29,x30,[sp,#imm] */ + R_UNLESS(_asm::Ignoring(ptr[2], NvLogStrSpillAsm, Rt, Off8), ldr::ResultInvalidNvLogRedirect()); /* str x?,[sp,#imm] */ + R_UNLESS(_asm::Ignoring(ptr[3], NvLogMovFpAsm, Imm12), ldr::ResultInvalidNvLogRedirect()); /* add x29,sp,#imm */ + R_UNLESS(ptr[4] == NvLogCmpSizeAsm, ldr::ResultInvalidNvLogRedirect()); /* cmp x1,#0 */ + } + + /* NvLog via the VDD_SOC log */ + static const char Fmt[] = "%s(%s): DVFS request VDD_SOC %d mV\n"; + constexpr size_t FmtLen = sizeof(Fmt) - 1; + uintptr_t strAddr = 0; + { + const char *hay = reinterpret_cast(mapped_nso); + for (size_t i = 0; i + FmtLen <= nso_size; ++i) { + if (std::memcmp(hay + i, Fmt, FmtLen) == 0) { strAddr = mapped_nso + i; break; } + } + } + if (strAddr == 0) { + LOGGING("NvLogRedirect: fmt string not found (vsnprintf@+%lx)", vsnprintf_addr - mapped_nso); + R_THROW(ldr::ResultInvalidNvLogRedirect()); + } + + uintptr_t nvlog_addr = 0; + for (u32 *p = nsoStart; reinterpret_cast(p + 2) <= textEnd; ++p) { + const uintptr_t pc = reinterpret_cast(p); + if (!_asm::IsOp(p[0], _asm::op::Adrp, _asm::field::Rd, _asm::field::ImmAdrpHi, _asm::field::ImmAdrpLo)) { + continue; + } + if (_asm::TargetAdrp(p[0], pc) != (strAddr & ~static_cast(0xFFFu))) { + continue; + } + const u32 adrpReg = _asm::Get(p[0], _asm::field::Rd); + if (!(_asm::IsOp(p[1], _asm::op::AddImm64, _asm::field::Rd, _asm::field::Rn, _asm::field::Imm12) + && _asm::Get(p[1], _asm::field::Rd) == adrpReg && _asm::Get(p[1], _asm::field::Rn) == adrpReg + && _asm::Get(p[1], _asm::field::Imm12) == (strAddr & 0xFFFu))) { + continue; + } + for (u32 k = 2; k <= 12 && (pc + (k + 1) * 4) <= textEnd; ++k) { + if (_asm::IsOp(p[k], _asm::op::Bl, _asm::field::Imm26)) { nvlog_addr = _asm::Target26(p[k], pc + k * 4); break; } + } + if (nvlog_addr != 0) { + break; + } + } + if (nvlog_addr == 0 || nvlog_addr < mapped_nso || nvlog_addr >= textEnd) { + LOGGING("NvLogRedirect: NvLog entry not found (fmt@+%lx)", strAddr - mapped_nso); + R_THROW(ldr::ResultInvalidNvLogRedirect()); + } + + nvLogCache.vsnprintf_addr = vsnprintf_addr; + nvLogCache.nvlog_addr = nvlog_addr; + R_SUCCEED(); + } + + namespace { + Result InstallNvLogRedirect() { + const uintptr_t mapped_nso = reinterpret_cast(nsoStart); + const uintptr_t textEnd = g_pcv_cave; + const uintptr_t vsnprintf_addr = nvLogCache.vsnprintf_addr; + const uintptr_t nvlog_addr = nvLogCache.nvlog_addr; + + const uintptr_t helper = CaveReserve(40); + if (helper == 0) { + LOGGING("NvLogRedirect: cave unavailable (cave=%lx size=%lx)", + static_cast(g_pcv_cave), static_cast(g_pcv_cave_size)); + R_THROW(ldr::ResultInvalidNvLogRedirect()); + } + u32 *t = reinterpret_cast(helper); + size_t n = 0; + auto emit = [&](u32 ins) { t[n] = ins; ++n; }; + + using namespace _asm::field; + constexpr u32 SP = _asm::reg::Sp; + + emit(_asm::Encode(_asm::op::SubImm64, {Rd, SP}, {Rn, SP}, {Imm12, 0x200})); + emit(_asm::Encode(_asm::op::StpImm64, {Rt, 0}, {Rt2, 1}, {Rn, SP}, {PairOff8, 0x100})); + emit(_asm::Encode(_asm::op::StpImm64, {Rt, 2}, {Rt2, 3}, {Rn, SP}, {PairOff8, 0x110})); + emit(_asm::Encode(_asm::op::StpImm64, {Rt, 4}, {Rt2, 5}, {Rn, SP}, {PairOff8, 0x120})); + emit(_asm::Encode(_asm::op::StpImm64, {Rt, 6}, {Rt2, 7}, {Rn, SP}, {PairOff8, 0x130})); + emit(_asm::Encode(_asm::op::StpImmQ, {Rt, 0}, {Rt2, 1}, {Rn, SP}, {PairOff16, 0x140})); + emit(_asm::Encode(_asm::op::StpImmQ, {Rt, 2}, {Rt2, 3}, {Rn, SP}, {PairOff16, 0x160})); + emit(_asm::Encode(_asm::op::StpImmQ, {Rt, 4}, {Rt2, 5}, {Rn, SP}, {PairOff16, 0x180})); + emit(_asm::Encode(_asm::op::StpImmQ, {Rt, 6}, {Rt2, 7}, {Rn, SP}, {PairOff16, 0x1A0})); + emit(_asm::Encode(_asm::op::StrImm64, {Rt, _asm::reg::Lr}, {Rn, SP}, {Off8, 0x1E0})); + emit(_asm::Encode(_asm::op::AddImm64, {Rd, 9}, {Rn, SP}, {Imm12, 0x200})); emit(_asm::Encode(_asm::op::StrImm64, {Rt, 9}, {Rn, SP}, {Off8, 0x1C0})); /* __stack */ + emit(_asm::Encode(_asm::op::AddImm64, {Rd, 9}, {Rn, SP}, {Imm12, 0x140})); emit(_asm::Encode(_asm::op::StrImm64, {Rt, 9}, {Rn, SP}, {Off8, 0x1C8})); /* __gr_top */ + emit(_asm::Encode(_asm::op::AddImm64, {Rd, 9}, {Rn, SP}, {Imm12, 0x1C0})); emit(_asm::Encode(_asm::op::StrImm64, {Rt, 9}, {Rn, SP}, {Off8, 0x1D0})); /* __vr_top */ + emit(_asm::Encode(_asm::op::MovnW, {Rd, 9}, {Imm16, 0x37})); emit(_asm::Encode(_asm::op::StrImm32, {Rt, 9}, {Rn, SP}, {Off4, 0x1D8})); /* __gr_offs = -56 */ + emit(_asm::Encode(_asm::op::MovnW, {Rd, 9}, {Imm16, 0x7F})); emit(_asm::Encode(_asm::op::StrImm32, {Rt, 9}, {Rn, SP}, {Off4, 0x1DC})); /* __vr_offs = -128 */ + emit(_asm::Encode(_asm::op::AddImm64, {Rd, 0}, {Rn, SP}, {Imm12, 0x00})); /* mov x0,sp (buf) */ + emit(_asm::Encode(_asm::op::MovzW, {Rd, 1}, {Imm16, 0x100})); /* size = 0x100 */ + emit(_asm::Encode(_asm::op::LdrImm64, {Rt, 2}, {Rn, SP}, {Off8, 0x100})); /* fmt (saved x0) */ + emit(_asm::Encode(_asm::op::AddImm64, {Rd, 3}, {Rn, SP}, {Imm12, 0x1C0})); /* ap */ + emit(_asm::Retarget26(_asm::op::Bl, helper + n * 4, vsnprintf_addr)); + emit(_asm::MovReg64(1, 0)); /* len = retval */ + emit(_asm::CmpImm32(1, 0x100)); + { /* b.lo +2 */ + const size_t at = n; + emit(_asm::Retarget19(_asm::Encode(_asm::op::BCond, {BCond, _asm::cond::Lo}), helper + at * 4, helper + (at + 2) * 4)); + } + emit(_asm::Encode(_asm::op::MovzW, {Rd, 1}, {Imm16, 0xFF})); /* clamp len */ + emit(_asm::Encode(_asm::op::AddImm64, {Rd, 0}, {Rn, SP}, {Imm12, 0x00})); /* mov x0,sp (str) */ + emit(_asm::Encode(_asm::op::Svc, {Imm16, 0x27})); /* svcOutputDebugString */ + emit(_asm::Encode(_asm::op::LdrImm64, {Rt, _asm::reg::Lr}, {Rn, SP}, {Off8, 0x1E0})); + emit(_asm::Encode(_asm::op::AddImm64, {Rd, SP}, {Rn, SP}, {Imm12, 0x200})); + emit(_asm::RetIns); + + /* Redirect the call sites as patching the actual function causes crash */ + const uintptr_t roStart = g_pcv_cave + g_pcv_cave_size; /* module .rodata start */ + size_t patchedSites = 0; + for (u32 *p = nsoStart; reinterpret_cast(p + 1) <= textEnd; ++p) { + if (!_asm::IsOp(*p, _asm::op::Bl, _asm::field::Imm26)) { + continue; + } + const uintptr_t pc = reinterpret_cast(p); + if (_asm::Target26(*p, pc) != nvlog_addr) { + continue; + } + bool isFmtCall = false; + for (u32 j = 1; j <= 8 && reinterpret_cast(p - j) >= reinterpret_cast(nsoStart); ++j) { + const u32 w = *(p - j); + if (_asm::IsOp(w, _asm::op::Adrp, _asm::field::Rd, _asm::field::ImmAdrpHi, _asm::field::ImmAdrpLo) && _asm::Get(w, _asm::field::Rd) == 0) { /* adrp x0, */ + const uintptr_t tgtPage = _asm::TargetAdrp(w, pc - j * 4); + if (tgtPage >= (roStart & ~static_cast(0xFFFu))) { isFmtCall = true; break; } + } + } + if (isFmtCall) { + PATCH_OFFSET(p, _asm::Retarget26(_asm::op::Bl, pc, helper)); + ++patchedSites; + } + } + + LOGGING("NvLogRedirect: stub@+%lx vsnprintf@+%lx helper@+%lx instr=%zu sites=%zu", nvlog_addr - mapped_nso, vsnprintf_addr - mapped_nso, helper - mapped_nso, n, patchedSites); + R_SUCCEED(); + } + } + + namespace { + struct { + u32 *sites[3] = {}; + u32 count = 0; + } forceVerbosityCache; + } + + HOOK_PAYLOAD_FN u32 ForceVerbosityImpl() { + HookPayloadData *data = HOOK_PAYLOAD_PTR(HookPayloadData, m_HookPayloadData); + return data->verbosityLevel; + } + + /* Force GetEffectiveVerbosityLevel to return a non-zero level so all NvLog runs. */ + Result ForceVerbosity(u32 *ptr) { + using namespace _asm::field; + + R_UNLESS(_asm::IsOp(ptr[1], _asm::op::StrImm64, Rt, Rn, Off8) && _asm::Get(ptr[1], Rn) == _asm::reg::Sp, + ldr::ResultInvalidForceVerbosityPattern()); /* str x?,[sp,#imm] */ + R_UNLESS(_asm::IsOp(ptr[2], _asm::op::AddImm64, Rd, Rn, Imm12) + && _asm::Get(ptr[2], Rd) == _asm::reg::Fp && _asm::Get(ptr[2], Rn) == _asm::reg::Sp, + ldr::ResultInvalidForceVerbosityPattern()); /* add x29,sp,#imm */ + R_UNLESS(_asm::IsOp(ptr[3], _asm::op::AddImm64, Rn, Imm12) + && _asm::Get(ptr[3], Rd) == 0 && _asm::Get(ptr[3], Rn) == _asm::reg::Fp, + ldr::ResultInvalidForceVerbosityPattern()); /* add x0,x29,#imm */ + R_UNLESS(_asm::IsOp(ptr[4], _asm::op::AddImm64, Rd, Rn, Imm12) && _asm::Get(ptr[4], Rn) == _asm::reg::Fp, + ldr::ResultInvalidForceVerbosityPattern()); /* add x?,x29,#imm */ + R_UNLESS(_asm::Get(ptr[3], Imm12) == _asm::Get(ptr[4], Imm12) + && _asm::IsOp(ptr[5], _asm::op::Bl, Imm26), + ldr::ResultInvalidForceVerbosityPattern()); + + bool foundCmp = false; + for (u32 j = 6; j <= 10; ++j) { + if (ptr[j] == 0x7100001Fu) { /* cmp w0,#0 */ + foundCmp = true; + break; + } + } + R_UNLESS(foundCmp, ldr::ResultInvalidForceVerbosityPattern()); + + R_UNLESS(forceVerbosityCache.count < std::size(forceVerbosityCache.sites), ldr::ResultInvalidForceVerbosityPattern()); + forceVerbosityCache.sites[forceVerbosityCache.count++] = ptr; + R_SUCCEED(); + } + + Result ForceVebosityInstallHooks(HookPayloadData *data) { + if (nvLogCache.nvlog_addr != 0) { + R_TRY(InstallNvLogRedirect()); + } + + if (forceVerbosityCache.count != 0 && C.pcvLogVerbosity != 0xff) { + data->verbosityLevel = C.pcvLogVerbosity; + for (u32 i = 0; i < forceVerbosityCache.count; ++i) { + R_DISCARD(INSTALL_IMPL_HOOK(forceVerbosityCache.sites[i], ForceVerbosityImpl)); + } + } + + R_SUCCEED(); + } +#endif + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_log.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_log.hpp new file mode 100644 index 00000000..f9855e19 --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_log.hpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) Souldbminer, Lightos and Horizon OC Contributors + * + * 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 . + */ + +#pragma once + +#include "../pcv.hpp" + +namespace ams::ldr::hoc::pcv::mariko { + + extern u32 *nsoStart; + extern size_t g_nso_size; + + inline bool ForceVerbosityPatternFn(u32 *ptr) { + if (g_pcv_cave == 0) { + return false; + } + if (reinterpret_cast(ptr + 11) > g_pcv_cave) { /* .text only */ + return false; + } + return _asm::IsFramePushPre(*ptr); + } + + /* + sub sp, sp, #imm + stp x29,x30,[sp,#imm] + str x?, [sp,#imm] + add x29,sp, #imm + subs xzr, x1, #0 + */ + constexpr u32 NvLogSubSpAsm = 0xD10003FFu; /* sub sp,sp,#0 */ + constexpr u32 NvLogStpFpLrAsm = 0xA9007BFDu; /* stp x29,x30,[sp,#0] */ + constexpr u32 NvLogStrSpillAsm = 0xF90003E0u; /* str x?,[sp,#0] */ + constexpr u32 NvLogMovFpAsm = 0x910003FDu; /* add x29,sp,#0 */ + constexpr u32 NvLogCmpSizeAsm = 0xF100003Fu; /* subs xzr,x1,#0 */ + + inline bool NvLogVsnprintfPatternFn(u32 *ptr) { + if (HOC_UART_LOG == 0 || g_pcv_cave == 0) { + return false; + } + if (reinterpret_cast(ptr + 5) > g_pcv_cave) { /* must sit in .text */ + return false; + } + return _asm::Ignoring(*ptr, NvLogSubSpAsm, _asm::field::Imm12); + } + + Result NvLogUartRedirect(u32 *ptr); + HOOK_PAYLOAD_FN u32 ForceVerbosityImpl(); + Result ForceVerbosity(u32 *ptr); + Result ForceVebosityInstallHooks(HookPayloadData *data); + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_mtc.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_mtc.cpp index 7dacbdbe..49fadc9b 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_mtc.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_mtc.cpp @@ -5,7 +5,7 @@ * * Copyright (c) B3711 * - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -23,6 +23,7 @@ #include "../pcv.hpp" #include "../../mtc_timing_value.hpp" #include "calculate_timings_mariko.hpp" +#include "pcv_mariko_mtc.hpp" namespace ams::ldr::hoc::pcv::mariko { @@ -35,6 +36,8 @@ namespace ams::ldr::hoc::pcv::mariko { * https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual * Section 18.11.1: MC Registers * Section 18.11.2: EMC Registers + * + * Additional information from reverse-engineering public Tegra K1 (T124) memory characterization tools. */ #define WRITE_PARAM_ALL_REG(TABLE, PARAM, VALUE) \ @@ -44,8 +47,6 @@ namespace ams::ldr::hoc::pcv::mariko { const double tCK_avg = 1000'000.0 / table->rate_khz; - #define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg)) - /* Ram power down */ /* B31: DRAM_CLKSTOP_PD */ /* B30: DRAM_CLKSTOP_SR */ @@ -56,13 +57,12 @@ namespace ams::ldr::hoc::pcv::mariko { WRITE_PARAM_ALL_REG(table, emc_cfg, 0xF3200000); } + CalculateTimings(tCK_avg, table->rate_khz); + u32 trefbw = refresh_raw + 0x40; trefbw = MIN(trefbw, static_cast(0x3FFF)); - const u32 dyn_self_ref_control = (static_cast(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000); - CalculateTimings(tCK_avg, table->rate_khz); - 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_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast(0xB9))); @@ -235,6 +235,9 @@ namespace ams::ldr::hoc::pcv::mariko { const u32 tRFCabStock = tRFC_values[0] * 2; table->dram_timings.t_rfc = tRFCabStock; + /* dram_timings.rl is used on Erista to calculate specific RL related timings during memory training for a workaround. */ + /* See fusee or minerva for more details. */ + /* This is unused on Mariko but we will set it regardless for completion. */ table->dram_timings.rl = RL; table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast(mrw2); table->emc_mrw = (table->emc_mrw & ~0x70u) | 0x40; /* nWR */ @@ -298,8 +301,18 @@ namespace ams::ldr::hoc::pcv::mariko { } } + void AppendMaxEmc(std::vector &emcList) { + if (emcList.back() != C.marikoEmcMaxClock) { + emcList.push_back(static_cast(C.marikoEmcMaxClock)); + } + } + + void TruncateToLutLimit(std::vector &emcList, size_t limit) { + emcList.resize(std::min(emcList.size(), limit)); + } + void MtcGenerateJedecTable() { - const u32 jedecFreqs[] = { 1866000, 1996000, 2133000, 2400000, 2666000, 2933000, 3200000 }; + const u32 jedecFreqs[] = { 1866000, 1996800, 2133000, 2400000, 2666000, 2933000, 3200000 }; constexpr u32 JedecFreqCount = std::size(jedecFreqs); for (u32 i = 0; i < JedecFreqCount; ++i) { @@ -310,11 +323,8 @@ namespace ams::ldr::hoc::pcv::mariko { } } - if (newEmcList.back() != C.marikoEmcMaxClock) { - newEmcList.push_back(static_cast(C.marikoEmcMaxClock)); - } - - newEmcList.resize(std::min(newEmcList.size(), EmcDvfsTableEntryLimit)); + AppendMaxEmc(newEmcList); + TruncateToLutLimit(newEmcList, EmcDvfsTableEntryLimit); } void MtcGenerate133StepTable() { @@ -329,11 +339,8 @@ namespace ams::ldr::hoc::pcv::mariko { } } - if (newEmcList.back() != C.marikoEmcMaxClock) { - newEmcList.push_back(static_cast(C.marikoEmcMaxClock)); - } - - newEmcList.resize(std::min(newEmcList.size(), EmcDvfsTableEntryLimit)); + AppendMaxEmc(newEmcList); + TruncateToLutLimit(newEmcList, EmcDvfsTableEntryLimit); } void MtcGenerate33StepTable() { @@ -356,11 +363,8 @@ namespace ams::ldr::hoc::pcv::mariko { } } - if (newEmcList.back() != C.marikoEmcMaxClock) { - newEmcList.push_back(static_cast(C.marikoEmcMaxClock)); - } - - newEmcList.resize(std::min(newEmcList.size(), EmcDvfsTableEntryLimit)); + AppendMaxEmc(newEmcList); + TruncateToLutLimit(newEmcList, EmcDvfsTableEntryLimit); } void MtcGenerateFreqTables() { @@ -399,15 +403,13 @@ namespace ams::ldr::hoc::pcv::mariko { u32 newFreq = EmcClkOSLimit + stepIndex * stepRate; newFreq = (newFreq / RoundHz) * RoundHz; if (newFreq > C.marikoEmcMaxClock) { - if (newEmcList.back() != C.marikoEmcMaxClock) { - newEmcList.push_back(static_cast(C.marikoEmcMaxClock)); - } + AppendMaxEmc(newEmcList); break; } newEmcList.push_back(newFreq); } - newEmcList.resize(std::min(newEmcList.size(), EmcDvfsTableEntryLimit)); + TruncateToLutLimit(newEmcList, EmcDvfsTableEntryLimit); } Result VerifyMtcTable(MarikoMtcTable *tableStart, u32 expectedFreq) { @@ -475,7 +477,6 @@ namespace ams::ldr::hoc::pcv::mariko { Result MemFreqMtcTable(u32 *ptr) { static const DramId dramId = [] { DramId id = GetDramId(); - id = HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF; return id; }(); @@ -522,6 +523,24 @@ namespace ams::ldr::hoc::pcv::mariko { R_SUCCEED(); } + void Get32LutEmcList(std::vector &emcList) { + /* No need to reduce outside of 33MHz stepmode. */ + if (C.stepMode != StepMode_33MHz || emcList.size() <= DvfsTableEntryLimit) { + return; + } + + /* Add every other oc entry. */ + std::vector reduced(emcList.begin(), emcList.begin() + mariko::MtcTableCountDefault); + for (size_t i = mariko::MtcTableCountDefault; i < emcList.size(); i += 2) { + reduced.push_back(emcList[i]); + } + + TruncateToLutLimit(reduced, DvfsTableEntryLimit); + AppendMaxEmc(reduced); + + emcList = std::move(reduced); + } + Result MemFreqDvbTable(u32 *ptr) { DvbEntry *default_end = reinterpret_cast(ptr); DvbEntry *new_start = default_end + 1; @@ -535,9 +554,9 @@ namespace ams::ldr::hoc::pcv::mariko { R_SKIP(); } - s32 max0 = 1050; - s32 max1 = 1025; - s32 max2 = 1000; + s32 max0 = 1050; + s32 max1 = 1025; + s32 max2 = 1000; if (C.marikoSocVmax && C.marikoSocVmax > 1000) { max0 = C.marikoSocVmax; @@ -612,12 +631,15 @@ namespace ams::ldr::hoc::pcv::mariko { #undef DVB #undef DVB_OC - const size_t dvbCount = std::min(newEmcList.size(), DvbTableCapacity); - DvbEntry emcDvbTableOc[DvbTableCapacity] = {}; + std::vector reducedEmcList = newEmcList; + Get32LutEmcList(reducedEmcList); + + const size_t dvbCount = std::min(reducedEmcList.size(), DvfsTableEntryCount); + DvbEntry emcDvbTableOc[DvfsTableEntryCount] = {}; u32 bracketIndex = 0; for (size_t i = 0; i < dvbCount; ++i) { - const u32 freq = (i == dvbCount - 1) ? static_cast(newEmcList.back()) : newEmcList[i]; + const u32 freq = reducedEmcList[i]; while (freq >= emcDvbOcTableBrackets[bracketIndex + 1].freq) { ++bracketIndex; } @@ -627,7 +649,7 @@ namespace ams::ldr::hoc::pcv::mariko { } /* Clear the entire 32-entry region */ - std::memset(mem_dvb_table_head, 0, DvbTableCapacity * sizeof(DvbEntry)); + std::memset(mem_dvb_table_head, 0, DvfsTableEntryCount * sizeof(DvbEntry)); std::memcpy(mem_dvb_table_head, emcDvbTableOc, dvbCount * sizeof(DvbEntry)); R_SUCCEED(); @@ -651,26 +673,78 @@ namespace ams::ldr::hoc::pcv::mariko { R_UNLESS(ptr - BrOffset >= nsoStart, ldr::ResultInvalidMtcTablePattern()); u32 adrp = *(ptr - AddpOffset); - R_UNLESS(AsmCompareAdrpNoImm(adrp, MtcAdrpAsm), ldr::ResultInvalidMtcTablePattern()); + R_UNLESS(_asm::Ignoring(adrp, MtcAdrpAsm, _asm::field::ImmAdrpHi, _asm::field::ImmAdrpLo), ldr::ResultInvalidMtcTablePattern()); /* We don't check for matching register because both registers must be x0 in order to pass the previous checks. */ /* The correct instructions will always be x0 since the mtcTable pointer is returned. */ /* Pray this does not break. */ u32 br = *(ptr - BrOffset); - R_UNLESS(AsmCompareBrNoRd(br, MtcBrAsm), ldr::ResultInvalidMtcTablePattern()); + R_UNLESS(_asm::Ignoring(br, MtcBrAsm, _asm::field::Rn), ldr::ResultInvalidMtcTablePattern()); /* Pray this does not break either. */ u32 mov = *(ptr - MovOffset); - R_UNLESS(asm_compare_no_rd(mov, MtcMovAsm), ldr::ResultInvalidMtcTablePattern()); + R_UNLESS(_asm::Ignoring(mov, MtcMovAsm, _asm::field::Rd), ldr::ResultInvalidMtcTablePattern()); - u8 movRd = asm_get_rd(mov); - u32 movCountPatch = asm_set_rd(asm_set_imm16(MtcMovAsm, newEmcList.size()), movRd); + u8 movRd = _asm::Get(mov, _asm::field::Rd); + u32 movCountPatch = _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, movRd}, {_asm::field::Imm16, newEmcList.size()}); - PATCH_OFFSET(ptr - BrOffset, NopIns); + PATCH_OFFSET(ptr - BrOffset, _asm::NopIns); PATCH_OFFSET(ptr - MovOffset, movCountPatch); R_SUCCEED(); } + Result I2cSet_U8(I2cDevice dev, u8 reg, u8 val) { + struct { + u8 reg; + u8 val; + } __attribute__((packed)) cmd; + + I2cSession _session; + R_TRY(i2cOpenSession(&_session, dev)); + + cmd.reg = reg; + cmd.val = val; + Result res = i2csessionSendAuto(&_session, &cmd, sizeof(cmd), I2cTransactionOption_All); + i2csessionClose(&_session); + + return res; + } + + Result EmcVddqVolt(u32 *ptr) { + regulator *entry = reinterpret_cast(reinterpret_cast(ptr) - offsetof(regulator, type_2_3.default_uv)); + + constexpr u32 uv_step = 5'000; + constexpr u32 uv_min = 250'000; + + auto validator = [entry]() { + R_UNLESS(entry->id == 2, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type == 3, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type_2_3.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry()); + R_UNLESS(entry->type_2_3.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry()); + R_SUCCEED(); + }; + + R_TRY(validator()); + + u32 emc_uv = C.marikoEmcVddqVolt; + + if (!emc_uv) { + R_SKIP(); + } + + if (emc_uv % uv_step) { + emc_uv = (emc_uv + uv_step - 1) / uv_step * uv_step; // rounding + } + + PATCH_OFFSET(ptr, emc_uv); + + i2cInitialize(); + Result resultI2C = I2cSet_U8(I2cDevice_Max77812_2, 0x25, (emc_uv - uv_min) / uv_step); + i2cExit(); + + return resultI2C; + } + } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_mtc.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_mtc.hpp index 99531813..f9c2826c 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_mtc.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_mtc.hpp @@ -5,7 +5,7 @@ * * Copyright (c) B3711 * - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -26,10 +26,181 @@ namespace ams::ldr::hoc::pcv::mariko { + extern u32 *nsoStart; + + struct DvbEntry { + u64 freq; + u32 volt[4] = {}; + }; + + constexpr DvbEntry EmcDvbTableDefault[] = { + { 204000, { 637, 637, 637, } }, + { 408000, { 637, 637, 637, } }, + { 800000, { 637, 637, 637, } }, + { 1065600, { 637, 637, 637, } }, + { 1331200, { 650, 637, 637, } }, + { 1600000, { 675, 650, 637, } }, + }; + + constexpr u32 EmcListDefault[] = { 204000, 1331200, 1600000, }; + constexpr u32 EmcListSizeDefault = std::size(EmcListDefault); + constexpr u32 EmcListEndDefault = EmcListSizeDefault - 1; + + constexpr u32 EmcClkOSAlt = 1331'200; + constexpr u32 EmcClkPllmLimit = 2133'000'000; + constexpr u32 EmcVddqDefault = 600'000; + constexpr u32 MemVdd2Default = 1100'000; + + constexpr u32 MTC_TABLE_REV = 3; + constexpr u32 MtcTableCountDefault = 3; + + constexpr size_t MtcFullTableSize = sizeof(MarikoMtcTable) * MtcTableCountDefault; + constexpr u32 MtcFullTableCount = 17; + + /* These dramids were copied from Hekate -- see /bdk/mem/sdram.h */ + enum DramId : u64 { + HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 3, + AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 5, + IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE = 6, + + IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 8, + IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 9, + IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 10, + IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE = 11, + + HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ = 12, + HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ = 13, + HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME = 14, + HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE = 15, + + IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 17, + IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 18, + HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 19, + + IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 20, + HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 21, + AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL = 22, + + HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 23, + AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL = 24, + + IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 25, + HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF = 26, + AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF = 27, + + AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL = 28, + + IOWA_4GB_HYNIX_H54G46CYRBX267 = 29, + HOAG_4GB_HYNIX_H54G46CYRBX267 = 30, + AULA_4GB_HYNIX_H54G46CYRBX267 = 31, + + IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 32, + HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB = 33, + AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB = 34, + }; + + enum MtcTableIndex { + T210b0SdevEmcDvfsTableS4gb01 = 0, /* (Unused) Samsung 4Gb */ + T210b0SdevEmcDvfsTableS4gb03 = 1, /* Samsung AM-MGCJ 4Gb */ + T210b0SdevEmcDvfsTableS8gb03 = 2, /* (Unused) Samsung 4Gb */ + T210b0SdevEmcDvfsTableH4gb03 = 3, /* Hynix NME 4Gb */ + T210b0SdevEmcDvfsTableM4gb03 = 4, /* Micron WT:F 4Gb */ + T210b0SdevEmcDvfsTableS4gbY01 = 5, /* (Unused) Samsung 4Gb */ + T210b0SdevEmcDvfsTableS1y4gbY01 = 6, /* (Unused) Samsung 4Gb */ + T210b0SdevEmcDvfsTableS1y8gbY01 = 7, /* (Unused) Samsung 4Gb */ + T210b0SdevEmcDvfsTableS1y4gbX03 = 8, /* Samsung AA-MGCL 4Gb */ + T210b0SdevEmcDvfsTableS1y8gbX03 = 9, /* Samsung AA-MGCL 8Gb */ + T210b0SdevEmcDvfsTableS1y4gb01 = 10, /* (Unused) Samsung 4Gb */ + T210b0SdevEmcDvfsTableM1y4gb01 = 11, /* Micron WT:E 4Gb */ + T210b0SdevEmcDvfsTableH1y4gb01 = 12, /* Hynix NEE 4Gb */ + T210b0SdevEmcDvfsTableS1y8gb04 = 13, /* Samsung AM-MGCJ 8Gb */ + T210b0SdevEmcDvfsTableS1z4gb01 = 14, /* Samsung AB-MGCL 4Gb */ + T210b0SdevEmcDvfsTableH1a4gb01 = 15, /* Hynix x267 4Gb */ + T210b0SdevEmcDvfsTableM1a4gb01 = 16, /* Micron WT:B 8Gb */ + MtcTableIndex_Invalid = 17, + }; + + struct MtcDramIndex { + DramId dramId; + MtcTableIndex index; + }; + + const inline MtcDramIndex mtcIndexTable[] = { + { HOAG_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, }, + { AULA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, }, + { IOWA_4GB_HYNIX_H9HCNNNBKMMLXR_NEE, T210b0SdevEmcDvfsTableH1y4gb01, }, + { IOWA_4GB_SAMSUNG_K4U6E3S4AM_MGCJ, T210b0SdevEmcDvfsTableS4gb03, }, + { IOWA_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, T210b0SdevEmcDvfsTableS1y8gb04, }, + { IOWA_4GB_HYNIX_H9HCNNNBKMMLHR_NME, T210b0SdevEmcDvfsTableH4gb03, }, + { IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTE, T210b0SdevEmcDvfsTableM1y4gb01, }, + { HOAG_4GB_SAMSUNG_K4U6E3S4AM_MGCJ, T210b0SdevEmcDvfsTableS4gb03, }, + { HOAG_8GB_SAMSUNG_K4UBE3D4AM_MGCJ, T210b0SdevEmcDvfsTableS1y8gb04, }, + { HOAG_4GB_HYNIX_H9HCNNNBKMMLHR_NME, T210b0SdevEmcDvfsTableH4gb03, }, + { HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTE, T210b0SdevEmcDvfsTableM1y4gb01, }, + { IOWA_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, }, + { IOWA_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, }, + { HOAG_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, }, + { IOWA_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1z4gb01, }, + { HOAG_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1y8gb04, }, + { AULA_4GB_SAMSUNG_K4U6E3S4AB_MGCL, T210b0SdevEmcDvfsTableS1y8gb04, }, + { HOAG_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, }, + { AULA_4GB_SAMSUNG_K4U6E3S4AA_MGCL, T210b0SdevEmcDvfsTableS1y4gbX03, }, + { IOWA_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, }, + { HOAG_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, }, + { AULA_4GB_MICRON_MT53E512M32D2NP_046_WTF, T210b0SdevEmcDvfsTableM4gb03, }, + { AULA_8GB_SAMSUNG_K4UBE3D4AA_MGCL, T210b0SdevEmcDvfsTableS1y8gbX03, }, + { IOWA_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, }, + { HOAG_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, }, + { AULA_4GB_HYNIX_H54G46CYRBX267, T210b0SdevEmcDvfsTableH1a4gb01, }, + { IOWA_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, }, + { HOAG_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, }, + { AULA_4GB_MICRON_MT53E512M32D1NP_046_WTB, T210b0SdevEmcDvfsTableM1a4gb01, }, + }; + + /* + 710006abfc 40 01 1f d6 br x10 + */ + + /* + 710006ac28 a0 03 00 90 adrp x0,0x71000de000 + 710006ac2c 00 80 16 91 add x0=>SdevEmcDvfsTableS4gb01,x0,#0x5a0 + */ + + /* Br */ + /* + | Z | OP | Fixed | A | M | RN | RM + 31 30 29 28 27 26 25 | 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 |11 | 10 | 9 8 7 6 5 | 4 3 2 1 0 + 1 1 0 1 0 1 1 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 Rn 0 0 0 0 0 + Z op A M Rm + */ + + /* Adrp */ + /* + OP | ImmLow | | ImmHigh | RD + 31 | 30 29 | 28 27 26 25 24 | 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0 + */ + + /* ADD (immediate) */ + /* + SF | OP | S | Fixed value | Sh | Imm12 | RN | RD + 31 | 30 | 29 | 28 27 26 25 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0 + */ + + constexpr u32 MtcBrAsm = 0xD61F0140; + constexpr u32 MtcMovAsm = 0x52800068; + constexpr u32 MtcAdrpAsm = 0x900003A0; + constexpr u32 MtcAddAsm = 0x91168000; + + ALWAYS_INLINE bool MemMtcGetGetTablePatternFn(u32 *ptr) { + /* This builds an address that gets returned, so the register must be x0 by convention. */ + return _asm::Ignoring(*ptr, MtcAddAsm, _asm::field::Imm12); + } + void MtcGenerateFreqTables(); Result MemFreqMtcTable(u32 *ptr); Result MemFreqDvbTable(u32 *ptr); Result MemFreqMax(u32 *ptr); Result MemMtcTableAsm(u32 *ptr); + Result EmcVddqVolt(u32 *ptr); } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_soc.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_soc.cpp new file mode 100644 index 00000000..e053248f --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_soc.cpp @@ -0,0 +1,325 @@ +/* + * Copyright (c) Souldbminer, Lightos and Horizon OC Contributors + * + * 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 . + */ + +#include "../pcv.hpp" +#include "pcv_mariko_soc.hpp" + +namespace ams::ldr::hoc::pcv::mariko { + + namespace { + + struct { + u32 *site = nullptr; + } busInitCache; + + Result GetSocSpeedo(u32 &socSpeedo) { + constexpr u64 FusePhysicalAddress = 0x7000F000; + u64 virtualAddress = 0; + constexpr u64 Size = 0x1000; + + u64 outSize; + /* TODO: use svc::QueryMemoryMapping instead. */ + R_TRY(svcQueryMemoryMapping(&virtualAddress, &outSize, FusePhysicalAddress, Size)); + + constexpr u32 FuseOffset = 2048; + constexpr u32 SocSpeedoOffset = 0x134; + socSpeedo = *reinterpret_cast(virtualAddress + FuseOffset + SocSpeedoOffset); + + R_SUCCEED(); + } + + u32 GetSocProcessId(u32 socSpeedo) { + if (socSpeedo <= 1597) { + return 0; + } + + if (socSpeedo <= 1708) { + return 1; + } + + /* >= 1709. */ + return 2; + } + + } + + Result SocVoltAsm(u32 *compareSpeedos) { + using namespace _asm::field; + + constexpr u32 VoltageScanLimit = 10; + /* Might actually be speedo id. */ + u32 *writeProcessId = _asm::ScanAssembly(compareSpeedos, VoltageScanLimit, SocVoltWriteProcessIdAsm, Rd); + R_UNLESS(writeProcessId != nullptr, ldr::ResultInvalidSocVoltPattern()); + u8 writeProcessIdRd = _asm::Get(*writeProcessId, Rd); + + /* This writes 1050mV. */ + u32 *writeVoltage = _asm::ScanAssembly(writeProcessId, VoltageScanLimit, SocVoltWriteVoltageAsm, Rd); + R_UNLESS(writeVoltage != nullptr, ldr::ResultInvalidSocVoltPattern()); + u8 writeVoltageRd = _asm::Get(*writeVoltage, Rd); + + /* A csel instruction is used to select the soc voltage limit register. */ + /* We care about its destination register since that is used for verification. */ + constexpr u32 VoltageSelectScanLimit = 24; + u32 *selectVoltage = _asm::ScanAssembly(writeVoltage, VoltageSelectScanLimit, SocVoltSelectRegisterAsm, Rd, Rn, Rm); + R_UNLESS(selectVoltage != nullptr, ldr::ResultInvalidSocVoltPattern()); + /* Todo: check rm and rn? */ + u8 selectVoltageRd = _asm::Get(*selectVoltage, Rd); + + /* rdCsel is then multiplied by 1000 to convert to uV. */ + /* This is pretty far down the function. */ + constexpr u32 MultiplierScanLimit = 200; + u32 *multiplier = _asm::ScanAssembly(selectVoltage, MultiplierScanLimit, SocVoltMultiplyVoltsAsm, Rd, Rn, Rm); + R_UNLESS(multiplier != nullptr, ldr::ResultInvalidSocVoltPattern()); + u8 multiplierRn = _asm::Get(*multiplier, Rn); + u8 multiplierRm = _asm::Get(*multiplier, Rm); + /* One of the two registers has to be rdCsel. */ + R_UNLESS((multiplierRn == selectVoltageRd) || (multiplierRm == selectVoltageRd), ldr::ResultInvalidSocVoltPattern()); + u8 multiplierRd = _asm::Get(*multiplier, Rd); + + /* Subs instruction is then used to verify against absolute limit. */ + /* NB: Rn is written into the pattern and then ignored by the comparison; only Rm is matched. */ + u32 limitValidationPattern = _asm::Set(SocVoltValidateLimitAsm, Rn, multiplierRd); + u32 *limitValidation = _asm::ScanAssembly(multiplier, VoltageScanLimit, limitValidationPattern, Rd, Rn); + R_UNLESS(limitValidation != nullptr, ldr::ResultInvalidSocVoltPattern()); + + /* There is a b.gt instruction right after (checks for socVoltageCap < socVoltageMax). */ + u32 *branchToAbort = limitValidation + 1; + R_UNLESS(_asm::Ignoring(*branchToAbort, SocVoltBranchToAbortAsm, Imm19), ldr::ResultInvalidSocVoltPattern()); + + if (!C.marikoSocVmax || C.marikoSocVmax <= 1000) { + R_SKIP(); + } + + /* Adjust 1598 speedo minimum to ensure it always goes down process id 0 branch. */ + /* 2200 should be high enough :D */ + u32 compareSpeedosPatch = _asm::Set(*compareSpeedos, Imm12, 2200); + PATCH_OFFSET(compareSpeedos, compareSpeedosPatch); + + u32 socSpeedo = 0; + R_TRY(GetSocSpeedo(socSpeedo)); + + /* Adjust processId from 0 to [process id of switch booting this]. */ + /* We're overwriting the orr instruction entirly. */ + u32 processId = GetSocProcessId(socSpeedo); + u32 writeProcessIdPatch = _asm::Encode(_asm::op::MovzW, {Rd, writeProcessIdRd}, {Imm16, processId}); + PATCH_OFFSET(writeProcessId, writeProcessIdPatch); + + /* Adjust voltage limit. */ + u32 voltageLimitPatch = _asm::Encode(_asm::op::MovzW, {Rd, writeVoltageRd}, {Imm16, C.marikoSocVmax}); + PATCH_OFFSET(writeVoltage, voltageLimitPatch); + + /* Branches to an abort if limits are invalid -- we patch the branch instruction with NOP. */ + PATCH_OFFSET(branchToAbort, _asm::NopIns); + + R_SUCCEED(); + } + + Result SocVoltLimit(u32 *ptr) { + R_UNLESS(!std::memcmp(ptr - SocVoltLimitMaxDefaultIndex, socVoltLimitArray, sizeof(socVoltLimitArray)), ldr::ResultInvalidSocVoltLimit()); + if (!C.marikoSocVmax || C.marikoSocVmax <= SocVoltLimitOfficial) { + R_SKIP(); + } + + constexpr u32 Step = 25; + u32 maxVolt = C.marikoSocVmax; + if (maxVolt % Step) { + maxVolt = maxVolt / Step * Step; /* Round. */ + } + + u32 volt = SocVoltLimitOfficial; + for (u32 i = 1; i < DvfsTableEntryCount - SocVoltLimitMaxDefaultIndex && volt < maxVolt; ++i) { + volt += Step; + PATCH_OFFSET(ptr + i, volt); + } + + R_SUCCEED(); + } + + HOOK_PAYLOAD_FN u64 BusFreqExtendImpl(SharedClkBus *bus) { + HookPayloadData *data = HOOK_PAYLOAD_PTR(HookPayloadData, m_HookPayloadData); + + u32 *table = data->busData.next; + bus->allowedFreqTable = table; + data->busData.next = table + EmcDvfsTableEntryCount; + + /* Call the original function. */ + return reinterpret_cast(data->busData.originalFnCallback)(bus); + } + + /* Relocate and extend C2/C3Bus to avoid issues (likely buffer overflow) */ + Result BusFreqReloc(u32 *ptr) { + using namespace _asm::field; + + const u32 bus = _asm::Get(ptr[0], Rn); + R_UNLESS(_asm::IsOp(ptr[1], _asm::op::AddImm64, Rd, Rn, Imm12) && _asm::Get(ptr[1], Imm12) == 0x18 && _asm::Get(ptr[1], Rn) == bus, + ldr::ResultInvalidBusFreqReloc()); /* add Xcnt,Xbus,#0x18 */ + R_UNLESS(_asm::IsOp(ptr[2], _asm::op::StrImm64, Rt, Rn, Off8) && _asm::Get(ptr[2], Off8) == 0x50 && _asm::Get(ptr[2], Rn) == bus, + ldr::ResultInvalidBusFreqReloc()); /* str Xrail,[Xbus,#0x50] */ + R_UNLESS(_asm::IsOp(ptr[3], _asm::op::Bl, Imm26), ldr::ResultInvalidBusFreqReloc()); /* bl GetDvfsRailUniqueFreqList */ + + constexpr u32 PrologueMargin = 140; + u32 *functionPrologue = _asm::FindFnPrologue(ptr, PrologueMargin, nsoStart); + R_UNLESS(functionPrologue != nullptr, ldr::ResultInvalidBusFreqReloc()); + + busInitCache.site = functionPrologue; + + R_SUCCEED(); + } + + /* Widen InitDram for a >32-entry EMC DVFS list. Freq array can be dropped to free 264 bytes, relocate the Soc LUT to that space */ + Result EmcSocLutReloc(u32 *ptr) { + constexpr u32 Window = 48; + + using namespace _asm::field; + + R_UNLESS(_asm::Ignoring(ptr[1], EmcSocLutCountStoreAsm, Rt), ldr::ResultInvalidEmcSocLut()); /* str w?,[x0,#0x154] */ + + u32 *freqStore = _asm::ScanAssembly(ptr - Window, Window, EmcSocFreqStoreAsm, Rt); /* str x?,[x8,#0x18] */ + u32 *voltStore = _asm::ScanAssembly(ptr - Window, Window, EmcSocVoltStoreAsm, Rt); /* str w?,[x8,#0x48] */ + u32 *readLoad = _asm::ScanAssembly(ptr - Window, Window, EmcSocReadLoadAsm, Rt); /* ldr w?,[x9,#0x48] */ + R_UNLESS(freqStore && voltStore && readLoad, ldr::ResultInvalidEmcSocLut()); + + u32 *voltBase = voltStore - 2; /* `add Xb,Xsrc,Xi,LSL#2` (a cmn sits between it and store) */ + R_UNLESS(_asm::IsOp(*voltBase, _asm::op::AddShifted64, Rd, Rn, Rm, Imm6) && _asm::Get(*voltBase, Rd) == _asm::Get(*voltStore, Rn), ldr::ResultInvalidEmcSocLut()); + + /* adrp Xl ; add Xl,Xl,#off ; ... ; str Xl,[rail,#0x120] */ + const u32 lutReg = _asm::Get(ptr[0], Rt); + const u32 railReg = _asm::Get(ptr[0], Rn); + R_UNLESS(_asm::IsOp(ptr[-3], _asm::op::Adrp, Rd, ImmAdrpHi, ImmAdrpLo) && _asm::Get(ptr[-3], Rd) == lutReg, ldr::ResultInvalidEmcSocLut()); + R_UNLESS(_asm::IsOp(ptr[-2], _asm::op::AddImm64, Rd, Rn, Imm12) && _asm::Get(ptr[-2], Rd) == lutReg && _asm::Get(ptr[-2], Rn) == lutReg, ldr::ResultInvalidEmcSocLut()); + + const u32 srcBase = _asm::Get(*voltBase, Rn); /* rail ptr at +0x20 */ + const u32 wBase = _asm::Get(*voltBase, Rd); /* base reg */ + const u32 wIdx = _asm::Get(*voltBase, Rm); /* loop index */ + + PATCH_OFFSET(freqStore, _asm::NopIns); /* Unneeded */ + PATCH_OFFSET(voltBase, _asm::Encode(_asm::op::LdrImm64, {Rt, wBase}, {Rn, srcBase}, {Off8, 0x20})); /* ldr Xb,[Xsrc,#0x20] (rail) */ + PATCH_OFFSET(voltStore - 1, _asm::Encode(_asm::op::AddImm64, {Rd, wBase}, {Rn, wBase}, {Imm12, 0x18})); /* add Xb,Xb,#0x18 (was cmn) */ + PATCH_OFFSET(voltStore, _asm::ToRegOffset(*voltStore, wIdx)); /* str Wv,[Xb,Xi,LSL#2] -> rail+0x18+i*4 */ + PATCH_OFFSET(voltStore + 1, _asm::NopIns); /* Unneeded */ + + /* rail+0x18 as the socMinLut pointer. */ + PATCH_OFFSET(ptr - 3, _asm::NopIns); + PATCH_OFFSET(ptr - 2, _asm::Encode(_asm::op::AddImm64, {Rd, lutReg}, {Rn, railReg}, {Imm12, 0x18})); /* add Xl,rail,#0x18 */ + + /* Drop the abort branch in case of a bad read */ + for (u32 i = 1; i <= 4; ++i) { + if (_asm::IsOp(readLoad[i], _asm::op::BCond, Imm19, BCond)) { + PATCH_OFFSET(&readLoad[i], _asm::NopIns); + break; + } + } + R_SUCCEED(); + } + + Result EmcDvfsCountLimit(u32 *ptr) { + R_UNLESS(_asm::IsOp(*(ptr - 1), _asm::op::Cbz, _asm::field::Imm19, _asm::field::Rt), ldr::ResultInvalidEmcDvfsCount()); /* cbz w?, */ + R_UNLESS(_asm::Ignoring(*(ptr + 1), _asm::Encode(_asm::op::BCond, {_asm::field::BCond, _asm::cond::Cs}), _asm::field::Imm19), + ldr::ResultInvalidEmcDvfsCount()); /* b.cs */ + + /* cmp w?,#0x21 -> cmp w?,#EmcDvfsTableEntryCount */ + PATCH_OFFSET(ptr, _asm::Set(*ptr, _asm::field::Imm12, EmcDvfsTableEntryCount)); + R_SUCCEED(); + } + + Result EmcRateListLimit(u32 *ptr) { + R_UNLESS(_asm::Ignoring(ptr[1], EmcRateCapCselAsm, _asm::field::Rd, _asm::field::Rn, _asm::field::Rm) + && _asm::Get(ptr[0], _asm::field::Rn) == _asm::Get(ptr[1], _asm::field::Rn), + ldr::ResultInvalidEmcRateList()); /* csel w?,w?,w?,lt, min(reg, 0x20) */ + R_UNLESS(_asm::IsOp(ptr[2], _asm::op::Bl, _asm::field::Imm26), ldr::ResultInvalidEmcRateList()); + + /* The csel's Rm holds the 32 cap. */ + const u32 capReg = _asm::Get(ptr[1], _asm::field::Rm); + const u32 capMov = _asm::Encode(_asm::op::MovzW, {_asm::field::Rd, capReg}, {_asm::field::Imm16, 0x20}); /* movz w,#0x20 */ + + u32 *movPtr = nullptr; + for (u32 i = 1; i <= 16; ++i) { + if (*(ptr - i) == capMov) { + movPtr = ptr - i; + break; + } + } + R_UNLESS(movPtr, ldr::ResultInvalidEmcRateList()); + + /* min(maxCount, 32) -> min(maxCount, EmcDvfsTableEntryCount). */ + PATCH_OFFSET(ptr, _asm::Set(*ptr, _asm::field::Imm12, EmcDvfsTableEntryCount)); /* cmp w?,#64 */ + PATCH_OFFSET(movPtr, _asm::Set(*movPtr, _asm::field::Imm16, EmcDvfsTableEntryCount)); /* movz w?,#64 */ + R_SUCCEED(); + } + + Result EmcRateSessLimit(u32 *ptr) { + u32 movzI = 0; + R_UNLESS(EmcRateSessFindClamp(ptr, nullptr, nullptr, &movzI), ldr::ResultInvalidEmcRateList()); + + /* Reject cmd11 GetDvfsTable. */ + for (u32 i = 1; i <= 24; ++i) { + const u32 w = ptr[i]; + if (_asm::IsOp(w, _asm::op::SubImm64, _asm::field::Rd, _asm::field::Rn, _asm::field::Imm12) + && _asm::Get(w, _asm::field::Rn) == _asm::reg::Fp && _asm::Get(w, _asm::field::Imm12) >= 0x20u) { /* sub x?,x29,#>=0x20 */ + R_THROW(ldr::ResultInvalidEmcRateList()); + } + } + + /* mov x,x2 */ + u32 descReg = 0xFFu; + for (u32 i = 1; i <= 24; ++i) { + if (_asm::Ignoring(ptr[i], _asm::MovReg64(0, 2), _asm::field::Rd)) { descReg = _asm::Get(ptr[i], _asm::field::Rd); break; } + } + R_UNLESS(descReg != 0xFFu, ldr::ResultInvalidEmcRateList()); + + /* Repoint the duplicated-imm pair */ + u32 *adds[8]; u32 addImm[8]; u32 nAdds = 0; + for (u32 i = 1; i <= 24 && nAdds < 8; ++i) { + const u32 w = ptr[i]; + if (_asm::IsOp(w, _asm::op::AddImm64, _asm::field::Rd, _asm::field::Rn, _asm::field::Imm12) && _asm::Get(w, _asm::field::Rn) == _asm::reg::Sp) { /* add x?,sp,#imm12 (shift 0) */ + adds[nAdds] = ptr + i; + addImm[nAdds] = _asm::Get(w, _asm::field::Imm12); + ++nAdds; + } + } + u32 patched = 0; + for (u32 a = 0; a < nAdds; ++a) { + bool dup = false; + for (u32 b = 0; b < nAdds; ++b) { + if (a != b && addImm[a] == addImm[b]) { dup = true; break; } + } + if (dup) { + PATCH_OFFSET(adds[a], _asm::Encode(_asm::op::LdrImm64, {_asm::field::Rt, _asm::Get(*adds[a], _asm::field::Rd)}, + {_asm::field::Rn, descReg}, + {_asm::field::Off8, 0})); /* ldr x?,[x] */ + ++patched; + } + } + R_UNLESS(patched == 2, ldr::ResultInvalidEmcRateList()); + + /* min(maxCount, 32) -> min(maxCount, EmcDvfsTableEntryCount) */ + PATCH_OFFSET(ptr, _asm::Set(*ptr, _asm::field::Imm12, EmcDvfsTableEntryCount)); /* cmp w?,#64 */ + PATCH_OFFSET(ptr + movzI, _asm::Set(*(ptr + movzI), _asm::field::Imm16, EmcDvfsTableEntryCount)); /* movz w?,#64 */ + R_SUCCEED(); + } + + Result SharedClkBusInstallHooks(HookPayloadData *data) { + R_UNLESS(busInitCache.site != nullptr, ldr::ResultInvalidBusFreqReloc()); + + uintptr_t originalFn = 0; + R_TRY(INSTALL_IMPL_HOOK_ORIG(busInitCache.site, BusFreqExtendImpl, &originalFn)); + data->busData.originalFnCallback = originalFn; + data->busData.next = reinterpret_cast(Hooks().ToVa(data->busData.table[0])); + + R_SUCCEED(); + } + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_soc.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_soc.hpp new file mode 100644 index 00000000..04ea6792 --- /dev/null +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/pcv_mariko_soc.hpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) Souldbminer, Lightos and Horizon OC Contributors + * + * 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 . + */ + +#pragma once + +#include "pcv_mariko.hpp" + +namespace ams::ldr::hoc::pcv::mariko { + + extern u32 *nsoStart; + + /* Movz */ + /* + SF | OPC | HW | Imm16 | RD + 31 | 30 29 28 27 26 25 24 23 | 22 21 | 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 | 4 3 2 1 0 + */ + constexpr u32 SocVoltCompareSpeedoAsm = 0x7118FAFF; /* subs imm, compares to >=1598 max speedo and then goes down process id 1 route. */ + constexpr u32 SocVoltWriteProcessIdAsm = 0x2A1F03F4; /* orr, writes id 0. */ + constexpr u32 SocVoltWriteVoltageAsm = 0x52808358; /* Movz imm, writes 1050mV. */ + constexpr u32 SocVoltSelectRegisterAsm = 0x1A9A3118; /* Csel, selects the voltage -- we need the register of this. */ + constexpr u32 SocVoltMultiplyVoltsAsm = 0x1B1A7F0B; /* Mul, converts from mV -> uV */ + constexpr u32 SocVoltValidateLimitAsm = 0x6B0A017F; /* Subs, checks limits */ + constexpr u32 SocVoltBranchToAbortAsm = 0x540020AC; /* B.ge Branches to abort if limits are invalid. */ + + ALWAYS_INLINE bool SocVoltPatternFn(u32 *ptr) { + return _asm::Ignoring(*ptr, SocVoltCompareSpeedoAsm, _asm::field::Rd); + } + + constexpr u32 SocVoltLimitOfficial = 1050; + constexpr u32 SocVoltLimitMaxDefaultIndex = 17; + static const u32 socVoltLimitArray[DvfsTableEntryCount] = { 637, 650, 675, 700, 725, 750, 775, 800, 825, 850, 875, 900, 925, 950, 975, 1000, 1025, 1050, }; + + constexpr u32 EmcCountCmpAsm = 0x7100851F; /* cmp w?,#0x21 (subs wzr,w?,#0x21) */ + + /* + str ,[,#0x120] ; volt-array pointer + str w?, [,#0x154] ; num_freqs + */ + constexpr u32 EmcSocLutPtrStoreAsm = 0xF9009009; /* str x?,[x0,#0x120] (anchor) */ + constexpr u32 EmcSocLutCountStoreAsm = 0xB9015408; /* str w?,[x0,#0x154] (anchor) */ + constexpr u32 EmcSocFreqStoreAsm = 0xF9000D00; /* str x?,[x8,#0x18] */ + constexpr u32 EmcSocVoltStoreAsm = 0xB9004900; /* str w?,[x8,#0x48] (socMinLut[i]) */ + constexpr u32 EmcSocReadLoadAsm = 0xB9404929; /* ldr w?,[x9,#0x48] (socMinLut) */ + + inline bool EmcDvfsCountPatternFn(u32 *ptr) { + return _asm::Ignoring(*ptr, EmcCountCmpAsm, _asm::field::Rd); + } + + inline bool EmcSocLutPatternFn(u32 *ptr) { + return _asm::Ignoring(*ptr, EmcSocLutPtrStoreAsm, _asm::field::Rt); /* str x?,[x0,#0x120] */ + } + + /* + mov w?,#0x20 ; the 32 cap + cmp w?,#0x20 + csel w?,w?,w?,lt ; w? = min(maxCount, 32) + bl TegraGetEmcDvfsFreqTable + + cmp w?,#0x20 ; (maxCount) + csel w?,,,lt ; min(maxCount, 32) + bl <_asm::Get*DvfsFreqTable> + */ + constexpr u32 EmcRateCapCmpAsm = 0x710082FF; /* cmp w?,#0x20 */ + constexpr u32 EmcRateCapCselAsm = 0x1A80B000; /* csel w?,w?,w?,lt */ + + inline bool EmcRateListPatternFn(u32 *ptr) { + return _asm::Ignoring(*ptr, EmcRateCapCmpAsm, _asm::field::Rd, _asm::field::Rn); + } + + constexpr u32 EmcRateSessCmpAsm = 0x710082FF; /* cmp w?,#0x20 */ + constexpr u32 EmcRateSessMovAsm = 0x52800400; /* movz w?,#0x20 */ + constexpr u32 EmcRateSessCselAsm = 0x1A80B000; /* csel w?,w?,w?,lt (opcode + cond) */ + + inline bool EmcRateSessFindClamp(u32 *ptr, u32 *out_c, u32 *out_cap, u32 *out_movz_i) { + const u32 c = _asm::Get(ptr[0], _asm::field::Rn); + for (u32 i = 1; i <= 14; ++i) { + const u32 w = ptr[i]; + if (_asm::Ignoring(w, EmcRateSessCselAsm, _asm::field::Rd, _asm::field::Rn, _asm::field::Rm) && _asm::Get(w, _asm::field::Rn) == c && _asm::Get(w, _asm::field::Rd) == c) { + const u32 cap = _asm::Get(w, _asm::field::Rm); + for (u32 j = 1; j < i; ++j) { + if (_asm::Ignoring(ptr[j], EmcRateSessMovAsm, _asm::field::Rd) && _asm::Get(ptr[j], _asm::field::Rd) == cap) { + if (out_c) *out_c = c; + if (out_cap) *out_cap = cap; + if (out_movz_i) *out_movz_i = j; + return true; + } + } + return false; + } + } + return false; + } + + inline bool EmcRateSessPatternFn(u32 *ptr) { + return _asm::Ignoring(*ptr, EmcRateSessCmpAsm, _asm::field::Rd, _asm::field::Rn); + } + + inline bool BusFreqRelocPatternFn(u32 *ptr) { + if (g_pcv_cave == 0) { + return false; + } + if (reinterpret_cast(ptr + 4) > g_pcv_cave) { /* the call site lives in .text */ + return false; + } + return _asm::IsOp(*ptr, _asm::op::LdrImm64, _asm::field::Rt, _asm::field::Rn, _asm::field::Off8) + && _asm::Get(*ptr, _asm::field::Off8) == 0x10; /* ldr Xbuf,[Xbus,#0x10] */ + } + + Result SocVoltAsm(u32 *compareSpeedos); + Result SocVoltLimit(u32 *ptr); + HOOK_PAYLOAD_FN u64 BusFreqExtendImpl(SharedClkBus *bus); + Result BusFreqReloc(u32 *ptr); + Result EmcSocLutReloc(u32 *ptr); + Result EmcDvfsCountLimit(u32 *ptr); + Result EmcRateListLimit(u32 *ptr); + Result EmcRateSessLimit(u32 *ptr); + Result SharedClkBusInstallHooks(HookPayloadData *data); + +} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/timing_tables.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/timing_tables.cpp deleted file mode 100644 index ecb4d47f..00000000 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/mariko/timing_tables.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 . - */ - -#include "../../oc_common.hpp" -#include "timing_tables.hpp" - -namespace ams::ldr::hoc::pcv::mariko { - - const ReplacePatch g_rext_table[] = { - {2'133'000, 0x1A}, {2'166'000, 0x19}, {2'200'000, 0x19}, - {2'233'000, 0x19}, {2'266'000, 0x1A}, {2'300'000, 0x1B}, - {2'333'000, 0x1B}, {2'366'000, 0x1B}, {2'400'000, 0x1B}, - {2'433'000, 0x1B}, {2'466'000, 0x1B}, {2'500'000, 0x1A}, - {2'533'000, 0x1C}, {2'566'000, 0x1B}, {2'600'000, 0x1B}, - {2'633'000, 0x1B}, {2'666'000, 0x1B}, {2'700'000, 0x1C}, - {2'733'000, 0x1C}, {2'766'000, 0x1D}, {2'800'000, 0x1D}, - {2'833'000, 0x1D}, {2'866'000, 0x1D}, {2'900'000, 0x1D}, - {2'933'000, 0x1C}, {2'966'000, 0x1D}, {3'000'000, 0x1D}, - {3'033'000, 0x1D}, {3'066'000, 0x1D}, {3'100'000, 0x1D}, - {3'133'000, 0x1D}, {3'166'000, 0x1C}, {3'200'000, 0x1C}, - }; - - const u32 g_rext_table_size = sizeof(g_rext_table) / sizeof(g_rext_table[0]); - - const ReplacePatch *FindRext() { - for (u32 i = 0; i < g_rext_table_size; i++) { - if (g_rext_table[i].freq >= C.marikoEmcMaxClock) { - return &g_rext_table[i]; - } - } - return nullptr; - } - -} diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp index dca615fc..42fd2423 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp @@ -82,6 +82,7 @@ namespace ams::ldr::hoc::pcv { u32 max; u32 panic; bool value_required = false; + const char *name = "unnamed"; Result Check() { if (!value_required && !value) { @@ -147,26 +148,28 @@ namespace ams::ldr::hoc::pcv { } Validator validators[] = { - { C.eristaCpuBoostClock, 1020'000, 2397'000, panic::Cpu, true }, - { C.marikoCpuBoostClock, 1020'000, 2703'000, panic::Cpu, true }, - { C.eristaCpuMaxVolt, 1000, 1260, panic::Cpu, }, - { C.marikoCpuMaxVolt, 1000, 1200, panic::Cpu, }, - { eristaCpuDvfsMaxFreq, 1785'000, 2397'000, panic::Cpu, }, - { marikoCpuDvfsMaxFreq, 1785'000, 2703'000, panic::Cpu, }, - { C.commonEmcMemVolt, 912'500, 1350'000, panic::Emc, }, /* Official vmax for the RAMs is 1400-1500mV */ - { C.eristaEmcMaxClock, 1600'000, 2600'000, panic::Emc, }, - { C.marikoEmcMaxClock, 1600'000, 3500'000, panic::Emc, }, - { C.marikoEmcVddqVolt, 400'000, 750'000, panic::Emc, }, - { C.marikoSocVmax, 1000, 1200, panic::Emc, }, - { eristaGpuDvfsMaxFreq, 768'000, 1152'000, panic::Gpu, }, - { marikoGpuDvfsMaxFreq, 768'000, 1536'000, panic::Gpu, }, - { C.marikoGpuVmax, 800, 960, panic::Gpu, }, + { C.eristaCpuBoostClock, 1020'000, 2397'000, panic::Cpu, true, "eristaCpuBoostClock" }, + { C.marikoCpuBoostClock, 1020'000, 2805'000, panic::Cpu, true, "marikoCpuBoostClock" }, + { C.eristaCpuMaxVolt, 1000, 1260, panic::Cpu, false, "eristaCpuMaxVolt" }, + { C.marikoCpuMaxVolt, 1000, 1235, panic::Cpu, false, "marikoCpuMaxVolt" }, + { eristaCpuDvfsMaxFreq, 1785'000, 2397'000, panic::Cpu, false, "eristaCpuDvfsMaxFreq"}, + { marikoCpuDvfsMaxFreq, 1785'000, 2805'000, panic::Cpu, false, "marikoCpuDvfsMaxFreq"}, + { C.commonEmcMemVolt, 912'500, 1350'000, panic::Emc, false, "commonEmcMemVolt" }, /* Official vmax for the RAMs is 1400-1500mV */ + { C.eristaEmcMaxClock, 1600'000, 2600'000, panic::Emc, false, "eristaEmcMaxClock" }, + { C.marikoEmcMaxClock, 1600'000, 3500'000, panic::Emc, false, "marikoEmcMaxClock" }, + { C.marikoEmcVddqVolt, 400'000, 750'000, panic::Emc, false, "marikoEmcVddqVolt" }, + { C.marikoSocVmax, 1000, 1200, panic::Emc, false, "marikoSocVmax" }, + { eristaGpuDvfsMaxFreq, 768'000, 1152'000, panic::Gpu, false, "eristaGpuDvfsMaxFreq"}, + { marikoGpuDvfsMaxFreq, 768'000, 1574'400, panic::Gpu, false, "marikoGpuDvfsMaxFreq"}, + { C.marikoGpuVmax, 800, 995, panic::Gpu, false, "marikoGpuVmax" }, /* Official GPU vMax is 1050mV */ }; for (auto &v : validators) { if (R_FAILED(v.Check())) { + LOGGING("Validation FAIL: %s value=%u min=%u max=%u", v.name, static_cast(v.value), v.min, v.max); panic::SmcError(v.panic); CRASH("Validation FAIL"); + } } } diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp index c50f55a8..1b45a170 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.hpp @@ -29,6 +29,9 @@ #include "erista/pcv_erista.hpp" #include "mariko/pcv_mariko.hpp" +#include "mariko/pcv_mariko_cpu.hpp" +#include "mariko/pcv_mariko_gpu.hpp" +#include "mariko/pcv_mariko_mtc.hpp" #include "pcv_hook.hpp" @@ -209,10 +212,6 @@ namespace ams::ldr::hoc::pcv { Result MemFreqPllmLimit(u32 *ptr); Result MemVoltHandler(u32 *ptr); // Used for Erista MEM Vdd2 + EMC Vddq or Mariko MEM Vdd2 - /* Extra pcv .bss */ - constexpr size_t HocPcvScratchSize = 0x2000; - constexpr size_t HocBusFreqBufOffset = 0x1000; /* start of the SOC bus region */ - void SafetyCheck(); void Patch(uintptr_t mapped_nso, size_t nso_size, uintptr_t cave, size_t cave_size, uintptr_t nso_address, uintptr_t data_arena); diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_asm.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_asm.hpp index 4f9f22f7..5e901a52 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_asm.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_asm.hpp @@ -22,11 +22,246 @@ #include -namespace ams::ldr::hoc::pcv { +namespace ams::ldr::hoc::pcv::_asm { constexpr u32 NopIns = 0xD503201F; + constexpr u32 RetIns = 0xD65F03C0; + constexpr u32 BrkIns = 0xD4200000; - template + constexpr u32 GetField(u32 ins, u8 lsb, u8 width) { + return (ins >> lsb) & ((1u << width) - 1u); + } + + constexpr u32 SetField(u32 ins, u8 lsb, u8 width, u32 val) { + const u32 mask = ((1u << width) - 1u) << lsb; + return (ins & ~mask) | ((val << lsb) & mask); + } + + constexpr u32 FieldMask(u8 lsb, u8 width) { + return ((1u << width) - 1u) << lsb; + } + + constexpr s64 SignExtend(u64 v, u32 bits) { + const u32 pad = 64u - bits; + return static_cast(v << pad) >> pad; + } + + namespace field { + struct Descriptor { + u8 lsb; + u8 width; + u8 shift = 0; + }; + + constexpr Descriptor Rd { 0, 5}; /* destination register */ + constexpr Descriptor Rn { 5, 5}; /* first source register */ + constexpr Descriptor Rm {16, 5}; /* second source register */ + constexpr Descriptor Ra {10, 5}; /* accumulator register */ + constexpr Descriptor Rt { 0, 5}; /* load/store transfer register */ + constexpr Descriptor Rt2 {10, 5}; /* second transfer register of a pair */ + + constexpr Descriptor Cond {12, 4}; /* condition code (CSEL) */ + constexpr Descriptor BCond { 0, 4}; /* condition code (B.cond) */ + constexpr Descriptor Hw {21, 2}; /* MOVZ/MOVK/MOVN shift */ + + constexpr Descriptor Sh {22, 1}; + constexpr Descriptor Shift {22, 2}; /* ADD/SUB (shifted register) shift type */ + constexpr Descriptor Imm6 {10, 6}; /* ADD/SUB (shifted register) shift amount */ + constexpr Descriptor Immr {16, 6}; /* UBFM immr */ + + constexpr Descriptor Imm16 { 5, 16}; /* MOVZ/MOVK/MOVN immediate */ + constexpr Descriptor Imm12 {10, 12}; /* ADD/SUB (immediate) */ + constexpr Descriptor Imm19 { 5, 19}; /* B.cond / CBZ / CBNZ immediate */ + constexpr Descriptor Imm26 { 0, 26}; /* B / BL immediate */ + + constexpr Descriptor ImmAdrpHi { 5, 19}; + constexpr Descriptor ImmAdrpLo {29, 2}; + + constexpr Descriptor Off1 {10, 12, 0}; /* LDRB/STRB */ + constexpr Descriptor Off4 {10, 12, 2}; /* 32-bit LDR/STR */ + constexpr Descriptor Imm9 {12, 9}; /* pre/post-index offset */ + + constexpr Descriptor Barrier { 8, 4}; /* DSB/DMB option (CRm) */ + constexpr Descriptor Off8 {10, 12, 3}; /* 64-bit LDR/STR */ + + constexpr Descriptor PairOff8 {15, 7, 3}; /* X pairs */ + constexpr Descriptor PairOff16 {15, 7, 4}; /* Q pairs */ + } + + /* Regs that read as a name in the encoding. */ + namespace reg { + constexpr u32 Fp = 29; + constexpr u32 Lr = 30; + constexpr u32 Sp = 31; + constexpr u32 Wzr = 31; + constexpr u32 Xzr = 31; + } + + namespace cond { + constexpr u32 Eq = 0x0, Ne = 0x1, Cs = 0x2, Cc = 0x3, + Mi = 0x4, Pl = 0x5, Vs = 0x6, Vc = 0x7, + Hi = 0x8, Ls = 0x9, Ge = 0xA, Lt = 0xB, + Gt = 0xC, Le = 0xD, Al = 0xE; + constexpr u32 Hs = Cs, Lo = Cc; + } + + /* Base opcodes. */ + /* Either pair with Encode or Ignoring. */ + namespace op { + constexpr u32 AddImm32 = 0x11000000; + constexpr u32 AddImm64 = 0x91000000; + constexpr u32 SubImm64 = 0xD1000000; + constexpr u32 SubsImm32 = 0x71000000; + constexpr u32 SubsImm64 = 0xF1000000; + + constexpr u32 MovzW = 0x52800000; + constexpr u32 MovkW = 0x72800000; + constexpr u32 MovnW = 0x12800000; + + constexpr u32 AddShifted64 = 0x8B000000; + constexpr u32 SubShifted64 = 0xCB000000; + constexpr u32 AndImm32 = 0x12000000; + constexpr u32 AndImm64 = 0x92400000; + constexpr u32 Ubfm32 = 0x53000000; /* UBFIZ/UBFX/LSL aliases */ + constexpr u32 OrrShifted32 = 0x2A000000; + constexpr u32 OrrShifted64 = 0xAA000000; + constexpr u32 SubsShifted32 = 0x6B000000; + + constexpr u32 Csel32 = 0x1A800000; + constexpr u32 Madd32 = 0x1B000000; + + constexpr u32 LdrbImm = 0x39400000; + constexpr u32 StrbImm = 0x39000000; + constexpr u32 LdrImm32 = 0xB9400000; + constexpr u32 LdrsWImm64 = 0xB9800000; /* LDRSW x, 32-bit mem, Off4-scaled */ + constexpr u32 StrImm32 = 0xB9000000; + constexpr u32 LdrImm64 = 0xF9400000; + constexpr u32 LdrPreImm64 = 0xF8400C00; /* LDR (pre-index): bits 11:10 fixed */ + constexpr u32 StrImm64 = 0xF9000000; + + constexpr u32 StpImm64 = 0xA9000000; + constexpr u32 StpPreImm64 = 0xA9800000; + constexpr u32 StpImmQ = 0xAD000000; + + constexpr u32 B = 0x14000000; + constexpr u32 Bl = 0x94000000; + constexpr u32 BCond = 0x54000000; + constexpr u32 Cbz = 0x34000000; + constexpr u32 Br = 0xD61F0000; + + constexpr u32 Adrp = 0x90000000; + constexpr u32 Svc = 0xD4000001; + + constexpr u32 Dsb = 0xD503309F; /* DSB, option cleared */ + constexpr u32 Dmb = 0xD50330BF; /* DMB, option cleared */ + constexpr u32 Isb = 0xD5033FDF; /* ISB SY (only valid option) */ + } + + /* Barrier options (CRm). */ + namespace barrier { + constexpr u32 Sy = 0xFu, St = 0xEu, Ld = 0xDu; + constexpr u32 Ish = 0xBu, Ishst = 0xAu, Ishld = 0x9u; + constexpr u32 Nsh = 0x7u, Nshst = 0x6u, Nshld = 0x5u; + constexpr u32 Osh = 0x3u, Oshst = 0x2u, Oshld = 0x1u; + } + + constexpr u32 Get(u32 ins, field::Descriptor f) { + return GetField(ins, f.lsb, f.width) << f.shift; + } + + constexpr u32 Set(u32 ins, field::Descriptor f, u64 val) { + return SetField(ins, f.lsb, f.width, static_cast(val >> f.shift)); + } + + template + constexpr bool Ignoring(u32 a, u32 b, Fs... fields) { + const u32 mask = (0u | ... | FieldMask(fields.lsb, fields.width)); + return (a & ~mask) == (b & ~mask); + } + + inline constexpr auto IgnoringRd = [](u32 a, u32 b) { + return Ignoring(a, b, field::Rd); + }; + + template + constexpr bool IsOp(u32 ins, u32 baseOpcode, Fs... variableFields) { + return Ignoring(ins, baseOpcode, variableFields...); + } + + struct FieldValue { + field::Descriptor f; + u64 val; + }; + + constexpr u32 Encode(u32 base, FieldValue a) { + return Set(base, a.f, a.val); + } + + constexpr u32 Encode(u32 base, FieldValue a, FieldValue b) { + return Encode(Encode(base, a), b); + } + + constexpr u32 Encode(u32 base, FieldValue a, FieldValue b, FieldValue c) { + return Encode(Encode(base, a, b), c); + } + + constexpr u32 Encode(u32 base, FieldValue a, FieldValue b, FieldValue c, FieldValue d) { + return Encode(Encode(base, a, b, c), d); + } + + constexpr u32 Encode(u32 base, FieldValue a, FieldValue b, FieldValue c, FieldValue d, FieldValue e) { + return Encode(Encode(base, a, b, c, d), e); + } + + constexpr uintptr_t Target26(u32 ins, uintptr_t pc) { + return static_cast(static_cast(pc) + SignExtend(static_cast(Get(ins, field::Imm26)) << 2, 28)); + } + + constexpr u32 Retarget26(u32 ins, uintptr_t pc, uintptr_t target) { + return Set(ins, field::Imm26, static_cast((static_cast(target) - static_cast(pc)) >> 2)); + } + + constexpr uintptr_t Target19(u32 ins, uintptr_t pc) { + return static_cast(static_cast(pc) + SignExtend(static_cast(Get(ins, field::Imm19)) << 2, 21)); + } + + constexpr u32 Retarget19(u32 ins, uintptr_t pc, uintptr_t target) { + return Set(ins, field::Imm19, static_cast((static_cast(target) - static_cast(pc)) >> 2)); + } + + constexpr uintptr_t TargetAdrp(u32 ins, uintptr_t pc) { + const u64 imm21 = (static_cast(Get(ins, field::ImmAdrpHi)) << 2) | Get(ins, field::ImmAdrpLo); + return static_cast(static_cast(pc & ~static_cast(0xFFF)) + SignExtend(imm21 << 12, 33)); + } + + constexpr u32 RetargetAdrp(u32 ins, uintptr_t pc, uintptr_t target) { + const s64 delta = static_cast(target & ~static_cast(0xFFF)) - static_cast(pc & ~static_cast(0xFFF)); + const u32 imm21 = static_cast((delta >> 12) & 0x1FFFFF); + return Set(Set(ins, field::ImmAdrpHi, imm21 >> 2), field::ImmAdrpLo, imm21 & 0x3u); + } + + constexpr u32 Dsb(u32 opt) { + return Encode(op::Dsb, {field::Barrier, opt}); + } + + constexpr u32 Dmb(u32 opt) { + return Encode(op::Dmb, {field::Barrier, opt}); + } + + constexpr u32 MovReg64(u32 rd, u32 rm) { + return Encode(op::OrrShifted64, {field::Rd, rd}, {field::Rn, reg::Xzr}, {field::Rm, rm}); + } + + constexpr u32 CmpImm32(u32 rn, u32 imm12) { + return Encode(op::SubsImm32, {field::Rd, reg::Wzr}, {field::Rn, rn}, {field::Imm12, imm12}); + } + + constexpr u32 ToRegOffset(u32 ldstImm, u32 rm) { + constexpr u32 Keep = 0xC0C00000u | FieldMask(field::Rt.lsb, field::Rt.width) | FieldMask(field::Rn.lsb, field::Rn.width); + return ((ldstImm & Keep) | 0x38207800u) | ((rm & 0x1Fu) << field::Rm.lsb); + } + + template requires (!std::is_same_v, field::Descriptor>) u32 *ScanAssembly(u32 *ptr, u32 scanLimit, u32 pattern, Compare comp) { for (u32 i = 0; i < scanLimit; ++i) { if (comp(pattern, ptr[i])) { @@ -36,341 +271,63 @@ namespace ams::ldr::hoc::pcv { return nullptr; } - inline auto asm_compare_no_rd = [](u32 ins1, u32 ins2) { - return ((ins1 ^ ins2) >> 5) == 0; - }; - - inline auto asm_get_rd = [](u32 ins) { - return ins & ((1 << 5) - 1); - }; - - /* Rn (bits 9:5) and Rm (bits 20:16) to get registers. */ - inline auto AsmGetRn = [](u32 ins) -> u32 { return (ins >> 5) & 0x1Fu; }; - inline auto AsmGetRm = [](u32 ins) -> u32 { return (ins >> 16) & 0x1Fu; }; - - /* Add (shifted register), 64-bit: sf=1 op=0 S=0 01011 shift(2) 0 Rm imm6 Rn Rd. */ - inline auto AsmIsAddShiftedReg64 = [](u32 ins) { - return (ins & 0xFF200000u) == 0x8B000000u; - }; - - inline auto asm_set_rd = [](u32 ins, u8 rd) { - return (ins & 0xFFFFFFE0) | (rd & 0x1F); - }; - - inline auto asm_set_imm16 = [](u32 ins, u16 imm) { - return (ins & 0xFFE0001F) | ((imm & 0xFFFF) << 5); - }; - - inline auto AsmGetImm16 = [](u32 ins) { - return static_cast((ins >> 5) & 0xFFFF); - }; - - inline auto AsmCompareBrNoRd = [](u32 ins1, u32 ins2) { - constexpr u32 RegMask = ~(((1 << 5) - 1) << 5); - return ((ins1 & RegMask) ^ (ins2 & RegMask)) == 0; - }; - - inline auto AsmCompareAddNoImm12 = [](u32 ins1, u32 ins2) { - constexpr u32 Imm12Mask = ~(((1 << 12) - 1) << 10); - return ((ins1 & Imm12Mask) ^ (ins2 & Imm12Mask)) == 0; - }; - - inline auto AsmCompareAdrpNoImm = [](u32 ins1, u32 ins2) { - constexpr u32 ImmMask = ~((((1 << 2) - 1) << 29) | (((1 << 19) - 1) << 5)); - return ((ins1 & ImmMask) ^ (ins2 & ImmMask)) == 0; - }; - - /* Csel (Conditional Select) */ - /* - SF | Op | S | | RM | Cond | 0 | 0 | Rn | Rd - 31 | 30 | 29 | 28 27 26 25 24 23 | 20 19 18 17 16 | 15 14 13 12 | 11 | 10 | 9 8 7 6 5 | 4 3 2 1 0 - */ - inline auto AsmCbzCompareOpcodeOnly = [](u32 ins1, u32 ins2) { - return ((ins1 ^ ins2) >> 24) == 0; - }; - - inline auto AsmBlCompareOpcodeOnly = [](u32 ins1, u32 ins2) { - return ((ins1 ^ ins2) >> 26) == 0; - }; - - inline auto AsmIsAdrX0 = [](u32 ins) { - return (ins & 0x9F00001Fu) == 0x10000000u; - }; - - inline auto AsmAdrTarget = [](u32 ins, uintptr_t pc) -> uintptr_t { - s64 imm = static_cast((((ins >> 5) & 0x7FFFFu) << 2) | ((ins >> 29) & 0x3u)); - imm = (imm << 43) >> 43; - return static_cast(static_cast(pc) + imm); - }; - - /* adrp Rd, target */ - inline auto AsmMakeAdrp = [](uintptr_t pc, uintptr_t target, u32 rd) -> u32 { - const s64 delta = static_cast(target & ~static_cast(0xFFF)) - - static_cast(pc & ~static_cast(0xFFF)); - const u32 imm = static_cast((delta >> 12) & 0x1FFFFF); /* 21-bit page */ - const u32 immlo = imm & 0x3; - const u32 immhi = (imm >> 2) & 0x7FFFF; - return 0x90000000u | (immlo << 29) | (immhi << 5) | (rd & 0x1Fu); - }; - - inline auto AsmSetAdrTarget = [](u32 ins, uintptr_t pc, uintptr_t target) -> u32 { - const s64 delta = static_cast(target) - static_cast(pc); - const u32 immlo = static_cast(delta & 0x3); - const u32 immhi = static_cast((delta >> 2) & 0x7FFFF); - return (ins & ~((0x3u << 29) | (0x7FFFFu << 5))) | (immlo << 29) | (immhi << 5); - }; - - /* adrp: bit31=1, bits 28:24 = 10000. */ - inline auto AsmIsAdrp = [](u32 ins) -> bool { - return (ins & 0x9F000000u) == 0x90000000u; - }; - - inline auto AsmAdrpPageOffset = [](u32 ins) -> s64 { - s64 imm = static_cast((((ins >> 5) & 0x7FFFFu) << 2) | ((ins >> 29) & 0x3u)); - imm = (imm << 43) >> 43; /* sign-extend the 21-bit immediate */ - return imm << 12; - }; - - /* add (immediate), 64-bit: sf=1 op=0 S=0 100010 sh imm12 Rn Rd. */ - inline auto AsmIsAddImm64 = [](u32 ins) -> bool { - return (ins & 0xFF800000u) == 0x91000000u; - }; - - inline auto AsmGetImm12 = [](u32 ins) -> u32 { - return (ins >> 10) & 0xFFFu; - }; - - inline auto AsmMakeAddImm64 = [](u32 rd, u32 rn, u32 imm12) -> u32 { - return 0x91000000u | ((imm12 & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5) | (rd & 0x1Fu); - }; - - /* movz Wd,#imm16 (no shift). */ - inline auto AsmMakeMovzW = [](u32 rd, u16 imm16) -> u32 { - return 0x52800000u | (static_cast(imm16) << 5) | (rd & 0x1Fu); - }; - - /* mov Xd,Xm == orr Xd,XZR,Xm. */ - inline auto AsmMakeMovReg = [](u32 rd, u32 rm) -> u32 { - return 0xAA0003E0u | ((rm & 0x1Fu) << 16) | (rd & 0x1Fu); - }; - - /* ldr Xt,[Xn,#byteOff] */ - inline auto AsmMakeLdrImm64 = [](u32 rt, u32 rn, u32 byteOff) -> u32 { - return 0xF9400000u | (((byteOff / 8u) & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5) | (rt & 0x1Fu); - }; - - /* b (PC-relative, +-128MB). */ - inline auto AsmMakeB = [](uintptr_t pc, uintptr_t target) -> u32 { - const s64 off = (static_cast(target) - static_cast(pc)) >> 2; - return 0x14000000u | (static_cast(off) & 0x03FFFFFFu); - }; - - /* b. (cond: LO/CC=0x3, LE=0xD, NE=0x1, ...). */ - inline auto AsmMakeBCond = [](uintptr_t pc, uintptr_t target, u32 cond) -> u32 { - const s64 off = (static_cast(target) - static_cast(pc)) >> 2; - return 0x54000000u | ((static_cast(off) & 0x7FFFFu) << 5) | (cond & 0xFu); - }; - - /* sub Xd,Xn,#imm12 (shift 0). */ - inline auto AsmMakeSubImm64 = [](u32 rd, u32 rn, u32 imm12) -> u32 { - return 0xD1000000u | ((imm12 & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5) | (rd & 0x1Fu); - }; - - /* cmp Wn,#imm12 == subs WZR,Wn,#imm12. */ - inline auto AsmMakeCmpImm32 = [](u32 rn, u32 imm12) -> u32 { - return 0x7100001Fu | ((imm12 & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5); - }; - - /* str Wt,[Xn,#byteOff] (32-bit, unsigned scaled by 4). */ - inline auto AsmMakeStrImm32 = [](u32 rt, u32 rn, u32 byteOff) -> u32 { - return 0xB9000000u | (((byteOff / 4u) & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5) | (rt & 0x1Fu); - }; - - /* ldr Wt,[Xn,#byteOff] (32-bit, unsigned scaled by 4). */ - inline auto AsmMakeLdrImm32 = [](u32 rt, u32 rn, u32 byteOff) -> u32 { - return 0xB9400000u | (((byteOff / 4u) & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5) | (rt & 0x1Fu); - }; - - /* add Xd,Xn,Xm,LSL #shift (64-bit shifted register, shift 0-63). */ - inline auto AsmMakeAddShiftedReg64 = [](u32 rd, u32 rn, u32 rm, u32 shift) -> u32 { - return 0x8B000000u | ((rm & 0x1Fu) << 16) | ((shift & 0x3Fu) << 10) | ((rn & 0x1Fu) << 5) | (rd & 0x1Fu); - }; - - /* stp Xt1,Xt2,[Xn,#imm] (signed offset, scaled by 8). */ - inline auto AsmMakeStpImm64 = [](u32 rt1, u32 rt2, u32 rn, s32 imm) -> u32 { - return 0xA9000000u | ((static_cast(imm / 8) & 0x7Fu) << 15) | ((rt2 & 0x1Fu) << 10) | ((rn & 0x1Fu) << 5) | (rt1 & 0x1Fu); - }; - - /* stp Qt1,Qt2,[Xn,#imm] (128-bit SIMD, signed offset scaled by 16). */ - inline auto AsmMakeStpqImm = [](u32 qt1, u32 qt2, u32 rn, s32 imm) -> u32 { - return 0xAD000000u | ((static_cast(imm / 16) & 0x7Fu) << 15) | ((qt2 & 0x1Fu) << 10) | ((rn & 0x1Fu) << 5) | (qt1 & 0x1Fu); - }; - - /* str Xt,[Xn,#byteOff] (unsigned scaled by 8). */ - inline auto AsmMakeStrImm64 = [](u32 rt, u32 rn, u32 byteOff) -> u32 { - return 0xF9000000u | (((byteOff / 8u) & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5) | (rt & 0x1Fu); - }; - - /* movn Wd,#imm16 (no shift): loads ~imm16, e.g. movn Wd,#0x37 == -56. */ - inline auto AsmMakeMovnW = [](u32 rd, u16 imm16) -> u32 { - return 0x12800000u | (static_cast(imm16) << 5) | (rd & 0x1Fu); - }; - - /* bl (PC-relative, +-128MB). */ - inline auto AsmMakeBl = [](uintptr_t pc, uintptr_t target) -> u32 { - const s64 off = (static_cast(target) - static_cast(pc)) >> 2; - return 0x94000000u | (static_cast(off) & 0x03FFFFFFu); - }; - - /* svc #imm16. */ - inline auto AsmMakeSvc = [](u16 imm16) -> u32 { - return 0xD4000001u | (static_cast(imm16) << 5); - }; - - constexpr u32 RetIns = 0xD65F03C0u; /* ret (x30) */ - - /* ldrb Wt,[Xn,#imm] (unsigned byte, scale 1). */ - inline auto AsmMakeLdrbImm = [](u32 rt, u32 rn, u32 byteOff) -> u32 { - return 0x39400000u | ((byteOff & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5) | (rt & 0x1Fu); - }; - - /* cbz Wt,. */ - inline auto AsmMakeCbz = [](uintptr_t pc, uintptr_t target, u32 rt) -> u32 { - const s64 off = (static_cast(target) - static_cast(pc)) >> 2; - return 0x34000000u | ((static_cast(off) & 0x7FFFFu) << 5) | (rt & 0x1Fu); - }; - - /* strb Wt,[Xn,#imm] (unsigned byte, scale 1). */ - inline auto AsmMakeStrbImm = [](u32 rt, u32 rn, u32 byteOff) -> u32 { - return 0x39000000u | ((byteOff & 0xFFFu) << 10) | ((rn & 0x1Fu) << 5) | (rt & 0x1Fu); - }; - - /* mov Xd,X == orr Xd,XZR,X (matches any Rd). */ - inline auto AsmIsMovReg = [](u32 ins, u32 rm) -> bool { - return (ins & 0xFFFFFFE0u) == (0xAA0003E0u | ((rm & 0x1Fu) << 16)); - }; - - /* add Xd,sp,#imm12 (shift 0). */ - inline auto AsmIsAddSpImm = [](u32 ins) -> bool { - return (ins & 0xFFC003E0u) == 0x910003E0u; - }; - - /* sub Xd,x29,#imm12 (shift 0). */ - inline auto AsmIsSubX29Imm = [](u32 ins) -> bool { - return (ins & 0xFFC003E0u) == 0xD10003A0u; - }; - - inline auto AsmIsB = [](u32 ins) -> bool { return (ins & 0xFC000000u) == 0x14000000u; }; /* b */ - inline auto AsmIsBl = [](u32 ins) -> bool { return (ins & 0xFC000000u) == 0x94000000u; }; /* bl */ - inline auto AsmIsBCond = [](u32 ins) -> bool { return (ins & 0xFF000010u) == 0x54000000u; }; /* b.c */ - - /* ldr/str Xt,[Xn,#imm] (64-bit, unsigned scaled offset). */ - inline auto AsmIsLdrImm64 = [](u32 ins) -> bool { return (ins & 0xFFC00000u) == 0xF9400000u; }; - inline auto AsmIsStrImm64 = [](u32 ins) -> bool { return (ins & 0xFFC00000u) == 0xF9000000u; }; - inline auto AsmGetLdStImm64Off = [](u32 ins) -> u32 { return ((ins >> 10) & 0xFFFu) * 8u; }; - - /* Byte target address of a b/bl at pc. */ - inline auto AsmBranchTarget = [](u32 ins, uintptr_t pc) -> uintptr_t { - s64 off = static_cast((ins & 0x03FFFFFFu) << 2); - off = (off << 36) >> 36; /* sign-extend the 28-bit branch offset */ - return static_cast(static_cast(pc) + off); - }; - - /* Rewrite a scaled immediate-offset load/store (`op Wt,[Xn,#imm]`) into its register-offset form */ - inline auto AsmSetLdStRegOffset = [](u32 ldstImm, u32 rm) -> u32 { - return (ldstImm & 0xC0C003FFu) | 0x38207800u | ((rm & 0x1Fu) << 16); - }; - - inline auto AsmIsLdpX = [](u32 ins) { - return (ins & 0xFE400000u) == 0xA8400000u; - }; - - inline bool AsmComparePrologue(u32 ins1, u32 ins2, u32 ins3, u32 cmp1, u32 cmp2, u32 cmp3) { - constexpr u32 StpImmMask = ~((((1u << 7) - 1u) << 15)); - - bool firstMatch = (ins1 & StpImmMask) == (cmp1 & StpImmMask); - - constexpr u32 StpRegsImmMask = ~(((1u << 5) - 1u) |(((1u << 5) - 1u) << 10) | (((1u << 7) - 1u) << 15)); - - bool secondMatch = (ins2 & StpRegsImmMask) == (cmp2 & StpRegsImmMask); - - constexpr u32 MovMask = ~((1u << 5) - 1u); - - bool thirdMatch = (ins3 & MovMask) == (cmp3 & MovMask); - - return firstMatch && secondMatch && thirdMatch; + template + u32 *ScanAssembly(u32 *ptr, u32 scanLimit, u32 pattern, Fs... ignoreFields) { + return ScanAssembly(ptr, scanLimit, pattern, [=](u32 a, u32 b) ALWAYS_INLINE_LAMBDA { return Ignoring(a, b, ignoreFields...); }); } - inline auto AsmCompareCselNoReg = [](u32 ins1, u32 ins2) { - constexpr u32 ClearReg = ~(((1 << 10) - 1) | (((1 << 5) - 1) << 16)); - return ((ins1 & ClearReg) ^ (ins2 & ClearReg)) == 0; - }; + constexpr bool IsFramePushPre(u32 ins) { + constexpr u32 Pattern = Encode(op::StpPreImm64, {field::Rt, reg::Fp}, {field::Rt2, reg::Lr}, {field::Rn, reg::Sp}); + return Ignoring(ins, Pattern, field::PairOff8); + } - /* Mul */ - /* - SF | Op54 | Op31 | RM | o0 | RA | RN | RD - 31 | 30 29 28 27 26 25 24 | 23 22 21 | 20 19 18 17 16 | 15 | 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0 - */ - inline auto AsmCompareMullNoReg = [](u32 ins1, u32 ins2) { - constexpr u32 ClearReg = ~(((1 << 10) - 1) | (((1 << 5) - 1) << 16)); - return ((ins1 & ClearReg) ^ (ins2 & ClearReg)) == 0; - }; + constexpr bool IsFramePushOffset(u32 ins) { + constexpr u32 Pattern = Encode(op::StpImm64, {field::Rt, reg::Fp}, {field::Rt2, reg::Lr}, {field::Rn, reg::Sp}); + return Ignoring(ins, Pattern, field::PairOff8); + } - /* Mul */ - /* MUL W11, W24, W26 */ - /* multiplies by 1000, mV -> uV */ - /* - SF | Op54 | Op31 | RM | o0 | RA | RN | RD - 31 | 30 29 28 27 26 25 24 | 23 22 21 | 20 19 18 17 16 | 15 | 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0 - */ - inline auto AsmGetMullRn = [](u32 ins) { - constexpr u32 Mask = ((1 << 5) - 1) << 5; - return (ins & Mask) >> 5; - }; + constexpr bool IsSpSubImm(u32 ins) { + constexpr u32 Pattern = Encode(op::SubImm64, {field::Rd, reg::Sp}, {field::Rn, reg::Sp}); + return Ignoring(ins, Pattern, field::Imm12); + } - inline auto AsmGetMullRm = [](u32 ins) { - constexpr u32 Mask = ((1 << 5) - 1) << 16; - return (ins & Mask) >> 16; - }; + constexpr bool IsFramePush(u32 ins) { + return IsFramePushPre(ins) || IsFramePushOffset(ins); + } - /* Subs (Shifted register) */ - /* - SF | Op | S | | Shift | 0 | RM | Imm6 | Rn | Rd - 31 | 30 | 29 | 28 27 26 25 24 | 23 22 | 21 | 20 19 18 17 16 | 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0 - */ - inline auto AsmSubsSetRn = [](u32 ins, u8 rn) { - constexpr u32 RnMaskClear = ~(((1u << 5) - 1u) << 5); - constexpr u32 RnMaskSet = (1u << 5) - 1u; + constexpr bool IsCondBranch(u32 ins) { + return (ins & 0xFF000010u) == op::BCond; + } - return (ins & RnMaskClear) | ((static_cast(rn) & RnMaskSet) << 5); - }; + constexpr bool IsCompareBranch(u32 ins) { + return (ins & 0x7E000000u) == op::Cbz; + } - /* Subs (Immediate) */ + constexpr bool IsTestBranch(u32 ins) { + return (ins & 0x7E000000u) == 0x36000000u; + } - /* - SF | Op | S | | Sh | Imm12 | Rn | Rd - 31 | 30 | 29 | 28 27 26 25 24 23 | 22 | 21 20 19 18 17 16 15 14 13 12 11 10 | 9 8 7 6 5 | 4 3 2 1 0 - */ - inline auto AsmSubsSetImm12 = [](u32 ins, u16 imm12) { - constexpr u32 ClearMask = ~(((1u << 12) - 1) << 10); - constexpr u32 SetImm12Mask = ( 1u << 12) - 1; + inline u32 *FindFnEnd(u32 *prologue, u32 *limit) { + u32 *furthest = prologue; + for (u32 *ptr = prologue; ptr < limit; ++ptr) { + const u32 ins = *ptr; + if (ins == RetIns && ptr >= furthest) { + return ptr + 1; + } - return (ins & ClearMask) | ((imm12 & SetImm12Mask) << 10); - }; + s64 delta = 0; + if (IsCondBranch(ins) || IsCompareBranch(ins)) { + delta = SignExtend(static_cast(Get(ins, field::Imm19)) << 2, 21); + } else if (IsTestBranch(ins)) { + delta = SignExtend(static_cast(GetField(ins, 5, 14)) << 2, 16); + } - inline auto AsmSubsCompareNoReg = [](u32 ins1, u32 ins2) { - return ((ins1 ^ ins2) >> 10) == 0; - }; + if (ptr + (delta >> 2) > furthest) { + furthest = ptr + (delta >> 2); + } + } - inline auto AsmCompareBrConNoImm19 = [](u32 ins1, u32 ins2) { - constexpr u32 ClearImm19 = ~(((1 << 19) - 1) << 5); - return (ins1 & ClearImm19) == (ins2 & ClearImm19); - }; - - inline bool AsmIsFramePush(u32 ins) { - constexpr u32 FramePushMask = 0xFFC07FFF; - constexpr u32 FramePushValue = 0xA9807BFD; - return (ins & FramePushMask) == FramePushValue; + return nullptr; } inline u32 *FindFnPrologue(u32 *ptr, u32 margin, u32 *nsoStart) { @@ -380,9 +337,13 @@ namespace ams::ldr::hoc::pcv { break; } - if (AsmIsFramePush(*candidate)) { + if (IsFramePushPre(*candidate)) { return candidate; } + + if (IsFramePushOffset(*candidate) && candidate - 1 >= nsoStart && IsSpSubImm(candidate[-1])) { + return candidate - 1; + } } return nullptr; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp index 1d3b9232..878f60e2 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_common.hpp @@ -163,6 +163,30 @@ namespace ams::ldr::hoc::pcv { }; static_assert(sizeof(CvbMeta) == 0x78); + struct SubClockStub { + u8 _unknown[0x48]; + }; + + struct SharedClkBus { + u64 moduleId; + u32 currentRateHz; + u32 padding0; + u32 *allowedFreqTable; + u32 allowedFreqCount; + u32 padding1; + SubClockStub *subClocksTable; + u32 subClockCount; + u32 padding2; + void *unk30; + void *clockSource; + u32 targetRateHz; + u32 saveDivFlag; + u32 idleRateHz; /* Unsure. */ + u32 alwaysOnFlag; + u64 clockSession; + }; + static_assert(sizeof(SharedClkBus) == 0x58); + constexpr u32 CpuClkOSLimit = 1785'000; constexpr u32 GpuClkOsLimit = 921'600; constexpr u32 EmcClkOSLimit = 1600'000; @@ -170,6 +194,7 @@ namespace ams::ldr::hoc::pcv { #define R_SKIP() R_SUCCEED() // Count 32 / Index 31 is reserved to be empty + /* The actual lut table has a size of 33. */ constexpr size_t DvfsTableEntryCount = 32; constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1; @@ -177,11 +202,8 @@ namespace ams::ldr::hoc::pcv { constexpr size_t EmcDvfsTableEntryCount = 64; constexpr size_t EmcDvfsTableEntryLimit = EmcDvfsTableEntryCount - 1; - // The pcv SoC-voltage DVB table is a fixed 32-entry region. (it doesn't need to be larger) - constexpr size_t DvbTableCapacity = 32; - - // extra .bss location, 0 until Patch() runs. - inline uintptr_t g_pcv_scratch = 0; + /* Note: According to TRM the lut size is 33, but up to 64 LUT is possible. */ + constexpr size_t ClDvfsLutSize = 64; inline uintptr_t g_pcv_cave = 0; inline size_t g_pcv_cave_size = 0; diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_hook.hpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_hook.hpp index fcc6a47a..ff66c42c 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_hook.hpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv_hook.hpp @@ -18,7 +18,8 @@ #include "../oc_common.hpp" -#define HOOK_PAYLOAD_FN __attribute__((section("hoc_hookpayload"), used, noinline, visibility("hidden"))) +/* aligned(4) is the ARM64 instruction alignment. This saves some memory over 16 byte padding */ +#define HOOK_PAYLOAD_FN __attribute__((section("hoc_hookpayload"), used, noinline, visibility("hidden"), aligned(4))) /* Inline asm because fuck compilers: GCC refuses to put a variable and a function in the same section. */ /* It wants alloc+write for one and alloc+exec for the other. */ @@ -54,6 +55,7 @@ namespace ams::ldr::hoc::pcv { constexpr size_t HookPageSize = 0x1000; constexpr size_t PcvDataArenaSize = 0x1000; + constexpr size_t HookStubReserve = 0x80; inline s64 SignExtend(u64 value, int bits) { const int shift = 64 - bits; @@ -126,6 +128,15 @@ namespace ams::ldr::hoc::pcv { m_data_used = 0; } + void SetCave(uintptr_t cave, size_t cave_size) { + m_cave = cave; + m_cave_size = cave_size; + } + + static size_t RequiredCaveSize() { + return util::AlignUp(static_cast(__stop_hoc_hookpayload - __start_hoc_hookpayload), sizeof(u32)) + HookStubReserve; + } + bool IsEnabled() const { return m_cave != 0 && m_cave_size != 0; } Result CheckEnabled() const { @@ -147,6 +158,10 @@ namespace ams::ldr::hoc::pcv { } uintptr_t CaveVa() const { return ToVa(reinterpret_cast(m_cave)); } + uintptr_t CaveBase() const { return m_cave; } + + /* Todo remove? */ + u32 *Reserve(size_t words) { return this->AllocCode(words); } Result CopyPayload() { R_TRY(this->CheckEnabled()); @@ -284,6 +299,8 @@ namespace ams::ldr::hoc::pcv { Result ValidatePayloadFn(const void *fn) const { constexpr u32 MaxInstructions = 512; constexpr u32 RetInsn = 0xD65F03C0u; + constexpr u32 BrMask = 0xFFFFFC1Fu; + constexpr u32 BrInsn = 0xD61F0000u; const uintptr_t lo = m_payload; const uintptr_t hi = m_payload + m_payload_sz; @@ -302,7 +319,7 @@ namespace ams::ldr::hoc::pcv { const u32 insn = insns[i]; const uintptr_t site = base + i * sizeof(u32); - if (insn == RetInsn) { + if (insn == RetInsn || (insn & BrMask) == BrInsn) { R_SUCCEED(); } @@ -334,7 +351,7 @@ namespace ams::ldr::hoc::pcv { private: u32 *AllocCode(size_t words) { const size_t bytes = words * sizeof(u32); - if (!this->IsEnabled() || m_used + bytes > m_cave_size) { + if (!this->IsEnabled() || m_payload == 0 || m_used + bytes > m_cave_size) { return nullptr; } diff --git a/Source/Benchmark-Toolbox/Makefile b/Source/Benchmark-Toolbox/Makefile index 975b9b43..c2dcf528 100644 --- a/Source/Benchmark-Toolbox/Makefile +++ b/Source/Benchmark-Toolbox/Makefile @@ -12,14 +12,14 @@ include $(DEVKITPRO)/libnx/switch_rules #--------------------------------------------------------------------------------- TARGET := Benchmark-Toolbox BUILD := build -SOURCES := source source/furmark source/memtester source/cpustress +SOURCES := source source/furmark source/memtester source/cpustress source/cuda95 DATA := data ICON := icon.jpg -INCLUDES := source source/furmark source/memtester source/cpustress ../hoc-clk/common/include +INCLUDES := source source/furmark source/memtester source/cpustress source/cuda95 ../hoc-clk/common/include APP_TITLE := Benchmark Toolbox APP_AUTHOR := Horizon-OC -APP_VERSION := 2.0.0 +APP_VERSION := 3.0.0 ROMFS := resources BOREALIS_PATH := lib/borealis diff --git a/Source/Benchmark-Toolbox/source/bench.c b/Source/Benchmark-Toolbox/source/bench.c index 40286586..ea5d5180 100644 --- a/Source/Benchmark-Toolbox/source/bench.c +++ b/Source/Benchmark-Toolbox/source/bench.c @@ -8,7 +8,6 @@ */ #include -#include #include #include #include @@ -24,110 +23,178 @@ #define ALIGN_PADDING 0x100000 #define CACHE_LINE_SIZE 128 -struct f_data { - void (*func)(int64_t *, int64_t *, int); - int64_t *arg1; - int64_t *arg2; - int arg3; -}; +#define BW_MAX_THREADS 4 -static pthread_cond_t p_ready, p_start; -static pthread_mutex_t p_lock; -static pthread_t *p_worker = NULL; -static struct f_data *worker_data = NULL; -static int p_worker_not_ready, p_workers_ready; +typedef void (*bench_kernel_fn)(int64_t *dst, int64_t *src, long size); -static void *thread_func(void *data) { - struct f_data *d = data; - pthread_mutex_lock(&p_lock); - p_worker_not_ready--; - if (!p_worker_not_ready) - pthread_cond_signal(&p_ready); - while (p_workers_ready != 1) - pthread_cond_wait(&p_start, &p_lock); - pthread_mutex_unlock(&p_lock); - (d->func)(d->arg1, d->arg2, d->arg3); - pthread_exit(NULL); +struct bw_pool; + +typedef struct { + Thread thread; + Semaphore start; + struct bw_pool *pool; + bench_kernel_fn func; + int64_t *dst; + int64_t *src; + long size; + int core; + bool created; + uint64_t ticks; +} bw_worker_t; + +typedef struct bw_pool { + bw_worker_t workers[BW_MAX_THREADS]; + Semaphore done; + int threads; + bool ok; +} bw_pool_t; + +static void bw_worker_entry(void *arg) { + bw_worker_t *w = (bw_worker_t *)arg; + bw_pool_t *p = w->pool; + /* Best-effort pin to own core. */ + svcSetThreadCoreMask(CUR_THREAD_HANDLE, w->core, (u64)1 << w->core); + for (;;) { + semaphoreWait(&w->start); + bench_kernel_fn f = w->func; + if (!f) + break; + uint64_t t0 = armGetSystemTick(); + f(w->dst, w->src, w->size); + w->ticks = armGetSystemTick() - t0; + semaphoreSignal(&p->done); + } } -static void parallel_run(void) { - pthread_mutex_lock(&p_lock); - p_workers_ready = 1; - pthread_mutex_unlock(&p_lock); - pthread_cond_broadcast(&p_start); +static bool bw_pool_init(bw_pool_t *p, int threads) { + memset(p, 0, sizeof(*p)); + if (threads > BW_MAX_THREADS) + threads = BW_MAX_THREADS; + p->threads = threads; + semaphoreInit(&p->done, 0); + s32 prio = 0x2C; + svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); + for (int i = 0; i < threads; i++) { + bw_worker_t *w = &p->workers[i]; + w->core = i; + w->func = NULL; + w->pool = p; + semaphoreInit(&w->start, 0); + if (R_FAILED(threadCreate(&w->thread, bw_worker_entry, w, NULL, 0x8000, prio, i))) + return false; + w->created = true; + if (R_FAILED(threadStart(&w->thread))) + return false; + } + p->ok = true; + return true; } -static void parallel_init(int threads) { - pthread_attr_t attr; - pthread_cond_init(&p_ready, NULL); - pthread_cond_init(&p_start, NULL); - pthread_mutex_init(&p_lock, NULL); - p_worker_not_ready = threads; - p_workers_ready = 0; - pthread_attr_init(&attr); - if (!p_worker || !worker_data) { - p_worker = malloc(threads * sizeof(pthread_t)); - worker_data = malloc(threads * sizeof(struct f_data)); +static void bw_pool_free(bw_pool_t *p) { + for (int i = 0; i < p->threads; i++) { + bw_worker_t *w = &p->workers[i]; + if (w->created) { + w->func = NULL; /* shutdown */ + semaphoreSignal(&w->start); + } + } + for (int i = 0; i < p->threads; i++) { + bw_worker_t *w = &p->workers[i]; + if (w->created) { + threadWaitForExit(&w->thread); + threadClose(&w->thread); + w->created = false; + } + } + p->ok = false; +} + +static double bw_run_once(bw_pool_t *p, bench_kernel_fn f, int64_t *dstbuf, int64_t *srcbuf, long size) { + int threads = p->threads; + for (int i = 0; i < threads; i++) { + bw_worker_t *w = &p->workers[i]; + w->func = f; + w->dst = dstbuf + (size * i) / (long)sizeof(int64_t); + w->src = srcbuf + (size * i) / (long)sizeof(int64_t); + w->size = size; } for (int i = 0; i < threads; i++) - pthread_create(p_worker + i, &attr, thread_func, worker_data + i); - pthread_mutex_lock(&p_lock); - while (p_worker_not_ready != 0) - pthread_cond_wait(&p_ready, &p_lock); - pthread_mutex_unlock(&p_lock); + semaphoreSignal(&p->workers[i].start); + for (int i = 0; i < threads; i++) + semaphoreWait(&p->done); + uint64_t sum = 0; + for (int i = 0; i < threads; i++) + sum += p->workers[i].ticks; + return (double)armTicksToNs(sum) / 1000000000.0 / threads; } -static void aligned_block_copy(int64_t *__restrict dst_, int64_t *__restrict src, int size) { - volatile int64_t *dst = dst_; - int64_t t1, t2, t3, t4; - while ((size -= 64) >= 0) { - t1 = *src++; - t2 = *src++; - t3 = *src++; - t4 = *src++; - *dst++ = t1; - *dst++ = t2; - *dst++ = t3; - *dst++ = t4; - t1 = *src++; - t2 = *src++; - t3 = *src++; - t4 = *src++; - *dst++ = t1; - *dst++ = t2; - *dst++ = t3; - *dst++ = t4; - } -} +#define BW_GPR_CLOBBERS \ + "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18" -static void aligned_block_fetch(int64_t *__restrict dst, int64_t *__restrict src_, int size) { - volatile int64_t *src = src_; - (void)dst; - while ((size -= 64) >= 0) { - *src++; - *src++; - *src++; - *src++; - *src++; - *src++; - *src++; - *src++; - } +static void aligned_block_copy(int64_t *dst, int64_t *src, long size) { + __asm__ __volatile__( + "1:\n" + "ldp x3, x4, [%[s], #0x00]\n" + "ldp x5, x6, [%[s], #0x10]\n" + "ldp x7, x8, [%[s], #0x20]\n" + "ldp x9, x10, [%[s], #0x30]\n" + "ldp x11, x12, [%[s], #0x40]\n" + "ldp x13, x14, [%[s], #0x50]\n" + "ldp x15, x16, [%[s], #0x60]\n" + "ldp x17, x18, [%[s], #0x70]\n" + "add %[s], %[s], #0x80\n" + "stp x3, x4, [%[d], #0x00]\n" + "stp x5, x6, [%[d], #0x10]\n" + "stp x7, x8, [%[d], #0x20]\n" + "stp x9, x10, [%[d], #0x30]\n" + "stp x11, x12, [%[d], #0x40]\n" + "stp x13, x14, [%[d], #0x50]\n" + "stp x15, x16, [%[d], #0x60]\n" + "stp x17, x18, [%[d], #0x70]\n" + "add %[d], %[d], #0x80\n" + "subs %[n], %[n], #0x80\n" + "b.gt 1b\n" + : [s] "+r"(src), [d] "+r"(dst), [n] "+r"(size) + : + : BW_GPR_CLOBBERS, "cc", "memory"); } - -static void aligned_block_fill(int64_t *__restrict dst_, int64_t *__restrict src, int size) { - volatile int64_t *dst = dst_; - int64_t data = *src; - while ((size -= 64) >= 0) { - *dst++ = data; - *dst++ = data; - *dst++ = data; - *dst++ = data; - *dst++ = data; - *dst++ = data; - *dst++ = data; - *dst++ = data; - } +static void aligned_block_fetch(int64_t *dst, int64_t *src, long size) { + (void)src; + __asm__ __volatile__( + "1:\n" + "ldp x3, x4, [%[p], #0x00]\n" + "ldp x5, x6, [%[p], #0x10]\n" + "ldp x7, x8, [%[p], #0x20]\n" + "ldp x9, x10, [%[p], #0x30]\n" + "ldp x11, x12, [%[p], #0x40]\n" + "ldp x13, x14, [%[p], #0x50]\n" + "ldp x15, x16, [%[p], #0x60]\n" + "ldp x17, x18, [%[p], #0x70]\n" + "add %[p], %[p], #0x80\n" + "subs %[n], %[n], #0x80\n" + "b.gt 1b\n" + : [p] "+r"(dst), [n] "+r"(size) + : + : BW_GPR_CLOBBERS, "cc", "memory"); +} +static void aligned_block_fill(int64_t *dst, int64_t *src, long size) { + (void)src; + __asm__ __volatile__( + "1:\n" + "stp x3, x4, [%[d], #0x00]\n" + "stp x5, x6, [%[d], #0x10]\n" + "stp x7, x8, [%[d], #0x20]\n" + "stp x9, x10, [%[d], #0x30]\n" + "stp x11, x12, [%[d], #0x40]\n" + "stp x13, x14, [%[d], #0x50]\n" + "stp x15, x16, [%[d], #0x60]\n" + "stp x17, x18, [%[d], #0x70]\n" + "add %[d], %[d], #0x80\n" + "subs %[n], %[n], #0x80\n" + "b.gt 1b\n" + : [d] "+r"(dst), [n] "+r"(size) + : + : BW_GPR_CLOBBERS, "cc", "memory"); } static double gettime(void) { @@ -136,47 +203,29 @@ static double gettime(void) { return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.; } -static double bandwidth_bench_helper(int threads, int64_t *dstbuf, int64_t *srcbuf, int size, void (*f)(int64_t *, int64_t *, int)) { +static double bandwidth_bench_helper(bw_pool_t *pool, int threads, int64_t *dstbuf, int64_t *srcbuf, long size, bench_kernel_fn f) { int i, loopcount, innerloopcount, n; - double t, t1, t2, speed, maxspeed, s, s0, s1, s2; + double t, speed, maxspeed; + + if (!pool || !pool->ok) + return 0.; - s = s0 = s1 = s2 = 0.; maxspeed = 0.; for (n = 0; n < MAXREPEATS; n++) { + bw_run_once(pool, f, dstbuf, srcbuf, size); loopcount = 0; innerloopcount = 1; t = 0.; do { loopcount += innerloopcount; - for (i = 0; i < innerloopcount; i++) { - parallel_init(threads); - for (int pt = 0; pt < threads; pt++) { - (worker_data + pt)->func = f; - (worker_data + pt)->arg1 = dstbuf + size * pt / sizeof(int64_t); - (worker_data + pt)->arg2 = srcbuf + size * pt / sizeof(int64_t); - (worker_data + pt)->arg3 = size; - } - t1 = gettime(); - parallel_run(); - for (int pt = 0; pt < threads; pt++) - pthread_join(p_worker[pt], NULL); - t2 = gettime(); - t += t2 - t1; - } + for (i = 0; i < innerloopcount; i++) + t += bw_run_once(pool, f, dstbuf, srcbuf, size); innerloopcount *= 2; - } while (t < 0.5); + } while (t < 0.25); speed = (double)size * threads * loopcount / t / 1000000.; - s0 += 1.; - s1 += speed; - s2 += speed * speed; if (speed > maxspeed) maxspeed = speed; - if (s0 > 2.) { - s = sqrt((s0 * s2 - s1 * s1) / (s0 * (s0 - 1))); - if (s < maxspeed / 1000.) - break; - } } return maxspeed; } @@ -306,13 +355,16 @@ void bench_run_full(bench_results_t *out, bench_progress_fn progress, void *user int64_t *srcbuf, *dstbuf; void *poolbuf = alloc_nonaliased_buffers((void **)&srcbuf, size * threads, (void **)&dstbuf, size * threads, NULL, 0); + bw_pool_t bw; + bw_pool_init(&bw, threads); STEP("CPU copy", 0.40f); - out->cpu_copy = bandwidth_bench_helper(threads, dstbuf, srcbuf, size, aligned_block_copy); + out->cpu_copy = bandwidth_bench_helper(&bw, threads, dstbuf, srcbuf, size, aligned_block_copy); STEP("CPU read", 0.55f); - out->cpu_read = bandwidth_bench_helper(threads, dstbuf, srcbuf, size, aligned_block_fetch); + out->cpu_read = bandwidth_bench_helper(&bw, threads, dstbuf, srcbuf, size, aligned_block_fetch); STEP("CPU write", 0.70f); - out->cpu_write = bandwidth_bench_helper(threads, dstbuf, srcbuf, size, aligned_block_fill); + out->cpu_write = bandwidth_bench_helper(&bw, threads, dstbuf, srcbuf, size, aligned_block_fill); + bw_pool_free(&bw); free(poolbuf); STEP("Latency", 0.85f); @@ -325,9 +377,10 @@ void bench_run_full(bench_results_t *out, bench_progress_fn progress, void *user struct bench_ctx { int phase; bool is_4gb; - void *pool; + void *buf; int64_t *src; int64_t *dst; + bw_pool_t bw; }; bench_ctx *bench_begin(void) { @@ -335,7 +388,8 @@ bench_ctx *bench_begin(void) { if (!c) return NULL; c->is_4gb = (appletGetAppletType() == AppletType_Application); - c->pool = alloc_nonaliased_buffers((void **)&c->src, SIZE * 3, (void **)&c->dst, SIZE * 3, NULL, 0); + c->buf = alloc_nonaliased_buffers((void **)&c->src, SIZE * 3, (void **)&c->dst, SIZE * 3, NULL, 0); + bw_pool_init(&c->bw, 3); return c; } @@ -349,24 +403,25 @@ bool bench_step(bench_ctx *c, bench_results_t *out, const char **label, float *f *frac = 0.25f; break; case 1: - out->cpu_copy = bandwidth_bench_helper(threads, c->dst, c->src, size, aligned_block_copy); + out->cpu_copy = bandwidth_bench_helper(&c->bw, threads, c->dst, c->src, size, aligned_block_copy); *label = "CPU copy"; *frac = 0.45f; break; case 2: - out->cpu_read = bandwidth_bench_helper(threads, c->dst, c->src, size, aligned_block_fetch); + out->cpu_read = bandwidth_bench_helper(&c->bw, threads, c->dst, c->src, size, aligned_block_fetch); *label = "CPU read"; *frac = 0.60f; break; case 3: - out->cpu_write = bandwidth_bench_helper(threads, c->dst, c->src, size, aligned_block_fill); + out->cpu_write = bandwidth_bench_helper(&c->bw, threads, c->dst, c->src, size, aligned_block_fill); *label = "CPU write"; *frac = 0.75f; break; case 4: - if (c->pool) { - free(c->pool); - c->pool = NULL; + bw_pool_free(&c->bw); + if (c->buf) { + free(c->buf); + c->buf = NULL; } latency_bench(&out->l2_ns, &out->ram_ns); *label = "Latency"; @@ -384,7 +439,8 @@ bool bench_step(bench_ctx *c, bench_results_t *out, const char **label, float *f void bench_end(bench_ctx *c) { if (!c) return; - if (c->pool) - free(c->pool); + bw_pool_free(&c->bw); + if (c->buf) + free(c->buf); free(c); -} +} \ No newline at end of file diff --git a/Source/Benchmark-Toolbox/source/cuda95/compareD_csh.glsl b/Source/Benchmark-Toolbox/source/cuda95/compareD_csh.glsl new file mode 100644 index 00000000..71be7615 --- /dev/null +++ b/Source/Benchmark-Toolbox/source/cuda95/compareD_csh.glsl @@ -0,0 +1,57 @@ +#version 430 core +layout(local_size_x = 16, local_size_y = 16) in; + +layout(std430, binding = 0) readonly buffer DataBuffer { + double data[]; +}; + +layout(std430, binding = 1) buffer ResultBuffer { + uint result; +}; + +layout(std140, binding = 0) uniform Params { + uint n_rows; + uint n_repeats; +}; + +const double THRESHOLD = 1e-3LF; + +shared uint s_partial[256]; + +void main() { + uint total_cols = gl_NumWorkGroups.x * gl_WorkGroupSize.x + * gl_NumWorkGroups.y * gl_WorkGroupSize.y; + + uint col = (gl_GlobalInvocationID.y * (gl_NumWorkGroups.x * gl_WorkGroupSize.x)) + + gl_GlobalInvocationID.x; + + uint count = 0u; + + if (n_rows >= 2u) { + for (uint k = 0u; k < n_repeats; ++k) { + double bias = double(k) * 1e-12LF; + double ref = data[col] + bias; + + for (uint row = 1u; row < n_rows; ++row) { + double val = data[row * total_cols + col]; + if (abs(ref - val) > THRESHOLD) + count++; + } + } + } + + uint lid = gl_LocalInvocationIndex; + s_partial[lid] = count; + memoryBarrierShared(); + barrier(); + + for (uint s = 128u; s > 0u; s >>= 1) { + if (lid < s) + s_partial[lid] += s_partial[lid + s]; + memoryBarrierShared(); + barrier(); + } + + if (lid == 0u) + atomicAdd(result, s_partial[0]); +} diff --git a/Source/Benchmark-Toolbox/source/cuda95/compare_csh.glsl b/Source/Benchmark-Toolbox/source/cuda95/compare_csh.glsl new file mode 100644 index 00000000..8d08496c --- /dev/null +++ b/Source/Benchmark-Toolbox/source/cuda95/compare_csh.glsl @@ -0,0 +1,59 @@ +#version 430 core +layout(local_size_x = 16, local_size_y = 16) in; + +layout(std430, binding = 0) readonly buffer DataBuffer { + float data[]; +}; + +layout(std430, binding = 1) buffer ResultBuffer { + uint result; +}; + +layout(std140, binding = 0) uniform Params { + uint n_rows; + uint n_repeats; +}; + +const float THRESHOLD = 0.001f; + +// One partial sum to force one atomic per WGP instead of 256. +shared uint s_partial[256]; + +void main() { + uint total_cols = gl_NumWorkGroups.x * gl_WorkGroupSize.x + * gl_NumWorkGroups.y * gl_WorkGroupSize.y; + + uint col = (gl_GlobalInvocationID.y * (gl_NumWorkGroups.x * gl_WorkGroupSize.x)) + + gl_GlobalInvocationID.x; + + uint count = 0u; + + if (n_rows >= 2u) { + for (uint k = 0u; k < n_repeats; ++k) { + // Fuck compiler optimizations, imma start throwing bullshit + float bias = float(k) * 1e-9; + float ref = data[col] + bias; + + for (uint row = 1u; row < n_rows; ++row) { + float val = data[row * total_cols + col]; + if (abs(ref - val) > THRESHOLD) + count++; + } + } + } + + uint lid = gl_LocalInvocationIndex; + s_partial[lid] = count; + memoryBarrierShared(); + barrier(); + + for (uint s = 128u; s > 0u; s >>= 1) { + if (lid < s) + s_partial[lid] += s_partial[lid + s]; + memoryBarrierShared(); + barrier(); + } + + if (lid == 0u) + atomicAdd(result, s_partial[0]); +} diff --git a/Source/Benchmark-Toolbox/source/cuda95/cuda95.cpp b/Source/Benchmark-Toolbox/source/cuda95/cuda95.cpp new file mode 100644 index 00000000..dca7a990 --- /dev/null +++ b/Source/Benchmark-Toolbox/source/cuda95/cuda95.cpp @@ -0,0 +1,948 @@ +#include "cuda95.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef DK_UNIFORM_BUF_ALIGNMENT +#define DK_UNIFORM_BUF_ALIGNMENT 0x100 +#endif + +#define ALIGN_UP(x, a) (((x) + ((a) - 1)) & ~((uint32_t)(a) - 1)) + +#define WG_SIZE_X 16 +#define WG_SIZE_Y 16 +// groups are dispatched in a 4x4 grid, for 2048 threads total +// 2048 per SM = 4096 on TX1, so we fully saturate the GPU +#define NUM_GROUPS_X 4 +#define NUM_GROUPS_Y 4 + +#define N_THREADS ((NUM_GROUPS_X * WG_SIZE_X) * (NUM_GROUPS_Y * WG_SIZE_Y)) // 4096 +#define N_ROWS 64 + +// Thread buffers = N_ROWS * N_THREADS, must be power of 2 +#define N_VEC ((uint64_t)N_ROWS * N_THREADS) // uvec4 elements, 2^18 +#define N_ELEMS (N_VEC * 4) // uints, 2^20 + +static_assert((N_VEC & (N_VEC - 1)) == 0, + "N_ROWS * N_THREADS must be a power of two for the scatter mask"); + +// Gather size, 8192 * 16B = 128KB per SM. Fits into L2 perfectly +#define L2_WINDOW_VEC 8192u +#define DISPATCHES_PER_LIST 32 +#define NUM_INFLIGHT 3 +#define MAX_RECORDS 64 // fault records per batch, per slot + +#define FENCE_TIMEOUT_NS (5ULL * 1000000000ULL) +#define DATA_CHECK_INTERVAL 512 + +#define CODEMEM_SIZE (128 * 1024) +#define CMDMEM_SIZE (512 * 1024) + +#define DKSH_MAGIC UINT32_C(0x48534B44) + +// TOOLBOX: console drawing removed, log kept as a ring buffer. +#define SCR_COLS 79 +#define LOG_LINES 14 + +typedef struct { + uint32_t magic; + uint32_t header_sz; + uint32_t control_sz; + uint32_t code_sz; + uint32_t programs_off; + uint32_t num_programs; +} DkshHeaderLocal; + +// Shader parameters +typedef struct { + uint32_t n_rows; + uint32_t n_repeats; + uint32_t alu_iters; + uint32_t gather_iters; + uint32_t max_records; + uint32_t mode; // 0 = capture golden, 1 = compare, 2 = ignore + uint32_t scatter_mask; // Gather window - 1, used for errors. + uint32_t chain_bias; +} Params; + +// Result buffer +typedef struct { + uint32_t mismatches; + uint32_t digest; + uint32_t selfFail; + uint32_t errCount; +} GpuResult; + +// Errorlog +typedef struct { + uint32_t id; // thread index + uint32_t stage; // 1 = ALU self-check, 2 = per-thread digest + uint32_t got; + uint32_t want; +} GpuRecord; + + +// Presets for calibration +typedef struct { + const char* name; + uint32_t alu; + uint32_t gather; + uint32_t window; // 0 = whole buffer +} Profile; + +// Testing modes +// Balanced tried to hit both +// Core forces 2x chains and not as much memory access, although in practice it strains it enough. +// Dram scatters reads accross allocated size (4MB, lol, lmao even) +// L2 changes this to 256KB. +static const Profile kProfiles[] = { + { "balanced", 64, 32, 0 }, + { "core", 512, 4, 0 }, + { "dram", 8, 256, 0 }, + { "l2", 8, 256, L2_WINDOW_VEC }, +}; +#define NUM_PROFILES ((int)(sizeof(kProfiles) / sizeof(kProfiles[0]))) + +static uint32_t scatterMaskFor(int profile) +{ + uint32_t win = kProfiles[profile].window; + if (win == 0u) win = (uint32_t)N_VEC; + return win - 1u; +} + +// Error storage +typedef struct { + uint64_t batches; + uint64_t detected; // batches where digest=/count + uint64_t transient; // corrected by the re-run vote + uint64_t persistent; // reproduced on re-run + uint64_t selfFail; // ALU DUP/COMP Fails + uint64_t dataBad; // corrupt inputs (how did this happen) + uint64_t warnings; + uint64_t timeouts; +} Tally; + +static Tally g_tally; +static uint64_t g_tStart; + +static char g_log[LOG_LINES][SCR_COLS + 1]; +static uint32_t g_logCount; + +// TOOLBOX: shared state +static std::thread g_thread; +static std::mutex g_lock; +static std::atomic g_stop{ false }; +static std::atomic g_running{ false }; +static cuda95_status_t g_pub{}; + +static int s_profile; +static unsigned s_repeats; +static uint32_t s_goldDigest; +static uint32_t s_goldMismatch; +static double s_dps; +static double s_gbps; +static int s_cal; +static int s_error; +static char s_state[96]; + +static int s_cfgProfile; +static unsigned s_cfgRepeats; +static int s_wantProfile; +static unsigned s_wantRepeats; +static bool s_wantDirty; + +static uint64_t elapsedSec(void) +{ + return armTicksToNs(armGetSystemTick() - g_tStart) / 1000000000ULL; +} + +static void note(const char* fmt, ...) +{ + char body[SCR_COLS + 1]; + va_list ap; + va_start(ap, fmt); + vsnprintf(body, sizeof(body), fmt, ap); + va_end(ap); + + // TOOLBOX: console branch removed + uint32_t idx = g_logCount % LOG_LINES; + int n = snprintf(g_log[idx], sizeof(g_log[idx]), "[%5llus] ", + (unsigned long long)elapsedSec()); + if (n < 0) n = 0; + size_t off = (size_t)n; + if (off > sizeof(g_log[idx]) - 1) off = sizeof(g_log[idx]) - 1; + size_t room = sizeof(g_log[idx]) - 1 - off; + size_t len = strlen(body); + if (len > room) len = room; + memcpy(g_log[idx] + off, body, len); + g_log[idx][off + len] = 0; + g_logCount++; +} + +// Generate seeds +static uint32_t hash32(uint32_t x) +{ + x ^= x >> 16; + x *= 0x7FEB352Du; + x ^= x >> 15; + x *= 0x846CA68Bu; + x ^= x >> 16; + return x; +} + + +// RNG, clamped so nothing fucking explodes too hard +static uint32_t dataBits(uint64_t index) +{ + uint32_t bits = hash32((uint32_t)index); + uint32_t exp = (bits >> 23) & 0xFFu; + if (exp < 0x30u) exp = 0x30u + (exp & 0x0Fu); + if (exp > 0xC0u) exp = 0xC0u - (exp & 0x0Fu); + return (bits & 0x807FFFFFu) | (exp << 23); +} + + +typedef struct { + DkMemBlock block; + uint32_t offset; + uint32_t size; +} BumpAlloc; + +static uint32_t bumpAlloc(BumpAlloc* a, uint32_t size, uint32_t align) +{ + uint32_t off = ALIGN_UP(a->offset, align); + if (off + size > a->size) { + note("out of memory (need %u, have %u)", off + size, a->size); + return UINT32_MAX; + } + a->offset = off + size; + return off; +} + +static void* cpuPtr(BumpAlloc* a, uint32_t off) +{ + return (uint8_t*)dkMemBlockGetCpuAddr(a->block) + off; +} + +static DkGpuAddr gpuPtr(BumpAlloc* a, uint32_t off) +{ + return dkMemBlockGetGpuAddr(a->block) + off; +} + +// TOOLBOX: copy worker state for the UI thread. +static void publish(void) +{ + cuda95_status_t s{}; + s.batches = g_tally.batches; + s.detected = g_tally.detected; + s.transient = g_tally.transient; + s.persistent = g_tally.persistent; + s.selfFail = g_tally.selfFail; + s.dataBad = g_tally.dataBad; + s.warnings = g_tally.warnings; + s.timeouts = g_tally.timeouts; + s.dispPerSec = s_dps; + s.gbps = s_gbps; + s.goldDigest = s_goldDigest; + s.goldMismatch = s_goldMismatch; + s.elapsedSec = elapsedSec(); + s.profile = s_profile; + s.repeats = s_repeats; + s.calibrating = s_cal; + s.running = g_running.load() ? 1 : 0; + s.error = s_error; + snprintf(s.status, sizeof(s.status), "%s", s_state); + + uint32_t total = g_logCount < LOG_LINES ? g_logCount : LOG_LINES; + uint32_t keep = total < CUDA95_LOG_LINES ? total : CUDA95_LOG_LINES; + s.logLines = keep; + for (unsigned i = 0; i < keep; i++) { + uint32_t idx = (g_logCount - keep + i) % LOG_LINES; + snprintf(s.log[i], sizeof(s.log[i]), "%s", g_log[idx]); + } + + std::lock_guard lk(g_lock); + g_pub = s; +} + +static void debugCallback(void* userData, const char* context, + DkResult result, const char* message) +{ + (void)userData; + if (result == DkResult_Success) { + g_tally.warnings++; + note("deko3d warn [%s]: %s", context, message); + publish(); + return; + } + // TOOLBOX: flag the error instead. + note("deko3d ERROR [%s]: %s", context, message); + s_error = 1; + snprintf(s_state, sizeof(s_state), "GPU error"); + publish(); + g_stop.store(true); +} + +static bool loadShader(DkShader* shader, BumpAlloc* codeMem, const char* path) +{ + FILE* f = fopen(path, "rb"); + if (!f) { note("cannot open %s", path); return false; } + + DkshHeaderLocal hdr; + if (fread(&hdr, sizeof(hdr), 1, f) != 1 || hdr.magic != DKSH_MAGIC) { + note("%s is not a DKSH file", path); + fclose(f); + return false; + } + + void* control = malloc(hdr.control_sz); + if (!control) { fclose(f); return false; } + + rewind(f); + if (fread(control, hdr.control_sz, 1, f) != 1) { + free(control); fclose(f); return false; + } + + uint32_t codeOff = bumpAlloc(codeMem, hdr.code_sz, DK_SHADER_CODE_ALIGNMENT); + if (codeOff == UINT32_MAX) { free(control); fclose(f); return false; } + + fseek(f, hdr.control_sz, SEEK_SET); + if (fread(cpuPtr(codeMem, codeOff), hdr.code_sz, 1, f) != 1) { + free(control); fclose(f); return false; + } + fclose(f); + + DkShaderMaker maker; + dkShaderMakerDefaults(&maker, codeMem->block, codeOff); + maker.control = control; + dkShaderInitialize(shader, &maker); + + free(control); + return dkShaderIsValid(shader); +} + +// Usual Deko3D memory allocation +typedef struct { + DkQueue queue; + DkCmdBuf cmdbuf; + DkShader shader; + + DkGpuAddr uboAddr; + uint32_t uboSize; + + //3x slots, two are constantly worked on while a third is checked + DkGpuAddr resultAddr[NUM_INFLIGHT]; + GpuResult* resultCpu[NUM_INFLIGHT]; + DkGpuAddr recAddr[NUM_INFLIGHT]; + GpuRecord* recCpu[NUM_INFLIGHT]; + DkCmdList batch[NUM_INFLIGHT]; + + DkGpuAddr dataAddr; + uint32_t dataSize; + uint32_t* dataCpu; + + // Golden digests + DkGpuAddr expAddr; + uint32_t expSize; +} Ctx; + +static void recordBatches(Ctx* c, Params params, uint32_t dispatches) +{ + dkCmdBufClear(c->cmdbuf); + + for (uint32_t s = 0; s < NUM_INFLIGHT; s++) { + const DkShader* shaders[] = { &c->shader }; + dkCmdBufBindShaders(c->cmdbuf, DkStageFlag_Compute, shaders, 1); + + DkBufExtents ubo = { c->uboAddr, c->uboSize }; + dkCmdBufBindUniformBuffers(c->cmdbuf, DkStage_Compute, 0, &ubo, 1); + dkCmdBufPushConstants(c->cmdbuf, c->uboAddr, c->uboSize, + 0, sizeof(params), ¶ms); + + DkBufExtents ssbos[4]; + ssbos[0].addr = c->dataAddr; ssbos[0].size = c->dataSize; + ssbos[1].addr = c->resultAddr[s]; ssbos[1].size = sizeof(GpuResult); + ssbos[2].addr = c->recAddr[s]; ssbos[2].size = MAX_RECORDS * sizeof(GpuRecord); + ssbos[3].addr = c->expAddr; ssbos[3].size = c->expSize; + dkCmdBufBindStorageBuffers(c->cmdbuf, DkStage_Compute, 0, ssbos, 4); + + for (uint32_t i = 0; i < dispatches; i++) + dkCmdBufDispatchCompute(c->cmdbuf, NUM_GROUPS_X, NUM_GROUPS_Y, 1); + + c->batch[s] = dkCmdBufFinishList(c->cmdbuf); + } +} + +typedef enum { RUN_OK = 0, RUN_TIMEOUT, RUN_QUEUE_ERROR } RunStatus; + +static RunStatus runSync(Ctx* c, uint32_t slot, GpuResult* out, uint64_t* outNs) +{ + memset(c->resultCpu[slot], 0, sizeof(GpuResult)); + + DkFence fence; + memset(&fence, 0, sizeof(fence)); + + uint64_t t0 = armGetSystemTick(); + dkQueueSubmitCommands(c->queue, c->batch[slot]); + // CPU politely asks for the data + dkQueueSignalFence(c->queue, &fence, true); + dkQueueFlush(c->queue); + + DkResult r = dkFenceWait(&fence, (int64_t)FENCE_TIMEOUT_NS); + uint64_t t1 = armGetSystemTick(); + if (outNs) *outNs = armTicksToNs(t1 - t0); + + // FAHHHHHHH + if (r != DkResult_Success) + return dkQueueIsInErrorState(c->queue) ? RUN_QUEUE_ERROR : RUN_TIMEOUT; + if (dkQueueIsInErrorState(c->queue)) + return RUN_QUEUE_ERROR; + + *out = *c->resultCpu[slot]; + return RUN_OK; +} + +// Gets reports from GPU results, mainly fault records +static void reportRecords(Ctx* c, uint32_t slot, uint32_t errCount) +{ + uint32_t shown = errCount < MAX_RECORDS ? errCount : MAX_RECORDS; + if (shown > 3) shown = 3; + + for (uint32_t i = 0; i < shown; i++) { + GpuRecord r = c->recCpu[slot][i]; + note(" rec thread %u %s got %08x want %08x", r.id, + r.stage == 1u ? "ALU" : "digest", r.got, r.want); + } + if (errCount > shown) + note(" (%u more records)", errCount - shown); +} + + +// Seperated because this way we can distinguish between source corruption and the GPU on a bender. +static uint32_t checkDataIntegrity(Ctx* c) +{ + const uint32_t stride = 997; + uint32_t bad = 0; + for (uint64_t i = 0; i < N_ELEMS; i += stride) + if (c->dataCpu[i] != dataBits(i)) bad++; + return bad; +} + + +// Capture golden values to confirm them as valid. +// Runs which cannot reproduce their own digests as valid 3 times are assumed as always unstable. +// Used to refuse baking in bad data and instead re compute. +static bool calibrate(Ctx* c, Params base, uint32_t* goldDigest, uint32_t* goldMismatch) +{ + GpuResult r; + Params p = base; + + // Capture data + p.mode = 0; + recordBatches(c, p, 1); + if (runSync(c, 0, &r, NULL) != RUN_OK) { + note("calibration: capture run failed"); + return false; + } + + // Compare against what we have + p.mode = 1; + recordBatches(c, p, 1); + + uint32_t d[3], m[3]; + for (int i = 0; i < 3; i++) { + // TOOLBOX: abort calibration when stopped. + if (g_stop.load()) return false; + if (runSync(c, 0, &r, NULL) != RUN_OK) { + note("calibration: confirm run %d failed", i + 1); + return false; + } + d[i] = r.digest; + m[i] = r.mismatches; + if (r.selfFail || r.errCount) { + g_tally.selfFail += r.selfFail; + note("calibration: run %d reported %u selfFail, %u records", + i + 1, r.selfFail, r.errCount); + reportRecords(c, 0, r.errCount); + } + } + + if (d[0] == d[1] && d[1] == d[2]) { + *goldDigest = d[0]; + *goldMismatch = m[0]; + return true; + } + + // Weigh the results, if nothing appeared twice, then flag these values. + g_tally.detected++; + if (d[0] == d[1] || d[0] == d[2]) { *goldDigest = d[0]; *goldMismatch = m[0]; } + else if (d[1] == d[2]) { *goldDigest = d[1]; *goldMismatch = m[1]; } + else { *goldDigest = d[0]; *goldMismatch = m[0]; } + note("CALIBRATION UNSTABLE: %08x %08x %08x -- reference may be wrong", + d[0], d[1], d[2]); + return true; +} + +// TOOLBOX: worker thread, replace runDemo() loop. +static void workerMain(void) +{ + g_running.store(true); + appletSetAutoSleepDisabled(true); + + { + std::lock_guard lk(g_lock); + s_profile = s_cfgProfile; + s_repeats = s_cfgRepeats; + } + int profile = s_profile; + uint32_t repeats = s_repeats; + + memset(&g_tally, 0, sizeof(g_tally)); + g_logCount = 0; + g_tStart = armGetSystemTick(); + s_goldDigest = 0; + s_goldMismatch = 0; + s_dps = 0.0; + s_gbps = 0.0; + s_cal = 0; + s_error = 0; + snprintf(s_state, sizeof(s_state), "starting"); + + Ctx c; + memset(&c, 0, sizeof(c)); + + note("CUDA95 %d rows x %d threads", N_ROWS, N_THREADS); + + DkDeviceMaker devMaker; + dkDeviceMakerDefaults(&devMaker); + devMaker.cbDebug = debugCallback; + DkDevice device = dkDeviceCreate(&devMaker); + + // Setup queues + DkQueueMaker queueMaker; + dkQueueMakerDefaults(&queueMaker, device); + queueMaker.flags = DkQueueFlags_Compute + | DkQueueFlags_MediumPrio + | DkQueueFlags_DisableZcull; + queueMaker.commandMemorySize = 512 * 1024; + queueMaker.flushThreshold = 128 * 1024; + DkQueue queue = dkQueueCreate(&queueMaker); + c.queue = queue; + + // Allocate and create memory regions + DkMemBlockMaker mbMaker; + dkMemBlockMakerDefaults(&mbMaker, device, CODEMEM_SIZE); + mbMaker.flags = DkMemBlockFlags_CpuUncached + | DkMemBlockFlags_GpuCached + | DkMemBlockFlags_Code; + BumpAlloc codeMem = { dkMemBlockCreate(&mbMaker), 0, CODEMEM_SIZE }; + + uint32_t dataSize = (uint32_t)(N_ELEMS * sizeof(uint32_t)); // 4 MiB + uint32_t expSize = N_THREADS * sizeof(uint32_t); // 16 KiB + uint32_t recSize = MAX_RECORDS * sizeof(GpuRecord); // 1 KiB + uint32_t dataMemSize = ALIGN_UP(CMDMEM_SIZE + dataSize + expSize + + NUM_INFLIGHT * (recSize + 0x100) + 0x4000, + DK_MEMBLOCK_ALIGNMENT); + + dkMemBlockMakerDefaults(&mbMaker, device, dataMemSize); + mbMaker.flags = DkMemBlockFlags_CpuUncached | DkMemBlockFlags_GpuCached; + BumpAlloc dataMem = { dkMemBlockCreate(&mbMaker), 0, dataMemSize }; + + DkCmdBufMaker cbMaker; + dkCmdBufMakerDefaults(&cbMaker, device); + c.cmdbuf = dkCmdBufCreate(&cbMaker); + + uint32_t cmdOff = bumpAlloc(&dataMem, CMDMEM_SIZE, DK_CMDMEM_ALIGNMENT); + dkCmdBufAddMemory(c.cmdbuf, dataMem.block, cmdOff, CMDMEM_SIZE); + + c.uboSize = ALIGN_UP(sizeof(Params), DK_UNIFORM_BUF_ALIGNMENT); + uint32_t uboOff = bumpAlloc(&dataMem, c.uboSize, DK_UNIFORM_BUF_ALIGNMENT); + c.uboAddr = gpuPtr(&dataMem, uboOff); + + // Allocate the result slots so we do not stall + for (uint32_t s = 0; s < NUM_INFLIGHT; s++) { + uint32_t ro = bumpAlloc(&dataMem, sizeof(GpuResult), 0x100); + c.resultAddr[s] = gpuPtr(&dataMem, ro); + c.resultCpu[s] = (GpuResult*)cpuPtr(&dataMem, ro); + + uint32_t eo = bumpAlloc(&dataMem, recSize, 0x100); + c.recAddr[s] = gpuPtr(&dataMem, eo); + c.recCpu[s] = (GpuRecord*)cpuPtr(&dataMem, eo); + } + + uint32_t expOff = bumpAlloc(&dataMem, expSize, 0x100); + c.expAddr = gpuPtr(&dataMem, expOff); + c.expSize = expSize; + + uint32_t dataOff = bumpAlloc(&dataMem, dataSize, 0x100); + c.dataAddr = gpuPtr(&dataMem, dataOff); + c.dataSize = dataSize; + c.dataCpu = (uint32_t*)cpuPtr(&dataMem, dataOff); + + // Fill memory + note("filling %u KiB of test data...", dataSize / 1024); + for (uint64_t i = 0; i < N_ELEMS; i++) { + if ((i & 0xFFFFF) == 0 && g_stop.load()) break; + c.dataCpu[i] = dataBits(i); + } + + uint32_t goldDigest = 0, goldMismatch = 0; + uint32_t expDigest = 0, expMismatch = 0; + bool ready = false; + + // TOOLBOX: host app owns romfs + if (!g_stop.load() && loadShader(&c.shader, &codeMem, "romfs:/shaders/stress_csh.dksh")) { + Params base = { N_ROWS, repeats, + kProfiles[profile].alu, kProfiles[profile].gather, + MAX_RECORDS, 1, scatterMaskFor(profile), 0u }; + + s_cal = 1; + snprintf(s_state, sizeof(s_state), "calibrating"); + note("calibrating (%s, repeats %u)...", kProfiles[profile].name, repeats); + publish(); + if (!g_stop.load() && calibrate(&c, base, &goldDigest, &goldMismatch)) { + expDigest = goldDigest * DISPATCHES_PER_LIST; + expMismatch = goldMismatch * DISPATCHES_PER_LIST; + s_goldDigest = goldDigest; + s_goldMismatch = goldMismatch; + note("golden digest %08x, mismatches %u", goldDigest, goldMismatch); + + Params runParams = base; + runParams.mode = 1; + recordBatches(&c, runParams, DISPATCHES_PER_LIST); + ready = true; + } else if (!g_stop.load()) { + s_error = 1; + snprintf(s_state, sizeof(s_state), "calibration failed"); + note("initial calibration failed, aborting"); + } + s_cal = 0; + + if (ready) { + // Dispatches are idential and use atomicAdd, so batches must be DISPATCHES_PER_lIST * 1 dispatch. + DkFence fences[NUM_INFLIGHT]; + memset(fences, 0, sizeof(fences)); + + uint64_t submitted = 0; + uint64_t windowDisp = 0; + uint64_t tWindow = armGetSystemTick(); + double dps = 0.0; + bool dirty = false; + bool fatal = false; + snprintf(s_state, sizeof(s_state), "running"); + publish(); + + while (!g_stop.load() && !fatal) { + // TOOLBOX: settings from the UI + { + std::lock_guard lk(g_lock); + if (s_wantDirty) { + s_wantDirty = false; + profile = s_wantProfile; + repeats = s_wantRepeats; + s_profile = profile; + s_repeats = repeats; + dirty = true; + } + } + + if (dirty) { + // If we get an error, recapture golden digest for comparisons to actually work. + dkQueueWaitIdle(queue); + + base.n_repeats = repeats; + base.alu_iters = kProfiles[profile].alu; + base.gather_iters = kProfiles[profile].gather; + base.scatter_mask = scatterMaskFor(profile); + base.mode = 1; + + s_cal = 1; + snprintf(s_state, sizeof(s_state), "calibrating"); + note("recalibrating (%s, repeats %u)...", kProfiles[profile].name, repeats); + publish(); + + if (g_stop.load()) break; + if (!calibrate(&c, base, &goldDigest, &goldMismatch)) { + note("recalibration failed"); + s_error = 1; + snprintf(s_state, sizeof(s_state), "recalibration failed"); + fatal = true; + s_cal = 0; + publish(); + break; + } + expDigest = goldDigest * DISPATCHES_PER_LIST; + expMismatch = goldMismatch * DISPATCHES_PER_LIST; + s_goldDigest = goldDigest; + s_goldMismatch = goldMismatch; + note("calibrated %s repeats %u -> digest %08x", + kProfiles[profile].name, repeats, goldDigest); + + Params runParams = base; + runParams.mode = 1; + recordBatches(&c, runParams, DISPATCHES_PER_LIST); + + memset(fences, 0, sizeof(fences)); + submitted = 0; + dirty = false; + s_cal = 0; + snprintf(s_state, sizeof(s_state), "running"); + publish(); + } + + uint32_t slot = (uint32_t)(submitted % NUM_INFLIGHT); + + if (submitted >= NUM_INFLIGHT) { + DkResult r = dkFenceWait(&fences[slot], (int64_t)FENCE_TIMEOUT_NS); + + if (dkQueueIsInErrorState(queue)) { + note("FATAL: queue entered error state"); + s_error = 1; + snprintf(s_state, sizeof(s_state), "GPU queue error"); + fatal = true; + publish(); + break; + } + if (r != DkResult_Success) { + g_tally.timeouts++; + note("FATAL: batch exceeded %llu s deadline", + (unsigned long long)(FENCE_TIMEOUT_NS / 1000000000ULL)); + s_error = 1; + snprintf(s_state, sizeof(s_state), "batch timeout"); + fatal = true; + publish(); + break; + } + + g_tally.batches++; + GpuResult res = *c.resultCpu[slot]; + + bool bad = (res.digest != expDigest) || (res.mismatches != expMismatch); + + // Shader COMP/DUP still occurs even if digests are bad. + // Allows to distinguish what died. + if (res.selfFail) { + g_tally.selfFail += res.selfFail; + note("batch %llu: %u ALU self-check failures", + (unsigned long long)g_tally.batches, res.selfFail); + bad = true; + } + if (res.errCount) { + reportRecords(&c, slot, res.errCount); + bad = true; + } + + // We outa stability + if (bad) { + if (res.digest != expDigest) + note("batch %llu: digest %08x want %08x", + (unsigned long long)g_tally.batches, res.digest, expDigest); + + g_tally.detected++; + + // Re run batches twice and average, mainly for transience. + dkQueueWaitIdle(queue); + GpuResult a, b; + RunStatus s1 = runSync(&c, slot, &a, NULL); + RunStatus s2 = runSync(&c, slot, &b, NULL); + if (s1 != RUN_OK || s2 != RUN_OK) { + note("FATAL: re-run failed during vote"); + s_error = 1; + snprintf(s_state, sizeof(s_state), "re-run failed"); + fatal = true; + publish(); + break; + } + + // If we rerun, replay the same list so batches are compared to what they should result in, not the golden value for single dispatches + bool aOk = (a.digest == expDigest) && !a.selfFail && !a.errCount; + bool bOk = (b.digest == expDigest) && !b.selfFail && !b.errCount; + + // If we detect transience, then we sorta ball, if its persistent, fucking overvolt. + if (aOk && bOk) { + g_tally.transient++; + note(" -> transient, corrected"); + } else { + g_tally.persistent++; + note(" -> PERSISTENT (re-runs %08x, %08x)", a.digest, b.digest); + } + + // How did this happen + // A long time ago + uint32_t badElems = checkDataIntegrity(&c); + if (badElems) { + g_tally.dataBad += badElems; + note(" -> input buffer: %u sampled elements wrong", badElems); + } + + publish(); + memset(fences, 0, sizeof(fences)); + submitted = 0; + continue; + } + + // que + if ((g_tally.batches % DATA_CHECK_INTERVAL) == 0) { + uint32_t badElems = checkDataIntegrity(&c); + if (badElems) { + g_tally.dataBad += badElems; + note("input buffer: %u sampled elements wrong", badElems); + } + publish(); + } + } + + memset(c.resultCpu[slot], 0, sizeof(GpuResult)); + dkQueueSubmitCommands(queue, c.batch[slot]); + dkQueueSignalFence(queue, &fences[slot], true); + dkQueueFlush(queue); + + submitted++; + windowDisp += DISPATCHES_PER_LIST; + + uint64_t now = armGetSystemTick(); + uint64_t windowNs = armTicksToNs(now - tWindow); + if (windowNs >= 500000000ULL) { + double secs = windowNs / 1.0e9; + dps = windowDisp / secs; + + double bytesPer = (double)N_THREADS * 16.0 * repeats + * ((double)N_ROWS + (double)kProfiles[profile].gather); + + s_dps = dps; + s_gbps = (dps * bytesPer) / 1.0e9; + publish(); + + windowDisp = 0; + tWindow = now; + } + } + } + } else if (!g_stop.load()) { + s_error = 1; + snprintf(s_state, sizeof(s_state), "shader load failed"); + note("could not load stress_csh.dksh, aborting"); + publish(); + } + + if (!dkQueueIsInErrorState(queue)) + dkQueueWaitIdle(queue); + dkCmdBufDestroy(c.cmdbuf); + dkMemBlockDestroy(dataMem.block); + dkMemBlockDestroy(codeMem.block); + dkQueueDestroy(queue); + dkDeviceDestroy(device); + + if (!s_error && g_stop.load()) + snprintf(s_state, sizeof(s_state), "stopped"); + publish(); + + appletSetAutoSleepDisabled(false); + g_running.store(false); + publish(); +} + +static unsigned normRepeats(unsigned r) +{ + if (r < CUDA95_REPEATS_MIN) r = CUDA95_REPEATS_MIN; + if (r > CUDA95_REPEATS_MAX) r = CUDA95_REPEATS_MAX; + unsigned p = 1; + while (p * 2u <= r) p *= 2u; + return p; +} + +static int normProfile(int p) +{ + if (p < 0) return 0; + if (p >= NUM_PROFILES) return NUM_PROFILES - 1; + return p; +} + +extern "C" { + +void cuda95_start(int profile, unsigned repeats) +{ + cuda95_stop(); + + { + std::lock_guard lk(g_lock); + s_cfgProfile = normProfile(profile); + s_cfgRepeats = normRepeats(repeats); + s_wantProfile = s_cfgProfile; + s_wantRepeats = s_cfgRepeats; + s_wantDirty = false; + memset(&g_pub, 0, sizeof(g_pub)); + snprintf(g_pub.status, sizeof(g_pub.status), "starting"); + } + + g_stop.store(false); + g_thread = std::thread(workerMain); +} + +void cuda95_stop(void) +{ + g_stop.store(true); + if (g_thread.joinable()) + g_thread.join(); +} + +int cuda95_running(void) +{ + return g_running.load() ? 1 : 0; +} + +void cuda95_get(cuda95_status_t *out) +{ + if (!out) return; + std::lock_guard lk(g_lock); + *out = g_pub; +} + +void cuda95_set_profile(int profile) +{ + std::lock_guard lk(g_lock); + s_cfgProfile = normProfile(profile); + if (g_running.load()) { + s_wantProfile = s_cfgProfile; + s_wantDirty = true; + } +} + +void cuda95_set_repeats(unsigned repeats) +{ + std::lock_guard lk(g_lock); + s_cfgRepeats = normRepeats(repeats); + if (g_running.load()) { + s_wantRepeats = s_cfgRepeats; + s_wantDirty = true; + } +} + +const char *cuda95_profile_name(int profile) +{ + profile = normProfile(profile); + return kProfiles[profile].name; +} + +unsigned cuda95_profile_alu(int profile) +{ + profile = normProfile(profile); + return kProfiles[profile].alu; +} + +unsigned cuda95_profile_gather(int profile) +{ + profile = normProfile(profile); + return kProfiles[profile].gather; +} + +} // extern C + diff --git a/Source/Benchmark-Toolbox/source/cuda95/cuda95.h b/Source/Benchmark-Toolbox/source/cuda95/cuda95.h new file mode 100644 index 00000000..67d0002c --- /dev/null +++ b/Source/Benchmark-Toolbox/source/cuda95/cuda95.h @@ -0,0 +1,70 @@ +#pragma once + +// CUDA-95NX backend. + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CUDA95_NUM_PROFILES 4 + +#define CUDA95_REPEATS_MIN 1u +#define CUDA95_REPEATS_MAX 256u + +#define CUDA95_LOG_LINES 8 +#define CUDA95_LOG_COLS 96 + +// Profiles +// 0 = balanced +// 1 = core +// 2 = dram +// 3 = l2 + +typedef struct { + uint64_t batches; + uint64_t detected; + uint64_t transient; + uint64_t persistent; + uint64_t selfFail; + uint64_t dataBad; + uint64_t warnings; + uint64_t timeouts; + + double dispPerSec; + double gbps; + + uint32_t goldDigest; + uint32_t goldMismatch; + + uint64_t elapsedSec; + + int profile; + unsigned repeats; + + int calibrating; + int running; + int error; + char status[96]; + + char log[CUDA95_LOG_LINES][CUDA95_LOG_COLS]; + unsigned logLines; +} cuda95_status_t; + +void cuda95_start(int profile, unsigned repeats); +void cuda95_stop(void); +int cuda95_running(void); +void cuda95_get(cuda95_status_t *out); + +void cuda95_set_profile(int profile); +void cuda95_set_repeats(unsigned repeats); + +const char *cuda95_profile_name(int profile); +unsigned cuda95_profile_alu(int profile); +unsigned cuda95_profile_gather(int profile); + +#ifdef __cplusplus +} +#endif + diff --git a/Source/Benchmark-Toolbox/source/cuda95/stress_csh.glsl b/Source/Benchmark-Toolbox/source/cuda95/stress_csh.glsl new file mode 100644 index 00000000..ac23b75d --- /dev/null +++ b/Source/Benchmark-Toolbox/source/cuda95/stress_csh.glsl @@ -0,0 +1,202 @@ +#version 430 core +// CRAWLING IN MY SKINNNNNN +// THESE WOUNDS THEY WILL NOT HEALLLLLLLL +// Furmark bored the fuck out of me tbh although the black hole bench I do want to revisit but thats besides the point. + +// Here we are, this compute shitpost draws more power than furmark. + +// TX1 has 2SMs with 4 schedulers with 2x issue. So 256 threads per block, 8 blocks per sm, 2048 threads dispatched as a max +layout(local_size_x = 16, local_size_y = 16) in; // 256 threads = 8 warps + + +// uvec4 used here to use LDG, essentially forcing data to be read from the unified instruction cache, diferenciating from a global/generic load +// For us, besdies the speedup this also means that lanes pulls 512 bytes instead of 128, forcing mem/l2 more. +layout(std430, binding = 0) readonly buffer DataBuffer { + uvec4 data[]; +}; + +layout(std430, binding = 1) buffer ResultBuffer { + uint mismatches; + uint digest; + uint selfFail; + uint errCount; +}; + +// ALU self checks/mismatch storage +layout(std430, binding = 2) buffer ErrorLog { + uvec4 record[]; +}; + +layout(std430, binding = 3) buffer ExpectedBuffer { + uint expected[]; +}; + +layout(std140, binding = 0) uniform Params { + uint n_rows; + uint n_repeats; + uint alu_iters; + uint gather_iters; + uint max_records; + uint mode; // 0 = capture golden, 1 = compare, 2 = ignore + uint scatter_mask; // limits size to stay in L2 or not + uint chain_bias; // normally 0; see aluChain2 +}; + +const float THRESHOLD = 0.001f; + + +// "scratchpad", not really. +// this is configured for 8kb per block (for 64Kb), any higher drops our block count +shared uint s_scratch[2048]; + +// FNV-1a. Surpringly heavy because maxwell. (XMAD) +uint hmix(uint h, uint v) +{ + h ^= v; + h *= 16777619u; + return h; +} + +// Constant shifts, so every index below must be a mask/add +uint xs32(uint x) +{ + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + return x; +} + +void pushRecord(uint id, uint stage, uint got, uint want) +{ + uint idx = atomicAdd(errCount, 1u); + if (idx < max_records) + record[idx] = uvec4(id, stage, got, want); +} + + +// Man fuck current limits. +// Here we issue 2 instructions per cycle, intervealing to achive this. +// chian_bias is only here to stop the compiler from optimizing it away. +// CPU side passes zero so results must be equal, otherwise we know an error occured. +// Giving anything else breaks. +uvec2 aluChain2(uint seed, uint iters) +{ + uint s2 = seed ^ chain_bias; + + uint h1 = seed, h2 = s2; + uint a1 = seed | 1u, a2 = s2 | 1u; + float f1 = uintBitsToFloat((seed & 0x007FFFFFu) | 0x3F800000u); + float f2 = uintBitsToFloat((s2 & 0x007FFFFFu) | 0x3F800000u); + + for (uint i = 0u; i < iters; ++i) { + // int/FP work + a1 = xs32(a1) + 0x9E3779B9u; + a2 = xs32(a2) + 0x9E3779B9u; + f1 = fma(f1, f1, 0.5); + f2 = fma(f2, f2, 0.5); + // Force values back into [1,2]. + f1 = uintBitsToFloat((floatBitsToUint(f1) & 0x007FFFFFu) | 0x3F800000u); + f2 = uintBitsToFloat((floatBitsToUint(f2) & 0x007FFFFFu) | 0x3F800000u); + h1 = hmix(h1 ^ a1, floatBitsToUint(f1)); + h2 = hmix(h2 ^ a2, floatBitsToUint(f2)); + } + return uvec2(h1, h2); +} + +// I hate myself +void main() +{ + uint gx = gl_NumWorkGroups.x * gl_WorkGroupSize.x; + uint tid = gl_GlobalInvocationID.y * gx + gl_GlobalInvocationID.x; + + // Distance in elements between rows. Also serves as the thread count + uint stride = gx * gl_NumWorkGroups.y * gl_WorkGroupSize.y; + + uint lid = gl_LocalInvocationIndex; + + uint count = 0u; + uint h = 2166136261u ^ tid; + + for (uint k = 0u; k < n_repeats; ++k) { + + // read uvec4 data continously + uvec4 ref = data[tid]; + h = hmix(hmix(hmix(hmix(h, ref.x), ref.y), ref.z), ref.w); + + vec4 fref = uintBitsToFloat(ref); + uint idx = tid; + + for (uint row = 1u; row < n_rows; ++row) { + + // On reduced load, adss per row instead of IMAD, which because Nvidia would expand into XMAD competing for resorces. + idx += stride; + + uvec4 v = data[idx]; + h = hmix(hmix(hmix(hmix(h, v.x), v.y), v.z), v.w); + + // FSETP + used instead of creating divergence. + bvec4 hit = greaterThan(abs(fref - uintBitsToFloat(v)), vec4(THRESHOLD)); + count += uint(hit.x) + uint(hit.y) + uint(hit.z) + uint(hit.w); + } + + // Gather data in a different line every lane. + // Sized under L2 max, because fuck cache + uint st = xs32(h | 1u); + for (uint g = 0u; g < gather_iters; ++g) { + st = xs32(st); + uvec4 v = data[st & scatter_mask]; + h = hmix(hmix(hmix(hmix(h, v.x), v.y), v.z), v.w); + } + + // 2x issue redundancy + uvec2 cc = aluChain2(h, alu_iters); + if (cc.x != cc.y) { + atomicAdd(selfFail, 1u); + pushRecord(tid, 1u, cc.x, cc.y); + } + h = cc.x; + + + // Write back to memory + for (uint j = 0u; j < 8u; ++j) + s_scratch[lid + j * 256u] = h + j; + memoryBarrierShared(); + barrier(); + + uint t = 0u; + for (uint j = 0u; j < 8u; ++j) + t = hmix(t, s_scratch[((lid * 37u + 11u) + j * 251u) & 2047u]); + h = hmix(h, t); + memoryBarrierShared(); + barrier(); + } + + // Compare golden samples + if (mode == 0u) { + expected[tid] = h; + } else if (mode == 1u && h != expected[tid]) { + pushRecord(tid, 2u, h, expected[tid]); + } + + + // Fused reduction, digest/count reduced to 8 barriers with one pass instead of 2. + s_scratch[lid] = h; + s_scratch[256u + lid] = count; + memoryBarrierShared(); + barrier(); + + for (uint s = 128u; s > 0u; s >>= 1) { + if (lid < s) { + s_scratch[lid] += s_scratch[lid + s]; + s_scratch[256u + lid] += s_scratch[256u + lid + s]; + } + memoryBarrierShared(); + barrier(); + } + + // Atomic (16 per WGP) + if (lid == 0u) { + atomicAdd(digest, s_scratch[0]); + atomicAdd(mismatches, s_scratch[256u]); + } +} diff --git a/Source/Benchmark-Toolbox/source/main.cpp b/Source/Benchmark-Toolbox/source/main.cpp index dad466bf..91bc8bf2 100644 --- a/Source/Benchmark-Toolbox/source/main.cpp +++ b/Source/Benchmark-Toolbox/source/main.cpp @@ -14,6 +14,7 @@ extern "C" { #include "bench.h" #include "cpu_stress.h" +#include "cuda95.h" #include "gpu_bw.h" #include "gpu_stress.h" #include "hoc_clk.h" @@ -436,6 +437,126 @@ class StressTab : public brls::Box { brls::Label *statusL, *gflops, *dispatches, *mismatches; }; +class Cuda95Tab : public brls::Box { + public: + Cuda95Tab() { + this->setAxis(brls::Axis::COLUMN); + this->setGrow(1.0f); + this->setPadding(40.0f, 60.0f, 40.0f, 60.0f); + + auto *profRow = new brls::Box(brls::Axis::ROW); + profRow->setMarginBottom(14.0f); + auto *pl = new brls::Label(); + pl->setText("Profile"); + pl->setGrow(1.0f); + profRow->addView(pl); + profVal = new brls::Label(); + profRow->addView(profVal); + this->addView(profRow); + + refreshOpts(); + + auto *hint = new brls::Label(); + hint->setText("L / R: profile. A: start / stop."); + hint->setFontSize(15.0f); + hint->setTextColor(nvgRGB(150, 150, 150)); + hint->setMarginBottom(18.0f); + this->addView(hint); + + toggle = new brls::Button(); + toggle->setText("Start"); + toggle->registerClickAction([this](brls::View *) { + onToggle(); + return true; + }); + this->addView(toggle); + + this->registerAction("Prev profile", brls::ControllerButton::BUTTON_LB, [this](brls::View *) { + cycleProfile(-1); + return true; + }); + this->registerAction("Next profile", brls::ControllerButton::BUTTON_RB, [this](brls::View *) { + cycleProfile(1); + return true; + }); + + statusL = new brls::Label(); + statusL->setText("Stopped"); + statusL->setMarginTop(10.0f); + statusL->setMarginBottom(8.0f); + this->addView(statusL); + + auto *h = new brls::Header(); + h->setTitle("Info"); + this->addView(h); + rowRate = makeRow(this, "Read rate"); + rowBatches = makeRow(this, "Batches"); + rowMismatch = makeRow(this, "Mismatches"); + } + + ~Cuda95Tab() override { + if (cuda95_running()) + cuda95_stop(); + } + + void willDisappear(bool resetState = false) override { + if (cuda95_running()) + cuda95_stop(); + brls::Box::willDisappear(resetState); + } + + void frame(brls::FrameContext *ctx) override { + cuda95_status_t st; + cuda95_get(&st); + if (cuda95_running() || lastRunning) { + rowRate->setText(fstr("%.2f GB/s", st.gbps)); + rowBatches->setText(fstru("%llu", (unsigned long long)st.batches)); + unsigned long long mm = (unsigned long long)st.detected + (unsigned long long)st.selfFail + + (unsigned long long)st.dataBad + (unsigned long long)st.timeouts; + rowMismatch->setText(fstru("%llu", mm)); + if (cuda95_running()) + statusL->setText(st.error ? std::string("Error: ") + st.status : std::string(st.status)); + } + syncToggle(cuda95_running() != 0); + brls::Box::frame(ctx); + } + + private: + void refreshOpts() { + char b[64]; + std::snprintf(b, sizeof b, "%s (%u/%u)", cuda95_profile_name(profile), + cuda95_profile_alu(profile), cuda95_profile_gather(profile)); + profVal->setText(b); + } + void cycleProfile(int dir) { + profile = (profile + dir + CUDA95_NUM_PROFILES) % CUDA95_NUM_PROFILES; + refreshOpts(); + if (cuda95_running()) + cuda95_set_profile(profile); + } + void onToggle() { + if (cuda95_running()) { + cuda95_stop(); + } else { + rowRate->setText("-"); + rowBatches->setText("-"); + rowMismatch->setText("-"); + cuda95_start(profile, 4); + } + } + void syncToggle(bool running) { + if (running == lastRunning) + return; + lastRunning = running; + toggle->setText(running ? "Stop" : "Start"); + if (!running) + statusL->setText("Stopped"); + } + int profile = 0; + bool lastRunning = false; + brls::Label *profVal, *statusL, *rowRate, *rowBatches, *rowMismatch; + brls::Button *toggle; +}; class FurmarkTab : public brls::Box { public: FurmarkTab(int which, const char *desc) : which(which) { @@ -849,6 +970,7 @@ class CreditsTab : public brls::Box { makeRow(this, "Memtester")->setText("Simon Kirby, Charles Cazabon, KazushiMe & CTCaer"); makeRow(this, "FurMark")->setText("StanislavPetrovV & AnxietyTimmy"); makeRow(this, "GPU Test")->setText("NaGaa95"); + makeRow(this, "CUDA95")->setText("AnxietyTimmy"); makeRow(this, "Membench")->setText("Siarhei Siamashka, KazushiMe & Lineon"); makeRow(this, "Stress-ng")->setText("ColinIanKing & Lineon"); @@ -944,6 +1066,7 @@ class MainActivity : public brls::Activity { tab->addHeader("GPU"); tab->addTab("GPU Test", [] { return new StressTab(); }); + tab->addTab("CUDA95", [] { return new Cuda95Tab(); }); tab->addTab("Furmark", [] { return new FurmarkTab(0, "FurMark for Switch (48 step)"); }); tab->addTab("GPU Path Trace", [] { return new FurmarkTab(2, "GPU Path Tracer"); }); @@ -988,6 +1111,8 @@ int main(int argc, char *argv[]) { mt_cpu_stop(); if (cpu_stress_running()) cpu_stress_stop(); + if (cuda95_running()) + cuda95_stop(); _exit(EXIT_SUCCESS); } diff --git a/Source/Horizon-OC-Monitor (deprecated)/.gitignore b/Source/Horizon-OC-Monitor (deprecated)/.gitignore deleted file mode 100644 index 3e35c18f..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ - -build/ - -*.ovl - -*.elf - -*.nacp - -*.nro diff --git a/Source/Horizon-OC-Monitor (deprecated)/Horizon-OC-Monitor.lst b/Source/Horizon-OC-Monitor (deprecated)/Horizon-OC-Monitor.lst deleted file mode 100644 index 1a834f7f..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/Horizon-OC-Monitor.lst +++ /dev/null @@ -1,2 +0,0 @@ --CSn -/home/sould/Documents/GitHub/Horizon-OC/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.elf diff --git a/Source/Horizon-OC-Monitor (deprecated)/LICENSE b/Source/Horizon-OC-Monitor (deprecated)/LICENSE deleted file mode 100644 index d159169d..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that 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, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/Source/Horizon-OC-Monitor (deprecated)/Makefile b/Source/Horizon-OC-Monitor (deprecated)/Makefile deleted file mode 100644 index e2e4776b..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/Makefile +++ /dev/null @@ -1,243 +0,0 @@ -#--------------------------------------------------------------------------------- -.SUFFIXES: -#--------------------------------------------------------------------------------- - -ifeq ($(strip $(DEVKITPRO)),) -$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=/devkitpro") -endif - -TOPDIR ?= $(CURDIR) -include $(DEVKITPRO)/libnx/switch_rules - -#--------------------------------------------------------------------------------- -# TARGET is the name of the output -# BUILD is the directory where object files & intermediate files will be placed -# SOURCES is a list of directories containing source code -# DATA is a list of directories containing data files -# INCLUDES is a list of directories containing header files -# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) -# -# NO_ICON: if set to anything, do not use icon. -# NO_NACP: if set to anything, no .nacp file is generated. -# APP_TITLE is the name of the app stored in the .nacp file (Optional) -# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) -# APP_VERSION is the version of the app stored in the .nacp file (Optional) -# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) -# ICON is the filename of the icon (.jpg), relative to the project folder. -# If not set, it attempts to use one of the following (in this order): -# - .jpg -# - icon.jpg -# - /default_icon.jpg -# -# CONFIG_JSON is the filename of the NPDM config file (.json), relative to the project folder. -# If not set, it attempts to use one of the following (in this order): -# - .json -# - config.json -# If a JSON file is provided or autodetected, an ExeFS PFS0 (.nsp) is built instead -# of a homebrew executable (.nro). This is intended to be used for sysmodules. -# NACP building is skipped as well. -#--------------------------------------------------------------------------------- -APP_TITLE := Horizon OC Monitor -APP_VERSION := 1.3.2+r4-hoc-r4 -TARGET := $(notdir $(CURDIR)) -BUILD := build -SOURCES := source -INCLUDES := include lib/Atmosphere-libs/libstratosphere/source/dmnt lib/Atmosphere-libs/libstratosphere/source ../hoc-clk/common/include/ -NO_ICON := 1 -#ROMFS := romfs - -# This location should reflect where you place the libultrahand directory (lib can vary between projects). -include ${TOPDIR}/lib/libultrahand/ultrahand.mk - - -#--------------------------------------------------------------------------------- -# options for code generation -#--------------------------------------------------------------------------------- -ARCH := -march=armv8-a+simd+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE - -CFLAGS := -g -Wall -Wno-address-of-packed-member -O3 -ffunction-sections -ffast-math -flto -fomit-frame-pointer \ - -fuse-linker-plugin -finline-small-functions \ - -fno-strict-aliasing -frename-registers -falign-functions=16 \ - $(ARCH) $(DEFINES) - -# For compiling Ultrahand Overlay only -IS_STATUS_MONITOR_DIRECTIVE := 1 -CFLAGS += -DIS_STATUS_MONITOR_DIRECTIVE=$(IS_STATUS_MONITOR_DIRECTIVE) - -# Enable appearance overriding -export MSYS2_ARG_CONV_EXCL := -DUI_OVERRIDE_PATH -UI_OVERRIDE_PATH := /config/status-monitor/ -CFLAGS += -DUI_OVERRIDE_PATH="\"$(UI_OVERRIDE_PATH)\"" - - -CFLAGS += $(INCLUDE) -D__SWITCH__ -DAPP_VERSION="\"$(APP_VERSION)\"" - -CXXFLAGS := $(CFLAGS) -std=c++26 -Wno-dangling-else -fno-unwind-tables -fno-asynchronous-unwind-tables - -ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) - -LIBS := -lnx - -CXXFLAGS += -fno-exceptions -ffunction-sections -fdata-sections -fno-rtti -LDFLAGS += -Wl,--gc-sections -Wl,--as-needed - - -# For Ensuring Parallel LTRANS Jobs w/ GCC, make -j6 -CXXFLAGS += -flto -fuse-linker-plugin -flto=6 -LDFLAGS += -flto=6 - -#--------------------------------------------------------------------------------- -# list of directories containing libraries, this must be the top level containing -# include and lib -#--------------------------------------------------------------------------------- -LIBDIRS := $(PORTLIBS) $(LIBNX) - - -#--------------------------------------------------------------------------------- -# no real need to edit anything past this point unless you need to add additional -# rules for different file extensions -#--------------------------------------------------------------------------------- -ifneq ($(BUILD),$(notdir $(CURDIR))) -#--------------------------------------------------------------------------------- - -export OUTPUT := $(CURDIR)/$(TARGET) -export TOPDIR := $(CURDIR) - -export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ - $(foreach dir,$(DATA),$(CURDIR)/$(dir)) - -export DEPSDIR := $(CURDIR)/$(BUILD) - -CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) -CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) -SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) -BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) - -#--------------------------------------------------------------------------------- -# use CXX for linking C++ projects, CC for standard C -#--------------------------------------------------------------------------------- -ifeq ($(strip $(CPPFILES)),) -#--------------------------------------------------------------------------------- - export LD := $(CC) -#--------------------------------------------------------------------------------- -else -#--------------------------------------------------------------------------------- - export LD := $(CXX) -#--------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------- - -export OFILES_BIN := $(addsuffix .o,$(BINFILES)) -export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) -export OFILES := $(OFILES_BIN) $(OFILES_SRC) -export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) - -export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ - $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) - -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) - -ifeq ($(strip $(CONFIG_JSON)),) - jsons := $(wildcard *.json) - ifneq (,$(findstring $(TARGET).json,$(jsons))) - export APP_JSON := $(TOPDIR)/$(TARGET).json - else - ifneq (,$(findstring config.json,$(jsons))) - export APP_JSON := $(TOPDIR)/config.json - endif - endif -else - export APP_JSON := $(TOPDIR)/$(CONFIG_JSON) -endif - -ifeq ($(strip $(ICON)),) - icons := $(wildcard *.jpg) - ifneq (,$(findstring $(TARGET).jpg,$(icons))) - export APP_ICON := $(TOPDIR)/$(TARGET).jpg - else - ifneq (,$(findstring icon.jpg,$(icons))) - export APP_ICON := $(TOPDIR)/icon.jpg - endif - endif -else - export APP_ICON := $(TOPDIR)/$(ICON) -endif - -ifeq ($(strip $(NO_ICON)),) - export NROFLAGS += --icon=$(APP_ICON) -endif - -ifeq ($(strip $(NO_NACP)),) - export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp -endif - -ifneq ($(APP_TITLEID),) - export NACPFLAGS += --titleid=$(APP_TITLEID) -endif - -ifneq ($(ROMFS),) - export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) -endif - -.PHONY: $(BUILD) clean all - -#--------------------------------------------------------------------------------- -all: $(BUILD) - - -$(BUILD): - @[ -d $@ ] || mkdir -p $@ - @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile - @rm -rf out/ - @mkdir -p out/switch/.overlays/ - @cp -a $(CURDIR)/config out/ - @cp $(CURDIR)/$(TARGET).ovl out/switch/.overlays/$(TARGET).ovl - -#--------------------------------------------------------------------------------- -clean: - @echo "Cleanning ... $(TARGET)" - @rm -fr $(BUILD) $(TARGET).ovl $(TARGET).nro $(TARGET).nacp $(TARGET).elf - @rm -rf out/ - @rm -f $(TARGET).zip - -#--------------------------------------------------------------------------------- -dist: all - @echo making dist ... - @rm -f $(TARGET).zip - @cd out; zip -r ../$(TARGET).zip ./*; cd ../ -#--------------------------------------------------------------------------------- -else -.PHONY: all - -DEPENDS := $(OFILES:.o=.d) - -#--------------------------------------------------------------------------------- -# main targets -#--------------------------------------------------------------------------------- -all : $(OUTPUT).ovl - -$(OUTPUT).ovl : $(OUTPUT).elf $(OUTPUT).nacp - @elf2nro $< $@ $(NROFLAGS) - @echo "built ... $(notdir $(OUTPUT).ovl)" - @printf 'ULTR' >> $@ - @printf "Ultrahand signature has been added.\n" - -$(OUTPUT).elf : $(OFILES) - -$(OFILES_SRC) : $(HFILES_BIN) - -#--------------------------------------------------------------------------------- -# you need a rule like this for each extension you use as binary data -#--------------------------------------------------------------------------------- -%.bin.o %_bin.h : %.bin -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - --include $(DEPENDS) - -#--------------------------------------------------------------------------------------- -endif -#--------------------------------------------------------------------------------------- diff --git a/Source/Horizon-OC-Monitor (deprecated)/README.md b/Source/Horizon-OC-Monitor (deprecated)/README.md deleted file mode 100644 index 234e0d02..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/README.md +++ /dev/null @@ -1,9 +0,0 @@ -Thanks to NaGa for Status Monitor Pro!

- -**Horizon-OC-Monitor is deprecated.** If you want to compile it anyway, create a `lib` folder and clone Atmosphere-libs and libultrahand into it:

- -```bash -mkdir lib -git clone https://github.com/Atmosphere-NX/Atmosphere-libs lib/Atmosphere-libs -git clone https://github.com/ppkantorski/libultrahand lib/libultrahand -``` diff --git a/Source/Horizon-OC-Monitor (deprecated)/config/status-monitor/config.ini.template b/Source/Horizon-OC-Monitor (deprecated)/config/status-monitor/config.ini.template deleted file mode 100644 index a11d524b..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/config/status-monitor/config.ini.template +++ /dev/null @@ -1,127 +0,0 @@ -[status-monitor] -battery_avg_iir_filter=false -battery_time_left_refreshrate=60 -average_gpu_load=false -use_old_fps_average=false - -[full] -refresh_rate=1 -layer_width_align=left -show_real_freqs=true -show_deltas=true -show_target_freqs=true -show_fps=true -show_res=true -show_read_speed=true -use_dynamic_colors=true -disable_screenshots=false -separator_color=#888F -cat_color_1=#8FFF -cat_color_2=#8CFF -text_color=#FFFF - -[mini] -refresh_rate=1 -handheld_font_size=15 -docked_font_size=15 -spacing=8 -real_freqs=true -real_volts=true -show_full_cpu=false -show_full_res=true -show_fan_percentage=true -show_soc_voltage=false -use_dynamic_colors=true -show_vddq=false -show_vdd2=true -decimal_vdd2=false -show_dtc=true -use_dtc_symbol=true -dtc_format=%m-%d-%Y%H:%M:%S -show=DTC+BAT+CPU+GPU+RAM+TMP+FPS+RES -replace_MB_with_RAM_load=true -show_RAM_load_CPU_GPU=false -invert_battery_display=true -disable_screenshots=false -sleep_exit=false -frame_offset_x=10 -frame_offset_y=10 -frame_padding=10 -background_color=#0009 -focus_background_color=#000F -separator_color=#888F -cat_color=#2DFF -text_color=#FFFF - -[micro] -refresh_rate=1 -layer_height_align=top -handheld_font_size=15 -docked_font_size=15 -text_align=center -real_freqs=true -real_volts=true -show_full_cpu=false -show_full_res=false -show_soc_voltage=true -use_dynamic_colors=true -show_vddq=false -show_vdd2=true -decimal_vdd2=false -show_dtc=true -use_dtc_symbol=true -dtc_format=%H:%M:%S -show=FPS+CPU+GPU+RAM+SOC+BAT+DTC -replace_GB_with_RAM_load=true -invert_battery_display=false -disable_screenshots=false -sleep_exit=false -background_color=#0009 -separator_color=#888F -cat_color=#2DFF -text_color=#FFFF - -[fps-counter] -refresh_rate=30 -handheld_font_size=40 -docked_font_size=40 -use_integer_counter=false -disable_screenshots=false -frame_offset_x=10 -frame_offset_y=10 -frame_padding=10 -background_color=#0009 -focus_background_color=#000F -text_color=#8CFF - -[fps-graph] -refresh_rate=30 -show_info=false -use_dynamic_colors=true -disable_screenshots=false -frame_offset_x=10 -frame_offset_y=10 -frame_padding=10 -background_color=#0009 -focus_background_color=#000F -fps_counter_color=#888C -border_color=#2DFF -dashed_line_color=#8888 -main_line_color=#FFFF -rounded_line_color=#F0FF -perfect_line_color=#0C0F -max_fps_text_color=#FFFF -min_fps_text_color=#FFFF -text_color=#FFFF -cat_color=#0F0F - -[game_resolutions] -refresh_rate=10 -disable_screenshots=false -frame_offset_x=10 -frame_offset_y=10 -frame_padding=10 -background_color=#0009 -focus_background_color=#000F -cat_color=#8FFF -text_color=#FFFF diff --git a/Source/Horizon-OC-Monitor (deprecated)/docs/config.md b/Source/Horizon-OC-Monitor (deprecated)/docs/config.md deleted file mode 100644 index e01b8466..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/docs/config.md +++ /dev/null @@ -1,103 +0,0 @@ -# Configuration file - -Configuration file is in `sdmc:/config/status-monitor/`. By default it's named `config.ini.template`. To be detected by overlay it must be renamed to `config.ini`. - ---- - -Explanation of what each setting does.
-Colors are provided in RGBA4444 format, which means that each character represents different channel: red, green, blue, alpha. - -> [status-monitor] - -| Key | Explanation | Possible values | Default Value | -|-----|-------------|-----------------|---------------| -| `key_combo` | Buttons combination that allows exiting Full, Mini, Micro, FPS Graph and FPS Counter modes; max 4 buttons, otherwise next buttons will be ignored. Combine different buttons with `+` | `A`, `B`, `X`, `Y`, `L`, `R`, `ZL`, `ZR`, `PLUS`, `MINUS`, `DUP`, `DDOWN`, `DLEFT`, `DRIGHT`, `SL`, `SR`, `LSTICK`, `RSTICK`, `UP`, `DOWN`, `LEFT`, `RIGHT` | `L+DDOWN+RSTICK` | -| `battery_avg_iir_filter` | Read voltage + current averages directly from fuel gauge, that uses infinite impulse response filter | `true`, `false` | `false` | -| `battery_time_left_refreshrate` | How many seconds must pass to refresh Battery Remaining Time | from `1` to `60` | `60` | -| `average_gpu_load` | Average 5 last GPU load readings. Because GPU load by design shows only load for last 1/60s, this option allows for more accurate gpu load readings at the cost of slight bump in CPU Core #3 usage (from 2 to 4 percentage points depending on CPU clock). | `true`, `false` | `false` | -| `font_cache` | Allow caching generated glyphs for better performance. Cache is cleaned up when moving between modes. | `true`, `false` | `true` | - - -> [full] - -| Key | Explanation | Possible values | Default Value | -|-----|-------------|-----------------|---------------| -| `refresh_rate` | How often per second this mode should be refreshed. Higher value means higher CPU Core #3 usage, that's why it is recommended to stay at 1. | From `1` to `60` | `1` | -| `layer_width_align` | On which side of the screen X axis you want this mode | `left`, `right` | `left` | -| `show_real_freqs` | This works only if you have sys-clk 2.0.0_rc4+ installed. Show real frequencies for CPU, GPU and RAM | `false`, `true` | `true` | -| `show_deltas` | This works only if you have sys-clk 2.0.0_rc4+ installed. Show difference for CPU, GPU and RAM between target frequencies and real frequencies. They are not showed if both keys `show_real_freqs` and `show_target_freqs` are set to `false` | `false`, `true` | `true` | -| `show_target_freqs` | Show target frequencies for CPU, GPU and RAM | `false`, `true` | `true` | -| `show_fps` | Show game's FPS and PFPS | `false`, `true` | `true` | -| `show_res` | Show game's 2 best candidates for internal resolution, it won't show when game is not using NVN | `false`, `true` | `true` | -| `show_read_speed` | Show game's read speed per second | `false`, `true` | `true` | - -> [mini] - -| Key | Explanation | Possible values | Default Value | -|-----|-------------|-----------------|---------------| -| `refresh_rate` | How often per second this mode should be refreshed. Higher value means higher CPU Core #3 usage, that's why it is recommended to stay at 1. | From `1` to `60` | `1` | -| `layer_width_align` | On which side of the screen X axis you want this mode | `left`, `center`, `right` | `left` | -| `layer_height_align` | On which side of the screen Y axis you want this mode | `top`, `center`, `bottom` | `top` | -| `handheld_font_size` | How big should be rendered text in handheld mode | From `8` to `22` | `15` | -| `docked_font_size` | How big should be rendered text in docked mode | From `8` to `22` | `15` | -| `real_freqs` | This works only if you have sys-clk 2.0.0_rc4+ installed. It shows real frequencies for CPU, GPU and RAM instead of target frequencies | `true`, `false` | `false` | -| `show` | Which data should be rendered. Connect different stats with `+` in any order. | `CPU`, `GPU`, `RAM`, `TEMP`, `FAN`, `DRAW`, `FPS`, `RES`, `READ` | `CPU+GPU+RAM+TEMP+FAN+DRAW+FPS+RES+READ` | -| `replace_MB_with_RAM_load` | This works only if you have sys-clk 2.0.0_rc4+ installed. Instead of RAM total usage it shows RAM load. | `true`, `false` | `true` | -| `background_color` | Background color in RGBA4444 format | From `#0000` to `#FFFF` | `#1117` | -| `cat_color` | Category text color (left side) in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | -| `text_color` | Stats text color (right side) in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | - -> [micro] - -| Key | Explanation | Possible values | Default Value | -|-----|-------------|-----------------|---------------| -| `refresh_rate` | How often per second this mode should be refreshed. Higher value means higher CPU Core #3 usage, that's why it is recommended to stay at 1. | From `1` to `60` | `1` | -| `layer_height_align` | On which side of the screen Y axis you want this mode | `top`, `bottom` | `top` | -| `handheld_font_size` | How big should be rendered text in handheld mode | From `8` to `18` | `18` | -| `docked_font_size` | How big should be rendered text in docked mode | From `8` to `18` | `18` | -| `text_align` | How shown text should be aligned | `left`, `center`, `right`| `center` | -| `real_freqs` | This works only if you have sys-clk 2.0.0_rc4+ installed. It shows real frequencies for CPU, GPU and RAM instead of target frequencies | `true`, `false` | `false` | -| `show` | Which data should be rendered. Connect different stats with `+` in any order. | `CPU`, `GPU`, `RAM`, `BRD`, `FAN`, `FPS` | `CPU+GPU+RAM+BRD+FAN+FPS` | -| `replace_GB_with_RAM_load` | This works only if you have sys-clk 2.0.0_rc4+ installed. Instead of RAM total usage it shows RAM load. | `true`, `false` | `true` | -| `background_color` | Background color in RGBA4444 format | From `#0000` to `#FFFF` | `#1117` | -| `cat_color` | Category text color (left side) in RGBA4444 format | From `#0000` to `#FFFF` | `#FCCF` | -| `text_color` | Stats text color (right side) in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | - - -> [fps-counter] - -| Key | Explanation | Possible values | Default Value | -|-----|-------------|-----------------|---------------| -| `layer_width_align` | On which side of the screen X axis you want this mode | `left`, `center`, `right` | `left` | -| `layer_height_align` | On which side of the screen Y axis you want this mode | `top`, `center`, `bottom` | `top` | -| `handheld_font_size` | How big should be rendered text in handheld mode | From `8` to `150` | `40` | -| `docked_font_size` | How big should be rendered text in docked mode | From `8` to `150` | `40` | -| `background_color` | Background color in RGBA4444 format | From `#0000` to `#FFFF` | `#1117` | -| `text_color` | Text color in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | - -> [fps-graph] - -| Key | Explanation | Possible values | Default Value | -|-----|-------------|-----------------|---------------| -| `layer_width_align` | On which side of the screen X axis you want this mode | `left`, `center`, `right` | `left` | -| `layer_height_align` | On which side of the screen Y axis you want this mode | `top`, `center`, `bottom` | `top` | -| `max_fps_text_color` | Text color of "60" in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | -| `min_fps_text_color` | Text color of "0" in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | -| `background_color` | Background color in RGBA4444 format | From `#0000` to `#FFFF` | `#1117` | -| `fps_counter_color` | Text color of average FPS printed behind graph in RGBA4444 format | From `#0000` to `#FFFF` | `#4444` | -| `border_color` | Color of rectangle in RGBA4444 format | From `#0000` to `#FFFF` | `#F77F` | -| `dashed_line_color` | Color of dashed line at the center of rectangle in RGBA4444 format | From `#0000` to `#FFFF` | `#8888` | -| `main_line_color` | Color of line representing FPS value on graph in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | -| `rounded_line_color` | Color of line representing FPS value on graph if it's divisble by 10 in RGBA4444 format | From `#0000` to `#FFFF` | `#F0FF` | -| `perfect_line_color` | Color of line representing FPS value on graph if it's divisble by 30 in RGBA4444 format | From `#0000` to `#FFFF` | `#0C0F` | - -> [game_resolutions] - -| Key | Explanation | Possible values | Default Value | -|-----|-------------|-----------------|---------------| -| `refresh_rate` | How often per second this mode should be refreshed. Higher value means higher CPU Core #3 usage, that's why it is recommended to stay at 1. | From `1` to `60` | `10` | -| `layer_width_align` | On which side of the screen X axis you want this mode | `left`, `center`, `right` | `left` | -| `layer_height_align` | On which side of the screen Y axis you want this mode | `top`, `center`, `bottom` | `top` | -| `background_color` | Background color in RGBA4444 format | From `#0000` to `#FFFF` | `#1117` | -| `cat_color` | Category text color (left side) in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | -| `text_color` | Stats text color (right side) in RGBA4444 format | From `#0000` to `#FFFF` | `#FFFF` | diff --git a/Source/Horizon-OC-Monitor (deprecated)/docs/modes.md b/Source/Horizon-OC-Monitor (deprecated)/docs/modes.md deleted file mode 100644 index 665237dd..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/docs/modes.md +++ /dev/null @@ -1,252 +0,0 @@ -# Modes - -Horizon OC Monitor Overlay from 1.0.0 release contains five modes to choose from Main Menu.
-For additional functions you need to install: -- [SaltyNX](https://github.com/masagrator/SaltyNX/releases) -- [sys-clk 2.0.0_rc4+](https://github.com/retronx-team/sys-clk/releases) (using closed source forks of sys-clk can result in retrieving wrong real clockrates and ram load) - -# Full - -This mode you can know from older releases of Horizon OC Monitor. It contains all informations properly described and supported with high precision. - -- CPU Usage - - Real Frequency: `%.1f` = Real clockrate of all CPU cores in MHz (This shows only when sys-clk 2.0.0_4c+ is installed) - - Target Frequency: `%.1f` = Target clockrate of all CPU cores in MHz - - Core #0-#3: `%.2f` = Load of CPU Cores calculated from IdleTickCount to percent value - -- GPU Usage - - Real Frequency: `%.1f` = Real clockrate of GPU in MHz (This shows only when sys-clk 2.0.0_rc4+ is installed) - - Target Frequency: `%.1f` = Target clockrate of GPU in MHz - - Load: `%.1f` = GPU Load provided by PMU in percent - -- RAM Usage - - Real Frequency: `%.1f` = Real clockrate of EMC in MHz (This shows only when sys-clk 2.0.0_rc4+ is installed) - - Target Frequency: `%.1f` = Target clockrate of EMC in MHz - - Load: `%.1f` (CPU `%.1f` | GPU `%.1f`) = RAM Load in % (Which part of that are CPU and GPU (with other hardware, but their impact on GPU readings is negligible)) - - `%s`: `%.2f`/`%.2f` = %s memory used/%s memory available in MB (not working with FW <5.0.0) - -- Board - - Battery Power Flow: `%+.2f`[h:mm] = How much power in watts is discharged from or charged to the battery [time left before shutdown] - - Temperatures: SoC: `%.1f` / PCB: `%.1f` / Skin: `%.1f` = SoC / PCB / Skin temperature in Celsius degrees (Explanation provided at the end of file) - - Fan Rotation Level: `%.1f` = Fan rotation level in percent - - -```Optional (shows only when SaltyNX is installed and game is running)``` - -| Category | Format | Explanation | -|----------|-------------------|--------------------------------------------------------------------------| -| PFPS | %u | Pushed Frames Per Second - how many frames were displayed in last second | -| FPS | %.2f | Frames Per Second - value calculated by averaging frametime | -| Resolutions | %dx%d \|\| %dx%d | Two the most promising candidates for internal game resolution `(^1)` | -| Read speed | %.2f MiB/s | Show game read speed in the last second | - -- ^1 - read more informations in explanation for "Game Resolutions" menu - -# Mini - -Contains most of supported informations with lower precision. You can use touch screen to change its position temporarily. - -| Category | Format | Explanation | -|----------|---------------------------------------------------|---------------------------------------------------------------------------| -| CPU | [%.0f,%.0f,%.0f,%.0f]@%.1f | Core #0 usage, Core #1 usage, Core #2 usage, Core #3 usage@CPU Target/Real frequency`(^1)` | -| GPU | %.1f@%.1f | Load@GPU Target/Real Frequency`(^1)` | -| RAM | %.0f/%.0f@%.1f
`or`
%.1f(%.1f \| %.1f)@%.1f | Total RAM used/Total RAM available in MB@EMC Target/Real frequency `or` RAM load (CPU \| GPU)@EMC Target frequency `(^1)` | -| TEMP | %2.1f/%2.1f/%2.1f | SoC temperature/PCB temperature/Skin temperature `(^2)` | -| FAN | %2.1f | Fan rotation level | -| DRAW | %+.2f[h:mm] | How much power in watts is discharged from or charged to the battery [Time left before shutdown] | -| RES | %dx%d \|\| %dx%d | Two the most promising candidates for internal game resolution `(^3)` | -| READ | %.2f MiB/s | Show game read speed in the last second | - -- ^1 - Real Frequency + RAM Load available only with sys-clk 2.0.0_rc4+ -- ^2 - Explanation provided at the end of file -- ^3 - read more informations in explanation for "Game Resolutions" menu - -```Optional``` - -> shows only when SaltyNX is installed and game is running -> -| Category | Format | Explanation | -|----------|-------------------|--------------------------------------------------------------------------| -| FPS | %.2f | Frames Per Second | - -# Micro - -Contains most of supported informations with lower precision in one line. - -| Category | Format | Explanation | -|----------|------------------------------------------------------------|---------------------------------------------------------------------------| -| CPU | [%.0f,%.0f,%.0f,%.0f]%s%.1f | [Core #0 usage, Core #1 usage, Core #2 usage, Core #3 usage] `(^1)` CPU Target/Real Frequency `(^3)` | -| GPU | %.1f%s%.1f | Load (^1) GPU Target/Real Frequency | -| RAM | %.1f/%.1f%s%.1f `or` %.1f%s%.1f | Total RAM used/Total RAM available in GB `(^1)` EMC Target frequency `or` RAM Load in % `(^1)` EMC Target frequency | -| BRD | %2.1f/%2.1f/%2.1f@+.1f[h:mm] | SoC temperature/PCB temperature/Skin temperature(^2)/Battery Power Flow[Time left before shutdown] | -| FAN | %2.1f | Fan rotation level | - -- ^1 - by default it's `@`, but if you have sys-clk 2.0.0_rc4+ installed, this changes depending on difference between real clocks and targeted clocks.
- - `△` - real clocks are higher by at least 20 MHz than expected - - `▽` - real clocks are lower by at least 20 MHz than expected - - `≠` - real clocks are lower by at least 50 MHz than expected (If this shows constantly for longer than few seconds, this is a sign of throttling, usually caused by bad overclocking configuration) -- ^2 - Explanation provided at the end of file -- ^3 - Real frequencies + RAM Load available only with sys-clk 2.0.0_rc4+ - -```Optional``` - -> shows only when SaltyNX is installed and game is running - -| Category | Format | Explanation | -|----------|--------------------|--------------------------------------------------------------------------| -| FPS | %.1f | Frames Per Second | - - -# FPS - -> Counter - -It shows only FPS value in 31Hz + vsync signal.
-If game is not launched, it will show always `n/d` aka `no data`.
- -Mode available only with SaltyNX installed. You can use touch screen to change its position temporarily. - -> Graph - -It shows average FPS graph in 31Hz + vsync signal. In background of graph you can see rendered actual average FPS.
-If game is not launched, graph will be empty.
-If game is not rendering any new frame, graph is not updated. - -If line is within rounding error of graph line, it's colored. Average FPS must be between -0.05 and +0.04 of graph line target FPS. So for 30 FPS it's between 29.95 - 30.04 FPS. For 43 FPS it's 42.95 - 43.04 FPS. -If it's in display refresh rate or half of it rounding error range, it's green. Any other FPS graph target is purple. - -Colors can be changed in config file. - -Mode available only with SaltyNX installed. You can use touch screen to change its position temporarily. - -# Other - -> Battery - -- Battery Actual Capacity: `%d` = Battery Designed Capacity multiplied by Battery Age in mAh -- Battery Designed Capacity: `%d` = Battery capacity targeted by manufacturer in mAh -- Battery Temperature: `%.1f` = Battery temperature in Celsius -- Battery Raw Charge: `%.1f` = Raw battery charged capacity in percent -- Battery Age: `%.1f` = How much of designed capacity was charged last time battery was charged completely in percent -- Battery Voltage: `%.0f` = Battery average voltage in mV (time period: 5s, or with `battery_avg_iir_filter` enabled: 45s) -- Battery Current Flow: `%+.0f` = Battery average current flow in mA (time period: 5s, or with `battery_avg_iir_filter` enabled: 11.25s) -- Battery Power Flow: `%+.3f` = Battery average power flow in W calculated from Battery Voltage and Battery Current Flow -- Battery Remaining Time: h:mm - How much time is left before shutdown - -Shows only if charger is connected: -| Category | Format | Explanation | -|---------------------------|--------------|----------------------------------------------------------------------------------| -| Charger Type | %u | Connected charger type, more in Battery.hpp "BatteryChargeInfoFieldsChargerType" | -| Charger Max Voltage | %u | Charger and external device voltage limit in mV | -| Charger Max Current | %u | Charger and external device current limit in mA | - -> Miscellaneous - -| Category | Format | Explanation | -|------------------------|-------------------|----------------------------------------------------------------------------------| -| DSP Usage | %u | In percent (not available on 17.0.0+) | -| NVDEC | %.2f | Target frequency in MHz (shows 0 if chip is not active) | -| NVENC | %.2f | Target frequency in MHz (shows 0 if chip is not active) | -| NVJPG | %.2f | Target frequency in MHz (shows 0 if chip is not active) | -| Network Type | %s | It shows if Switch is connected to internet, and if it's using Ethernet or Wi-Fi | - -If Network Type is "Wi-Fi", you can press Y to show password. Since max password length is 64 characters, it may show in up to 3 lines. - -> Game Resolutions - -For this mode to show and work properly you must have SaltyNX 0.9.0+ installed. You can use touch screen to change its position temporarily. - -When game runs, this menu shows what resolutions and how many times they were passed to GPU via two functions: -- __Depth__ shows info from depth texture passed to `nvnCommandBufferSetRenderTargets` -- __Viewport__ shows info from arguments passed to: - - for NVN: `nvnCommandBufferSetViewport`, `nvnCommandBufferSetViewports`, `nvnCommandBufferSetScissor` and `nvnCommandBufferSetScissors` - - for EGL: `glViewport`, `glViewportArrayv`, `glViewportIndexedf`, `glViewportIndexedfv` and all their variations - - for Vulkan: `vkCmdSetViewport` and `vkCmdSetViewportWithCount` - -This menu shows first 8 resolutions passed to those functions in last frame rendering loop, sorted in descending order of calls number.
-Its main purpose is to catch game rendering resolution, but user must deduce which ones are correct.
-I have limited catched resolutions only to ones that have ratio higher than 0.6 and lower than 1.8. Such low value comes from the fact that some games are rendering at width lower than height (f.e. 480x720). There is also a limit where it won't accept resolutions which height is lower than 160 px or higher than 1440 px.
- -Remember that resolutions you can see in this mode may be used in different ways - for example Tokyo Xanadu Ex+ max dynamic resolution in handheld will show 1280x736, but it's not that game will squeeze this into 720p screen, it's just removing those additional 16 pixels from showing on screen. - -Those commands are used by all 3D games using NVN, EGL and Vulkan APIs (that's why it may not work with games using 2D engines).
-This mode is not 100% fullproof, so it can show that nothing is catched or it won't catch what is used for 3D rendering (if this happens for some 3D game, please report an issue). - -By default refresh rate of this menu is 10 FPS. You can change that in config.ini, more in config.md
-Exiting is done by using the same combo buttons used in other main modes. - -Games that don't mesh well with RES category in `Mini` and Resolution in `Full` modes while showing properly rendering resolutions in this menu: -- `Kirby and The Forgotten Land`: dynamic resolution has much less calls than other resolutions, it shows up correctly only when it's max dynamic resolution set. It shows up always first in Depth category of Game Resolutions menu. -- `Darksiders 2`: Dynamic resolution is randomly showing up, fighting for attention with native resolution call. In Game Resolutions menu it shows up either at 2nd or 3rd place of Viewport. - -# Additional info - -> How Battery Remaining Time is calculated - -It is calculated from the last 3 minutes of power draw readings. In the first minute of running any mode, it is updated every 0.5s, after one minute it's updated every minute. When exiting the currently used mode, calculations are reset. When connecting or disconnecting the charger, calculations are reset. When Battery Power Draw is positive instead of negative, time is shown as [-:--] and calculations are reset. - -> What is Skin temperature ($\mathbf{T}skin$)? - -This is temperature calculated from SoC and PCB temperatures that is mainly used to prevent Switch from overheating. Reading it is not supported on FWs <5.0.0. - -Explanation provided by CTCaer ->Temperature ($\mathbf{T}skin$) calculation. -> -> ->Console and Handheld: -> ->$\mathbf{T}soc >= 84°C$ - Immediate sleep. No questions asked. -> ->$\mathbf{T}pcb >= 84°C$ - Immediate sleep. No questions asked. -> -> ->Console only: -> ->$\mathbf{T}skin < 63°C$ - Clears both timers. -> ->$\mathbf{T}skin >= 63°C$ - Immediate sleep. No questions asked. -> -> ->Handheld only: -> ->$\mathbf{T}skin < 58°C$ - Clears both timers. -> ->$58°C <= \mathbf{T}skin < 61°C$ - Starts 60s timer and clears 10s timer. -> ->$61°C <= \mathbf{T}skin < 63°C$ - Starts 10s timer. -> ->$\mathbf{T}skin >= 63°C$ - Immediate sleep. No questions asked. -> -> ->The two timers are separate. If 61°C is reached, the 10s timer is immediatly started. -> ->If a timer ends and the temperature is not dropped, goes into sleep. -> -> ->tskin is the specific calculation below: -``` -soc_adj = (temps.iir_filter_gain_soc * (temps.soc - temps.soc_adj_prev)) + temps.soc_adj_prev; -pcb_adj = (temps.iir_filter_gain_pcb * (temps.pcb - temps.pcb_adj_prev)) + temps.pcb_adj_prev; -temps.soc_adj_prev = soc_adj; -temps.pcb_adj_prev = pcb_adj; - -if (soc_adj >= 38000) -{ - if (temps.handheld) - soc_adj = (temps.tskin_soc_coeff_handheld[0] * soc_adj) + (1000 * temps.tskin_soc_coeff_handheld[1]); - else - soc_adj = (temps.tskin_soc_coeff_console[0] * soc_adj) + (1000 * temps.tskin_soc_coeff_console[1]); - soc_adj = (soc_adj / 10000) + 500; -} - -if (pcb_adj >= 38000) -{ - if (temps.handheld) - pcb_adj = (temps.tskin_pcb_coeff_handheld[0] * pcb_adj) + (1000 * temps.tskin_pcb_coeff_handheld[1]); - else - pcb_adj = (temps.tskin_pcb_coeff_console[0] * soc_adj) + (1000 * temps.tskin_pcb_coeff_console[1]); - pcb_adj = (pcb_adj / 10000) + 500; -} - -skin_adj = MAX(soc_adj, pcb_adj); //tskin -``` diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/Battery.hpp b/Source/Horizon-OC-Monitor (deprecated)/include/Battery.hpp deleted file mode 100644 index 8c39547c..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/Battery.hpp +++ /dev/null @@ -1,81 +0,0 @@ -///* Notes VoltageAvg -// -// Vavg time = 175.8ms x 2^(6+VOLT), default: VOLT = 2 (Vavg time = 45s) -// -///End of Notes - -typedef enum { - NoHub = BIT(0), //If hub is disconnected - Rail = BIT(8), //At least one Joy-con is charging from rail - SPDSRC = BIT(12), //OTG - ACC = BIT(16) //Accessory -} BatteryChargeInfoFieldsFlags; - -typedef enum { - NewPDO = 1, //Received new Power Data Object - NoPD = 2, //No Power Delivery source is detected - AcceptedRDO = 3 //Received and accepted Request Data Object -} BatteryChargeInfoFieldsPDControllerState; //BM92T series - -typedef enum { - None = 0, - PD = 1, - TypeC_1500mA = 2, - TypeC_3000mA = 3, - DCP = 4, - CDP = 5, - SDP = 6, - Apple_500mA = 7, - Apple_1000mA = 8, - Apple_2000mA = 9 -} BatteryChargeInfoFieldsChargerType; - -typedef enum { - Sink = 1, - Source = 2 -} BatteryChargeInfoFieldsPowerRole; - -typedef struct { - int32_t InputCurrentLimit; //Input (Sink) current limit in mA - int32_t VBUSCurrentLimit; //Output (Source/VBUS/OTG) current limit in mA - int32_t ChargeCurrentLimit; //Battery charging current limit in mA (512mA when Docked, 768mA when BatteryTemperature < 17.0 C) - int32_t ChargeVoltageLimit; //Battery charging voltage limit in mV (3952mV when BatteryTemperature >= 51.0 C) - int32_t unk_x10; //Possibly an emum, getting the same value as PowerRole in all tested cases - int32_t unk_x14; //Possibly flags - BatteryChargeInfoFieldsPDControllerState PDControllerState; //Power Delivery Controller State - int32_t BatteryTemperature; //Battery temperature in milli C - int32_t RawBatteryCharge; //Raw battery charged capacity per cent-mille (i.e. 100% = 100000 pcm) - int32_t VoltageAvg; //Voltage avg in mV (more in Notes) - int32_t BatteryAge; //Battery age (capacity full / capacity design) per cent-mille (i.e. 100% = 100000 pcm) - BatteryChargeInfoFieldsPowerRole PowerRole; - BatteryChargeInfoFieldsChargerType ChargerType; - int32_t ChargerVoltageLimit; //Charger and external device voltage limit in mV - int32_t ChargerCurrentLimit; //Charger and external device current limit in mA - BatteryChargeInfoFieldsFlags Flags; //Unknown flags - char reserved[0x14]; //17.0.0+ data -} BatteryChargeInfoFields; - -typedef struct { - int32_t InputCurrentLimit; //Input (Sink) current limit in mA - int32_t VBUSCurrentLimit; //Output (Source/VBUS/OTG) current limit in mA - int32_t ChargeCurrentLimit; //Battery charging current limit in mA (512mA when Docked, 768mA when BatteryTemperature < 17.0 C) - int32_t ChargeVoltageLimit; //Battery charging voltage limit in mV (3952mV when BatteryTemperature >= 51.0 C) - int32_t unk_x10; //Possibly an emum, getting the same value as PowerRole in all tested cases - int32_t unk_x14; //Possibly flags - BatteryChargeInfoFieldsPDControllerState PDControllerState; //Power Delivery Controller State - int32_t BatteryTemperature; //Battery temperature in milli C - int32_t RawBatteryCharge; //Raw battery charged capacity per cent-mille (i.e. 100% = 100000 pcm) - int32_t VoltageAvg; //Voltage avg in mV (more in Notes) - int32_t BatteryAge; //Battery age (capacity full / capacity design) per cent-mille (i.e. 100% = 100000 pcm) - char reserved[4]; //17.0.0+ data - BatteryChargeInfoFieldsPowerRole PowerRole; - BatteryChargeInfoFieldsChargerType ChargerType; - int32_t ChargerVoltageLimit; //Charger and external device voltage limit in mV - int32_t ChargerCurrentLimit; //Charger and external device current limit in mA - BatteryChargeInfoFieldsFlags Flags; //Unknown flags - char reserved2[0x10]; //17.0.0+ data -} BatteryChargeInfoFields17; - -Result psmGetBatteryChargeInfoFields(Service* psmService, BatteryChargeInfoFields *out) { - return serviceDispatchOut(psmService, 17, *out); -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/Misc.hpp b/Source/Horizon-OC-Monitor (deprecated)/include/Misc.hpp deleted file mode 100644 index d5f21a08..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/Misc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -typedef struct { - u8 ssid_len; ///< NifmSfWirelessSettingData::ssid_len - char ssid[0x21]; ///< NifmSfWirelessSettingData::ssid - u8 unk_x22; ///< NifmSfWirelessSettingData::unk_x21 - u8 pad; ///< Padding - u32 unk_x24; ///< NifmSfWirelessSettingData::unk_x22 - u32 unk_x28; ///< NifmSfWirelessSettingData::unk_x23 - u8 passphrase_len; ///< Passphrase length - u8 passphrase[0x41]; ///< NifmSfWirelessSettingData::passphrase - u8 pad2[0x2]; ///< Padding -} NifmWirelessSettingData_new; - -/// NetworkProfileData. Converted from/to \ref NifmSfNetworkProfileData. -typedef struct { - Uuid uuid; ///< NifmSfNetworkProfileData::uuid - char network_name[0x40]; ///< NifmSfNetworkProfileData::network_name - u32 unk_x50; ///< NifmSfNetworkProfileData::unk_x112 - u32 unk_x54; ///< NifmSfNetworkProfileData::unk_x113 - u8 unk_x58; ///< NifmSfNetworkProfileData::unk_x114 - u8 unk_x59; ///< NifmSfNetworkProfileData::unk_x115 - u8 pad[2]; ///< Padding - NifmWirelessSettingData_new wireless_setting_data; ///< \ref NifmWirelessSettingData - NifmIpSettingData ip_setting_data; ///< \ref NifmIpSettingData -} NifmNetworkProfileData_new; - -Result getNvChannelClockRate(NvChannel *channel, u32 module_id, u32 *clock_rate) { - struct nvhost_clk_rate_args { - uint32_t rate; - uint32_t moduleid; - } args = { - .rate = 0, - .moduleid = module_id, - }; - - const u32 id = hosversionBefore(8,0,0) ? _NV_IOWR(0, 0x14, args) : _NV_IOWR(0, 0x23, args); - Result rc = nvIoctl(channel->fd, id, &args); - if (R_SUCCEEDED(rc) && clock_rate) - *clock_rate = args.rate; - - return rc; -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/SaltyNX.h b/Source/Horizon-OC-Monitor (deprecated)/include/SaltyNX.h deleted file mode 100644 index e0dbb80b..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/SaltyNX.h +++ /dev/null @@ -1,231 +0,0 @@ -#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; -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/audsnoop.h b/Source/Horizon-OC-Monitor (deprecated)/include/audsnoop.h deleted file mode 100644 index ac0dacdf..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/audsnoop.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -Result audsnoopInitialize(void); -void audsnoopExit(void); - -Result audsnoopEnableDspUsageMeasurement(void); -Result audsnoopDisableDspUsageMeasurement(void); - -Result audsnoopGetDspUsage(u32 *usage); - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/i2c.h b/Source/Horizon-OC-Monitor (deprecated)/include/i2c.h deleted file mode 100644 index 6c2d68eb..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/i2c.h +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -Result I2cReadRegHandler16(u8 reg, I2cDevice dev, u16 *out) -{ - struct readReg { - u8 send; - u8 sendLength; - u8 sendData; - u8 receive; - u8 receiveLength; - }; - - I2cSession _session; - - Result res = i2cOpenSession(&_session, dev); - if (res) - return res; - - u16 val; - - struct readReg readRegister = { - .send = 0 | (I2cTransactionOption_Start << 6), - .sendLength = sizeof(reg), - .sendData = reg, - .receive = 1 | (I2cTransactionOption_All << 6), - .receiveLength = sizeof(val), - }; - - res = i2csessionExecuteCommandList(&_session, &val, sizeof(val), &readRegister, sizeof(readRegister)); - if (res) - { - i2csessionClose(&_session); - return res; - } - - *out = val; - i2csessionClose(&_session); - return 0; -} - -Result I2cReadRegHandler8(u8 reg, I2cDevice dev, u8 *out) -{ - struct readReg { - u8 send; - u8 sendLength; - u8 sendData; - u8 receive; - u8 receiveLength; - }; - - I2cSession _session; - - Result res = i2cOpenSession(&_session, dev); - if (res) - return res; - - u8 val; - - struct readReg readRegister = { - .send = 0 | (I2cTransactionOption_Start << 6), - .sendLength = sizeof(reg), - .sendData = reg, - .receive = 1 | (I2cTransactionOption_All << 6), - .receiveLength = sizeof(val), - }; - - res = i2csessionExecuteCommandList(&_session, &val, sizeof(val), &readRegister, sizeof(readRegister)); - if (res) - { - i2csessionClose(&_session); - return res; - } - - *out = val; - i2csessionClose(&_session); - return 0; -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/ipc.h b/Source/Horizon-OC-Monitor (deprecated)/include/ipc.h deleted file mode 100644 index ef370f7e..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/ipc.h +++ /dev/null @@ -1,755 +0,0 @@ -/** - * @file ipc.h - * @brief Inter-process communication handling - * @author plutoo - * @copyright libnx Authors - */ -#pragma once - -/// 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) { - const 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) { - const 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) { - const 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) { - const 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) { - const 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; iNumStaticIn; i++, buf+=2) { - IpcStaticSendDescriptor* desc = (IpcStaticSendDescriptor*) buf; - - const 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]; - - const uintptr_t ptr = (uintptr_t) cmd->Buffers[i]; - desc->Addr = ptr; - desc->Packed = cmd->BufferTypes[i] | - (((ptr >> 32) & 15) << 28) | ((ptr >> 36) << 2); - } - - const 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; iNumStaticOut; i++) { - const size_t off = cmd->NumStaticIn + i; - const size_t sz = (uintptr_t) cmd->StaticSizes[off]; - - buf_u16[i] = (sz > 0xFFFF) ? 0 : sz; - } - - const 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; iNumStaticOut; i++, buf+=2) { - IpcStaticRecvDescriptor* desc = (IpcStaticRecvDescriptor*) buf; - const size_t off = cmd->NumStaticIn + i; - - const 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; - } - - const size_t num_handles_copy = ((ctrl2 >> 1) & 15); - const 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; iHandles[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; iPacked; - - 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; - - const size_t num_bufs_send = (ctrl0 >> 20) & 15; - const size_t num_bufs_recv = (ctrl0 >> 24) & 15; - const 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; iPacked; - - 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 -} - -///@} diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/max17050.h b/Source/Horizon-OC-Monitor (deprecated)/include/max17050.h deleted file mode 100644 index e69ab9b1..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/max17050.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Fuel gauge driver for Nintendo Switch's Maxim 17050 - * - * Copyright (c) 2011 Samsung Electronics - * MyungJoo Ham - * Copyright (c) 2018-2020 CTCaer - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Modified by: MasaGratoR - */ - -#ifndef __MAX17050_H_ -#define __MAX17050_H_ - -//#include -#include "i2c.h" - -/* Board default values */ -#define MAX17050_BOARD_CGAIN 2 /* Actual: 1.99993 */ -#define MAX17050_BOARD_SNS_RESISTOR_UOHM 5000 /* 0.005 Ohm */ - -//#define MAX17050_STATUS_BattAbsent BIT(3) - -/* Consider RepCap which is less then 10 units below FullCAP full */ -/* -#define MAX17050_FULL_THRESHOLD 10 - -#define MAX17050_CHARACTERIZATION_DATA_SIZE 48 - -#define MAXIM17050_I2C_ADDR 0x36 -*/ - -#define MAX17050_WAIT_NS 1000000000 - -constexpr float max17050SenseResistor = MAX17050_BOARD_SNS_RESISTOR_UOHM / 1000; // in uOhm -constexpr float max17050CGain = 1.99993; - - -enum MAX17050_reg { - MAX17050_STATUS = 0x00, - MAX17050_VALRT_Th = 0x01, - MAX17050_TALRT_Th = 0x02, - MAX17050_SALRT_Th = 0x03, - MAX17050_AtRate = 0x04, - MAX17050_RepCap = 0x05, - MAX17050_RepSOC = 0x06, - MAX17050_Age = 0x07, - MAX17050_TEMP = 0x08, - MAX17050_VCELL = 0x09, - MAX17050_Current = 0x0A, - MAX17050_AvgCurrent = 0x0B, - - MAX17050_SOC = 0x0D, - MAX17050_AvSOC = 0x0E, - MAX17050_RemCap = 0x0F, - MAX17050_FullCAP = 0x10, - MAX17050_TTE = 0x11, - MAX17050_QRTbl00 = 0x12, - MAX17050_FullSOCThr = 0x13, - MAX17050_RSLOW = 0x14, - - MAX17050_AvgTA = 0x16, - MAX17050_Cycles = 0x17, - MAX17050_DesignCap = 0x18, - MAX17050_AvgVCELL = 0x19, - MAX17050_MinMaxTemp = 0x1A, - MAX17050_MinMaxVolt = 0x1B, - MAX17050_MinMaxCurr = 0x1C, - MAX17050_CONFIG = 0x1D, - MAX17050_ICHGTerm = 0x1E, - MAX17050_AvCap = 0x1F, - MAX17050_ManName = 0x20, - MAX17050_DevName = 0x21, - MAX17050_QRTbl10 = 0x22, - MAX17050_FullCAPNom = 0x23, - MAX17050_TempNom = 0x24, - MAX17050_TempLim = 0x25, - MAX17050_TempHot = 0x26, - MAX17050_AIN = 0x27, - MAX17050_LearnCFG = 0x28, - MAX17050_FilterCFG = 0x29, - MAX17050_RelaxCFG = 0x2A, - MAX17050_MiscCFG = 0x2B, - MAX17050_TGAIN = 0x2C, - MAX17050_TOFF = 0x2D, - MAX17050_CGAIN = 0x2E, - MAX17050_COFF = 0x2F, - - MAX17050_QRTbl20 = 0x32, - MAX17050_SOC_empty = 0x33, - MAX17050_T_empty = 0x34, - MAX17050_FullCAP0 = 0x35, - MAX17050_LAvg_empty = 0x36, - MAX17050_FCTC = 0x37, - MAX17050_RCOMP0 = 0x38, - MAX17050_TempCo = 0x39, - MAX17050_V_empty = 0x3A, - MAX17050_K_empty0 = 0x3B, - MAX17050_TaskPeriod = 0x3C, - MAX17050_FSTAT = 0x3D, - MAX17050_TIMER = 0x3E, - MAX17050_SHDNTIMER = 0x3F, - - MAX17050_QRTbl30 = 0x42, - - MAX17050_dQacc = 0x45, - MAX17050_dPacc = 0x46, - - MAX17050_VFSOC0 = 0x48, - - Max17050_QH0 = 0x4C, - MAX17050_QH = 0x4D, - MAX17050_QL = 0x4E, - - MAX17050_MinVolt = 0x50, // Custom ID. Not to be sent to i2c. - MAX17050_MaxVolt = 0x51, // Custom ID. Not to be sent to i2c. - - MAX17050_VFSOC0Enable = 0x60, - MAX17050_MODELEnable1 = 0x62, - MAX17050_MODELEnable2 = 0x63, - - MAX17050_MODELChrTbl = 0x80, - - MAX17050_OCV = 0xEE, - - MAX17050_OCVInternal = 0xFB, - - MAX17050_VFSOC = 0xFF, -}; - -/* -int max17050_get_property(enum MAX17050_reg reg, int *value); -int max17050_fix_configuration(); -u32 max17050_get_cached_batt_volt(); -*/ -#endif /* __MAX17050_H_ */ - -Result Max17050ReadReg(u8 reg, u16 *out) -{ - u16 data = 0; - Result res = I2cReadRegHandler16(reg, I2cDevice_Max17050, &data); - - if (R_FAILED(res)) - { - return res; - } - - *out = data; - return res; -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/pcv_types.h b/Source/Horizon-OC-Monitor (deprecated)/include/pcv_types.h deleted file mode 100644 index 50d3e3ea..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/pcv_types.h +++ /dev/null @@ -1,41 +0,0 @@ -typedef enum { - PcvPowerDomain_Max77620_Sd0 = 0, - PcvPowerDomain_Max77620_Sd1 = 1, - PcvPowerDomain_Max77620_Sd2 = 2, - PcvPowerDomain_Max77620_Sd3 = 3, - PcvPowerDomain_Max77620_Ldo0 = 4, - PcvPowerDomain_Max77620_Ldo1 = 5, - PcvPowerDomain_Max77620_Ldo2 = 6, - PcvPowerDomain_Max77620_Ldo3 = 7, - PcvPowerDomain_Max77620_Ldo4 = 8, - PcvPowerDomain_Max77620_Ldo5 = 9, - PcvPowerDomain_Max77620_Ldo6 = 10, - PcvPowerDomain_Max77620_Ldo7 = 11, - PcvPowerDomain_Max77620_Ldo8 = 12, - PcvPowerDomain_Max77621_Cpu = 13, - PcvPowerDomain_Max77621_Gpu = 14, - PcvPowerDomain_Max77812_Cpu = 15, - PcvPowerDomain_Max77812_Gpu = 16, - PcvPowerDomain_Max77812_Dram = 17, -} PowerDomain; - -typedef enum { - PcvPowerDomainId_Max77620_Sd0 = 0x3A000080, - PcvPowerDomainId_Max77620_Sd1 = 0x3A000081, - PcvPowerDomainId_Max77620_Sd2 = 0x3A000082, - PcvPowerDomainId_Max77620_Sd3 = 0x3A000083, - PcvPowerDomainId_Max77620_Ldo0 = 0x3A0000A0, - PcvPowerDomainId_Max77620_Ldo1 = 0x3A0000A1, - PcvPowerDomainId_Max77620_Ldo2 = 0x3A0000A2, - PcvPowerDomainId_Max77620_Ldo3 = 0x3A0000A3, - PcvPowerDomainId_Max77620_Ldo4 = 0x3A0000A4, - PcvPowerDomainId_Max77620_Ldo5 = 0x3A0000A5, - PcvPowerDomainId_Max77620_Ldo6 = 0x3A0000A6, - PcvPowerDomainId_Max77620_Ldo7 = 0x3A0000A7, - PcvPowerDomainId_Max77620_Ldo8 = 0x3A0000A8, - PcvPowerDomainId_Max77621_Cpu = 0x3A000003, - PcvPowerDomainId_Max77621_Gpu = 0x3A000004, - PcvPowerDomainId_Max77812_Cpu = 0x3A000003, - PcvPowerDomainId_Max77812_Gpu = 0x3A000004, - PcvPowerDomainId_Max77812_Dram = 0x3A000005, -} PowerDomainId; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/pwm.h b/Source/Horizon-OC-Monitor (deprecated)/include/pwm.h deleted file mode 100644 index 559ff873..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/pwm.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - Service s; -} PwmChannelSession; - -Result pwmInitialize(void); -void pwmExit(void); -Service* pwmGetServiceSession(void); -Result pwmOpenSession2(PwmChannelSession *out, u32 device_code); -Result pwmChannelSessionGetDutyCycle(PwmChannelSession *c, double* out); -void pwmChannelSessionClose(PwmChannelSession *c); - -#ifdef __cplusplus -} // extern "C" -#endif diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/rgltr.h b/Source/Horizon-OC-Monitor (deprecated)/include/rgltr.h deleted file mode 100644 index dd57f4c5..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/rgltr.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include -#include "pcv_types.h" - -typedef struct { - Service s; -} RgltrSession; - -Result rgltrInitialize(void); - -void rgltrExit(void); - -Service* rgltrGetServiceSession(void); - -Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id); -void rgltrCloseSession(RgltrSession* session); -Result rgltrGetVoltage(RgltrSession* session, u32 *out_volt); -Result rgltrGetPowerModuleNumLimit(u32 *out); -Result rgltrGetVoltageEnabled(RgltrSession* session, u32 *out); diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/rgltr_services.h b/Source/Horizon-OC-Monitor (deprecated)/include/rgltr_services.h deleted file mode 100644 index 32becbf8..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/rgltr_services.h +++ /dev/null @@ -1,29 +0,0 @@ -// rgltr_services.h -// ======== -// Minimal header declarations for rgltr‐related functionality. -// Any file that wants to call rgltrOpenSession(), rgltrGetVoltage(), etc. should -// simply do `#include "infonx.h"` (NOT infonx.cpp). - -#pragma once - -#include // for Service, Result, hosversionBefore(), smGetService(), serviceClose(), etc. -#include "rgltr.h" // for RgltrSession, PowerDomainId, etc. - -// Global service handle for "rgltr". Defined in infonx.cpp. -extern Service g_rgltrSrv; - -// Open/close the "rgltr" service. You must call rgltrInitialize() (once) before using -// rgltrOpenSession() & friends. Call rgltrExit() when your app is shutting down. -Result rgltrInitialize(void); -void rgltrExit(void); - -// Open a regulator session for the given PowerDomainId (e.g. CPU, GPU, DRAM). -// On success, (*session_out).s will contain a valid Service handle. -Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id); - -// Query the current voltage (in microvolts, µV) from a previously opened session. -// Writes the result into *out_volt. -Result rgltrGetVoltage(RgltrSession* session, u32* out_volt); - -// Close a previously opened regulator session. -void rgltrCloseSession(RgltrSession* session); diff --git a/Source/Horizon-OC-Monitor (deprecated)/include/tmp451.h b/Source/Horizon-OC-Monitor (deprecated)/include/tmp451.h deleted file mode 100644 index 507585da..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/include/tmp451.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * SOC/PCB Temperature driver for Nintendo Switch's TI TMP451 - * - * Copyright (c) 2018 CTCaer - * - * 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 . - */ - -/* - * Modified by: MasaGratoR - */ - -#ifndef __TMP451_H_ -#define __TMP451_H_ - -//#include -#include "i2c.h" - -//#define TMP451_I2C_ADDR 0x4C - -#define TMP451_PCB_TEMP_REG 0x00 -#define TMP451_SOC_TEMP_REG 0x01 - -/* -#define TMP451_CONFIG_REG 0x09 -#define TMP451_CNV_RATE_REG 0x0A -*/ - -#define TMP451_SOC_TEMP_DEC_REG 0x10 -#define TMP451_PCB_TEMP_DEC_REG 0x15 - -/* -#define TMP451_SOC_TMP_OFH_REG 0x11 -#define TMP451_SOC_TMP_OFL_REG 0x12 -*/ - -// If input is false, the return value is packed. MSByte is the integer in oC -// and the LSByte is the decimal point truncated to 2 decimal places. -// Otherwise it's an integer oC. -/* -u16 tmp451_get_soc_temp(bool integer); -u16 tmp451_get_pcb_temp(bool integer); -void tmp451_init(); -void tmp451_end(); -*/ - -Result Tmp451ReadReg(u8 reg, u8 *out) -{ - u8 data = 0; - Result res = I2cReadRegHandler8(reg, I2cDevice_Tmp451, &data); - - if (R_FAILED(res)) - { - return res; - } - - *out = data; - return res; -} - -Result Tmp451GetSocTemp(float* temperature) { - u8 integer = 0; - u8 decimals = 0; - - Result rc = Tmp451ReadReg(TMP451_SOC_TEMP_REG, &integer); - if (R_FAILED(rc)) - return rc; - rc = Tmp451ReadReg(TMP451_SOC_TEMP_DEC_REG, &decimals); - if (R_FAILED(rc)) - return rc; - - decimals = ((u16)(decimals >> 4) * 625) / 100; - *temperature = (float)(integer) + ((float)(decimals) / 100); - return rc; -} - -Result Tmp451GetPcbTemp(float* temperature) { - u8 integer = 0; - u8 decimals = 0; - - Result rc = Tmp451ReadReg(TMP451_PCB_TEMP_REG, &integer); - if (R_FAILED(rc)) - return rc; - rc = Tmp451ReadReg(TMP451_PCB_TEMP_DEC_REG, &decimals); - if (R_FAILED(rc)) - return rc; - - decimals = ((u16)(decimals >> 4) * 625) / 100; - *temperature = (float)(integer) + ((float)(decimals) / 100); - return rc; -} - -#endif /* __TMP451_H_ */ diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/de.json b/Source/Horizon-OC-Monitor (deprecated)/lang/de.json deleted file mode 100644 index f7c9a332..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/de.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Modi", - "Modes   Configure": "Modi   Konfigurieren", - "Full": "Voll", - "Mini": "Mini", - "Micro": "Mikro", - "FPS Graph": "FPS-Diagramm", - "FPS Counter": "FPS-Zähler", - "Game Resolutions": "Spielauflösungen", - "Other": "Sonstiges", - "Battery/Charger": "Akku/Ladegerät", - "Miscellaneous": "Verschiedenes", - "CPU Usage": "CPU-Auslastung", - "GPU Usage": "GPU-Auslastung", - "RAM Usage": "RAM-Auslastung", - "Target Frequency": "Ziel-Frequenz", - "Real Frequency": "Aktuelle Frequenz", - "Core 0 ": "Kern 0 ", - "Core 1 ": "Kern 1 ", - "Core 2 ": "Kern 2 ", - "Core 3 ": "Kern 3 ", - "Load": "Auslastung", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Gesamt\nAnwendung\nApplet\nSystem\nSystem (unsicher)", - "Board": "Board", - "Battery Power Flow": "Akkuleistungsfluss", - "\nTemperatures": "\nTemperaturen", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Lüfterdrehzahl", - "Game": "Spiel", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Auflösungen ", - "Read Speed ": "Lesegeschwindigkeit ", - "Press ": "Drücke ", - " to Exit": " zum Beenden", - "Depth": "Tiefe", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "Spiel läuft nicht\noder ist inkompatibel.", - "Battery Stats": "Akkustatistiken", - "Actual Capacity": "Aktuelle Kapazität", - "Designed Capacity": "Nennkapazität", - "Temperature": "Temperatur", - "Raw Charge": "Rohladung", - "Age": "Alter", - "Voltage": "Spannung", - "Current Flow": "Stromfluss", - "Power Flow": "Leistungsfluss", - "Remaining Time": "Verbleibende Zeit", - "Charger Stats": "Ladegerät-Statistiken", - "Input Current Limit": "Eingangsstrombegrenzung", - "VBUS Current Limit": "VBUS-Strombegrenzung", - "Voltage Limit": "Spannungsbegrenzung", - "Current Limit": "Strombegrenzung", - "Type": "Typ", - "Max Voltage": "Max. Spannung", - "Max Current": "Max. Strom", - "Multimedia Clock Rates": "Multimedia-Taktraten", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Netzwerk", - "Type: Wi-Fi": "Typ: Wi-Fi", - "Press Y to show password": "Drücke Y, um Passwort anzuzeigen", - "Type: Ethernet": "Typ: Ethernet", - "Type: Not connected": "Typ: Nicht verbunden", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Elemente   Nach unten   Nach oben", - "Transparent": "Transparent", - "Opaque": "Undurchsichtig", - "Alpha": "Alpha", - "Pretty": "Hübsch", - "Compact": "Kompakt", - "FileSafe": "Dateisicher", - "Day+Time": "Tag+Uhrzeit", - "Date+Time(s)": "Datum+Uhrzeit(s)", - "Date+Time AM/PM": "Datum+Uhrzeit AM/PM", - "Date+Time(s) AM/PM": "Datum+Uhrzeit(s) AM/PM", - "Date+Time EU": "Datum+Uhrzeit EU", - "Date+Time EU AM/PM": "Datum+Uhrzeit EU AM/PM", - "Date+Time(s) EU AM/PM": "Datum+Uhrzeit(s) EU AM/PM", - "Date+Time ISO": "Datum+Uhrzeit ISO", - "Time 24h": "Uhrzeit 24h", - "Time AM/PM": "Uhrzeit AM/PM", - "Time(s) 24h": "Uhrzeit(s) 24h", - "Time(s) AM/PM": "Uhrzeit(s) AM/PM", - "Date US": "Datum US", - "Date EU": "Datum EU", - "Date ISO": "Datum ISO", - "Date Short": "Datum kurz", - "DTC Format": "DTC-Format", - "Toggles": "Schalter", - "Info": "Info anzeigen", - "Disable Screenshots": "Bildschirmfotos deaktivieren", - "Real Freqs": "Aktuelle Frequenzen", - "Deltas": "Deltas", - "Target Freqs": "Ziel-Frequenzen", - "FPS": "FPS", - "RES": "AUFL", - "Read Speed": "Lesegeschwindigkeit", - "Real Frequencies": "Aktuelle Frequenzen", - "Real Voltages": "Aktuelle Spannungen", - "Full CPU": "Volle CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Volle Auflösung", - "SOC Voltage": "SOC-Spannung", - "RAM Load CPU/GPU": "RAM-Last CPU/GPU", - "Use DTC Symbol": "DTC-Symbol verwenden", - "Use Dynamic Colors": "Dynamische Farben verwenden", - "Sleep Exit": "Beenden aus Ruhezustand", - "Configuration": "Konfiguration", - "Refresh Rate": "Bildwiederholrate", - "Frame Padding": "Rahmenabstand", - " Font Size": " Schriftgröße", - "Font Sizes": "Schriftgrößen", - "Handheld Font Size": "Handheld-Schriftgröße", - "Docked Font Size": "Docked-Schriftgröße", - "Black": "Schwarz", - "Dark Gray": "Dunkelgrau", - "Gray": "Grau", - "Light Gray": "Hellgrau", - "Silver": "Silber", - "White": "Weiß", - "Dark Red": "Dunkelrot", - "Red": "Rot", - "Light Red": "Hellrot", - "Pink": "Pink", - "Dark Green": "Dunkelgrün", - "Green": "Grün", - "Lime Green": "Limette", - "Light Green": "Hellgrün", - "Dark Blue": "Dunkelblau", - "Blue": "Blau", - "Light Blue": "Hellblau", - "Sky Blue": "Himmelblau", - "Dark Purple": "Dunkellila", - "Purple": "Lila", - "Light Purple": "Helllila", - "Violet": "Violett", - "Orange": "Orange", - "Yellow": "Gelb", - "Light Yellow": "Hellgelb", - "Teal": "Petrol", - "Cyan": "Cyan", - "Light Cyan": "Hellcyan", - "Magenta": "Magenta", - "Hot Pink": "Knallpink", - "Brown": "Braun", - "Light Brown": "Hellbraun", - "Colors": "Farben", - "Background Color": "Hintergrundfarbe", - "Background Alpha": "Hintergrund-Alpha", - "Focus Color": "Fokusfarbe", - "Focus Alpha": "Fokus-Alpha", - "Text Color": "Textfarbe", - "Border": "Rahmen", - "Dashed Line": "Gestrichelte Linie", - "Max FPS Text": "Max-FPS-Text", - "Min FPS Text": "Min-FPS-Text", - "Main Line": "Hauptlinie", - "Rounded Line": "Abgerundete Linie", - "Perfect Line": "Perfekte Linie", - " Color": " Farbe", - " Alpha": " Alpha", - "Category Color": "Kategoriefarbe", - "Category Color 1": "Kategoriefarbe 1", - "Category Color 2": "Kategoriefarbe 2", - "Separator Color": "Trennlinienfarbe", - "Elements": "Elemente", - "Text Alignment": "Textausrichtung", - "Vertical Position": "Vertikale Position", - "Horizontal Position": "Horizontale Position", - "Left": "Links", - "Right": "Rechts", - "Top": "Oben", - "Center": "Mitte", - "Bottom": "Unten", - "FPS Counter Color": "FPS-Zähler-Farbe", - "FPS Counter Alpha": "FPS-Zähler-Alpha", - "Border Color": "Rahmenfarbe", - "Dashed Line Color": "Gestrichelte-Linie-Farbe", - "Dashed Line Alpha": "Gestrichelte-Linie-Alpha", - "Max FPS Text Color": "Max-FPS-Textfarbe", - "Min FPS Text Color": "Min-FPS-Textfarbe", - "Main Line Color": "Hauptlinienfarbe", - "Rounded Line Color": "Abgerundete-Linienfarbe", - "Perfect Line Color": "Perfekte-Linienfarbe" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/en.json b/Source/Horizon-OC-Monitor (deprecated)/lang/en.json deleted file mode 100644 index 836b8f0d..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/en.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Modes", - "Modes   Configure": "Modes   Configure", - "Full": "Full", - "Mini": "Mini", - "Micro": "Micro", - "FPS Graph": "FPS Graph", - "FPS Counter": "FPS Counter", - "Game Resolutions": "Game Resolutions", - "Other": "Other", - "Battery/Charger": "Battery/Charger", - "Miscellaneous": "Miscellaneous", - "CPU Usage": "CPU Usage", - "GPU Usage": "GPU Usage", - "RAM Usage": "RAM Usage", - "Target Frequency": "Target Frequency", - "Real Frequency": "Real Frequency", - "Core 0 ": "Core 0 ", - "Core 1 ": "Core 1 ", - "Core 2 ": "Core 2 ", - "Core 3 ": "Core 3 ", - "Load": "Load", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Total\nApplication\nApplet\nSystem\nSystem Unsafe", - "Board": "Board", - "Battery Power Flow": "Battery Power Flow", - "\nTemperatures": "\nTemperatures", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Fan Rotation Level", - "Game": "Game", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Resolutions ", - "Read Speed ": "Read speed ", - "Press ": "Press ", - " to Exit": " to Exit", - "Depth": "Depth", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "Game is not running\nor it's incompatible.", - "Battery Stats": "Battery Stats", - "Actual Capacity": "Actual Capacity", - "Designed Capacity": "Designed Capacity", - "Temperature": "Temperature", - "Raw Charge": "Raw Charge", - "Age": "Age", - "Voltage": "Voltage", - "Current Flow": "Current Flow", - "Power Flow": "Power Flow", - "Remaining Time": "Remaining Time", - "Charger Stats": "Charger Stats", - "Input Current Limit": "Input Current Limit", - "VBUS Current Limit": "VBUS Current Limit", - "Voltage Limit": "Voltage Limit", - "Current Limit": "Current Limit", - "Type": "Type", - "Max Voltage": "Max Voltage", - "Max Current": "Max Current", - "Multimedia Clock Rates": "Multimedia Clock Rates", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Network", - "Type: Wi-Fi": "Type: Wi-Fi", - "Press Y to show password": "Press Y to show password", - "Type: Ethernet": "Type: Ethernet", - "Type: Not connected": "Tipo: Not connected", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Elements   Move Down   Move Up", - "Transparent": "Transparent", - "Opaque": "Opaque", - "Alpha": "Alpha", - "Pretty": "Pretty", - "Compact": "Compact", - "FileSafe": "FileSafe", - "Day+Time": "Day+Time", - "Date+Time(s)": "Date+Time(s)", - "Date+Time AM/PM": "Date+Time AM/PM", - "Date+Time(s) AM/PM": "Date+Time(s) AM/PM", - "Date+Time EU": "Date+Time EU", - "Date+Time EU AM/PM": "Date+Time EU AM/PM", - "Date+Time(s) EU AM/PM": "Date+Time(s) EU AM/PM", - "Date+Time ISO": "Date+Time ISO", - "Time 24h": "Time 24h", - "Time AM/PM": "Time AM/PM", - "Time(s) 24h": "Time(s) 24h", - "Time(s) AM/PM": "Time(s) AM/PM", - "Date US": "Date US", - "Date EU": "Date EU", - "Date ISO": "Date ISO", - "Date Short": "Date Short", - "DTC Format": "DTC Format", - "Toggles": "Toggles", - "Info": "Show Info", - "Disable Screenshots": "Disable Screenshots", - "Real Freqs": "Real Freqs", - "Deltas": "Deltas", - "Target Freqs": "Target Freqs", - "FPS": "FPS", - "RES": "RES", - "Read Speed": "Read Speed", - "Real Frequencies": "Real Frequencies", - "Real Voltages": "Real Voltages", - "Full CPU": "Full CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Full Resolution", - "SOC Voltage": "SOC Voltage", - "RAM Load CPU/GPU": "RAM Load CPU/GPU", - "Use DTC Symbol": "Use DTC Symbol", - "Use Dynamic Colors": "Use Dynamic Colors", - "Sleep Exit": "Sleep Exit", - "Configuration": "Configuration", - "Refresh Rate": "Refresh Rate", - "Frame Padding": "Frame Padding", - " Font Size": " Font Size", - "Font Sizes": "Font Sizes", - "Handheld Font Size": "Handheld Font Size", - "Docked Font Size": "Docked Font Size", - "Black": "Black", - "Dark Gray": "Dark Gray", - "Gray": "Gray", - "Light Gray": "Light Gray", - "Silver": "Silver", - "White": "White", - "Dark Red": "Dark Red", - "Red": "Red", - "Light Red": "Light Red", - "Pink": "Pink", - "Dark Green": "Dark Green", - "Green": "Green", - "Lime Green": "Lime Green", - "Light Green": "Light Green", - "Dark Blue": "Dark Blue", - "Blue": "Blue", - "Light Blue": "Light Blue", - "Sky Blue": "Sky Blue", - "Dark Purple": "Dark Purple", - "Purple": "Purple", - "Light Purple": "Light Purple", - "Violet": "Violet", - "Orange": "Orange", - "Yellow": "Yellow", - "Light Yellow": "Light Yellow", - "Teal": "Teal", - "Cyan": "Cyan", - "Light Cyan": "Light Cyan", - "Magenta": "Magenta", - "Hot Pink": "Hot Pink", - "Brown": "Brown", - "Light Brown": "Light Brown", - "Colors": "Colors", - "Background Color": "Background Color", - "Background Alpha": "Background Alpha", - "Focus Color": "Focus Color", - "Focus Alpha": "Focus Alpha", - "Text Color": "Text Color", - "Border": "Border", - "Dashed Line": "Dashed Line", - "Max FPS Text": "Max FPS Text", - "Min FPS Text": "Min FPS Text", - "Main Line": "Main Line", - "Rounded Line": "Rounded Line", - "Perfect Line": "Perfect Line", - " Color": " Color", - " Alpha": " Alpha", - "Category Color": "Category Color", - "Category Color 1": "Category Color 1", - "Category Color 2": "Category Color 2", - "Separator Color": "Separator Color", - "Elements": "Elements", - "Text Alignment": "Text Alignment", - "Vertical Position": "Vertical Position", - "Horizontal Position": "Horizontal Position", - "Left": "Left", - "Right": "Right", - "Top": "Top", - "Center": "Center", - "Bottom": "Bottom", - "FPS Counter Color":"FPS Counter Color", - "FPS Counter Alpha":"FPS Counter Alpha", - "Border Color":"Border Color", - "Dashed Line Color":"Dashed Line Color", - "Dashed Line Alpha":"Dashed Line Alpha", - "Max FPS Text Color":"Max FPS Text Color", - "Min FPS Text Color":"Min FPS Text Color", - "Main Line Color":"Main Line Color", - "Rounded Line Color":"Rounded Line Color", - "Perfect Line Color":"Perfect Line Color" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/es.json b/Source/Horizon-OC-Monitor (deprecated)/lang/es.json deleted file mode 100644 index bacf1152..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/es.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Modos", - "Modes   Configure": "Modos   Configurar", - "Full": "Completo", - "Mini": "Mini", - "Micro": "Micro", - "FPS Graph": "Gráfico FPS", - "FPS Counter": "Contador FPS", - "Game Resolutions": "Resoluciones del juego", - "Other": "Otros", - "Battery/Charger": "Batería/Cargador", - "Miscellaneous": "Varios", - "CPU Usage": "Uso de CPU", - "GPU Usage": "Uso de GPU", - "RAM Usage": "Uso de RAM", - "Target Frequency": "Frecuencia objetivo", - "Real Frequency": "Frecuencia real", - "Core 0 ": "Núcleo 0 ", - "Core 1 ": "Núcleo 1 ", - "Core 2 ": "Núcleo 2 ", - "Core 3 ": "Núcleo 3 ", - "Load": "Carga", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Total\nAplicación\nApplet\nSistema\nSistema (inseguro)", - "Board": "Placa", - "Battery Power Flow": "Flujo de energía de batería", - "\nTemperatures": "\nTemperaturas", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Nivel de rotación del ventilador", - "Game": "Juego", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Resoluciones ", - "Read Speed ": "Velocidad de lectura ", - "Press ": "Pulsa ", - " to Exit": " para salir", - "Depth": "Profundidad", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "El juego no está en ejecución\no es incompatible.", - "Battery Stats": "Estadísticas de batería", - "Actual Capacity": "Capacidad actual", - "Designed Capacity": "Capacidad nominal", - "Temperature": "Temperatura", - "Raw Charge": "Carga bruta", - "Age": "Edad", - "Voltage": "Voltaje", - "Current Flow": "Flujo de corriente", - "Power Flow": "Flujo de potencia", - "Remaining Time": "Tiempo restante", - "Charger Stats": "Estadísticas del cargador", - "Input Current Limit": "Límite de corriente de entrada", - "VBUS Current Limit": "Límite de corriente VBUS", - "Voltage Limit": "Límite de voltaje", - "Current Limit": "Límite de corriente", - "Type": "Tipo", - "Max Voltage": "Voltaje máx.", - "Max Current": "Corriente máx.", - "Multimedia Clock Rates": "Frecuencias de reloj multimedia", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Red", - "Type: Wi-Fi": "Tipo: Wi-Fi", - "Press Y to show password": "Pulsa Y para mostrar contraseña", - "Type: Ethernet": "Tipo: Ethernet", - "Type: Not connected": "Tipo: No conectado", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Elementos   Bajar   Subir", - "Transparent": "Transparente", - "Opaque": "Opaco", - "Alpha": "Alfa", - "Pretty": "Bonito", - "Compact": "Compacto", - "FileSafe": "FileSafe", - "Day+Time": "Día+Hora", - "Date+Time(s)": "Fecha+Hora(s)", - "Date+Time AM/PM": "Fecha+Hora AM/PM", - "Date+Time(s) AM/PM": "Fecha+Hora(s) AM/PM", - "Date+Time EU": "Fecha+Hora EU", - "Date+Time EU AM/PM": "Fecha+Hora EU AM/PM", - "Date+Time(s) EU AM/PM": "Fecha+Hora(s) EU AM/PM", - "Date+Time ISO": "Fecha+Hora ISO", - "Time 24h": "Hora 24h", - "Time AM/PM": "Hora AM/PM", - "Time(s) 24h": "Hora(s) 24h", - "Time(s) AM/PM": "Hora(s) AM/PM", - "Date US": "Fecha EE.UU.", - "Date EU": "Fecha EU", - "Date ISO": "Fecha ISO", - "Date Short": "Fecha corta", - "DTC Format": "Formato DTC", - "Toggles": "Conmutadores", - "Info": "Mostrar info", - "Disable Screenshots": "Desactivar capturas", - "Real Freqs": "Frecuencias reales", - "Deltas": "Deltas", - "Target Freqs": "Frecuencias objetivo", - "FPS": "FPS", - "RES": "RES", - "Read Speed": "Velocidad de lectura", - "Real Frequencies": "Frecuencias reales", - "Real Voltages": "Voltajes reales", - "Full CPU": "CPU completo", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Resolución completa", - "SOC Voltage": "Voltaje SOC", - "RAM Load CPU/GPU": "Carga RAM CPU/GPU", - "Use DTC Symbol": "Usar símbolo DTC", - "Use Dynamic Colors": "Usar colores dinámicos", - "Sleep Exit": "Salir del reposo", - "Configuration": "Configuración", - "Refresh Rate": "Tasa de refresco", - "Frame Padding": "Relleno de marco", - " Font Size": " Tamaño de fuente", - "Font Sizes": "Tamaños de fuente", - "Handheld Font Size": "Tamaño fuente portátil", - "Docked Font Size": "Tamaño fuente acoplado", - "Black": "Negro", - "Dark Gray": "Gris oscuro", - "Gray": "Gris", - "Light Gray": "Gris claro", - "Silver": "Plata", - "White": "Blanco", - "Dark Red": "Rojo oscuro", - "Red": "Rojo", - "Light Red": "Rojo claro", - "Pink": "Rosa", - "Dark Green": "Verde oscuro", - "Green": "Verde", - "Lime Green": "Verde lima", - "Light Green": "Verde claro", - "Dark Blue": "Azul oscuro", - "Blue": "Azul", - "Light Blue": "Azul claro", - "Sky Blue": "Azul cielo", - "Dark Purple": "Púrpura oscuro", - "Purple": "Púrpura", - "Light Purple": "Púrpura claro", - "Violet": "Violeta", - "Orange": "Naranja", - "Yellow": "Amarillo", - "Light Yellow": "Amarillo claro", - "Teal": "Verde azulado", - "Cyan": "Cian", - "Light Cyan": "Cian claro", - "Magenta": "Magenta", - "Hot Pink": "Rosa intenso", - "Brown": "Marrón", - "Light Brown": "Marrón claro", - "Colors": "Colores", - "Background Color": "Color de fondo", - "Background Alpha": "Alfa de fondo", - "Focus Color": "Color de foco", - "Focus Alpha": "Alfa de foco", - "Text Color": "Color de texto", - "Border": "Borde", - "Dashed Line": "Línea discontinua", - "Max FPS Text": "Texto FPS máx.", - "Min FPS Text": "Texto FPS mín.", - "Main Line": "Línea principal", - "Rounded Line": "Línea redondeada", - "Perfect Line": "Línea perfecta", - " Color": " Color", - " Alpha": " Alfa", - "Category Color": "Color de categoría", - "Category Color 1": "Color categoría 1", - "Category Color 2": "Color categoría 2", - "Separator Color": "Color separador", - "Elements": "Elementos", - "Text Alignment": "Alineación de texto", - "Vertical Position": "Posición vertical", - "Horizontal Position": "Posición horizontal", - "Left": "Izquierda", - "Right": "Derecha", - "Top": "Arriba", - "Center": "Centro", - "Bottom": "Abajo", - "FPS Counter Color": "Color contador FPS", - "FPS Counter Alpha": "Alfa contador FPS", - "Border Color": "Color de borde", - "Dashed Line Color": "Color línea discontinua", - "Dashed Line Alpha": "Alfa línea discontinua", - "Max FPS Text Color": "Color texto FPS máx.", - "Min FPS Text Color": "Color texto FPS mín.", - "Main Line Color": "Color línea principal", - "Rounded Line Color": "Color línea redondeada", - "Perfect Line Color": "Color línea perfecta" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/fr.json b/Source/Horizon-OC-Monitor (deprecated)/lang/fr.json deleted file mode 100644 index 95bc2d9e..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/fr.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Modes", - "Modes   Configure": "Modes   Configurer", - "Full": "Complet", - "Mini": "Mini", - "Micro": "Micro", - "FPS Graph": "Graphique FPS", - "FPS Counter": "Compteur FPS", - "Game Resolutions": "Résolutions du jeu", - "Other": "Autres", - "Battery/Charger": "Batterie/Chargeur", - "Miscellaneous": "Divers", - "CPU Usage": "Utilisation CPU", - "GPU Usage": "Utilisation GPU", - "RAM Usage": "Utilisation RAM", - "Target Frequency": "Fréquence cible", - "Real Frequency": "Fréquence réelle", - "Core 0 ": "Cœur 0 ", - "Core 1 ": "Cœur 1 ", - "Core 2 ": "Cœur 2 ", - "Core 3 ": "Cœur 3 ", - "Load": "Charge", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Total\nApplication\nApplet\nSystème\nSystème non sécurisé", - "Board": "Carte", - "Battery Power Flow": "Flux de puissance batterie", - "\nTemperatures": "\nTempératures", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Niveau de rotation ventilateur", - "Game": "Jeu", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Résolutions ", - "Read Speed ": "Vitesse de lecture ", - "Press ": "Appuyez sur ", - " to Exit": " pour quitter", - "Depth": "Profondeur", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "Le jeu ne fonctionne pas\nou est incompatible.", - "Battery Stats": "Statistiques batterie", - "Actual Capacity": "Capacité actuelle", - "Designed Capacity": "Capacité nominale", - "Temperature": "Température", - "Raw Charge": "Charge brute", - "Age": "Âge", - "Voltage": "Tension", - "Current Flow": "Flux de courant", - "Power Flow": "Flux de puissance", - "Remaining Time": "Temps restant", - "Charger Stats": "Statistiques chargeur", - "Input Current Limit": "Limite courant entrée", - "VBUS Current Limit": "Limite courant VBUS", - "Voltage Limit": "Limite tension", - "Current Limit": "Limite courant", - "Type": "Type", - "Max Voltage": "Tension max", - "Max Current": "Courant max", - "Multimedia Clock Rates": "Fréquences horloge multimédia", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Réseau", - "Type: Wi-Fi": "Type : Wi-Fi", - "Press Y to show password": "Appuyez sur Y pour afficher le mot de passe", - "Type: Ethernet": "Type : Ethernet", - "Type: Not connected": "Type : Non connecté", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Éléments   Descendre   Monter", - "Transparent": "Transparent", - "Opaque": "Opaque", - "Alpha": "Alpha", - "Pretty": "Joli", - "Compact": "Compact", - "FileSafe": "FileSafe", - "Day+Time": "Jour+Heure", - "Date+Time(s)": "Date+Heure(s)", - "Date+Time AM/PM": "Date+Heure AM/PM", - "Date+Time(s) AM/PM": "Date+Heure(s) AM/PM", - "Date+Time EU": "Date+Heure EU", - "Date+Time EU AM/PM": "Date+Heure EU AM/PM", - "Date+Time(s) EU AM/PM": "Date+Heure(s) EU AM/PM", - "Date+Time ISO": "Date+Heure ISO", - "Time 24h": "Heure 24h", - "Time AM/PM": "Heure AM/PM", - "Time(s) 24h": "Heure(s) 24h", - "Time(s) AM/PM": "Heure(s) AM/PM", - "Date US": "Date US", - "Date EU": "Date EU", - "Date ISO": "Date ISO", - "Date Short": "Date courte", - "DTC Format": "Format DTC", - "Toggles": "Basculement", - "Info": "Afficher infos", - "Disable Screenshots": "Désactiver captures d'écran", - "Real Freqs": "Fréquences réelles", - "Deltas": "Deltas", - "Target Freqs": "Fréquences cibles", - "FPS": "FPS", - "RES": "RÉS", - "Read Speed": "Vitesse de lecture", - "Real Frequencies": "Fréquences réelles", - "Real Voltages": "Tensions réelles", - "Full CPU": "CPU complet", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Résolution complète", - "SOC Voltage": "Tension SOC", - "RAM Load CPU/GPU": "Charge RAM CPU/GPU", - "Use DTC Symbol": "Utiliser symbole DTC", - "Use Dynamic Colors": "Utiliser couleurs dynamiques", - "Sleep Exit": "Sortie veille", - "Configuration": "Configuration", - "Refresh Rate": "Taux de rafraîchissement", - "Frame Padding": "Marge de cadre", - " Font Size": " Taille police", - "Font Sizes": "Tailles de police", - "Handheld Font Size": "Taille police portable", - "Docked Font Size": "Taille police dockée", - "Black": "Noir", - "Dark Gray": "Gris foncé", - "Gray": "Gris", - "Light Gray": "Gris clair", - "Silver": "Argent", - "White": "Blanc", - "Dark Red": "Rouge foncé", - "Red": "Rouge", - "Light Red": "Rouge clair", - "Pink": "Rose", - "Dark Green": "Vert foncé", - "Green": "Vert", - "Lime Green": "Vert citron", - "Light Green": "Vert clair", - "Dark Blue": "Bleu foncé", - "Blue": "Bleu", - "Light Blue": "Bleu clair", - "Sky Blue": "Bleu ciel", - "Dark Purple": "Violet foncé", - "Purple": "Violet", - "Light Purple": "Violet clair", - "Violet": "Violet", - "Orange": "Orange", - "Yellow": "Jaune", - "Light Yellow": "Jaune clair", - "Teal": "Sarcelle", - "Cyan": "Cyan", - "Light Cyan": "Cyan clair", - "Magenta": "Magenta", - "Hot Pink": "Rose vif", - "Brown": "Marron", - "Light Brown": "Marron clair", - "Colors": "Couleurs", - "Background Color": "Couleur d'arrière-plan", - "Background Alpha": "Alpha d'arrière-plan", - "Focus Color": "Couleur de focus", - "Focus Alpha": "Alpha de focus", - "Text Color": "Couleur du texte", - "Border": "Bordure", - "Dashed Line": "Ligne pointillée", - "Max FPS Text": "Texte FPS max", - "Min FPS Text": "Texte FPS min", - "Main Line": "Ligne principale", - "Rounded Line": "Ligne arrondie", - "Perfect Line": "Ligne parfaite", - " Color": " Couleur", - " Alpha": " Alpha", - "Category Color": "Couleur de catégorie", - "Category Color 1": "Couleur catégorie 1", - "Category Color 2": "Couleur catégorie 2", - "Separator Color": "Couleur de séparateur", - "Elements": "Éléments", - "Text Alignment": "Alignement du texte", - "Vertical Position": "Position verticale", - "Horizontal Position": "Position horizontale", - "Left": "Gauche", - "Right": "Droite", - "Top": "Haut", - "Center": "Centre", - "Bottom": "Bas", - "FPS Counter Color": "Couleur compteur FPS", - "FPS Counter Alpha": "Alpha compteur FPS", - "Border Color": "Couleur de bordure", - "Dashed Line Color": "Couleur ligne pointillée", - "Dashed Line Alpha": "Alpha ligne pointillée", - "Max FPS Text Color": "Couleur texte FPS max", - "Min FPS Text Color": "Couleur texte FPS min", - "Main Line Color": "Couleur ligne principale", - "Rounded Line Color": "Couleur ligne arrondie", - "Perfect Line Color": "Couleur ligne parfaite" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/it.json b/Source/Horizon-OC-Monitor (deprecated)/lang/it.json deleted file mode 100644 index 3a76ba57..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/it.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Modalità", - "Modes   Configure": "Modalità   Configura", - "Full": "Completo", - "Mini": "Mini", - "Micro": "Micro", - "FPS Graph": "Grafico FPS", - "FPS Counter": "Contatore FPS", - "Game Resolutions": "Risoluzioni di gioco", - "Other": "Altro", - "Battery/Charger": "Batteria/Caricatore", - "Miscellaneous": "Varie", - "CPU Usage": "Utilizzo CPU", - "GPU Usage": "Utilizzo GPU", - "RAM Usage": "Utilizzo RAM", - "Target Frequency": "Frequenza target", - "Real Frequency": "Frequenza reale", - "Core 0 ": "Core 0 ", - "Core 1 ": "Core 1 ", - "Core 2 ": "Core 2 ", - "Core 3 ": "Core 3 ", - "Load": "Carico", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Totale\nApplicazione\nApplet\nSistema\nSistema non sicuro", - "Board": "Scheda", - "Battery Power Flow": "Flusso potenza batteria", - "\nTemperatures": "\nTemperature", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Livello rotazione ventola", - "Game": "Gioco", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Risoluzioni ", - "Read Speed ": "Velocità di lettura ", - "Press ": "Premi ", - " to Exit": " per uscire", - "Depth": "Profondità", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "Il gioco non è in esecuzione\no è incompatibile.", - "Battery Stats": "Statistiche batteria", - "Actual Capacity": "Capacità attuale", - "Designed Capacity": "Capacità nominale", - "Temperature": "Temperatura", - "Raw Charge": "Carica grezza", - "Age": "Età", - "Voltage": "Voltaggio", - "Current Flow": "Flusso corrente", - "Power Flow": "Flusso potenza", - "Remaining Time": "Tempo rimanente", - "Charger Stats": "Statistiche caricatore", - "Input Current Limit": "Limite corrente ingresso", - "VBUS Current Limit": "Limite corrente VBUS", - "Voltage Limit": "Limite tensione", - "Current Limit": "Limite corrente", - "Type": "Tipo", - "Max Voltage": "Tensione max", - "Max Current": "Corrente max", - "Multimedia Clock Rates": "Frequenze clock multimediali", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Rete", - "Type: Wi-Fi": "Tipo: Wi-Fi", - "Press Y to show password": "Premi Y per mostrare la password", - "Type: Ethernet": "Tipo: Ethernet", - "Type: Not connected": "Tipo: Non connesso", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Elementi   Sposta giù   Sposta su", - "Transparent": "Trasparente", - "Opaque": "Opaco", - "Alpha": "Alfa", - "Pretty": "Carino", - "Compact": "Compatto", - "FileSafe": "FileSafe", - "Day+Time": "Giorno+Ora", - "Date+Time(s)": "Data+Ora(s)", - "Date+Time AM/PM": "Data+Ora AM/PM", - "Date+Time(s) AM/PM": "Data+Ora(s) AM/PM", - "Date+Time EU": "Data+Ora EU", - "Date+Time EU AM/PM": "Data+Ora EU AM/PM", - "Date+Time(s) EU AM/PM": "Data+Ora(s) EU AM/PM", - "Date+Time ISO": "Data+Ora ISO", - "Time 24h": "Ora 24h", - "Time AM/PM": "Ora AM/PM", - "Time(s) 24h": "Ora(s) 24h", - "Time(s) AM/PM": "Ora(s) AM/PM", - "Date US": "Data US", - "Date EU": "Data EU", - "Date ISO": "Data ISO", - "Date Short": "Data breve", - "DTC Format": "Formato DTC", - "Toggles": "Interruttori", - "Info": "Mostra info", - "Disable Screenshots": "Disabilita screenshot", - "Real Freqs": "Frequenze reali", - "Deltas": "Delta", - "Target Freqs": "Frequenze target", - "FPS": "FPS", - "RES": "RIS", - "Read Speed": "Velocità di lettura", - "Real Frequencies": "Frequenze reali", - "Real Voltages": "Voltaggi reali", - "Full CPU": "CPU completo", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Risoluzione completa", - "SOC Voltage": "Voltaggio SOC", - "RAM Load CPU/GPU": "Carico RAM CPU/GPU", - "Use DTC Symbol": "Usa simbolo DTC", - "Use Dynamic Colors": "Usa colori dinamici", - "Sleep Exit": "Uscita standby", - "Configuration": "Configurazione", - "Refresh Rate": "Frequenza di aggiornamento", - "Frame Padding": "Spaziatura cornice", - " Font Size": " Dimensione font", - "Font Sizes": "Dimensioni font", - "Handheld Font Size": "Dimensione font portatile", - "Docked Font Size": "Dimensione font docked", - "Black": "Nero", - "Dark Gray": "Grigio scuro", - "Gray": "Grigio", - "Light Gray": "Grigio chiaro", - "Silver": "Argento", - "White": "Bianco", - "Dark Red": "Rosso scuro", - "Red": "Rosso", - "Light Red": "Rosso chiaro", - "Pink": "Rosa", - "Dark Green": "Verde scuro", - "Green": "Verde", - "Lime Green": "Verde lime", - "Light Green": "Verde chiaro", - "Dark Blue": "Blu scuro", - "Blue": "Blu", - "Light Blue": "Azzurro", - "Sky Blue": "Azzurro cielo", - "Dark Purple": "Viola scuro", - "Purple": "Viola", - "Light Purple": "Viola chiaro", - "Violet": "Viola", - "Orange": "Arancione", - "Yellow": "Giallo", - "Light Yellow": "Giallo chiaro", - "Teal": "Verde acqua", - "Cyan": "Ciano", - "Light Cyan": "Ciano chiaro", - "Magenta": "Magenta", - "Hot Pink": "Rosa shocking", - "Brown": "Marrone", - "Light Brown": "Marrone chiaro", - "Colors": "Colori", - "Background Color": "Colore sfondo", - "Background Alpha": "Alfa sfondo", - "Focus Color": "Colore focus", - "Focus Alpha": "Alfa focus", - "Text Color": "Colore testo", - "Border": "Bordo", - "Dashed Line": "Linea tratteggiata", - "Max FPS Text": "Testo FPS max", - "Min FPS Text": "Testo FPS min", - "Main Line": "Linea principale", - "Rounded Line": "Linea arrotondata", - "Perfect Line": "Linea perfetta", - " Color": " Colore", - " Alpha": " Alfa", - "Category Color": "Colore categoria", - "Category Color 1": "Colore categoria 1", - "Category Color 2": "Colore categoria 2", - "Separator Color": "Colore separatore", - "Elements": "Elementi", - "Text Alignment": "Allineamento testo", - "Vertical Position": "Posizione verticale", - "Horizontal Position": "Posizione orizzontale", - "Left": "Sinistra", - "Right": "Destra", - "Top": "Sopra", - "Center": "Centro", - "Bottom": "Sotto", - "FPS Counter Color": "Colore contatore FPS", - "FPS Counter Alpha": "Alfa contatore FPS", - "Border Color": "Colore bordo", - "Dashed Line Color": "Colore linea tratteggiata", - "Dashed Line Alpha": "Alfa linea tratteggiata", - "Max FPS Text Color": "Colore testo FPS max", - "Min FPS Text Color": "Colore testo FPS min", - "Main Line Color": "Colore linea principale", - "Rounded Line Color": "Colore linea arrotondata", - "Perfect Line Color": "Colore linea perfetta" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/ja.json b/Source/Horizon-OC-Monitor (deprecated)/lang/ja.json deleted file mode 100644 index a4000d02..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/ja.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "モード", - "Modes   Configure": "モード   設定", - "Full": "フル", - "Mini": "ミニ", - "Micro": "マイクロ", - "FPS Graph": "FPSグラフ", - "FPS Counter": "FPSカウンター", - "Game Resolutions": "ゲーム解像度", - "Other": "その他", - "Battery/Charger": "バッテリー/充電器", - "Miscellaneous": "その他", - "CPU Usage": "CPU使用率", - "GPU Usage": "GPU使用率", - "RAM Usage": "RAM使用率", - "Target Frequency": "目標周波数", - "Real Frequency": "実際の周波数", - "Core 0 ": "コア 0 ", - "Core 1 ": "コア 1 ", - "Core 2 ": "コア 2 ", - "Core 3 ": "コア 3 ", - "Load": "負荷", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "合計\nアプリケーション\nアプレット\nシステム\nシステム(非安全)", - "Board": "ボード", - "Battery Power Flow": "バッテリー電力フロー", - "\nTemperatures": "\n温度", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "ファン回転レベル", - "Game": "ゲーム", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "解像度 ", - "Read Speed ": "読み込み速度 ", - "Press ": "押す ", - " to Exit": " で終了", - "Depth": "深度", - "Viewport": "ビューポート", - "Game is not running\nor it's incompatible.": "ゲームが実行されていない\nまたは非対応です。", - "Battery Stats": "バッテリー統計", - "Actual Capacity": "実際の容量", - "Designed Capacity": "設計容量", - "Temperature": "温度", - "Raw Charge": "生充電量", - "Age": "経年", - "Voltage": "電圧", - "Current Flow": "電流フロー", - "Power Flow": "電力フロー", - "Remaining Time": "残り時間", - "Charger Stats": "充電器統計", - "Input Current Limit": "入力電流制限", - "VBUS Current Limit": "VBUS電流制限", - "Voltage Limit": "電圧制限", - "Current Limit": "電流制限", - "Type": "タイプ", - "Max Voltage": "最大電圧", - "Max Current": "最大電流", - "Multimedia Clock Rates": "マルチメディアクロックレート", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "ネットワーク", - "Type: Wi-Fi": "タイプ: Wi-Fi", - "Press Y to show password": "Yを押してパスワードを表示", - "Type: Ethernet": "タイプ: Ethernet", - "Type: Not connected": "タイプ: 未接続", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "要素   下へ   上へ", - "Transparent": "透明", - "Opaque": "不透明", - "Alpha": "アルファ", - "Pretty": "プリティ", - "Compact": "コンパクト", - "FileSafe": "ファイルセーフ", - "Day+Time": "日+時間", - "Date+Time(s)": "日付+時間(s)", - "Date+Time AM/PM": "日付+時間 AM/PM", - "Date+Time(s) AM/PM": "日付+時間(s) AM/PM", - "Date+Time EU": "日付+時間 EU", - "Date+Time EU AM/PM": "日付+時間 EU AM/PM", - "Date+Time(s) EU AM/PM": "日付+時間(s) EU AM/PM", - "Date+Time ISO": "日付+時間 ISO", - "Time 24h": "時間 24h", - "Time AM/PM": "時間 AM/PM", - "Time(s) 24h": "時間(s) 24h", - "Time(s) AM/PM": "時間(s) AM/PM", - "Date US": "日付 US", - "Date EU": "日付 EU", - "Date ISO": "日付 ISO", - "Date Short": "短い日付", - "DTC Format": "DTC形式", - "Toggles": "トグル", - "Info": "情報表示", - "Disable Screenshots": "スクリーンショット無効", - "Real Freqs": "実際の周波数", - "Deltas": "デルタ", - "Target Freqs": "目標周波数", - "FPS": "FPS", - "RES": "解像度", - "Read Speed": "読み込み速度", - "Real Frequencies": "実際の周波数", - "Real Voltages": "実際の電圧", - "Full CPU": "フルCPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "フル解像度", - "SOC Voltage": "SOC電圧", - "RAM Load CPU/GPU": "RAM負荷 CPU/GPU", - "Use DTC Symbol": "DTCシンボル使用", - "Use Dynamic Colors": "ダイナミックカラー使用", - "Sleep Exit": "スリープ解除", - "Configuration": "設定", - "Refresh Rate": "リフレッシュレート", - "Frame Padding": "フレームパディング", - " Font Size": " フォントサイズ", - "Font Sizes": "フォントサイズ", - "Handheld Font Size": "携帯モードフォントサイズ", - "Docked Font Size": "ドックモードフォントサイズ", - "Black": "黒", - "Dark Gray": "ダークグレー", - "Gray": "グレー", - "Light Gray": "ライトグレー", - "Silver": "シルバー", - "White": "白", - "Dark Red": "ダークレッド", - "Red": "赤", - "Light Red": "ライト レッド", - "Pink": "ピンク", - "Dark Green": "ダークグリーン", - "Green": "緑", - "Lime Green": "ライムグリーン", - "Light Green": "ライトグリーン", - "Dark Blue": "ダークブルー", - "Blue": "青", - "Light Blue": "ライトブルー", - "Sky Blue": "スカイブルー", - "Dark Purple": "ダークパープル", - "Purple": "パープル", - "Light Purple": "ライトパープル", - "Violet": "バイオレット", - "Orange": "オレンジ", - "Yellow": "黄", - "Light Yellow": "ライトイエロー", - "Teal": "ティール", - "Cyan": "シアン", - "Light Cyan": "ライトシアン", - "Magenta": "マゼンタ", - "Hot Pink": "ホットピンク", - "Brown": "ブラウン", - "Light Brown": "ライトブラウン", - "Colors": "色", - "Background Color": "背景色", - "Background Alpha": "背景アルファ", - "Focus Color": "フォーカス色", - "Focus Alpha": "フォーカスアルファ", - "Text Color": "文字色", - "Border": "枠線", - "Dashed Line": "破線", - "Max FPS Text": "最大FPSテキスト", - "Min FPS Text": "最小FPSテキスト", - "Main Line": "主線", - "Rounded Line": "丸角線", - "Perfect Line": "完璧線", - " Color": " 色", - " Alpha": " アルファ", - "Category Color": "カテゴリ色", - "Category Color 1": "カテゴリ色 1", - "Category Color 2": "カテゴリ色 2", - "Separator Color": "セパレータ色", - "Elements": "要素", - "Text Alignment": "テキスト配置", - "Vertical Position": "垂直位置", - "Horizontal Position": "水平位置", - "Left": "左", - "Right": "右", - "Top": "上", - "Center": "中央", - "Bottom": "下", - "FPS Counter Color": "FPSカウンター色", - "FPS Counter Alpha": "FPSカウンターアルファ", - "Border Color": "枠線色", - "Dashed Line Color": "破線色", - "Dashed Line Alpha": "破線アルファ", - "Max FPS Text Color": "最大FPSテキスト色", - "Min FPS Text Color": "最小FPSテキスト色", - "Main Line Color": "主線色", - "Rounded Line Color": "丸角線色", - "Perfect Line Color": "完璧線色" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/ko.json b/Source/Horizon-OC-Monitor (deprecated)/lang/ko.json deleted file mode 100644 index a001d36d..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/ko.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "모드", - "Modes   Configure": "모드   설정", - "Full": "전체", - "Mini": "미니", - "Micro": "마이크로", - "FPS Graph": "FPS 그래프", - "FPS Counter": "FPS 카운터", - "Game Resolutions": "게임 해상도", - "Other": "기타", - "Battery/Charger": "배터리/충전기", - "Miscellaneous": "기타", - "CPU Usage": "CPU 사용량", - "GPU Usage": "GPU 사용량", - "RAM Usage": "RAM 사용량", - "Target Frequency": "목표 주파수", - "Real Frequency": "실제 주파수", - "Core 0 ": "코어 0 ", - "Core 1 ": "코어 1 ", - "Core 2 ": "코어 2 ", - "Core 3 ": "코어 3 ", - "Load": "부하", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "합계\n앱\n애플릿\n시스템\n시스템(비안전)", - "Board": "보드", - "Battery Power Flow": "배터리 전력 흐름", - "\nTemperatures": "\n온도", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "팬 회전 레벨", - "Game": "게임", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "해상도 ", - "Read Speed ": "읽기 속도 ", - "Press ": "누르기 ", - " to Exit": " 종료", - "Depth": "깊이", - "Viewport": "뷰포트", - "Game is not running\nor it's incompatible.": "게임이 실행 중이 아니거나\n호환되지 않습니다.", - "Battery Stats": "배터리 통계", - "Actual Capacity": "실제 용량", - "Designed Capacity": "설계 용량", - "Temperature": "온도", - "Raw Charge": "원시 충전량", - "Age": "수명", - "Voltage": "전압", - "Current Flow": "전류 흐름", - "Power Flow": "전력 흐름", - "Remaining Time": "남은 시간", - "Charger Stats": "충전기 통계", - "Input Current Limit": "입력 전류 제한", - "VBUS Current Limit": "VBUS 전류 제한", - "Voltage Limit": "전압 제한", - "Current Limit": "전류 제한", - "Type": "유형", - "Max Voltage": "최대 전압", - "Max Current": "최대 전류", - "Multimedia Clock Rates": "멀티미디어 클럭 속도", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "네트워크", - "Type: Wi-Fi": "유형: Wi-Fi", - "Press Y to show password": "Y를 눌러 비밀번호 표시", - "Type: Ethernet": "유형: 이더넷", - "Type: Not connected": "유형: 연결 안 됨", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "요소   아래로   위로", - "Transparent": "투명", - "Opaque": "불투명", - "Alpha": "알파", - "Pretty": "예쁨", - "Compact": "컴팩트", - "FileSafe": "파일세이프", - "Day+Time": "일+시간", - "Date+Time(s)": "날짜+시간(s)", - "Date+Time AM/PM": "날짜+시간 AM/PM", - "Date+Time(s) AM/PM": "날짜+시간(s) AM/PM", - "Date+Time EU": "날짜+시간 EU", - "Date+Time EU AM/PM": "날짜+시간 EU AM/PM", - "Date+Time(s) EU AM/PM": "날짜+시간(s) EU AM/PM", - "Date+Time ISO": "날짜+시간 ISO", - "Time 24h": "시간 24시", - "Time AM/PM": "시간 AM/PM", - "Time(s) 24h": "시간(s) 24시", - "Time(s) AM/PM": "시간(s) AM/PM", - "Date US": "날짜 US", - "Date EU": "날짜 EU", - "Date ISO": "날짜 ISO", - "Date Short": "짧은 날짜", - "DTC Format": "DTC 형식", - "Toggles": "토글", - "Info": "정보 표시", - "Disable Screenshots": "스크린샷 비활성화", - "Real Freqs": "실제 주파수", - "Deltas": "델타", - "Target Freqs": "목표 주파수", - "FPS": "FPS", - "RES": "해상도", - "Read Speed": "읽기 속도", - "Real Frequencies": "실제 주파수", - "Real Voltages": "실제 전압", - "Full CPU": "전체 CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "전체 해상도", - "SOC Voltage": "SOC 전압", - "RAM Load CPU/GPU": "RAM 부하 CPU/GPU", - "Use DTC Symbol": "DTC 심볼 사용", - "Use Dynamic Colors": "동적 색상 사용", - "Sleep Exit": "절전 종료", - "Configuration": "설정", - "Refresh Rate": "리프레시 레이트", - "Frame Padding": "프레임 패딩", - " Font Size": " 글꼴 크기", - "Font Sizes": "글꼴 크기", - "Handheld Font Size": "핸드헬드 글꼴 크기", - "Docked Font Size": "도킹 글꼴 크기", - "Black": "검정", - "Dark Gray": "짙은 회색", - "Gray": "회색", - "Light Gray": "밝은 회색", - "Silver": "은색", - "White": "흰색", - "Dark Red": "짙은 빨강", - "Red": "빨강", - "Light Red": "밝은 빨강", - "Pink": "분홍", - "Dark Green": "짙은 초록", - "Green": "초록", - "Lime Green": "라임 그린", - "Light Green": "밝은 초록", - "Dark Blue": "짙은 파랑", - "Blue": "파랑", - "Light Blue": "밝은 파랑", - "Sky Blue": "하늘색", - "Dark Purple": "짙은 보라", - "Purple": "보라", - "Light Purple": "밝은 보라", - "Violet": "바이올렛", - "Orange": "주황", - "Yellow": "노랑", - "Light Yellow": "밝은 노랑", - "Teal": "청록", - "Cyan": "시안", - "Light Cyan": "밝은 시안", - "Magenta": "마젠타", - "Hot Pink": "핫핑크", - "Brown": "갈색", - "Light Brown": "밝은 갈색", - "Colors": "색상", - "Background Color": "배경색", - "Background Alpha": "배경 투명도", - "Focus Color": "포커스 색상", - "Focus Alpha": "포커스 투명도", - "Text Color": "텍스트 색상", - "Border": "테두리", - "Dashed Line": "점선", - "Max FPS Text": "최대 FPS 텍스트", - "Min FPS Text": "최소 FPS 텍스트", - "Main Line": "주선", - "Rounded Line": "둥근 선", - "Perfect Line": "완벽 선", - " Color": " 색상", - " Alpha": " 투명도", - "Category Color": "카테고리 색상", - "Category Color 1": "카테고리 색상 1", - "Category Color 2": "카테고리 색상 2", - "Separator Color": "구분선 색상", - "Elements": "요소", - "Text Alignment": "텍스트 정렬", - "Vertical Position": "세로 위치", - "Horizontal Position": "가로 위치", - "Left": "왼쪽", - "Right": "오른쪽", - "Top": "위", - "Center": "가운데", - "Bottom": "아래", - "FPS Counter Color": "FPS 카운터 색상", - "FPS Counter Alpha": "FPS 카운터 투명도", - "Border Color": "테두리 색상", - "Dashed Line Color": "점선 색상", - "Dashed Line Alpha": "점선 투명도", - "Max FPS Text Color": "최대 FPS 텍스트 색상", - "Min FPS Text Color": "최소 FPS 텍스트 색상", - "Main Line Color": "주선 색상", - "Rounded Line Color": "둥근 선 색상", - "Perfect Line Color": "완벽 선 색상" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/nl.json b/Source/Horizon-OC-Monitor (deprecated)/lang/nl.json deleted file mode 100644 index febfacdc..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/nl.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Modi", - "Modes   Configure": "Modi   Configureren", - "Full": "Volledig", - "Mini": "Mini", - "Micro": "Micro", - "FPS Graph": "FPS-grafiek", - "FPS Counter": "FPS-teller", - "Game Resolutions": "Spelresoluties", - "Other": "Overig", - "Battery/Charger": "Batterij/Oplader", - "Miscellaneous": "Diversen", - "CPU Usage": "CPU-gebruik", - "GPU Usage": "GPU-gebruik", - "RAM Usage": "RAM-gebruik", - "Target Frequency": "Doelfrequentie", - "Real Frequency": "Werkelijke frequentie", - "Core 0 ": "Kern 0 ", - "Core 1 ": "Kern 1 ", - "Core 2 ": "Kern 2 ", - "Core 3 ": "Kern 3 ", - "Load": "Belasting", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Totaal\nApplicatie\nApplet\nSysteem\nSysteem onveilig", - "Board": "Bord", - "Battery Power Flow": "Batterijstroom", - "\nTemperatures": "\nTemperaturen", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Ventilatorrotatieniveau", - "Game": "Spel", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Resoluties ", - "Read Speed ": "Leessnelheid ", - "Press ": "Druk op ", - " to Exit": " om af te sluiten", - "Depth": "Diepte", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "Spel draait niet\nof is incompatibel.", - "Battery Stats": "Batterijstatistieken", - "Actual Capacity": "Werkelijke capaciteit", - "Designed Capacity": "Ontworpen capaciteit", - "Temperature": "Temperatuur", - "Raw Charge": "Ruwe lading", - "Age": "Leeftijd", - "Voltage": "Spanning", - "Current Flow": "Stroomstroom", - "Power Flow": "Stroomverbruik", - "Remaining Time": "Resterende tijd", - "Charger Stats": "Opladerstatistieken", - "Input Current Limit": "Ingangsstroomlimiet", - "VBUS Current Limit": "VBUS-stroomlimiet", - "Voltage Limit": "Spanningslimiet", - "Current Limit": "Stroomlimiet", - "Type": "Type", - "Max Voltage": "Max spanning", - "Max Current": "Max stroom", - "Multimedia Clock Rates": "Multimedia kloksnelheden", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Netwerk", - "Type: Wi-Fi": "Type: Wi-Fi", - "Press Y to show password": "Druk op Y om wachtwoord te tonen", - "Type: Ethernet": "Type: Ethernet", - "Type: Not connected": "Type: Niet verbonden", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Elementen   Omlaag verplaatsen   Omhoog verplaatsen", - "Transparent": "Transparant", - "Opaque": "Ondoorzichtig", - "Alpha": "Alpha", - "Pretty": "Mooi", - "Compact": "Compact", - "FileSafe": "FileSafe", - "Day+Time": "Dag+Tijd", - "Date+Time(s)": "Datum+Tijd(s)", - "Date+Time AM/PM": "Datum+Tijd AM/PM", - "Date+Time(s) AM/PM": "Datum+Tijd(s) AM/PM", - "Date+Time EU": "Datum+Tijd EU", - "Date+Time EU AM/PM": "Datum+Tijd EU AM/PM", - "Date+Time(s) EU AM/PM": "Datum+Tijd(s) EU AM/PM", - "Date+Time ISO": "Datum+Tijd ISO", - "Time 24h": "Tijd 24u", - "Time AM/PM": "Tijd AM/PM", - "Time(s) 24h": "Tijd(s) 24u", - "Time(s) AM/PM": "Tijd(s) AM/PM", - "Date US": "Datum VS", - "Date EU": "Datum EU", - "Date ISO": "Datum ISO", - "Date Short": "Datum kort", - "DTC Format": "DTC-formaat", - "Toggles": "Schakelaars", - "Info": "Info tonen", - "Disable Screenshots": "Schermafbeeldingen uitschakelen", - "Real Freqs": "Werkelijke frequenties", - "Deltas": "Delta's", - "Target Freqs": "Doelfrequenties", - "FPS": "FPS", - "RES": "RES", - "Read Speed": "Leessnelheid", - "Real Frequencies": "Werkelijke frequenties", - "Real Voltages": "Werkelijke spanningen", - "Full CPU": "Volledige CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Volledige resolutie", - "SOC Voltage": "SOC-spanning", - "RAM Load CPU/GPU": "RAM-belasting CPU/GPU", - "Use DTC Symbol": "DTC-symbool gebruiken", - "Use Dynamic Colors": "Dynamische kleuren gebruiken", - "Sleep Exit": "Slaap afsluiten", - "Configuration": "Configuratie", - "Refresh Rate": "Vernieuwingsfrequentie", - "Frame Padding": "Frame opvulling", - " Font Size": " Lettergrootte", - "Font Sizes": "Lettergroottes", - "Handheld Font Size": "Handheld lettergrootte", - "Docked Font Size": "Docked lettergrootte", - "Black": "Zwart", - "Dark Gray": "Donkergrijs", - "Gray": "Grijs", - "Light Gray": "Lichtgrijs", - "Silver": "Zilver", - "White": "Wit", - "Dark Red": "Donkerrood", - "Red": "Rood", - "Light Red": "Lichtrood", - "Pink": "Roze", - "Dark Green": "Donkergroen", - "Green": "Groen", - "Lime Green": "Limoengroen", - "Light Green": "Lichtgroen", - "Dark Blue": "Donkerblauw", - "Blue": "Blauw", - "Light Blue": "Lichtblauw", - "Sky Blue": "Hemelsblauw", - "Dark Purple": "Donkerpaars", - "Purple": "Paars", - "Light Purple": "Lichtpaars", - "Violet": "Violet", - "Orange": "Oranje", - "Yellow": "Geel", - "Light Yellow": "Lichtgeel", - "Teal": "Teal", - "Cyan": "Cyaan", - "Light Cyan": "Lichtcyaan", - "Magenta": "Magenta", - "Hot Pink": "Felroze", - "Brown": "Bruin", - "Light Brown": "Lichtbruin", - "Colors": "Kleuren", - "Background Color": "Achtergrondkleur", - "Background Alpha": "Achtergrond alpha", - "Focus Color": "Focuskleur", - "Focus Alpha": "Focus alpha", - "Text Color": "Tekstkleur", - "Border": "Rand", - "Dashed Line": "Gestippelde lijn", - "Max FPS Text": "Max FPS tekst", - "Min FPS Text": "Min FPS tekst", - "Main Line": "Hoofdlijn", - "Rounded Line": "Afgeronde lijn", - "Perfect Line": "Perfecte lijn", - " Color": " Kleur", - " Alpha": " Alpha", - "Category Color": "Categoriekleur", - "Category Color 1": "Categoriekleur 1", - "Category Color 2": "Categoriekleur 2", - "Separator Color": "Scheidingskleur", - "Elements": "Elementen", - "Text Alignment": "Tekstuitlijning", - "Vertical Position": "Verticale positie", - "Horizontal Position": "Horizontale positie", - "Left": "Links", - "Right": "Rechts", - "Top": "Boven", - "Center": "Midden", - "Bottom": "Onder", - "FPS Counter Color":"FPS-tellerkleur", - "FPS Counter Alpha":"FPS-teller alpha", - "Border Color":"Randkleur", - "Dashed Line Color":"Gestippelde lijnkleur", - "Dashed Line Alpha":"Gestippelde lijn alpha", - "Max FPS Text Color":"Max FPS tekstkleur", - "Min FPS Text Color":"Min FPS tekstkleur", - "Main Line Color":"Hoofdlijnkleur", - "Rounded Line Color":"Afgeronde lijnkleur", - "Perfect Line Color":"Perfecte lijnkleur" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/pl.json b/Source/Horizon-OC-Monitor (deprecated)/lang/pl.json deleted file mode 100644 index e2dd49e5..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/pl.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Tryby", - "Modes   Configure": "Tryby   Konfiguruj", - "Full": "Pełny", - "Mini": "Mini", - "Micro": "Mikro", - "FPS Graph": "Wykres FPS", - "FPS Counter": "Licznik FPS", - "Game Resolutions": "Rozdzielczości gry", - "Other": "Inne", - "Battery/Charger": "Bateria/Ładowarka", - "Miscellaneous": "Różne", - "CPU Usage": "Użycie CPU", - "GPU Usage": "Użycie GPU", - "RAM Usage": "Użycie RAM", - "Target Frequency": "Częstotliwość docelowa", - "Real Frequency": "Rzeczywista częstotliwość", - "Core 0 ": "Rdzeń 0 ", - "Core 1 ": "Rdzeń 1 ", - "Core 2 ": "Rdzeń 2 ", - "Core 3 ": "Rdzeń 3 ", - "Load": "Obciążenie", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Razem\nAplikacja\nApplet\nSystem\nSystem (niebezpieczny)", - "Board": "Płyta", - "Battery Power Flow": "Przepływ mocy baterii", - "\nTemperatures": "\nTemperatury", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Poziom obrotów wentylatora", - "Game": "Gra", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Rozdzielczości ", - "Read Speed ": "Prędkość odczytu ", - "Press ": "Naciśnij ", - " to Exit": " aby wyjść", - "Depth": "Głębia", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "Gra nie jest uruchomiona\nlub jest niekompatybilna.", - "Battery Stats": "Statystyki baterii", - "Actual Capacity": "Rzeczywista pojemność", - "Designed Capacity": "Pojemność znamionowa", - "Temperature": "Temperatura", - "Raw Charge": "Surowy poziom naładowania", - "Age": "Wiek", - "Voltage": "Napięcie", - "Current Flow": "Przepływ prądu", - "Power Flow": "Przepływ mocy", - "Remaining Time": "Pozostały czas", - "Charger Stats": "Statystyki ładowarki", - "Input Current Limit": "Limit prądu wejściowego", - "VBUS Current Limit": "Limit prądu VBUS", - "Voltage Limit": "Limit napięcia", - "Current Limit": "Limit prądu", - "Type": "Typ", - "Max Voltage": "Maks. napięcie", - "Max Current": "Maks. prąd", - "Multimedia Clock Rates": "Taktowanie multimediów", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Sieć", - "Type: Wi-Fi": "Typ: Wi-Fi", - "Press Y to show password": "Naciśnij Y, aby pokazać hasło", - "Type: Ethernet": "Typ: Ethernet", - "Type: Not connected": "Typ: Nie połączono", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Elementy   Przesuń w dół   Przesuń w górę", - "Transparent": "Przezroczysty", - "Opaque": "Nieprzezroczysty", - "Alpha": "Alfa", - "Pretty": "Ładny", - "Compact": "Kompaktowy", - "FileSafe": "FileSafe", - "Day+Time": "Dzień+Czas", - "Date+Time(s)": "Data+Czas(s)", - "Date+Time AM/PM": "Data+Czas AM/PM", - "Date+Time(s) AM/PM": "Data+Czas(s) AM/PM", - "Date+Time EU": "Data+Czas EU", - "Date+Time EU AM/PM": "Data+Czas EU AM/PM", - "Date+Time(s) EU AM/PM": "Data+Czas(s) EU AM/PM", - "Date+Time ISO": "Data+Czas ISO", - "Time 24h": "Czas 24h", - "Time AM/PM": "Czas AM/PM", - "Time(s) 24h": "Czas(s) 24h", - "Time(s) AM/PM": "Czas(s) AM/PM", - "Date US": "Data US", - "Date EU": "Data EU", - "Date ISO": "Data ISO", - "Date Short": "Krótka data", - "DTC Format": "Format DTC", - "Toggles": "Przełączniki", - "Info": "Pokaż informacje", - "Disable Screenshots": "Wyłącz zrzuty ekranu", - "Real Freqs": "Rzeczywiste częstotliwości", - "Deltas": "Delty", - "Target Freqs": "Docelowe częstotliwości", - "FPS": "FPS", - "RES": "ROZDZ.", - "Read Speed": "Prędkość odczytu", - "Real Frequencies": "Rzeczywiste częstotliwości", - "Real Voltages": "Rzeczywiste napięcia", - "Full CPU": "Pełny CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Pełna rozdzielczość", - "SOC Voltage": "Napięcie SOC", - "RAM Load CPU/GPU": "Obciążenie RAM CPU/GPU", - "Use DTC Symbol": "Użyj symbolu DTC", - "Use Dynamic Colors": "Użyj dynamicznych kolorów", - "Sleep Exit": "Wyjście z uśpienia", - "Configuration": "Konfiguracja", - "Refresh Rate": "Częstotliwość odświeżania", - "Frame Padding": "Wypełnienie ramki", - " Font Size": " Rozmiar czcionki", - "Font Sizes": "Rozmiary czcionki", - "Handheld Font Size": "Rozmiar czcionki w trybie przenośnym", - "Docked Font Size": "Rozmiar czcionki w trybie stacjonarnym", - "Black": "Czarny", - "Dark Gray": "Ciemnoszary", - "Gray": "Szary", - "Light Gray": "Jasnoszary", - "Silver": "Srebrny", - "White": "Biały", - "Dark Red": "Ciemnoczerwony", - "Red": "Czerwony", - "Light Red": "Jasnoczerwony", - "Pink": "Różowy", - "Dark Green": "Ciemnozielony", - "Green": "Zielony", - "Lime Green": "Limonkowy", - "Light Green": "Jasnozielony", - "Dark Blue": "Ciemnoniebieski", - "Blue": "Niebieski", - "Light Blue": "Jasnoniebieski", - "Sky Blue": "Błękitny", - "Dark Purple": "Ciemnofioletowy", - "Purple": "Fioletowy", - "Light Purple": "Jasnofioletowy", - "Violet": "Fiolet", - "Orange": "Pomarańczowy", - "Yellow": "Żółty", - "Light Yellow": "Jasnożółty", - "Teal": "Morski", - "Cyan": "Cyjan", - "Light Cyan": "Jasny cyjan", - "Magenta": "Magenta", - "Hot Pink": "Jaskrawo różowy", - "Brown": "Brązowy", - "Light Brown": "Jasnobrązowy", - "Colors": "Kolory", - "Background Color": "Kolor tła", - "Background Alpha": "Przezroczystość tła", - "Focus Color": "Kolor fokusu", - "Focus Alpha": "Przezroczystość fokusu", - "Text Color": "Kolor tekstu", - "Border": "Obramowanie", - "Dashed Line": "Linia przerywana", - "Max FPS Text": "Tekst maks. FPS", - "Min FPS Text": "Tekst min. FPS", - "Main Line": "Główna linia", - "Rounded Line": "Zaokrąglona linia", - "Perfect Line": "Idealna linia", - " Color": " Kolor", - " Alpha": " Alfa", - "Category Color": "Kolor kategorii", - "Category Color 1": "Kolor kategorii 1", - "Category Color 2": "Kolor kategorii 2", - "Separator Color": "Kolor separatora", - "Elements": "Elementy", - "Text Alignment": "Wyrównanie tekstu", - "Vertical Position": "Pozycja pionowa", - "Horizontal Position": "Pozycja pozioma", - "Left": "Lewo", - "Right": "Prawo", - "Top": "Góra", - "Center": "Środek", - "Bottom": "Dół", - "FPS Counter Color": "Kolor licznika FPS", - "FPS Counter Alpha": "Alfa licznika FPS", - "Border Color": "Kolor obramowania", - "Dashed Line Color": "Kolor linii przerywanej", - "Dashed Line Alpha": "Alfa linii przerywanej", - "Max FPS Text Color": "Kolor tekstu maks. FPS", - "Min FPS Text Color": "Kolor tekstu min. FPS", - "Main Line Color": "Kolor głównej linii", - "Rounded Line Color": "Kolor zaokrąglonej linii", - "Perfect Line Color": "Kolor idealnej linii" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/pt.json b/Source/Horizon-OC-Monitor (deprecated)/lang/pt.json deleted file mode 100644 index 3805ce59..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/pt.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Modos", - "Modes   Configure": "Modos   Configurar", - "Full": "Completo", - "Mini": "Mini", - "Micro": "Micro", - "FPS Graph": "Gráfico FPS", - "FPS Counter": "Contador FPS", - "Game Resolutions": "Resoluções no Jogo", - "Other": "Outros", - "Battery/Charger": "Bateria/Carregador", - "Miscellaneous": "Diversos", - "CPU Usage": "Uso da CPU", - "GPU Usage": "Uso da GPU", - "RAM Usage": "Uso da RAM", - "Target Frequency": "Frequência Alvo", - "Real Frequency": "Frequência Real", - "Core 0 ": "Núcleo 0 ", - "Core 1 ": "Núcleo 1 ", - "Core 2 ": "Núcleo 2 ", - "Core 3 ": "Núcleo 3 ", - "Load": "Carga", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Total\nAplicativo\nMiniAplicativo\nSistema\nSistema Inseguro", - "Board": "Placa", - "Battery Power Flow": "Fluxo de Energia", - "\nTemperatures": "\nTemperaturas", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Rotação da Fan", - "Game": "Jogo", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Resoluções ", - "Read Speed ": "Velocidade de Leitura ", - "Press ": "Pressione ", - " to Exit": " para Sair", - "Depth": "Profundidade", - "Viewport": "Visualização", - "Game is not running\nor it's incompatible.": "O jogo não está rodando\n ou não é compatível.", - "Battery Stats": "Estatísticas da Bateria", - "Actual Capacity": "Capacidade Atual", - "Designed Capacity": "Capacidade Designada", - "Temperature": "Temperatura", - "Raw Charge": "Carga Bruta", - "Age": "Idade", - "Voltage": "Voltagem", - "Current Flow": "Fluxo de Corrente", - "Power Flow": "Fluxo de Potência", - "Remaining Time": "Tempo Restante", - "Charger Stats": "Estatísticas do Carregador", - "Input Current Limit": "Limite Corrente Entrada", - "VBUS Current Limit": "Limite Corrente VBUS", - "Voltage Limit": "Limite de Voltagem", - "Current Limit": "Limite Atual", - "Type": "Tipo", - "Max Voltage": "Voltagem Máxima", - "Max Current": "Corrente Máxima", - "Multimedia Clock Rates": "Frequências Multimídia", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Rede", - "Type: Wi-Fi": "Tipo: Wi-Fi", - "Press Y to show password": "Pressione Y para exibir a senha", - "Type: Ethernet": "Tipo: Ethernet", - "Type: Not connected": "Tipo: Não conectado", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Elementos   Descer   Subir", - "Transparent": "Transparente", - "Opaque": "Opaco", - "Alpha": "Alfa", - "Pretty": "Bonito", - "Compact": "Compacto", - "FileSafe": "Seguro", - "Day+Time": "Dia+Hora", - "Date+Time(s)": "Data+Hora(s)", - "Date+Time AM/PM": "Data+Hora AM/PM", - "Date+Time(s) AM/PM": "Data+Hora(s) AM/PM", - "Date+Time EU": "Data+Hora EU", - "Date+Time EU AM/PM": "Data+Hora EU AM/PM", - "Date+Time(s) EU AM/PM": "Data+Hora(s) EU AM/PM", - "Date+Time ISO": "Data+Hora ISO", - "Time 24h": "Hora 24h", - "Time AM/PM": "Hora AM/PM", - "Time(s) 24h": "Hora(s) 24h", - "Time(s) AM/PM": "Hora(s) AM/PM", - "Date US": "Data US", - "Date EU": "Data EU", - "Date ISO": "Data ISO", - "Date Short": "Data Abreviada", - "DTC Format": "Formato DTC", - "Toggles": "Alternar", - "Info": "Informações", - "Disable Screenshots": "Desativar Capturas", - "Real Freqs": "Frequências Reais", - "Deltas": "Deltas", - "Target Freqs": "Frequências Alvo", - "FPS": "FPS", - "RES": "RES", - "Read Speed": "Velocidade de Leitura", - "Real Frequencies": "Frequências Reais", - "Real Voltages": "Voltagens Reais", - "Full CPU": "CPU Completa", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Resolução Completa", - "SOC Voltage": "Voltagem do SOC", - "RAM Load CPU/GPU": "Carga na CPU/GPU", - "Use DTC Symbol": "Usar Símbolo DTC", - "Use Dynamic Colors": "Usar Cores Dinâmicas", - "Sleep Exit": "Sair do Repouso", - "Configuration": "Configuração", - "Refresh Rate": "Taxa de Atualização", - "Frame Padding": "Preenc. de Quadro", - " Font Size": " Tamanho da Fonte", - "Font Sizes": "Tamanho das Fontes", - "Handheld Font Size": "Modo Portátil", - "Docked Font Size": "Modo Dock", - "Black": "Preto", - "Dark Gray": "Cinza Escuro", - "Gray": "Cinza", - "Light Gray": "Cinza Claro", - "Silver": "Prata", - "White": "Branco", - "Dark Red": "Vermelho Escuro", - "Red": "Vermelho", - "Light Red": "LVermelho Claro", - "Pink": "Rosa", - "Dark Green": "Verde Escuro", - "Green": "Verde", - "Lime Green": "Verde Limão", - "Light Green": "Verde Claro", - "Dark Blue": "Azul Escuro", - "Blue": "Azul", - "Light Blue": "Azul Claro", - "Sky Blue": "Azul Céu", - "Dark Purple": "Roxo Escuro", - "Purple": "Roxo", - "Light Purple": "Roxo Claro", - "Violet": "Violeta", - "Orange": "Laranja", - "Yellow": "Amarelo", - "Light Yellow": "Amarelo Claro", - "Teal": "Verde Azulado", - "Cyan": "Ciano", - "Light Cyan": "Ciano Claro", - "Magenta": "Magenta", - "Hot Pink": "Rosa Choque", - "Brown": "Marrom", - "Light Brown": "Marrom Claro", - "Colors": "Cores", - "Background Color": "Cor de Fundo", - "Background Alpha": "Opacidade", - "Focus Color": "Cor em Foco", - "Focus Alpha": "Alfa em Foco", - "Text Color": "Cor do Texto", - "Border": "Borda", - "Dashed Line": "Linha Tracejada", - "Max FPS Text": "Texto Máx. FPS", - "Min FPS Text": "Texto Min. FPS", - "Main Line": "Linha Principal", - "Rounded Line": "Linha Arredondada", - "Perfect Line": "Linha Perfeita", - " Color": " Cor", - " Alpha": " Alfa", - "Category Color": "Cor da Categoria", - "Category Color 1": "Cor Categoria 1", - "Category Color 2": "Cor Categoria 2", - "Separator Color": "Cor do Separador", - "Elements": "Elementos", - "Text Alignment": "Alinhamento do Texto", - "Vertical Position": "Posição Vertical", - "Horizontal Position": "Posição Horizontal", - "Left": "Esquerdo", - "Right": "Direito", - "Top": "Topo", - "Center": "Centro", - "Bottom": "Baixo", - "FPS Counter Color":"Cor Contador FPS", - "FPS Counter Alpha":"Opac. Contador FPS", - "Border Color":"Cor da Borda", - "Dashed Line Color":"Cor Linha Trac.", - "Dashed Line Alpha":"Opac. Linha Trac.", - "Max FPS Text Color":"Cor Texto FPS Máx.", - "Min FPS Text Color":"Cor Texto FPS Min.", - "Main Line Color":"Cor Linha Principal", - "Rounded Line Color":"Cor Linha Arrend.", - "Perfect Line Color":"Cor Linha Perfeita" -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/ru.json b/Source/Horizon-OC-Monitor (deprecated)/lang/ru.json deleted file mode 100644 index 841b0b75..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/ru.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Режимы", - "Modes   Configure": "Режимы   Настроить", - "Full": "Полный", - "Mini": "Мини", - "Micro": "Микро", - "FPS Graph": "График FPS", - "FPS Counter": "Счётчик FPS", - "Game Resolutions": "Разрешения игры", - "Other": "Прочее", - "Battery/Charger": "Аккумулятор/Зарядка", - "Miscellaneous": "Разное", - "CPU Usage": "Загрузка CPU", - "GPU Usage": "Загрузка GPU", - "RAM Usage": "Загрузка RAM", - "Target Frequency": "Целевая частота", - "Real Frequency": "Реальная частота", - "Core 0 ": "Ядро 0 ", - "Core 1 ": "Ядро 1 ", - "Core 2 ": "Ядро 2 ", - "Core 3 ": "Ядро 3 ", - "Load": "Нагрузка", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Всего\nПриложение\nАпплет\nСистема\nСистема (небезопасно)", - "Board": "Плата", - "Battery Power Flow": "Поток энергии аккумулятора", - "\nTemperatures": "\nТемпературы", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Уровень вращения вентилятора", - "Game": "Игра", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Разрешения ", - "Read Speed ": "Скорость чтения ", - "Press ": "Нажмите ", - " to Exit": " для выхода", - "Depth": "Глубина", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "Игра не запущена\nили несовместима.", - "Battery Stats": "Статистика аккумулятора", - "Actual Capacity": "Фактическая ёмкость", - "Designed Capacity": "Номинальная ёмкость", - "Temperature": "Температура", - "Raw Charge": "Сырой заряд", - "Age": "Возраст", - "Voltage": "Напряжение", - "Current Flow": "Ток", - "Power Flow": "Мощность", - "Remaining Time": "Оставшееся время", - "Charger Stats": "Статистика зарядки", - "Input Current Limit": "Лимит входного тока", - "VBUS Current Limit": "Лимит тока VBUS", - "Voltage Limit": "Лимит напряжения", - "Current Limit": "Лимит тока", - "Type": "Тип", - "Max Voltage": "Макс. напряжение", - "Max Current": "Макс. ток", - "Multimedia Clock Rates": "Частоты мультимедиа", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Сеть", - "Type: Wi-Fi": "Тип: Wi-Fi", - "Press Y to show password": "Нажмите Y, чтобы показать пароль", - "Type: Ethernet": "Тип: Ethernet", - "Type: Not connected": "Тип: Не подключено", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Элементы   Вниз   Вверх", - "Transparent": "Прозрачный", - "Opaque": "Непрозрачный", - "Alpha": "Альфа", - "Pretty": "Красивый", - "Compact": "Компактный", - "FileSafe": "FileSafe", - "Day+Time": "День+Время", - "Date+Time(s)": "Дата+Время(с)", - "Date+Time AM/PM": "Дата+Время AM/PM", - "Date+Time(s) AM/PM": "Дата+Время(с) AM/PM", - "Date+Time EU": "Дата+Время EU", - "Date+Time EU AM/PM": "Дата+Время EU AM/PM", - "Date+Time(s) EU AM/PM": "Дата+Время(с) EU AM/PM", - "Date+Time ISO": "Дата+Время ISO", - "Time 24h": "Время 24ч", - "Time AM/PM": "Время AM/PM", - "Time(s) 24h": "Время(с) 24ч", - "Time(s) AM/PM": "Время(с) AM/PM", - "Date US": "Дата US", - "Date EU": "Дата EU", - "Date ISO": "Дата ISO", - "Date Short": "Краткая дата", - "DTC Format": "Формат DTC", - "Toggles": "Переключатели", - "Info": "Показать информацию", - "Disable Screenshots": "Отключить скриншоты", - "Real Freqs": "Реальные частоты", - "Deltas": "Дельты", - "Target Freqs": "Целевые частоты", - "FPS": "FPS", - "RES": "РАЗР.", - "Read Speed": "Скорость чтения", - "Real Frequencies": "Реальные частоты", - "Real Voltages": "Реальные напряжения", - "Full CPU": "Полный CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Полное разрешение", - "SOC Voltage": "Напряжение SOC", - "RAM Load CPU/GPU": "Нагрузка RAM CPU/GPU", - "Use DTC Symbol": "Использовать символ DTC", - "Use Dynamic Colors": "Использовать динамические цвета", - "Sleep Exit": "Выход из сна", - "Configuration": "Конфигурация", - "Refresh Rate": "Частота обновления", - "Frame Padding": "Отступ кадра", - " Font Size": " Размер шрифта", - "Font Sizes": "Размеры шрифта", - "Handheld Font Size": "Размер шрифта в портативном режиме", - "Docked Font Size": "Размер шрифта в док-режиме", - "Black": "Чёрный", - "Dark Gray": "Тёмно-серый", - "Gray": "Серый", - "Light Gray": "Светло-серый", - "Silver": "Серебряный", - "White": "Белый", - "Dark Red": "Тёмно-красный", - "Red": "Красный", - "Light Red": "Светло-красный", - "Pink": "Розовый", - "Dark Green": "Тёмно-зелёный", - "Green": "Зелёный", - "Lime Green": "Лаймовый", - "Light Green": "Светло-зелёный", - "Dark Blue": "Тёмно-синий", - "Blue": "Синий", - "Light Blue": "Светло-синий", - "Sky Blue": "Небесно-голубой", - "Dark Purple": "Тёмно-фиолетовый", - "Purple": "Фиолетовый", - "Light Purple": "Светло-фиолетовый", - "Violet": "Фиолетовый", - "Orange": "Оранжевый", - "Yellow": "Жёлтый", - "Light Yellow": "Светло-жёлтый", - "Teal": "Бирюзовый", - "Cyan": "Голубой", - "Light Cyan": "Светло-голубой", - "Magenta": "Пурпурный", - "Hot Pink": "Ярко-розовый", - "Brown": "Коричневый", - "Light Brown": "Светло-коричневый", - "Colors": "Цвета", - "Background Color": "Цвет фона", - "Background Alpha": "Прозрачность фона", - "Focus Color": "Цвет фокуса", - "Focus Alpha": "Прозрачность фокуса", - "Text Color": "Цвет текста", - "Border": "Граница", - "Dashed Line": "Пунктирная линия", - "Max FPS Text": "Текст макс. FPS", - "Min FPS Text": "Текст мин. FPS", - "Main Line": "Основная линия", - "Rounded Line": "Скруглённая линия", - "Perfect Line": "Идеальная линия", - " Color": " Цвет", - " Alpha": " Прозрачность", - "Category Color": "Цвет категории", - "Category Color 1": "Цвет категории 1", - "Category Color 2": "Цвет категории 2", - "Separator Color": "Цвет разделителя", - "Elements": "Элементы", - "Text Alignment": "Выравнивание текста", - "Vertical Position": "Вертикальная позиция", - "Horizontal Position": "Горизонтальная позиция", - "Left": "Слева", - "Right": "Справа", - "Top": "Сверху", - "Center": "По центру", - "Bottom": "Снизу", - "FPS Counter Color": "Цвет счётчика FPS", - "FPS Counter Alpha": "Прозрачность счётчика FPS", - "Border Color": "Цвет границы", - "Dashed Line Color": "Цвет пунктирной линии", - "Dashed Line Alpha": "Прозрачность пунктирной линии", - "Max FPS Text Color": "Цвет текста макс. FPS", - "Min FPS Text Color": "Цвет текста мин. FPS", - "Main Line Color": "Цвет основной линии", - "Rounded Line Color": "Цвет скруглённой линии", - "Perfect Line Color": "Цвет идеальной линии" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/uk.json b/Source/Horizon-OC-Monitor (deprecated)/lang/uk.json deleted file mode 100644 index c41c1beb..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/uk.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "Режими", - "Modes   Configure": "Режими   Налаштувати", - "Full": "Повний", - "Mini": "Міні", - "Micro": "Мікро", - "FPS Graph": "Графік FPS", - "FPS Counter": "Лічильник FPS", - "Game Resolutions": "Роздільна здатність гри", - "Other": "Інше", - "Battery/Charger": "Акумулятор/Зарядка", - "Miscellaneous": "Різне", - "CPU Usage": "Завантаження CPU", - "GPU Usage": "Завантаження GPU", - "RAM Usage": "Завантаження RAM", - "Target Frequency": "Цільова частота", - "Real Frequency": "Реальна частота", - "Core 0 ": "Ядро 0 ", - "Core 1 ": "Ядро 1 ", - "Core 2 ": "Ядро 2 ", - "Core 3 ": "Ядро 3 ", - "Load": "Навантаження", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "Всього\nДодаток\nАплет\nСистема\nСистема (небезпечно)", - "Board": "Плата", - "Battery Power Flow": "Потік енергії акумулятора", - "\nTemperatures": "\nТемператури", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "Рівень обертання вентилятора", - "Game": "Гра", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "Роздільна здатність ", - "Read Speed ": "Швидкість зчитування ", - "Press ": "Натисніть ", - " to Exit": " для виходу", - "Depth": "Глибина", - "Viewport": "Viewport", - "Game is not running\nor it's incompatible.": "Гра не запущена\nабо несумісна.", - "Battery Stats": "Статистика акумулятора", - "Actual Capacity": "Фактична ємність", - "Designed Capacity": "Номінальна ємність", - "Temperature": "Температура", - "Raw Charge": "Сирий заряд", - "Age": "Вік", - "Voltage": "Напруга", - "Current Flow": "Струм", - "Power Flow": "Потужність", - "Remaining Time": "Залишковий час", - "Charger Stats": "Статистика зарядки", - "Input Current Limit": "Ліміт вхідного струму", - "VBUS Current Limit": "Ліміт струму VBUS", - "Voltage Limit": "Ліміт напруги", - "Current Limit": "Ліміт струму", - "Type": "Тип", - "Max Voltage": "Макс. напруга", - "Max Current": "Макс. струм", - "Multimedia Clock Rates": "Частоти мультимедіа", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "Мережа", - "Type: Wi-Fi": "Тип: Wi-Fi", - "Press Y to show password": "Натисніть Y, щоб показати пароль", - "Type: Ethernet": "Тип: Ethernet", - "Type: Not connected": "Тип: Не підключено", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "Елементи   Вниз   Вгору", - "Transparent": "Прозорий", - "Opaque": "Непрозорий", - "Alpha": "Альфа", - "Pretty": "Красивий", - "Compact": "Компактний", - "FileSafe": "FileSafe", - "Day+Time": "День+Час", - "Date+Time(s)": "Дата+Час(с)", - "Date+Time AM/PM": "Дата+Час AM/PM", - "Date+Time(s) AM/PM": "Дата+Час(с) AM/PM", - "Date+Time EU": "Дата+Час EU", - "Date+Time EU AM/PM": "Дата+Час EU AM/PM", - "Date+Time(s) EU AM/PM": "Дата+Час(с) EU AM/PM", - "Date+Time ISO": "Дата+Час ISO", - "Time 24h": "Час 24год", - "Time AM/PM": "Час AM/PM", - "Time(s) 24h": "Час(с) 24год", - "Time(s) AM/PM": "Час(с) AM/PM", - "Date US": "Дата US", - "Date EU": "Дата EU", - "Date ISO": "Дата ISO", - "Date Short": "Коротка дата", - "DTC Format": "Формат DTC", - "Toggles": "Перемикачі", - "Info": "Показати інформацію", - "Disable Screenshots": "Вимкнути знімки екрана", - "Real Freqs": "Реальні частоти", - "Deltas": "Дельти", - "Target Freqs": "Цільові частоти", - "FPS": "FPS", - "RES": "РОЗД.", - "Read Speed": "Швидкість зчитування", - "Real Frequencies": "Реальні частоти", - "Real Voltages": "Реальні напруги", - "Full CPU": "Повний CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "Повна роздільна здатність", - "SOC Voltage": "Напруга SOC", - "RAM Load CPU/GPU": "Навантаження RAM CPU/GPU", - "Use DTC Symbol": "Використовувати символ DTC", - "Use Dynamic Colors": "Використовувати динамічні кольори", - "Sleep Exit": "Вихід зі сну", - "Configuration": "Конфігурація", - "Refresh Rate": "Частота оновлення", - "Frame Padding": "Відступ кадру", - " Font Size": " Розмір шрифту", - "Font Sizes": "Розміри шрифту", - "Handheld Font Size": "Розмір шрифту в портативному режимі", - "Docked Font Size": "Розмір шрифту в док-режимі", - "Black": "Чорний", - "Dark Gray": "Темно-сірий", - "Gray": "Сірий", - "Light Gray": "Світло-сірий", - "Silver": "Сріблястий", - "White": "Білий", - "Dark Red": "Темно-червоний", - "Red": "Червоний", - "Light Red": "Світло-червоний", - "Pink": "Рожевий", - "Dark Green": "Темно-зелений", - "Green": "Зелений", - "Lime Green": "Лаймовий", - "Light Green": "Світло-зелений", - "Dark Blue": "Темно-синій", - "Blue": "Синій", - "Light Blue": "Світло-синій", - "Sky Blue": "Небесно-блакитний", - "Dark Purple": "Темно-фіолетовий", - "Purple": "Фіолетовий", - "Light Purple": "Світло-фіолетовий", - "Violet": "Фіолетовий", - "Orange": "Помаранчевий", - "Yellow": "Жовтий", - "Light Yellow": "Світло-жовтий", - "Teal": "Бірюзовий", - "Cyan": "Блакитний", - "Light Cyan": "Світло-блакитний", - "Magenta": "Пурпуровий", - "Hot Pink": "Яскраво-рожевий", - "Brown": "Коричневий", - "Light Brown": "Світло-коричневий", - "Colors": "Кольори", - "Background Color": "Колір фону", - "Background Alpha": "Прозорість фону", - "Focus Color": "Колір фокусу", - "Focus Alpha": "Прозорість фокусу", - "Text Color": "Колір тексту", - "Border": "Межа", - "Dashed Line": "Пунктирна лінія", - "Max FPS Text": "Текст макс. FPS", - "Min FPS Text": "Текст мін. FPS", - "Main Line": "Основна лінія", - "Rounded Line": "Закруглена лінія", - "Perfect Line": "Ідеальна лінія", - " Color": " Колір", - " Alpha": " Прозорість", - "Category Color": "Колір категорії", - "Category Color 1": "Колір категорії 1", - "Category Color 2": "Колір категорії 2", - "Separator Color": "Колір роздільника", - "Elements": "Елементи", - "Text Alignment": "Вирівнювання тексту", - "Vertical Position": "Вертикальна позиція", - "Horizontal Position": "Горизонтальна позиція", - "Left": "Зліва", - "Right": "Справа", - "Top": "Зверху", - "Center": "По центру", - "Bottom": "Знизу", - "FPS Counter Color": "Колір лічильника FPS", - "FPS Counter Alpha": "Прозорість лічильника FPS", - "Border Color": "Колір межі", - "Dashed Line Color": "Колір пунктирної лінії", - "Dashed Line Alpha": "Прозорість пунктирної лінії", - "Max FPS Text Color": "Колір тексту макс. FPS", - "Min FPS Text Color": "Колір тексту мін. FPS", - "Main Line Color": "Колір основної лінії", - "Rounded Line Color": "Колір закругленої лінії", - "Perfect Line Color": "Колір ідеальної лінії" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/zh-cn.json b/Source/Horizon-OC-Monitor (deprecated)/lang/zh-cn.json deleted file mode 100644 index df7d264a..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/zh-cn.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "模式", - "Modes   Configure": "模式   配置", - "Full": "完整", - "Mini": "迷你", - "Micro": "微型", - "FPS Graph": "FPS 图表", - "FPS Counter": "FPS 计数器", - "Game Resolutions": "游戏分辨率", - "Other": "其他", - "Battery/Charger": "电池/充电器", - "Miscellaneous": "杂项", - "CPU Usage": "CPU 使用率", - "GPU Usage": "GPU 使用率", - "RAM Usage": "RAM 使用率", - "Target Frequency": "目标频率", - "Real Frequency": "实际频率", - "Core 0 ": "核心 0 ", - "Core 1 ": "核心 1 ", - "Core 2 ": "核心 2 ", - "Core 3 ": "核心 3 ", - "Load": "负载", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "总计\n应用\n小程序\n系统\n系统(不安全)", - "Board": "主板", - "Battery Power Flow": "电池功率流", - "\nTemperatures": "\n温度", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "风扇转速级别", - "Game": "游戏", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "分辨率 ", - "Read Speed ": "读取速度 ", - "Press ": "按 ", - " to Exit": " 退出", - "Depth": "深度", - "Viewport": "视口", - "Game is not running\nor it's incompatible.": "游戏未运行\n或不兼容。", - "Battery Stats": "电池统计", - "Actual Capacity": "实际容量", - "Designed Capacity": "设计容量", - "Temperature": "温度", - "Raw Charge": "原始电量", - "Age": "寿命", - "Voltage": "电压", - "Current Flow": "电流", - "Power Flow": "功率", - "Remaining Time": "剩余时间", - "Charger Stats": "充电器统计", - "Input Current Limit": "输入电流限制", - "VBUS Current Limit": "VBUS 电流限制", - "Voltage Limit": "电压限制", - "Current Limit": "电流限制", - "Type": "类型", - "Max Voltage": "最大电压", - "Max Current": "最大电流", - "Multimedia Clock Rates": "多媒体时钟频率", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "网络", - "Type: Wi-Fi": "类型:Wi-Fi", - "Press Y to show password": "按 Y 显示密码", - "Type: Ethernet": "类型:以太网", - "Type: Not connected": "类型:未连接", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "元素   下移   上移", - "Transparent": "透明", - "Opaque": "不透明", - "Alpha": "透明度", - "Pretty": "美观", - "Compact": "紧凑", - "FileSafe": "文件安全", - "Day+Time": "日期+时间", - "Date+Time(s)": "日期+时间(秒)", - "Date+Time AM/PM": "日期+时间 AM/PM", - "Date+Time(s) AM/PM": "日期+时间(秒) AM/PM", - "Date+Time EU": "日期+时间 EU", - "Date+Time EU AM/PM": "日期+时间 EU AM/PM", - "Date+Time(s) EU AM/PM": "日期+时间(秒) EU AM/PM", - "Date+Time ISO": "日期+时间 ISO", - "Time 24h": "时间 24时", - "Time AM/PM": "时间 AM/PM", - "Time(s) 24h": "时间(秒) 24时", - "Time(s) AM/PM": "时间(秒) AM/PM", - "Date US": "日期 US", - "Date EU": "日期 EU", - "Date ISO": "日期 ISO", - "Date Short": "短日期", - "DTC Format": "DTC 格式", - "Toggles": "开关", - "Info": "显示信息", - "Disable Screenshots": "禁用截图", - "Real Freqs": "实际频率", - "Deltas": "差值", - "Target Freqs": "目标频率", - "FPS": "FPS", - "RES": "分辨率", - "Read Speed": "读取速度", - "Real Frequencies": "实际频率", - "Real Voltages": "实际电压", - "Full CPU": "完整 CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "完整分辨率", - "SOC Voltage": "SOC 电压", - "RAM Load CPU/GPU": "RAM 负载 CPU/GPU", - "Use DTC Symbol": "使用 DTC 符号", - "Use Dynamic Colors": "使用动态颜色", - "Sleep Exit": "退出睡眠", - "Configuration": "配置", - "Refresh Rate": "刷新率", - "Frame Padding": "帧填充", - " Font Size": " 字体大小", - "Font Sizes": "字体大小", - "Handheld Font Size": "手持模式字体大小", - "Docked Font Size": "底座模式字体大小", - "Black": "黑色", - "Dark Gray": "深灰", - "Gray": "灰色", - "Light Gray": "浅灰", - "Silver": "银色", - "White": "白色", - "Dark Red": "深红", - "Red": "红色", - "Light Red": "浅红", - "Pink": "粉红", - "Dark Green": "深绿", - "Green": "绿色", - "Lime Green": "酸橙绿", - "Light Green": "浅绿", - "Dark Blue": "深蓝", - "Blue": "蓝色", - "Light Blue": "浅蓝", - "Sky Blue": "天蓝", - "Dark Purple": "深紫", - "Purple": "紫色", - "Light Purple": "浅紫", - "Violet": "紫罗兰", - "Orange": "橙色", - "Yellow": "黄色", - "Light Yellow": "浅黄", - "Teal": "蓝绿", - "Cyan": "青色", - "Light Cyan": "浅青", - "Magenta": "品红", - "Hot Pink": "艳粉", - "Brown": "棕色", - "Light Brown": "浅棕", - "Colors": "颜色", - "Background Color": "背景颜色", - "Background Alpha": "背景透明度", - "Focus Color": "焦点颜色", - "Focus Alpha": "焦点透明度", - "Text Color": "文字颜色", - "Border": "边框", - "Dashed Line": "虚线", - "Max FPS Text": "最大 FPS 文字", - "Min FPS Text": "最小 FPS 文字", - "Main Line": "主线", - "Rounded Line": "圆角线", - "Perfect Line": "完美线", - " Color": " 颜色", - " Alpha": " 透明度", - "Category Color": "分类颜色", - "Category Color 1": "分类颜色 1", - "Category Color 2": "分类颜色 2", - "Separator Color": "分隔线颜色", - "Elements": "元素", - "Text Alignment": "文字对齐", - "Vertical Position": "垂直位置", - "Horizontal Position": "水平位置", - "Left": "左", - "Right": "右", - "Top": "上", - "Center": "中", - "Bottom": "下", - "FPS Counter Color": "FPS 计数器颜色", - "FPS Counter Alpha": "FPS 计数器透明度", - "Border Color": "边框颜色", - "Dashed Line Color": "虚线颜色", - "Dashed Line Alpha": "虚线透明度", - "Max FPS Text Color": "最大 FPS 文字颜色", - "Min FPS Text Color": "最小 FPS 文字颜色", - "Main Line Color": "主线颜色", - "Rounded Line Color": "圆角线颜色", - "Perfect Line Color": "完美线颜色" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/lang/zh-tw.json b/Source/Horizon-OC-Monitor (deprecated)/lang/zh-tw.json deleted file mode 100644 index ce8015e4..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/lang/zh-tw.json +++ /dev/null @@ -1,189 +0,0 @@ -{ - "Horizon OC Monitor": "Horizon OC Monitor", - "Modes": "模式", - "Modes   Configure": "模式   設定", - "Full": "完整", - "Mini": "迷你", - "Micro": "微型", - "FPS Graph": "FPS 圖表", - "FPS Counter": "FPS 計數器", - "Game Resolutions": "遊戲解析度", - "Other": "其他", - "Battery/Charger": "電池/充電器", - "Miscellaneous": "雜項", - "CPU Usage": "CPU 使用率", - "GPU Usage": "GPU 使用率", - "RAM Usage": "RAM 使用率", - "Target Frequency": "目標頻率", - "Real Frequency": "實際頻率", - "Core 0 ": "核心 0 ", - "Core 1 ": "核心 1 ", - "Core 2 ": "核心 2 ", - "Core 3 ": "核心 3 ", - "Load": "負載", - "Total\nApplication\nApplet\nSystem\nSystem Unsafe": "總計\n應用程式\n小程式\n系統\n系統(不安全)", - "Board": "主機板", - "Battery Power Flow": "電池功率流", - "\nTemperatures": "\n溫度", - "SoC\nPCB\nSkin": "SoC\nPCB\nSkin", - "Fan Rotation Level": "風扇轉速等級", - "Game": "遊戲", - "PFPS ": "PFPS ", - "FPS ": "FPS ", - "Resolutions ": "解析度 ", - "Read Speed ": "讀取速度 ", - "Press ": "按 ", - " to Exit": " 退出", - "Depth": "深度", - "Viewport": "視口", - "Game is not running\nor it's incompatible.": "遊戲未執行\n或不相容。", - "Battery Stats": "電池統計", - "Actual Capacity": "實際容量", - "Designed Capacity": "設計容量", - "Temperature": "溫度", - "Raw Charge": "原始電量", - "Age": "壽命", - "Voltage": "電壓", - "Current Flow": "電流", - "Power Flow": "功率", - "Remaining Time": "剩餘時間", - "Charger Stats": "充電器統計", - "Input Current Limit": "輸入電流限制", - "VBUS Current Limit": "VBUS 電流限制", - "Voltage Limit": "電壓限制", - "Current Limit": "電流限制", - "Type": "類型", - "Max Voltage": "最大電壓", - "Max Current": "最大電流", - "Multimedia Clock Rates": "多媒體時脈頻率", - "NVDEC": "NVDEC", - "NVENC": "NVENC", - "NVJPG": "NVJPG", - "Network": "網路", - "Type: Wi-Fi": "類型:Wi-Fi", - "Press Y to show password": "按 Y 顯示密碼", - "Type: Ethernet": "類型:乙太網路", - "Type: Not connected": "類型:未連線", - "CPU\nGPU\nRAM\nSOC\nPCB\nSKN": "CPU\nGPU\nRAM\nSOC\nPCB\nSKN", - "Elements   Move Down   Move Up": "元素   下移   上移", - "Transparent": "透明", - "Opaque": "不透明", - "Alpha": "透明度", - "Pretty": "美觀", - "Compact": "緊湊", - "FileSafe": "檔案安全", - "Day+Time": "日期+時間", - "Date+Time(s)": "日期+時間(秒)", - "Date+Time AM/PM": "日期+時間 AM/PM", - "Date+Time(s) AM/PM": "日期+時間(秒) AM/PM", - "Date+Time EU": "日期+時間 EU", - "Date+Time EU AM/PM": "日期+時間 EU AM/PM", - "Date+Time(s) EU AM/PM": "日期+時間(秒) EU AM/PM", - "Date+Time ISO": "日期+時間 ISO", - "Time 24h": "時間 24時", - "Time AM/PM": "時間 AM/PM", - "Time(s) 24h": "時間(秒) 24時", - "Time(s) AM/PM": "時間(秒) AM/PM", - "Date US": "日期 US", - "Date EU": "日期 EU", - "Date ISO": "日期 ISO", - "Date Short": "短日期", - "DTC Format": "DTC 格式", - "Toggles": "開關", - "Info": "顯示資訊", - "Disable Screenshots": "停用截圖", - "Real Freqs": "實際頻率", - "Deltas": "差值", - "Target Freqs": "目標頻率", - "FPS": "FPS", - "RES": "解析度", - "Read Speed": "讀取速度", - "Real Frequencies": "實際頻率", - "Real Voltages": "實際電壓", - "Full CPU": "完整 CPU", - "VDDQ": "VDDQ", - "VDD2": "VDD2", - "Full Resolution": "完整解析度", - "SOC Voltage": "SOC 電壓", - "RAM Load CPU/GPU": "RAM 負載 CPU/GPU", - "Use DTC Symbol": "使用 DTC 符號", - "Use Dynamic Colors": "使用動態顏色", - "Sleep Exit": "退出睡眠", - "Configuration": "設定", - "Refresh Rate": "更新率", - "Frame Padding": "畫面邊距", - " Font Size": " 字型大小", - "Font Sizes": "字型大小", - "Handheld Font Size": "掌機模式字型大小", - "Docked Font Size": "主機模式字型大小", - "Black": "黑色", - "Dark Gray": "深灰", - "Gray": "灰色", - "Light Gray": "淺灰", - "Silver": "銀色", - "White": "白色", - "Dark Red": "深紅", - "Red": "紅色", - "Light Red": "淺紅", - "Pink": "粉紅", - "Dark Green": "深綠", - "Green": "綠色", - "Lime Green": "萊姆綠", - "Light Green": "淺綠", - "Dark Blue": "深藍", - "Blue": "藍色", - "Light Blue": "淺藍", - "Sky Blue": "天空藍", - "Dark Purple": "深紫", - "Purple": "紫色", - "Light Purple": "淺紫", - "Violet": "紫羅蘭", - "Orange": "橙色", - "Yellow": "黃色", - "Light Yellow": "淺黃", - "Teal": "藍綠", - "Cyan": "青色", - "Light Cyan": "淺青", - "Magenta": "洋紅", - "Hot Pink": "熱粉", - "Brown": "棕色", - "Light Brown": "淺棕", - "Colors": "顏色", - "Background Color": "背景顏色", - "Background Alpha": "背景透明度", - "Focus Color": "焦點顏色", - "Focus Alpha": "焦點透明度", - "Text Color": "文字顏色", - "Border": "邊框", - "Dashed Line": "虛線", - "Max FPS Text": "最大 FPS 文字", - "Min FPS Text": "最小 FPS 文字", - "Main Line": "主線", - "Rounded Line": "圓角線", - "Perfect Line": "完美線", - " Color": " 顏色", - " Alpha": " 透明度", - "Category Color": "分類顏色", - "Category Color 1": "分類顏色 1", - "Category Color 2": "分類顏色 2", - "Separator Color": "分隔線顏色", - "Elements": "元素", - "Text Alignment": "文字對齊", - "Vertical Position": "垂直位置", - "Horizontal Position": "水平位置", - "Left": "左", - "Right": "右", - "Top": "上", - "Center": "中", - "Bottom": "下", - "FPS Counter Color": "FPS 計數器顏色", - "FPS Counter Alpha": "FPS 計數器透明度", - "Border Color": "邊框顏色", - "Dashed Line Color": "虛線顏色", - "Dashed Line Alpha": "虛線透明度", - "Max FPS Text Color": "最大 FPS 文字顏色", - "Min FPS Text Color": "最小 FPS 文字顏色", - "Main Line Color": "主線顏色", - "Rounded Line Color": "圓角線顏色", - "Perfect Line Color": "完美線顏色" -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/out/config/status-monitor/config.ini.template b/Source/Horizon-OC-Monitor (deprecated)/out/config/status-monitor/config.ini.template deleted file mode 100644 index a11d524b..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/out/config/status-monitor/config.ini.template +++ /dev/null @@ -1,127 +0,0 @@ -[status-monitor] -battery_avg_iir_filter=false -battery_time_left_refreshrate=60 -average_gpu_load=false -use_old_fps_average=false - -[full] -refresh_rate=1 -layer_width_align=left -show_real_freqs=true -show_deltas=true -show_target_freqs=true -show_fps=true -show_res=true -show_read_speed=true -use_dynamic_colors=true -disable_screenshots=false -separator_color=#888F -cat_color_1=#8FFF -cat_color_2=#8CFF -text_color=#FFFF - -[mini] -refresh_rate=1 -handheld_font_size=15 -docked_font_size=15 -spacing=8 -real_freqs=true -real_volts=true -show_full_cpu=false -show_full_res=true -show_fan_percentage=true -show_soc_voltage=false -use_dynamic_colors=true -show_vddq=false -show_vdd2=true -decimal_vdd2=false -show_dtc=true -use_dtc_symbol=true -dtc_format=%m-%d-%Y%H:%M:%S -show=DTC+BAT+CPU+GPU+RAM+TMP+FPS+RES -replace_MB_with_RAM_load=true -show_RAM_load_CPU_GPU=false -invert_battery_display=true -disable_screenshots=false -sleep_exit=false -frame_offset_x=10 -frame_offset_y=10 -frame_padding=10 -background_color=#0009 -focus_background_color=#000F -separator_color=#888F -cat_color=#2DFF -text_color=#FFFF - -[micro] -refresh_rate=1 -layer_height_align=top -handheld_font_size=15 -docked_font_size=15 -text_align=center -real_freqs=true -real_volts=true -show_full_cpu=false -show_full_res=false -show_soc_voltage=true -use_dynamic_colors=true -show_vddq=false -show_vdd2=true -decimal_vdd2=false -show_dtc=true -use_dtc_symbol=true -dtc_format=%H:%M:%S -show=FPS+CPU+GPU+RAM+SOC+BAT+DTC -replace_GB_with_RAM_load=true -invert_battery_display=false -disable_screenshots=false -sleep_exit=false -background_color=#0009 -separator_color=#888F -cat_color=#2DFF -text_color=#FFFF - -[fps-counter] -refresh_rate=30 -handheld_font_size=40 -docked_font_size=40 -use_integer_counter=false -disable_screenshots=false -frame_offset_x=10 -frame_offset_y=10 -frame_padding=10 -background_color=#0009 -focus_background_color=#000F -text_color=#8CFF - -[fps-graph] -refresh_rate=30 -show_info=false -use_dynamic_colors=true -disable_screenshots=false -frame_offset_x=10 -frame_offset_y=10 -frame_padding=10 -background_color=#0009 -focus_background_color=#000F -fps_counter_color=#888C -border_color=#2DFF -dashed_line_color=#8888 -main_line_color=#FFFF -rounded_line_color=#F0FF -perfect_line_color=#0C0F -max_fps_text_color=#FFFF -min_fps_text_color=#FFFF -text_color=#FFFF -cat_color=#0F0F - -[game_resolutions] -refresh_rate=10 -disable_screenshots=false -frame_offset_x=10 -frame_offset_y=10 -frame_padding=10 -background_color=#0009 -focus_background_color=#000F -cat_color=#8FFF -text_color=#FFFF diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/Utils.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/Utils.hpp deleted file mode 100644 index 466a86aa..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/Utils.hpp +++ /dev/null @@ -1,2538 +0,0 @@ -#pragma once -#define ALWAYS_INLINE inline __attribute__((always_inline)) -#include "SaltyNX.h" - -#include "Battery.hpp" -#include "audsnoop.h" -#include "Misc.hpp" -#include "max17050.h" -#include "tmp451.h" -#include "pwm.h" -#include -#include -#include - -// rgltr_services.cpp (no changes needed here—just compile it once) -#include -#include "rgltr.h" -#include "rgltr_services.h" // for extern Service g_rgltrSrv, etc. - - - -#if defined(__cplusplus) -extern "C" -{ -#endif - -#include - -#if defined(__cplusplus) -} -#endif - -#define NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD 0x80044715 -#define FieldDescriptor uint32_t -#define BASE_SNS_UOHM 5000 - -static bool fixHiding = false; -static bool fixForeground = false; - -//Common -bool isMariko = false; -Thread t0; -Thread t1; -Thread t2; -Thread t3; -Thread t4; -Thread t5; -Thread t6; -Thread t7; -uint64_t systemtickfrequency = 19200000; - -LEvent threadexit; -PwmChannelSession g_ICon; -const std::string folderpath = "sdmc:/switch/.overlays/"; - -// Use const string_view for paths to avoid string copying -constexpr const char* directoryPath = "sdmc:/config/status-monitor/"; -constexpr const char* configIniPath = "sdmc:/config/status-monitor/config.ini"; -constexpr const char* ultrahandConfigIniPath = "sdmc:/config/ultrahand/config.ini"; -constexpr const char* teslaConfigIniPath = "sdmc:/config/tesla/config.ini"; - -std::string filename; -std::string filepath; -std::string keyCombo = "ZL+ZR+DDOWN"; // default Ultrahand Menu combo - -//Misc2 -MmuRequest nvdecRequest; -MmuRequest nvencRequest; -MmuRequest nvjpgRequest; - -//Checks -Result nvCheck = 1; -Result i2cCheck = 1; -Result pwmCheck = 1; -Result tcCheck = 1; -Result Hinted = 1; -Result pmdmntCheck = 1; -Result psmCheck = 1; -Result audsnoopCheck = 1; -Result nvdecCheck = 1; -Result nvencCheck = 1; -Result nvjpgCheck = 1; -Result nifmCheck = 1; -Result hocclkCheck = 1; -Result pwmDutyCycleCheck = 1; - -//Wi-Fi -NifmInternetConnectionType NifmConnectionType = (NifmInternetConnectionType)-1; -NifmInternetConnectionStatus NifmConnectionStatus = (NifmInternetConnectionStatus)-1; -bool Nifm_showpass = false; -Result Nifm_internet_rc = -1; -Result Nifm_profile_rc = -1; -NifmNetworkProfileData_new Nifm_profile = {0}; - -//Multimedia engines -uint32_t NVDEC_Hz = 0; -uint32_t NVENC_Hz = 0; -uint32_t NVJPG_Hz = 0; - -//DSP -uint32_t DSP_Load_u = -1; - -//Battery -Service* psmService = 0; -BatteryChargeInfoFields _batteryChargeInfoFields = {0}; -float batCurrentAvg = 0; -float batVoltageAvg = 0; -float PowerConsumption = 0; -int16_t batTimeEstimate = -1; -float actualFullBatCapacity = 0; -float designedFullBatCapacity = 0; -bool batteryFiltered = false; -uint8_t batteryTimeLeftRefreshRate = 60; -int32_t BatteryTimeCache[120]; - -//Temperatures -float SOC_temperatureF = 0; -float PCB_temperatureF = 0; -int32_t skin_temperaturemiliC = 0; - -//CPU Usage -//uint64_t idletick0 = systemtickfrequency; -//uint64_t idletick1 = systemtickfrequency; -//uint64_t idletick2 = systemtickfrequency; -//uint64_t idletick3 = systemtickfrequency; - -std::atomic idletick0{systemtickfrequency}; -std::atomic idletick1{systemtickfrequency}; -std::atomic idletick2{systemtickfrequency}; -std::atomic idletick3{systemtickfrequency}; - - -//Frequency -uint32_t CPU_Hz = 0; -uint32_t GPU_Hz = 0; -uint32_t RAM_Hz = 0; - -//RAM Size -uint64_t RAM_Total_all_u = 0; -uint64_t RAM_Total_application_u = 0; -uint64_t RAM_Total_applet_u = 0; -uint64_t RAM_Total_system_u = 0; -uint64_t RAM_Total_systemunsafe_u = 0; -uint64_t RAM_Used_all_u = 0; -uint64_t RAM_Used_application_u = 0; -uint64_t RAM_Used_applet_u = 0; -uint64_t RAM_Used_system_u = 0; -uint64_t RAM_Used_systemunsafe_u = 0; - -//Fan -double Rotation_Duty = 0; - -//GPU Usage -FieldDescriptor fd = 0; -uint32_t GPU_Load_u = 0; -bool GPULoadPerFrame = true; - -//NX-FPS - -struct resolutionCalls { - uint16_t width; - uint16_t height; - uint16_t calls; -}; - -struct NxFpsSharedBlock { - 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; -std::atomic GameRunning{false}; -std::atomic check{true}; -std::atomic SaltySD{false}; -std::atomic realVoltsPolling{false}; -uintptr_t FPSaddress = 0; -uintptr_t FPSavgaddress = 0; -uint64_t PID = 0; -uint32_t FPS = 0xFE; -float FPSmin = 254; -float FPSmax = 0; -float FPSavg = 254; -float FPSavg_old = 254; -bool useOldFPSavg = false; -SharedMemory _sharedmemory = {}; -std::atomic SharedMemoryUsed{false}; -Handle remoteSharedMemory = 1; -uint64_t lastFrameNumber = 0; - -//Read real freqs from sys-clk sysmodule -uint32_t realCPU_Hz = 0; -uint32_t realGPU_Hz = 0; -uint32_t realRAM_Hz = 0; -uint32_t partLoad[HocClkPartLoad_EnumMax]; -uint32_t realCPU_mV = 0; -uint32_t realGPU_mV = 0; -uint32_t realVDD2_mV = 0; -uint32_t realVDDQ_mV = 0; -uint32_t realSOC_mV = 0; -uint8_t refreshRate = 0; - -//Read real temps from sys-clk sysmodule -int32_t realCPU_Temp = 0; -int32_t realGPU_Temp = 0; -u32 realPLLX_Temp = 0; -int32_t realRAM_Temp = 0; - -int compare (const void* elem1, const void* elem2) { - if ((((resolutionCalls*)(elem1))->calls) > (((resolutionCalls*)(elem2))->calls)) return -1; - else return 1; -} - -void LoadSharedMemoryAndRefreshRate() { - if (SaltySD_Connect()) - return; - - SaltySD_GetSharedMemoryHandle(&remoteSharedMemory); - SaltySD_GetDisplayRefreshRate(&refreshRate); - SaltySD_Term(); - - shmemLoadRemote(&_sharedmemory, remoteSharedMemory, 0x1000, Perm_Rw); - if (!shmemMap(&_sharedmemory)) - SharedMemoryUsed = true; - else FPS = 1234; -} - -void LoadSharedMemory() { - if (SaltySD_Connect()) - return; - - SaltySD_GetSharedMemoryHandle(&remoteSharedMemory); - SaltySD_Term(); - - shmemLoadRemote(&_sharedmemory, remoteSharedMemory, 0x1000, Perm_Rw); - if (!shmemMap(&_sharedmemory)) - SharedMemoryUsed = true; - else FPS = 1234; -} - -void searchSharedMemoryBlock(uintptr_t base) { - if (!base || !SharedMemoryUsed) { - NxFps = 0; - return; - } - - ptrdiff_t search_offset = 0; - const uintptr_t memory_end = base + 0x1000; - - while (search_offset < 0x1000) { - const uintptr_t current_addr = base + search_offset; - - // Ensure we don't read past the end of shared memory - if (current_addr + sizeof(NxFpsSharedBlock) > memory_end) { - break; - } - - NxFps = (NxFpsSharedBlock*)current_addr; - - // Add bounds checking and magic validation - if (NxFps && current_addr >= base && NxFps->MAGIC == 0x465053) { - return; - } - search_offset += 4; - } - NxFps = 0; -} - -//Check if SaltyNX is working -bool CheckPort() { - Handle saltysd; - - // Try up to 67 times with exponential backoff for better responsiveness - for (int i = 0; i < 50; i++) { - if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) { - svcCloseHandle(saltysd); - return true; - } - - // Progressive sleep - start fast, then slow down - //if (i < 10) { - // svcSleepThread(100'000); // 0.1ms for first 10 attempts - //} else if (i < 30) { - // svcSleepThread(500'000); // 0.5ms for next 20 attempts - //} else { - // svcSleepThread(1'000'000); // 1ms for remaining attempts - //} - } - - return false; -} - -Mutex mutex_Misc = {0}; - -void CheckIfGameRunning(void*) { - do { - mutexLock(&mutex_Misc); - if (!check && R_FAILED(pmdmntGetApplicationProcessId(&PID))) { - GameRunning = false; - check = true; - } - else if (!GameRunning && SharedMemoryUsed) { - const uintptr_t base = (uintptr_t)shmemGetAddr(&_sharedmemory); - searchSharedMemoryBlock(base); - if (NxFps) { - (NxFps->pluginActive) = false; - mutexUnlock(&mutex_Misc); // ← Fix: Unlock before return - if (leventWait(&threadexit, 100'000'000)) { - return; - } - mutexLock(&mutex_Misc); - if ((NxFps->pluginActive)) { - GameRunning = true; - check = false; - } - } - } - mutexUnlock(&mutex_Misc); - } while (!leventWait(&threadexit, 1'000'000'000)); -} - -// Utils.hpp or your relevant header -static constexpr size_t CACHE_ELEMENTS = sizeof(BatteryTimeCache) / sizeof(BatteryTimeCache[0]); - -Mutex mutex_BatteryChecker = {0}; -void BatteryChecker(void*) { - if (R_FAILED(psmCheck) || R_FAILED(i2cCheck)){ - return; - } - uint16_t data = 0; - float tempV = 0.0; - float tempA = 0.0; - size_t ArraySize = 10; - if (batteryFiltered) { - ArraySize = 1; - } - float* readingsAmp = new float[ArraySize]; - float* readingsVolt = new float[ArraySize]; - - Max17050ReadReg(MAX17050_AvgCurrent, &data); - tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; - for (size_t i = 0; i < ArraySize; i++) { - readingsAmp[i] = tempA; - } - Max17050ReadReg(MAX17050_AvgVCELL, &data); - tempV = 0.625 * (data >> 3); - for (size_t i = 0; i < ArraySize; i++) { - readingsVolt[i] = tempV; - } - if (!actualFullBatCapacity) { - Max17050ReadReg(MAX17050_FullCAP, &data); - actualFullBatCapacity = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; - } - if (!designedFullBatCapacity) { - Max17050ReadReg(MAX17050_DesignCap, &data); - designedFullBatCapacity = data * (BASE_SNS_UOHM / MAX17050_BOARD_SNS_RESISTOR_UOHM) / MAX17050_BOARD_CGAIN; - } - if (readingsAmp[0] >= 0) { - batTimeEstimate = -1; - } - else { - Max17050ReadReg(MAX17050_TTE, &data); - float batteryTimeEstimateInMinutes = (5.625 * data) / 60; - if (batteryTimeEstimateInMinutes > (99.0*60.0)+59.0) { - batTimeEstimate = (99*60)+59; - } - else batTimeEstimate = (int16_t)batteryTimeEstimateInMinutes; - } - - size_t counter = 0; - uint64_t tick_TTE = svcGetSystemTick(); - uint64_t nanoseconds = 1000; - do { - mutexLock(&mutex_BatteryChecker); - const uint64_t startTick = svcGetSystemTick(); - - psmGetBatteryChargeInfoFields(psmService, &_batteryChargeInfoFields); - - // Calculation is based on Hekate's max17050.c - // Source: https://github.com/CTCaer/hekate/blob/master/bdk/power/max17050.c - - if (!batteryFiltered) { - Max17050ReadReg(MAX17050_Current, &data); - tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; - Max17050ReadReg(MAX17050_VCELL, &data); - tempV = 0.625 * (data >> 3); - } else { - Max17050ReadReg(MAX17050_AvgCurrent, &data); - tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; - Max17050ReadReg(MAX17050_AvgVCELL, &data); - tempV = 0.625 * (data >> 3); - } - - if (tempA && tempV) { - readingsAmp[counter % ArraySize] = tempA; - readingsVolt[counter % ArraySize] = tempV; - counter++; - } - - float batCurrent = 0.0; - float batVoltage = 0.0; - float batPowerAvg = 0.0; - for (size_t x = 0; x < ArraySize; x++) { - batCurrent += readingsAmp[x]; - batVoltage += readingsVolt[x]; - batPowerAvg += (readingsAmp[x] * readingsVolt[x]) / 1'000; - } - batCurrent /= ArraySize; - batVoltage /= ArraySize; - batCurrentAvg = batCurrent; - batVoltageAvg = batVoltage; - batPowerAvg /= ArraySize * 1000; - PowerConsumption = batPowerAvg; - - if (batCurrentAvg >= 0) { - batTimeEstimate = -1; - } - else { - static float batteryTimeEstimateInMinutes = 0; - Max17050ReadReg(MAX17050_TTE, &data); - batteryTimeEstimateInMinutes = (5.625 * data) / 60; - if (batteryTimeEstimateInMinutes > (99.0*60.0)+59.0) { - batteryTimeEstimateInMinutes = (99.0*60.0)+59.0; - } - static int itr = 0; - const int cacheElements = (sizeof(BatteryTimeCache) / sizeof(BatteryTimeCache[0])); - BatteryTimeCache[itr++ % cacheElements] = (int32_t)batteryTimeEstimateInMinutes; - const uint64_t new_tick_TTE = svcGetSystemTick(); - if (armTicksToNs(new_tick_TTE - tick_TTE) / 1'000'000'000 >= batteryTimeLeftRefreshRate) { - const size_t to_divide = itr < cacheElements ? itr : cacheElements; - batTimeEstimate = (int16_t)(std::accumulate(&BatteryTimeCache[0], &BatteryTimeCache[to_divide], 0) / to_divide); - tick_TTE = new_tick_TTE; - } - } - - mutexUnlock(&mutex_BatteryChecker); - nanoseconds = armTicksToNs(svcGetSystemTick() - startTick); - if (nanoseconds < 1'000'000'000 / 2) { - nanoseconds = (1'000'000'000 / 2) - nanoseconds; - } else { - nanoseconds = 1000; - } - } while(!leventWait(&threadexit, nanoseconds)); - - batTimeEstimate = -1; - _batteryChargeInfoFields = {0}; - memset(BatteryTimeCache, 0, sizeof(BatteryTimeCache)); - delete[] readingsAmp; - delete[] readingsVolt; -} - - -void StartBatteryThread() { - //if (!skip) { - // threadWaitForExit(&t7); - // threadClose(&t7); - // leventClear(&threadexit); - //} - leventClear(&threadexit); - threadCreate(&t7, BatteryChecker, NULL, NULL, 0x2000, 0x3F, 3); - threadStart(&t7); -} - -void CloseBatteryThread() { - leventSignal(&threadexit); - threadWaitForExit(&t7); - threadClose(&t7); -} - - - -void gpuLoadThread(void*) { - #define gpu_samples_average 8 - uint32_t gpu_load_array[gpu_samples_average] = {0}; - size_t i = 0; - if (!GPULoadPerFrame && R_SUCCEEDED(nvCheck)) do { - u32 temp; - if (R_SUCCEEDED(nvIoctl(fd, NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD, &temp))) { - gpu_load_array[i++ % gpu_samples_average] = temp; - GPU_Load_u = std::accumulate(&gpu_load_array[0], &gpu_load_array[gpu_samples_average], 0) / gpu_samples_average; - } - } while(!leventWait(&threadexit, 16'666'000)); -} - -std::string getVersionString() { - char buf[0x100] = ""; // 256 bytes — safe for any expected version string - Result rc = hocclkIpcGetVersionString(buf, sizeof(buf)); - if (R_FAILED(rc) || buf[0] == '\0') { - return "unknown"; - } - return std::string(buf); -} - - -bool usingEOS() { - const std::string versionString = getVersionString(); - return versionString.find("eos") != std::string::npos; -} - -// === ULTRA-FAST VOLTAGE READING === -static constexpr PowerDomainId domains[] = { - PcvPowerDomainId_Max77621_Cpu, // [0] CPU - PcvPowerDomainId_Max77621_Gpu, // [1] GPU - PcvPowerDomainId_Max77812_Dram, // [2] VDD2 (EMC/DRAM) - PcvPowerDomainId_Max77620_Sd0, // [3] SOC - PcvPowerDomainId_Max77620_Sd1 // [4] VDDQ -}; - - -// Stuff that doesn't need multithreading -void Misc(void*) { - const uint64_t timeout_ns = TeslaFPS < 10 ? (1'000'000'000 / TeslaFPS) : 100'000'000; - const bool isUsingEOS = usingEOS(); - - // Initialize voltage reading if needed - bool canReadVoltages = false; - if (!isUsingEOS && realVoltsPolling) { - canReadVoltages = R_SUCCEEDED(rgltrInitialize()); - if (!canReadVoltages) { - realVoltsPolling = false; - } - } - - do { - mutexLock(&mutex_Misc); - - // Get sys-clk data - if (R_SUCCEEDED(hocclkCheck)) { - HocClkContext hocclkCTX; - if (R_SUCCEEDED(hocclkIpcGetCurrentContext(&hocclkCTX))) { - realCPU_Hz = hocclkCTX.realFreqs[HocClkModule_CPU]; - realGPU_Hz = hocclkCTX.realFreqs[HocClkModule_GPU]; - realRAM_Hz = hocclkCTX.realFreqs[HocClkModule_MEM]; - partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC]; - partLoad[HocClkPartLoad_EMCCpu] = hocclkCTX.partLoad[HocClkPartLoad_EMCCpu]; - partLoad[HocClkPartLoad_RamBWAll] = hocclkCTX.partLoad[HocClkPartLoad_RamBWAll]; - partLoad[HocClkPartLoad_RamBWCpu] = hocclkCTX.partLoad[HocClkPartLoad_RamBWCpu]; - partLoad[HocClkPartLoad_RamBWGpu] = hocclkCTX.partLoad[HocClkPartLoad_RamBWGpu]; - partLoad[HocClkPartLoad_RamBWPeak] = hocclkCTX.partLoad[HocClkPartLoad_RamBWPeak]; - realCPU_Temp = hocclkCTX.temps[HocClkThermalSensor_CPU]; - realGPU_Temp = hocclkCTX.temps[HocClkThermalSensor_GPU]; - realPLLX_Temp = hocclkCTX.temps[HocClkThermalSensor_PLLX]; - realRAM_Temp = hocclkCTX.temps[HocClkThermalSensor_MEM]; - - realCPU_mV = hocclkCTX.voltages[HocClkVoltage_CPU]; - realGPU_mV = hocclkCTX.voltages[HocClkVoltage_GPU]; - realSOC_mV = hocclkCTX.voltages[HocClkVoltage_SOC]; - realVDD2_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDD2]; - realVDDQ_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDDQ]; - CPU_Hz = hocclkCTX.freqs[HocClkModule_CPU]; - GPU_Hz = hocclkCTX.freqs[HocClkModule_GPU]; - RAM_Hz = hocclkCTX.freqs[HocClkModule_MEM]; - } - } - - - // Temperatures - if (R_SUCCEEDED(i2cCheck)) { - Tmp451GetSocTemp(&SOC_temperatureF); - Tmp451GetPcbTemp(&PCB_temperatureF); - } - if (R_SUCCEEDED(tcCheck)) { - tcGetSkinTemperatureMilliC(&skin_temperaturemiliC); - } - - // RAM Memory Used - if (R_SUCCEEDED(Hinted)) { - svcGetSystemInfo(&RAM_Total_application_u, 0, INVALID_HANDLE, 0); - svcGetSystemInfo(&RAM_Total_applet_u, 0, INVALID_HANDLE, 1); - svcGetSystemInfo(&RAM_Total_system_u, 0, INVALID_HANDLE, 2); - svcGetSystemInfo(&RAM_Total_systemunsafe_u, 0, INVALID_HANDLE, 3); - svcGetSystemInfo(&RAM_Used_application_u, 1, INVALID_HANDLE, 0); - svcGetSystemInfo(&RAM_Used_applet_u, 1, INVALID_HANDLE, 1); - svcGetSystemInfo(&RAM_Used_system_u, 1, INVALID_HANDLE, 2); - svcGetSystemInfo(&RAM_Used_systemunsafe_u, 1, INVALID_HANDLE, 3); - } - - // Fan - if (R_SUCCEEDED(pwmCheck)) { - double temp = 0; - if (R_SUCCEEDED(pwmChannelSessionGetDutyCycle(&g_ICon, &temp))) { - temp *= 10; - temp = trunc(temp); - temp /= 10; - Rotation_Duty = 100.0 - temp; - if (Rotation_Duty <= 0) { - Rotation_Duty = 0.0000001; - } - } - } - - // GPU Load - if (R_SUCCEEDED(nvCheck) && GPULoadPerFrame) { - nvIoctl(fd, NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD, &GPU_Load_u); - } - - // FPS - with proper null checks - if (GameRunning) { - if (NxFps && SharedMemoryUsed) { - FPS = NxFps->FPS; - const size_t element_count = sizeof(NxFps->FPSticks) / sizeof(NxFps->FPSticks[0]); - FPSavg_old = static_cast(systemtickfrequency) / - (std::accumulate(&NxFps->FPSticks[0], &NxFps->FPSticks[element_count], 0.0f) / element_count); - - const float FPS_in = static_cast(FPS); - if (FPSavg_old >= (FPS_in - 0.25f) && FPSavg_old <= (FPS_in + 0.25f)) { - FPSavg = FPS_in; - } else { - FPSavg = FPSavg_old; - } - - lastFrameNumber = NxFps->frameNumber; - - if (FPSavg > FPSmax) FPSmax = FPSavg; - if (FPSavg < FPSmin) FPSmin = FPSavg; - } - } else { - FPSavg = 254; - FPSmin = 254; - FPSmax = 0; - } - - mutexUnlock(&mutex_Misc); - - } while (!leventWait(&threadexit, timeout_ns)); - - // Cleanup voltage reading if initialized - if (canReadVoltages) { - rgltrExit(); - } -} - -void Misc2(void*) { - u32 dummy = 0; - do { - //DSP - if (R_SUCCEEDED(audsnoopCheck)) audsnoopGetDspUsage(&DSP_Load_u); - - //Multimedia clock rates - if (R_SUCCEEDED(nvdecCheck)) mmuRequestGet(&nvdecRequest, &NVDEC_Hz); - if (R_SUCCEEDED(nvencCheck)) mmuRequestGet(&nvencRequest, &NVENC_Hz); - if (R_SUCCEEDED(nvjpgCheck)) mmuRequestGet(&nvjpgRequest, &NVJPG_Hz); - - if (R_SUCCEEDED(nifmCheck)) { - //u32 dummy = 0; - Nifm_internet_rc = nifmGetInternetConnectionStatus(&NifmConnectionType, &dummy, &NifmConnectionStatus); - if (!Nifm_internet_rc && (NifmConnectionType == NifmInternetConnectionType_WiFi)) - Nifm_profile_rc = nifmGetCurrentNetworkProfile((NifmNetworkProfileData*)&Nifm_profile); - } - } while (!leventWait(&threadexit, 100'000'000)); -} - -void Misc3(void*) { - const bool isUsingEOS = usingEOS(); - - // Initialize voltage reading if needed - bool canReadVoltages = false; - if (!isUsingEOS && realVoltsPolling) { - canReadVoltages = R_SUCCEEDED(rgltrInitialize()); - if (!canReadVoltages) { - realVoltsPolling = false; - } - } - - do { - mutexLock(&mutex_Misc); - - // Get sys-clk data - if (R_SUCCEEDED(hocclkCheck)) { - HocClkContext hocclkCTX; - if (R_SUCCEEDED(hocclkIpcGetCurrentContext(&hocclkCTX))) { - partLoad[HocClkPartLoad_EMC] = hocclkCTX.partLoad[HocClkPartLoad_EMC]; - partLoad[HocClkPartLoad_EMCCpu] = hocclkCTX.partLoad[HocClkPartLoad_EMCCpu]; - partLoad[HocClkPartLoad_RamBWAll] = hocclkCTX.partLoad[HocClkPartLoad_RamBWAll]; - partLoad[HocClkPartLoad_RamBWCpu] = hocclkCTX.partLoad[HocClkPartLoad_RamBWCpu]; - partLoad[HocClkPartLoad_RamBWGpu] = hocclkCTX.partLoad[HocClkPartLoad_RamBWGpu]; - partLoad[HocClkPartLoad_RamBWPeak] = hocclkCTX.partLoad[HocClkPartLoad_RamBWPeak]; - - realCPU_Temp = hocclkCTX.temps[HocClkThermalSensor_CPU]; - realGPU_Temp = hocclkCTX.temps[HocClkThermalSensor_GPU]; - realPLLX_Temp = hocclkCTX.temps[HocClkThermalSensor_PLLX]; - realRAM_Temp = hocclkCTX.temps[HocClkThermalSensor_MEM]; - - realCPU_mV = hocclkCTX.voltages[HocClkVoltage_CPU]; - realGPU_mV = hocclkCTX.voltages[HocClkVoltage_GPU]; - realSOC_mV = hocclkCTX.voltages[HocClkVoltage_SOC]; - realVDD2_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDD2]; - realVDDQ_mV = hocclkCTX.voltages[HocClkVoltage_EMCVDDQ]; - - } - } - - - // Temperatures - if (R_SUCCEEDED(i2cCheck)) { - Tmp451GetSocTemp(&SOC_temperatureF); - Tmp451GetPcbTemp(&PCB_temperatureF); - } - if (R_SUCCEEDED(tcCheck)) { - tcGetSkinTemperatureMilliC(&skin_temperaturemiliC); - } - - // Fan - if (R_SUCCEEDED(pwmCheck)) { - double temp = 0; - if (R_SUCCEEDED(pwmChannelSessionGetDutyCycle(&g_ICon, &temp))) { - temp *= 10; - temp = trunc(temp); - temp /= 10; - Rotation_Duty = 100.0 - temp; - if (Rotation_Duty <= 0) { - Rotation_Duty = 0.0000001; - } - } - } - - // GPU Load - if (R_SUCCEEDED(nvCheck)) { - nvIoctl(fd, NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD, &GPU_Load_u); - } - - mutexUnlock(&mutex_Misc); - - } while (!leventWait(&threadexit, 1'000'000'000)); // 1 second timeout - - // Cleanup voltage reading if initialized - if (canReadVoltages) { - rgltrExit(); - } -} - -//Check each core for idled ticks in intervals, they cannot read info about other core than they are assigned -//In case of getting more than systemtickfrequency in idle, make it equal to systemtickfrequency to get 0% as output and nothing less -//This is because making each loop also takes time, which is not considered because this will take also additional time - -//Check each core for idled ticks in intervals, they cannot read info about other core than they are assigned -//In case of getting more than systemtickfrequency in idle, make it equal to systemtickfrequency to get 0% as output and nothing less -//This is because making each loop also takes time, which is not considered because this will take also additional time -//void CheckCore0(void*) { -// uint64_t timeout_ns = 1'000'000'000 / TeslaFPS; -// while(true) { -// uint64_t idletick_a0 = 0; -// uint64_t idletick_b0 = 0; -// svcGetInfo(&idletick_b0, InfoType_IdleTickCount, INVALID_HANDLE, 0); -// if (leventWait(&threadexit, timeout_ns)) -// return; -// svcGetInfo(&idletick_a0, InfoType_IdleTickCount, INVALID_HANDLE, 0); -// idletick0 = idletick_a0 - idletick_b0; -// } -//} -// -//void CheckCore1(void*) { -// uint64_t timeout_ns = 1'000'000'000 / TeslaFPS; -// while(true) { -// uint64_t idletick_a1 = 0; -// uint64_t idletick_b1 = 0; -// svcGetInfo(&idletick_b1, InfoType_IdleTickCount, INVALID_HANDLE, 1); -// if (leventWait(&threadexit, timeout_ns)) -// return; -// svcGetInfo(&idletick_a1, InfoType_IdleTickCount, INVALID_HANDLE, 1); -// idletick1 = idletick_a1 - idletick_b1; -// } -//} -// -//void CheckCore2(void*) { -// uint64_t timeout_ns = 1'000'000'000 / TeslaFPS; -// while(true) { -// uint64_t idletick_a2 = 0; -// uint64_t idletick_b2 = 0; -// svcGetInfo(&idletick_b2, InfoType_IdleTickCount, INVALID_HANDLE, 2); -// if (leventWait(&threadexit, timeout_ns)) -// return; -// svcGetInfo(&idletick_a2, InfoType_IdleTickCount, INVALID_HANDLE, 2); -// idletick2 = idletick_a2 - idletick_b2; -// } -//} -// -//void CheckCore3(void*) { -// uint64_t timeout_ns = 1'000'000'000 / TeslaFPS; -// while(true) { -// uint64_t idletick_a3 = 0; -// uint64_t idletick_b3 = 0; -// svcGetInfo(&idletick_b3, InfoType_IdleTickCount, INVALID_HANDLE, 3); -// if (leventWait(&threadexit, timeout_ns)) -// return; -// svcGetInfo(&idletick_a3, InfoType_IdleTickCount, INVALID_HANDLE, 3); -// idletick3 = idletick_a3 - idletick_b3; -// } -//} - -void CheckCore(void* idletick_ptr) { - const uint64_t timeout_ns = 1'000'000'000ULL / TeslaFPS; - std::atomic* idletick = (std::atomic*)idletick_ptr; - while (true) { - uint64_t idletick_a; - uint64_t idletick_b; - svcGetInfo(&idletick_b, InfoType_IdleTickCount, INVALID_HANDLE, -1); - Result rc_break = leventWait(&threadexit, timeout_ns); - svcGetInfo(&idletick_a, InfoType_IdleTickCount, INVALID_HANDLE, -1); - if (rc_break) return; - idletick->store(idletick_a - idletick_b, std::memory_order_release); - } -} - - -//Start reading all stats -void StartThreads() { - // Clear the thread exit event for new threads - leventClear(&threadexit); - - threadCreate(&t0, CheckCore, &idletick0, NULL, 0x1000, 0x10, 0); - threadCreate(&t1, CheckCore, &idletick1, NULL, 0x1000, 0x10, 1); - threadCreate(&t2, CheckCore, &idletick2, NULL, 0x1000, 0x10, 2); - threadCreate(&t3, CheckCore, &idletick3, NULL, 0x1000, 0x10, 3); - - //threadCreate(&t0, CheckCore, &coreIds[0], NULL, 0x1000, 0x10, 0); - //threadCreate(&t1, CheckCore, &coreIds[1], NULL, 0x1000, 0x10, 1); - //threadCreate(&t2, CheckCore, &coreIds[2], NULL, 0x1000, 0x10, 2); - //threadCreate(&t3, CheckCore, &coreIds[3], NULL, 0x1000, 0x10, 3); - threadCreate(&t4, Misc, NULL, NULL, 0x4000, 0x3F, -2); - threadCreate(&t5, gpuLoadThread, NULL, NULL, 0x1000, 0x3F, -2); - threadCreate(&t7, BatteryChecker, NULL, NULL, 0x4000, 0x3F, -2); - - threadStart(&t0); - threadStart(&t1); - threadStart(&t2); - threadStart(&t3); - threadStart(&t4); - threadStart(&t5); - threadStart(&t7); - - if (SaltySD) { - //Assign NX-FPS to default core - threadCreate(&t6, CheckIfGameRunning, NULL, NULL, 0x1000, 0x38, -2); - threadStart(&t6); - } -} - -//End reading all stats -void CloseThreads() { - leventSignal(&threadexit); - threadWaitForExit(&t0); - threadWaitForExit(&t1); - threadWaitForExit(&t2); - threadWaitForExit(&t3); - threadWaitForExit(&t4); - threadWaitForExit(&t5); - threadWaitForExit(&t6); - threadWaitForExit(&t7); - threadClose(&t0); - threadClose(&t1); - threadClose(&t2); - threadClose(&t3); - threadClose(&t4); - threadClose(&t5); - threadClose(&t6); - threadClose(&t7); -} - -//Separate functions dedicated to "FPS Counter" mode -void FPSCounter(void*) { - const uint64_t timeout_ns = 1'000'000'000 / TeslaFPS; - do { - if (GameRunning) { - if (SharedMemoryUsed && NxFps) { - FPS = (NxFps -> FPS); - const size_t element_count = sizeof(NxFps -> FPSticks) / sizeof(NxFps -> FPSticks[0]); - FPSavg_old = (float)systemtickfrequency / (std::accumulate(&NxFps->FPSticks[0], &NxFps->FPSticks[element_count], 0) / element_count); - const float FPS_in = (float)FPS; - if (FPSavg_old >= (FPS_in-0.25) && FPSavg_old <= (FPS_in+0.25)) - FPSavg = FPS_in; - else FPSavg = FPSavg_old; - lastFrameNumber = NxFps -> frameNumber; - } - } - else FPSavg = 254; - } while (!leventWait(&threadexit, timeout_ns)); -} - -void StartFPSCounterThread() { - leventClear(&threadexit); - - threadCreate(&t6, CheckIfGameRunning, NULL, NULL, 0x1000, 0x38, -2); - threadStart(&t6); - - threadCreate(&t4, FPSCounter, NULL, NULL, 0x1000, 0x3F, 3); - threadStart(&t4); -} - -void EndFPSCounterThread() { - leventSignal(&threadexit); - threadWaitForExit(&t6); - threadWaitForExit(&t4); - threadClose(&t6); - threadClose(&t4); -} - -void StartInfoThread() { - // Clear the thread exit event for new threads - leventClear(&threadexit); - - threadCreate(&t0, CheckCore, &idletick0, NULL, 0x1000, 0x10, 0); - threadCreate(&t1, CheckCore, &idletick1, NULL, 0x1000, 0x10, 1); - threadCreate(&t2, CheckCore, &idletick2, NULL, 0x1000, 0x10, 2); - threadCreate(&t3, CheckCore, &idletick3, NULL, 0x1000, 0x10, 3); - - //threadCreate(&t1, CheckCore, &coreIds[0], NULL, 0x1000, 0x10, 0); - //threadCreate(&t2, CheckCore, &coreIds[1], NULL, 0x1000, 0x10, 1); - //threadCreate(&t3, CheckCore, &coreIds[2], NULL, 0x1000, 0x10, 2); - //threadCreate(&t4, CheckCore, &coreIds[3], NULL, 0x1000, 0x10, 3); - threadCreate(&t7, Misc3, NULL, NULL, 0x1000, 0x3F, -2); - - threadStart(&t0); - threadStart(&t1); - threadStart(&t2); - threadStart(&t3); - threadStart(&t7); -} - -void EndInfoThread() { - // Signal the thread exit event - leventSignal(&threadexit); - - // Wait for all threads to exit - threadWaitForExit(&t0); - threadWaitForExit(&t1); - threadWaitForExit(&t2); - threadWaitForExit(&t3); - threadWaitForExit(&t7); - - // Close thread handles - threadClose(&t0); - threadClose(&t1); - threadClose(&t2); - threadClose(&t3); - threadClose(&t7); -} - -// String formatting functions -void removeSpaces(std::string& str) { - str.erase(std::remove(str.begin(), str.end(), ' '), str.end()); -} - -void convertToUpper(std::string& str) { - std::transform(str.begin(), str.end(), str.begin(), ::toupper); -} - -void convertToLower(std::string& str) { - std::transform(str.begin(), str.end(), str.begin(), ::tolower); -} - -std::map replaces{ - {"A", "\uE0E0"}, - {"B", "\uE0E1"}, - {"X", "\uE0E2"}, - {"Y", "\uE0E3"}, - {"L", "\uE0E4"}, - {"R", "\uE0E5"}, - {"ZL", "\uE0E6"}, - {"ZR", "\uE0E7"}, - {"SL", "\uE0E8"}, - {"SR", "\uE0E9"}, - {"DUP", "\uE0EB"}, - {"DDOWN", "\uE0EC"}, - {"DLEFT", "\uE0ED"}, - {"DRIGHT", "\uE0EE"}, - {"PLUS", "\uE0EF"}, - {"MINUS", "\uE0F0"}, - {"LSTICK", "\uE104"}, - {"RSTICK", "\uE105"}, - {"RS", "\uE105"}, - {"LS", "\uE104"} -}; - -void formatButtonCombination(std::string& line) { - // Remove all spaces from the line - line.erase(std::remove(line.begin(), line.end(), ' '), line.end()); - - // Replace '+' with ' + ' - size_t pos = 0; - size_t max_pluses = 3; - while ((pos = line.find('+', pos)) != std::string::npos) { - if (!max_pluses) { - line = line.substr(0, pos); - return; - } - if (pos > 0 && pos < line.size() - 1) { - if (std::isalnum(line[pos - 1]) && std::isalnum(line[pos + 1])) { - line.replace(pos, 1, " + "); - pos += 3; - } - } - ++pos; - max_pluses--; - } - pos = 0; - size_t old_pos = 0; - - static std::string button; - while ((pos = line.find(" + ", pos)) != std::string::npos) { - - button = line.substr(old_pos, pos - old_pos); - if (replaces.find(button) != replaces.end()) { - line.replace(old_pos, button.length(), replaces[button]); - pos = 0; - old_pos = 0; - } - else pos += 3; - old_pos = pos; - } - button = line.substr(old_pos); - if (replaces.find(button) != replaces.end()) { - line.replace(old_pos, button.length(), replaces[button]); - } -} - -//uint64_t comboBitmask = 0; -// -//constexpr uint64_t MapButtons(const std::string& buttonCombo) { -// static std::map buttonMap = { -// {"A", HidNpadButton_A}, -// {"B", HidNpadButton_B}, -// {"X", HidNpadButton_X}, -// {"Y", HidNpadButton_Y}, -// {"L", HidNpadButton_L}, -// {"R", HidNpadButton_R}, -// {"ZL", HidNpadButton_ZL}, -// {"ZR", HidNpadButton_ZR}, -// {"PLUS", HidNpadButton_Plus}, -// {"MINUS", HidNpadButton_Minus}, -// {"DUP", HidNpadButton_Up}, -// {"DDOWN", HidNpadButton_Down}, -// {"DLEFT", HidNpadButton_Left}, -// {"DRIGHT", HidNpadButton_Right}, -// {"SL", HidNpadButton_AnySL}, -// {"SR", HidNpadButton_AnySR}, -// {"LSTICK", HidNpadButton_StickL}, -// {"RSTICK", HidNpadButton_StickR}, -// {"LS", HidNpadButton_StickL}, -// {"RS", HidNpadButton_StickR}, -// {"UP", HidNpadButton_AnyUp}, -// {"DOWN", HidNpadButton_AnyDown}, -// {"LEFT", HidNpadButton_AnyLeft}, -// {"RIGHT", HidNpadButton_AnyRight} -// }; -// -// -// std::string comboCopy = buttonCombo; // Make a copy of buttonCombo -// -// static const std::string delimiter = "+"; -// size_t pos = 0; -// static std::string button; -// size_t max_delimiters = 4; -// while ((pos = comboCopy.find(delimiter)) != std::string::npos) { -// button = comboCopy.substr(0, pos); -// if (buttonMap.find(button) != buttonMap.end()) { -// comboBitmask |= buttonMap[button]; -// } -// comboCopy.erase(0, pos + delimiter.length()); -// if (!--max_delimiters) { -// return comboBitmask; -// } -// } -// if (buttonMap.find(comboCopy) != buttonMap.end()) { -// comboBitmask |= buttonMap[comboCopy]; -// } -// return comboBitmask; -//} - -ALWAYS_INLINE bool isKeyComboPressed(uint64_t keysHeld, uint64_t keysDown) { - // Check if any of the combo buttons are pressed down this frame - // while the rest of the combo buttons are being held - - const uint64_t comboButtonsDown = keysDown & tsl::cfg::launchCombo; - const uint64_t comboButtonsHeld = keysHeld & tsl::cfg::launchCombo; - - // If any combo buttons are pressed down this frame - if (comboButtonsDown != 0) { - // Check if the remaining combo buttons are being held - // (the full combo should be active when combining held + down) - const uint64_t totalComboActive = comboButtonsHeld | comboButtonsDown; - - if (totalComboActive == tsl::cfg::launchCombo) { - fixHiding = true; // for fixing hiding when returning - //triggerRumbleDoubleClick.store(true, std::memory_order_release); - //triggerExitSound.store(true, std::memory_order_release); - return true; - } - } - - return false; -} - -inline int safeFanDuty(int raw) { - if (raw < 0) return 0; - if (raw > 100) return 100; - return raw; -} - -// Helper function to check if comboBitmask is satisfied with at least one key in keysDown and the rest in keysHeld -bool isKeyComboPressed2(uint64_t keysDown, uint64_t keysHeld) { - uint64_t requiredKeys = tsl::cfg::launchCombo; - bool hasKeyDown = false; // Tracks if at least one key is in keysDown - - static uint64_t keyBit; - // Iterate over each bit in the comboBitmask - while (requiredKeys) { - keyBit = requiredKeys & ~(requiredKeys - 1); // Get the lowest bit set in requiredKeys - - // Check if the key is in keysDown or keysHeld - if (keysDown & keyBit) { - hasKeyDown = true; // Found at least one key in keysDown - } else if (!(keysHeld & keyBit)) { - return false; // If the key is neither in keysDown nor keysHeld, the combo is incomplete - } - - // Remove the lowest bit and continue to check other keys - requiredKeys &= ~keyBit; - } - - // Ensure that at least one key was in keysDown and the rest were in keysHeld - return hasKeyDown; -} - - -// Custom utility function for parsing an ini file -void ParseIniFile() { - // Check and create directory if needed - //struct stat st; - //if (stat(directoryPath, &st) != 0) { - // mkdir(directoryPath, 0777); - //} - ult::createSingleDirectory(directoryPath); - - // Load main config INI once - auto configData = ult::getParsedDataFromIniFile(configIniPath); - auto statusIt = configData.find("status-monitor"); - - if (statusIt != configData.end()) { - const auto& statusSection = statusIt->second; - std::string key; - - // Process all settings with direct lookups - auto batteryFilterIt = statusSection.find("battery_avg_iir_filter"); - if (batteryFilterIt != statusSection.end()) { - key = batteryFilterIt->second; - convertToUpper(key); - batteryFiltered = (key == "TRUE"); - } - - auto refreshRateIt = statusSection.find("battery_time_left_refreshrate"); - if (refreshRateIt != statusSection.end()) { - batteryTimeLeftRefreshRate = std::clamp(atol(refreshRateIt->second.c_str()), 1L, 60L); - } - - auto gpuLoadIt = statusSection.find("average_gpu_load"); - if (gpuLoadIt != statusSection.end()) { - key = gpuLoadIt->second; - convertToUpper(key); - GPULoadPerFrame = (key != "TRUE"); - } - - auto fpsAvgIt = statusSection.find("use_old_fps_average"); - if (fpsAvgIt != statusSection.end()) { - key = fpsAvgIt->second; - convertToUpper(key); - useOldFPSavg = (key == "TRUE"); - } - } - - // Handle external combo - load each file once - const struct { const char* path; const char* section; } externalConfigs[] = { - {ultrahandConfigIniPath, "ultrahand"}, - {teslaConfigIniPath, "tesla"} - }; - - for (const auto& config : externalConfigs) { - auto extConfigData = ult::getParsedDataFromIniFile(config.path); - auto sectionIt = extConfigData.find(config.section); - - if (sectionIt != extConfigData.end()) { - auto keyComboIt = sectionIt->second.find("key_combo"); - if (keyComboIt != sectionIt->second.end() && !keyComboIt->second.empty()) { - keyCombo = keyComboIt->second; - removeSpaces(keyCombo); - convertToUpper(keyCombo); - break; - } - } - } - - //comboBitmask = MapButtons(keyCombo); -} - -ALWAYS_INLINE bool isValidRGBA4Color(const std::string& hexColor) { - const char* data = hexColor.data(); - const size_t size = hexColor.size(); - - static unsigned char c; - for (size_t i = 0; i < size; ++i) { - c = data[i]; - // Branchless hex digit check: (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f') - if (!((c - '0') <= 9 || (c - 'A') <= 5 || (c - 'a') <= 5)) { - return false; - } - } - - return true; -} - -bool convertStrToRGBA4444(std::string hexColor, uint16_t* returnValue) { - // Check if # is present - if (hexColor.size() != 5 || hexColor[0] != '#') - return false; - - hexColor = hexColor.substr(1); - - if (isValidRGBA4Color(hexColor)) { - *returnValue = std::stoi(std::string(hexColor.rbegin(), hexColor.rend()), nullptr, 16); - return true; - } - return false; -} - -struct FullSettings { - uint8_t refreshRate; - bool setPosRight; - bool showRealFreqs; - bool realVolts; - bool realTemps; - bool showDeltas; - bool showTargetFreqs; - bool showFPS; - bool showRES; - bool showRDSD; - std::string ramInfoMode; - bool useDynamicColors; - bool disableScreenshots; - uint16_t separatorColor; - uint16_t catColor1; - uint16_t catColor2; - uint16_t textColor; -}; - -struct MiniSettings { - uint8_t refreshRate; - bool realFrequencies; - bool realVolts; - bool realTemps; - bool showFullCPU; - bool showFullResolution; - bool showFanPercentage; - bool showSOCVoltage; - bool useDynamicColors; - bool showVDDQ; - bool showVDD2; - bool decimalVDD2; - bool showDTC; - bool useDTCSymbol; - std::string dtcFormat; - size_t handheldFontSize; - size_t dockedFontSize; - size_t spacing; - uint16_t backgroundColor; - uint16_t focusBackgroundColor; - uint16_t separatorColor; - uint16_t catColor; - uint16_t textColor; - std::string show; - bool showpartLoad; - bool showpartLoadCPUGPU; - std::string ramInfoMode; - bool invertBatteryDisplay; - bool disableScreenshots; - bool sleepExit; - //int setPos; - int frameOffsetX; - int frameOffsetY; - size_t framePadding; -}; - -struct MicroSettings { - uint8_t refreshRate; - bool realFrequencies; - bool realVolts; - bool realTemps; - bool showFullCPU; - bool showFullResolution; - bool showSOCVoltage; - bool useDynamicColors; - bool showVDDQ; - bool showVDD2; - bool decimalVDD2; - bool showDTC; - bool useDTCSymbol; - std::string dtcFormat; - bool invertBatteryDisplay; - size_t handheldFontSize; - size_t dockedFontSize; - uint8_t alignTo; - uint16_t backgroundColor; - uint16_t separatorColor; - uint16_t catColor; - uint16_t textColor; - std::string show; - bool showpartLoad; - std::string ramInfoMode; - bool setPosBottom; - bool disableScreenshots; - bool sleepExit; -}; - -struct FpsCounterSettings { - uint8_t refreshRate; - size_t handheldFontSize; - size_t dockedFontSize; - uint16_t backgroundColor; - uint16_t focusBackgroundColor; - uint16_t textColor; - //int setPos; - bool useIntegerCounter; - bool disableScreenshots; - int frameOffsetX; - int frameOffsetY; - size_t framePadding; -}; - -struct FpsGraphSettings { - bool showInfo; - bool realTemps; - uint8_t refreshRate; - uint16_t backgroundColor; - uint16_t focusBackgroundColor; - uint16_t fpsColor; - uint16_t mainLineColor; - uint16_t roundedLineColor; - uint16_t perfectLineColor; - uint16_t dashedLineColor; - uint16_t borderColor; - uint16_t maxFPSTextColor; - uint16_t minFPSTextColor; - uint16_t textColor; - uint16_t catColor; - //int setPos; - bool useDynamicColors; - bool disableScreenshots; - int frameOffsetX; - int frameOffsetY; - size_t framePadding; -}; - -struct ResolutionSettings { - uint8_t refreshRate; - uint16_t backgroundColor; - uint16_t focusBackgroundColor; - uint16_t catColor; - //uint16_t catColor2; - uint16_t textColor; - //int setPos; - bool disableScreenshots; - - int frameOffsetX; - int frameOffsetY; - size_t framePadding; -}; - -ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) { - // Initialize defaults - settings->realFrequencies = true; - settings->realVolts = true; - settings->realTemps = true; - settings->showFullCPU = false; - settings->showFullResolution = true; - settings->showFanPercentage = true; - settings->useDynamicColors = true; - settings->showFullCPU = false; - settings->showSOCVoltage = false; - settings->showVDDQ = false; - settings->showVDD2 = true; - settings->decimalVDD2 = false; - settings->showDTC = true; - settings->useDTCSymbol = true; - settings->dtcFormat = "%m-%d-%Y%H:%M:%S";//"%Y-%m-%d %I:%M:%S %p"; - settings->handheldFontSize = 15; - settings->dockedFontSize = 15; - settings->spacing = 8; - convertStrToRGBA4444("#0009", &(settings->backgroundColor)); - convertStrToRGBA4444("#000F", &(settings->focusBackgroundColor)); - convertStrToRGBA4444("#888F", &(settings->separatorColor)); - convertStrToRGBA4444("#2DFF", &(settings->catColor)); - convertStrToRGBA4444("#FFFF", &(settings->textColor)); - settings->show = "DTC+BAT+CPU+GPU+RAM+TMP+FPS+RES"; - settings->showpartLoad = true; - settings->showpartLoadCPUGPU = false; - settings->ramInfoMode = "LOAD"; - settings->invertBatteryDisplay = true; - settings->refreshRate = 1; - settings->disableScreenshots = false; - settings->sleepExit = false; - //settings->setPos = 0; - settings->frameOffsetX = 10; - settings->frameOffsetY = 10; - settings->framePadding = 10; - - // Open and read file efficiently - FILE* configFile = fopen(configIniPath, "r"); - if (!configFile) return; - - fseek(configFile, 0, SEEK_END); - const long fileSize = ftell(configFile); - fseek(configFile, 0, SEEK_SET); - - std::string fileData; - fileData.resize(fileSize); - fread(fileData.data(), 1, fileSize, configFile); - fclose(configFile); - - auto parsedData = ult::parseIni(fileData); - - // Cache section lookup - auto sectionIt = parsedData.find("mini"); - if (sectionIt == parsedData.end()) return; - - std::string key; - uint16_t temp; - - const auto& section = sectionIt->second; - - // Process refresh_rate - auto it = section.find("refresh_rate"); - if (it != section.end()) { - settings->refreshRate = std::clamp(atol(it->second.c_str()), 1L, 60L); - } - - // Process boolean flags - it = section.find("real_freqs"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->realFrequencies = (key == "TRUE"); - } - - it = section.find("real_volts"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->realVolts = (key == "TRUE"); - } - - it = section.find("real_temps"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->realTemps = (key == "TRUE"); - } - - // Process font sizes with shared bounds - static constexpr long minFontSize = 8; - static constexpr long maxFontSize = 22; - - it = section.find("handheld_font_size"); - if (it != section.end()) { - settings->handheldFontSize = std::clamp(atol(it->second.c_str()), minFontSize, maxFontSize); - } - - it = section.find("docked_font_size"); - if (it != section.end()) { - settings->dockedFontSize = std::clamp(atol(it->second.c_str()), minFontSize, maxFontSize); - } - - it = section.find("spacing"); - if (it != section.end()) { - settings->spacing = atol(it->second.c_str()); - } - - // Process colors - it = section.find("background_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->backgroundColor = temp; - } - it = section.find("focus_background_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->focusBackgroundColor = temp; - } - - it = section.find("separator_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->separatorColor = temp; - } - - it = section.find("cat_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->catColor = temp; - } - - it = section.find("text_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->textColor = temp; - } - - // Process RAM load flag - it = section.find("show_full_cpu"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showFullCPU = !(key == "FALSE"); - } - - it = section.find("show_full_res"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showFullResolution = !(key == "FALSE"); - } - - it = section.find("show_soc_voltage"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showSOCVoltage = !(key == "FALSE"); - } - - it = section.find("use_dynamic_colors"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->useDynamicColors = (key == "TRUE"); - } - - it = section.find("show_vddq"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showVDDQ = !(key == "FALSE"); - } - - it = section.find("show_vdd2"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showVDD2 = !(key == "FALSE"); - } - - it = section.find("decimal_vdd2"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->decimalVDD2 = !(key == "FALSE"); - } - - it = section.find("show_dtc"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showDTC = !(key == "FALSE"); - } - - it = section.find("use_dtc_symbol"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->useDTCSymbol = !(key == "FALSE"); - } - - it = section.find("dtc_format"); - if (it != section.end()) { - key = it->second; - settings->dtcFormat = std::move(key); - } - - // Process show string - it = section.find("show"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->show = std::move(key); - } - - // Process RAM load flag - it = section.find("replace_MB_with_RAM_load"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showpartLoad = (key != "FALSE"); - } - - // Process CPU/GPU RAM load flag - it = section.find("show_RAM_load_CPU_GPU"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showpartLoadCPUGPU = (key != "FALSE"); - } - - // Process RAM info mode - it = section.find("ram_info_mode"); - if (it != section.end()) { - settings->ramInfoMode = it->second; - } - - // Invert the battery display value - it = section.find("invert_battery_display"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->invertBatteryDisplay = (key != "FALSE"); - } - - // Process disable screenshots - it = section.find("disable_screenshots"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->disableScreenshots = (key != "FALSE"); - } - - // Process exit on sleep - it = section.find("sleep_exit"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->sleepExit = (key != "FALSE"); - } - - // Process alignment settings - //it = section.find("layer_width_align"); - //if (it != section.end()) { - // key = it->second; - // convertToUpper(key); - // if (key == "CENTER") { - // settings->setPos = 1; - // } else if (key == "RIGHT") { - // settings->setPos = 2; - // } - //} - // - //it = section.find("layer_height_align"); - //if (it != section.end()) { - // key = it->second; - // convertToUpper(key); - // if (key == "CENTER") { - // settings->setPos += 3; - // } else if (key == "BOTTOM") { - // settings->setPos += 6; - // } - //} - - it = section.find("frame_offset_x"); - if (it != section.end()) { - settings->frameOffsetX = atol(it->second.c_str()); - } - - it = section.find("frame_offset_y"); - if (it != section.end()) { - settings->frameOffsetY = atol(it->second.c_str()); - } - - it = section.find("frame_padding"); - if (it != section.end()) { - settings->framePadding = atol(it->second.c_str()); - } -} - -ALWAYS_INLINE void GetConfigSettings(MicroSettings* settings) { - // Initialize defaults - settings->realFrequencies = true; - settings->realVolts = true; - settings->realTemps = true; - settings->showFullCPU = false; - settings->showFullResolution = false; - settings->showSOCVoltage = true; - settings->useDynamicColors = true; - settings->showVDDQ = false; - settings->showVDD2 = true; - settings->decimalVDD2 = false; - settings->showDTC = true; - settings->useDTCSymbol = true; - settings->dtcFormat = "%H:%M:%S";//"%Y-%m-%d %I:%M:%S %p"; - settings->invertBatteryDisplay = false; - settings->handheldFontSize = 14; - settings->dockedFontSize = 14; - settings->alignTo = 1; // CENTER - convertStrToRGBA4444("#0009", &(settings->backgroundColor)); - convertStrToRGBA4444("#888F", &(settings->separatorColor)); - convertStrToRGBA4444("#2DFF", &(settings->catColor)); - convertStrToRGBA4444("#FFFF", &(settings->textColor)); - settings->show = "FPS+CPU+GPU+RAM+SOC+BAT+DTC"; - settings->showpartLoad = true; - settings->ramInfoMode = "LOAD"; - settings->setPosBottom = false; - settings->disableScreenshots = false; - settings->sleepExit = false; - settings->refreshRate = 1; - - // Open and read file efficiently - FILE* configFile = fopen(configIniPath, "r"); - if (!configFile) return; - - fseek(configFile, 0, SEEK_END); - const long fileSize = ftell(configFile); - fseek(configFile, 0, SEEK_SET); - - std::string fileData; - fileData.resize(fileSize); - fread(fileData.data(), 1, fileSize, configFile); - fclose(configFile); - - auto parsedData = ult::parseIni(fileData); - - // Cache section lookup - auto sectionIt = parsedData.find("micro"); - if (sectionIt == parsedData.end()) return; - - std::string key; - uint16_t temp; - - const auto& section = sectionIt->second; - - // Process refresh_rate - auto it = section.find("refresh_rate"); - if (it != section.end()) { - settings->refreshRate = std::clamp(atol(it->second.c_str()), 1L, 60L); - } - - // Process boolean flags - it = section.find("real_freqs"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->realFrequencies = (key == "TRUE"); - } - - it = section.find("real_volts"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->realVolts = (key == "TRUE"); - } - - it = section.find("real_temps"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->realTemps = (key == "TRUE"); - } - - it = section.find("show_full_cpu"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showFullCPU = (key == "TRUE"); - } - - it = section.find("show_full_res"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showFullResolution = (key == "TRUE"); - } - - it = section.find("show_soc_voltage"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showSOCVoltage = !(key == "FALSE"); - } - - it = section.find("use_dynamic_colors"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->useDynamicColors = (key == "TRUE"); - } - - it = section.find("show_vddq"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showVDDQ = !(key == "FALSE"); - } - - it = section.find("show_vdd2"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showVDD2 = !(key == "FALSE"); - } - - it = section.find("decimal_vdd2"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->decimalVDD2 = !(key == "FALSE"); - } - - it = section.find("show_dtc"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showDTC = !(key == "FALSE"); - } - - it = section.find("use_dtc_symbol"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->useDTCSymbol = !(key == "FALSE"); - } - - it = section.find("dtc_format"); - if (it != section.end()) { - key = it->second; - settings->dtcFormat = std::move(key); - } - - // Invert the battery display value - it = section.find("invert_battery_display"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->invertBatteryDisplay = (key != "FALSE"); - } - - // Process font sizes with shared bounds - static constexpr long minFontSize = 8; - static constexpr long maxFontSize = 18; - - it = section.find("handheld_font_size"); - if (it != section.end()) { - settings->handheldFontSize = std::clamp(atol(it->second.c_str()), minFontSize, maxFontSize); - } - - it = section.find("docked_font_size"); - if (it != section.end()) { - settings->dockedFontSize = std::clamp(atol(it->second.c_str()), minFontSize, maxFontSize); - } - - // Process colors - it = section.find("background_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->backgroundColor = temp; - } - - it = section.find("separator_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->separatorColor = temp; - } - - it = section.find("cat_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->catColor = temp; - } - - it = section.find("text_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->textColor = temp; - } - - // Process text alignment - it = section.find("text_align"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - if (key == "LEFT") { - settings->alignTo = 0; - } else if (key == "CENTER") { - settings->alignTo = 1; - } else if (key == "RIGHT") { - settings->alignTo = 2; - } - } - - // Process RAM load flag - it = section.find("replace_GB_with_RAM_load"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showpartLoad = (key != "FALSE"); - } - - // Process RAM info mode - it = section.find("ram_info_mode"); - if (it != section.end()) { - settings->ramInfoMode = it->second; - } - - // Process show string - it = section.find("show"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->show = std::move(key); - } - - // Process layer height alignment - it = section.find("layer_height_align"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->setPosBottom = (key == "BOTTOM"); - } - - // Process disable screenshots - it = section.find("disable_screenshots"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->disableScreenshots = (key != "FALSE"); - } - - // Process exit on sleep - it = section.find("sleep_exit"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->sleepExit = (key != "FALSE"); - } - -} - -ALWAYS_INLINE void GetConfigSettings(FpsCounterSettings* settings) { - // Initialize defaults - settings->handheldFontSize = 40; - settings->dockedFontSize = 40; - convertStrToRGBA4444("#0009", &(settings->backgroundColor)); - convertStrToRGBA4444("#000F", &(settings->focusBackgroundColor)); - convertStrToRGBA4444("#8CFF", &(settings->textColor)); - //settings->setPos = 0; - settings->refreshRate = 30; - settings->useIntegerCounter = false; - settings->disableScreenshots = false; - - settings->frameOffsetX = 10; - settings->frameOffsetY = 10; - settings->framePadding = 10; - - // Open and read file efficiently - FILE* configFile = fopen(configIniPath, "r"); - if (!configFile) return; - - fseek(configFile, 0, SEEK_END); - const long fileSize = ftell(configFile); - fseek(configFile, 0, SEEK_SET); - - std::string fileData; - fileData.resize(fileSize); - fread(fileData.data(), 1, fileSize, configFile); - fclose(configFile); - - auto parsedData = ult::parseIni(fileData); - - // Cache section lookup - auto sectionIt = parsedData.find("fps-counter"); - if (sectionIt == parsedData.end()) return; - - - std::string key; - uint16_t temp; - - const auto& section = sectionIt->second; - - // Process font sizes with shared bounds - static constexpr long minFontSize = 8; - static constexpr long maxFontSize = 150; - - auto it = section.find("handheld_font_size"); - if (it != section.end()) { - settings->handheldFontSize = std::clamp(atol(it->second.c_str()), minFontSize, maxFontSize); - } - - it = section.find("docked_font_size"); - if (it != section.end()) { - settings->dockedFontSize = std::clamp(atol(it->second.c_str()), minFontSize, maxFontSize); - } - - // Process colors - it = section.find("background_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->backgroundColor = temp; - } - - it = section.find("focus_background_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->focusBackgroundColor = temp; - } - - - it = section.find("text_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->textColor = temp; - } - - // Process alignment settings - //it = section.find("layer_width_align"); - //if (it != section.end()) { - // key = it->second; - // convertToUpper(key); - // if (key == "CENTER") { - // settings->setPos = 1; - // } else if (key == "RIGHT") { - // settings->setPos = 2; - // } - //} - - //it = section.find("layer_height_align"); - //if (it != section.end()) { - // key = it->second; - // convertToUpper(key); - // if (key == "CENTER") { - // settings->setPos += 3; - // } else if (key == "BOTTOM") { - // settings->setPos += 6; - // } - //} - - it = section.find("use_integer_counter"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->useIntegerCounter = (key != "FALSE"); - } - - // Process disable screenshots - it = section.find("disable_screenshots"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->disableScreenshots = (key != "FALSE"); - } - - it = section.find("frame_offset_x"); - if (it != section.end()) { - settings->frameOffsetX = atol(it->second.c_str()); - } - - it = section.find("frame_offset_y"); - if (it != section.end()) { - settings->frameOffsetY = atol(it->second.c_str()); - } - - it = section.find("frame_padding"); - if (it != section.end()) { - settings->framePadding = atol(it->second.c_str()); - } -} - -ALWAYS_INLINE void GetConfigSettings(FpsGraphSettings* settings) { - // Initialize defaults - settings->showInfo = true; - settings->realTemps = false; - //settings->setPos = 0; - convertStrToRGBA4444("#0009", &(settings->backgroundColor)); - convertStrToRGBA4444("#000F", &(settings->focusBackgroundColor)); - convertStrToRGBA4444("#888C", &(settings->fpsColor)); - convertStrToRGBA4444("#2DFF", &(settings->borderColor)); - convertStrToRGBA4444("#8888", &(settings->dashedLineColor)); - convertStrToRGBA4444("#FFFF", &(settings->maxFPSTextColor)); - convertStrToRGBA4444("#FFFF", &(settings->minFPSTextColor)); - convertStrToRGBA4444("#FFFF", &(settings->mainLineColor)); - convertStrToRGBA4444("#F0FF", &(settings->roundedLineColor)); - convertStrToRGBA4444("#0C0F", &(settings->perfectLineColor)); - - convertStrToRGBA4444("#FFFF", &(settings->textColor)); - convertStrToRGBA4444("#0F0F", &(settings->catColor)); - - settings->refreshRate = 30; - settings->useDynamicColors = true; - settings->disableScreenshots = false; - - settings->frameOffsetX = 10; - settings->frameOffsetY = 10; - settings->framePadding = 10; - - - // Open and read file efficiently - FILE* configFile = fopen(configIniPath, "r"); - if (!configFile) return; - - fseek(configFile, 0, SEEK_END); - const long fileSize = ftell(configFile); - fseek(configFile, 0, SEEK_SET); - - std::string fileData; - fileData.resize(fileSize); - fread(fileData.data(), 1, fileSize, configFile); - fclose(configFile); - - auto parsedData = ult::parseIni(fileData); - - // Cache section lookup - auto sectionIt = parsedData.find("fps-graph"); - if (sectionIt == parsedData.end()) return; - - std::string key; - uint16_t temp; - - const auto& section = sectionIt->second; - - // Process alignment settings - //auto it = section.find("layer_width_align"); - //if (it != section.end()) { - // key = it->second; - // convertToUpper(key); - // if (key == "CENTER") { - // settings->setPos = 1; - // } else if (key == "RIGHT") { - // settings->setPos = 2; - // } - //} - // - //it = section.find("layer_height_align"); - //if (it != section.end()) { - // key = it->second; - // convertToUpper(key); - // if (key == "CENTER") { - // settings->setPos += 3; - // } else if (key == "BOTTOM") { - // settings->setPos += 6; - // } - //} - - // Process show_info boolean - auto it = section.find("show_info"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showInfo = (key == "TRUE"); - } - - it = section.find("real_temps"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->realTemps = (key == "TRUE"); - } - - it = section.find("use_dynamic_colors"); - - it = section.find("use_dynamic_colors"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->useDynamicColors = (key == "TRUE"); - } - - // Process disable screenshots - it = section.find("disable_screenshots"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->disableScreenshots = (key != "FALSE"); - } - - it = section.find("frame_offset_x"); - if (it != section.end()) { - settings->frameOffsetX = atol(it->second.c_str()); - } - - it = section.find("frame_offset_y"); - if (it != section.end()) { - settings->frameOffsetY = atol(it->second.c_str()); - } - - it = section.find("frame_padding"); - if (it != section.end()) { - settings->framePadding = atol(it->second.c_str()); - } - - - // Process colors - using a struct for cleaner code - struct ColorMapping { - const char* key; - uint16_t* target; - }; - - const ColorMapping colorMappings[] = { - {"min_fps_text_color", &settings->minFPSTextColor}, - {"max_fps_text_color", &settings->maxFPSTextColor}, - {"background_color", &settings->backgroundColor}, - {"focus_background_color", &settings->focusBackgroundColor}, - {"fps_counter_color", &settings->fpsColor}, - {"border_color", &settings->borderColor}, - {"dashed_line_color", &settings->dashedLineColor}, - {"main_line_color", &settings->mainLineColor}, - {"rounded_line_color", &settings->roundedLineColor}, - {"perfect_line_color", &settings->perfectLineColor}, - {"text_color", &settings->textColor}, - {"cat_color", &settings->catColor} - }; - - for (const auto& mapping : colorMappings) { - it = section.find(mapping.key); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - *(mapping.target) = temp; - } - } -} - -ALWAYS_INLINE void GetConfigSettings(FullSettings* settings) { - // Initialize defaults - settings->setPosRight = false; - settings->refreshRate = 1; - settings->showRealFreqs = true; - settings->realTemps = false; - settings->showDeltas = true; - settings->showTargetFreqs = true; - settings->showFPS = true; - settings->showRES = true; - settings->showRDSD = true; - settings->ramInfoMode = "LOAD"; - settings->useDynamicColors = true; - settings->disableScreenshots = false; - convertStrToRGBA4444("#888F", &(settings->separatorColor)); - convertStrToRGBA4444("#8FFF", &(settings->catColor1)); - convertStrToRGBA4444("#8CFF", &(settings->catColor2)); - convertStrToRGBA4444("#FFFF", &(settings->textColor)); - - // Open and read file efficiently - FILE* configFile = fopen(configIniPath, "r"); - if (!configFile) return; - - fseek(configFile, 0, SEEK_END); - const long fileSize = ftell(configFile); - fseek(configFile, 0, SEEK_SET); - - std::string fileData; - fileData.resize(fileSize); - fread(fileData.data(), 1, fileSize, configFile); - fclose(configFile); - - auto parsedData = ult::parseIni(fileData); - - // Cache section lookup - auto sectionIt = parsedData.find("full"); - if (sectionIt == parsedData.end()) return; - - std::string key; - uint16_t temp; - - const auto& section = sectionIt->second; - - // Process refresh_rate - auto it = section.find("refresh_rate"); - if (it != section.end()) { - settings->refreshRate = std::clamp(atol(it->second.c_str()), 1L, 60L); - } - - // Process layer position - it = section.find("layer_width_align"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->setPosRight = (key == "RIGHT"); - } - - // Process boolean flags - it = section.find("show_real_freqs"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showRealFreqs = !(key == "FALSE"); - } - - it = section.find("real_temps"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->realTemps = (key == "TRUE"); - } - - it = section.find("show_deltas"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showDeltas = !(key == "FALSE"); - } - - it = section.find("show_target_freqs"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showTargetFreqs = !(key == "FALSE"); - } - - it = section.find("show_fps"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showFPS = !(key == "FALSE"); - } - - it = section.find("show_res"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showRES = !(key == "FALSE"); - } - - it = section.find("show_read_speed"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->showRDSD = !(key == "FALSE"); - } - - it = section.find("ram_info_mode"); - if (it != section.end()) { - settings->ramInfoMode = it->second; - } - - it = section.find("use_dynamic_colors"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->useDynamicColors = (key == "TRUE"); - } - - // Process disable screenshots - it = section.find("disable_screenshots"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->disableScreenshots = (key != "FALSE"); - } - - it = section.find("separator_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->separatorColor = temp; - } - - it = section.find("cat_color_1"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->catColor1 = temp; - } - - it = section.find("cat_color_2"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->catColor2 = temp; - } - - it = section.find("text_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->textColor = temp; - } -} - -ALWAYS_INLINE void GetConfigSettings(ResolutionSettings* settings) { - // Initialize defaults - convertStrToRGBA4444("#0009", &(settings->backgroundColor)); - convertStrToRGBA4444("#000F", &(settings->focusBackgroundColor)); - convertStrToRGBA4444("#8FFF", &(settings->catColor)); - //convertStrToRGBA4444("#8CFF", &(settings->catColor2)); - convertStrToRGBA4444("#FFFF", &(settings->textColor)); - settings->refreshRate = 10; - //ettings->setPos = 0; - settings->disableScreenshots = false; - - settings->frameOffsetX = 10; - settings->frameOffsetY = 10; - settings->framePadding = 10; - - - // Open and read file efficiently - FILE* configFile = fopen(configIniPath, "r"); - if (!configFile) return; - - fseek(configFile, 0, SEEK_END); - const long fileSize = ftell(configFile); - fseek(configFile, 0, SEEK_SET); - - std::string fileData; - fileData.resize(fileSize); - fread(fileData.data(), 1, fileSize, configFile); - fclose(configFile); - - auto parsedData = ult::parseIni(fileData); - - // Cache section lookup - auto sectionIt = parsedData.find("game_resolutions"); - if (sectionIt == parsedData.end()) return; - - std::string key; - - const auto& section = sectionIt->second; - - // Process refresh_rate - auto it = section.find("refresh_rate"); - if (it != section.end()) { - settings->refreshRate = std::clamp(atol(it->second.c_str()), 1L, 60L); - } - - uint16_t temp; - - // Process colors - it = section.find("background_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->backgroundColor = temp; - } - - it = section.find("focus_background_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->focusBackgroundColor = temp; - } - - it = section.find("cat_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->catColor = temp; - } - - //it = section.find("cat_color_2"); - //if (it != section.end()) { - // temp = 0; - // if (convertStrToRGBA4444(it->second, &temp)) - // settings->catColor2 = temp; - //} - - - it = section.find("text_color"); - if (it != section.end()) { - temp = 0; - if (convertStrToRGBA4444(it->second, &temp)) - settings->textColor = temp; - } - - it = section.find("frame_offset_x"); - if (it != section.end()) { - settings->frameOffsetX = atol(it->second.c_str()); - } - - it = section.find("frame_offset_y"); - if (it != section.end()) { - settings->frameOffsetY = atol(it->second.c_str()); - } - - it = section.find("frame_padding"); - if (it != section.end()) { - settings->framePadding = atol(it->second.c_str()); - } - - // Process alignment settings - //it = section.find("layer_width_align"); - //if (it != section.end()) { - // key = it->second; - // convertToUpper(key); - // if (key == "CENTER") { - // settings->setPos = 1; - // } else if (key == "RIGHT") { - // settings->setPos = 2; - // } - //} - // - //it = section.find("layer_height_align"); - //if (it != section.end()) { - // key = it->second; - // convertToUpper(key); - // if (key == "CENTER") { - // settings->setPos += 3; - // } else if (key == "BOTTOM") { - // settings->setPos += 6; - // } - //} - - // Process disable screenshots - it = section.find("disable_screenshots"); - if (it != section.end()) { - key = it->second; - convertToUpper(key); - settings->disableScreenshots = (key != "FALSE"); - } -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/audsnoop.c b/Source/Horizon-OC-Monitor (deprecated)/source/audsnoop.c deleted file mode 100644 index 6bc801f9..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/audsnoop.c +++ /dev/null @@ -1,35 +0,0 @@ -#define NX_SERVICE_ASSUME_NON_DOMAIN -#include -#include - -static Service g_audsnoopSrv; - -NX_GENERATE_SERVICE_GUARD(audsnoop); - -Result _audsnoopInitialize(void) { - return smGetService(&g_audsnoopSrv, "auddev"); -} - -void _audsnoopCleanup(void) { - serviceClose(&g_audsnoopSrv); -} - -Service* audsnoopGetServiceSession(void) { - return &g_audsnoopSrv; -} - -Result audsnoopEnableDspUsageMeasurement(void) { - return serviceDispatch(&g_audsnoopSrv, 0); -} - -Result audsnoopDisableDspUsageMeasurement(void) { - return serviceDispatch(&g_audsnoopSrv, 1); -} - -Result audsnoopGetDspUsage(u32 *usage) { - u32 tmp = 0; - Result rc = serviceDispatchOut(&g_audsnoopSrv, 6, tmp); - if (R_SUCCEEDED(rc) && usage) - *usage = tmp; - return rc; -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/main.cpp b/Source/Horizon-OC-Monitor (deprecated)/source/main.cpp deleted file mode 100644 index 082fb503..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/main.cpp +++ /dev/null @@ -1,1164 +0,0 @@ -#define TESLA_INIT_IMPL -#include -#include "Utils.hpp" -#include -#include - -//static tsl::elm::HeaderOverlayFrame* rootFrame = nullptr; -static bool skipMain = false; -static std::string lastSelectedItem; - -#include "modes/FPS_Counter.hpp" -#include "modes/FPS_Graph.hpp" -#include "modes/Full.hpp" -#include "modes/Mini.hpp" -#include "modes/Micro.hpp" -#include "modes/Battery.hpp" -#include "modes/Misc.hpp" -#include "modes/Resolutions.hpp" -#include "modes/Configurator.hpp" - - - -//Graphs -//class GraphsMenu : public tsl::Gui { -//public: -// GraphsMenu() {} -// -// virtual tsl::elm::Element* createUI() override { -// -// auto* list = new tsl::elm::List(); -// -// list->addItem(new tsl::elm::CategoryHeader("FPS")); -// -// auto* comFPSGraph = new tsl::elm::ListItem("Graph"); -// comFPSGraph->setClickListener([](uint64_t keys) { -// if (keys & KEY_A) { -// tsl::swapTo(); -// return true; -// } -// return false; -// }); -// list->addItem(comFPSGraph); -// -// auto* comFPSCounter = new tsl::elm::ListItem("Counter"); -// comFPSCounter->setClickListener([](uint64_t keys) { -// if (keys & KEY_A) { -// tsl::swapTo(); -// return true; -// } -// return false; -// }); -// list->addItem(comFPSCounter); -// -// tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", "Modes"); -// rootFrame->setContent(list); -// -// return rootFrame; -// } -// -// virtual void update() override { -// if (fixForeground) { -// fixForeground = false; -// tsl::hlp::requestForeground(true); -// } -// } -// -// virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { -// if (disableJumpTo) -// disableJumpTo = false; -// if (fixHiding) { -// if (isKeyComboPressed2(keysDown, keysHeld)) { -// tsl::Overlay::get()->hide(); -// fixHiding = false; -// return true; -// } -// } -// -// if (keysDown & KEY_B) { -// tsl::goBack(); -// return true; -// } -// return false; -// } -//}; - -//Other -class OtherMenu : public tsl::Gui { -public: - OtherMenu() { } - - virtual tsl::elm::Element* createUI() override { - - auto* list = new tsl::elm::List(); - - list->addItem(new tsl::elm::CategoryHeader("Other")); - - auto* Battery = new tsl::elm::ListItem("Battery/Charger"); - Battery->disableClickAnimation(); - Battery->setClickListener([](uint64_t keys) { - if (keys & KEY_A) { - tsl::swapTo(); - return true; - } - return false; - }); - list->addItem(Battery); - - auto* Misc = new tsl::elm::ListItem("Miscellaneous"); - Misc->disableClickAnimation(); - Misc->setClickListener([](uint64_t keys) { - if (keys & KEY_A) { - tsl::swapTo(); - return true; - } - return false; - }); - list->addItem(Misc); - - //if (SaltySD) { - // auto* Res = new tsl::elm::ListItem("Game Resolutions"); - // Res->setClickListener([](uint64_t keys) { - // if (keys & KEY_A) { - // tsl::swapTo(); - // return true; - // } - // return false; - // }); - // list->addItem(Res); - //} - //tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", "Modes"); - if (!lastSelectedItem.empty()) - list->jumpToItem(lastSelectedItem); - - rootFrame->setContent(list); - - return rootFrame; - } - - virtual void update() override { - if (fixForeground) { - fixForeground = false; - tsl::hlp::requestForeground(true); - } - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (disableJumpTo) - disableJumpTo = false; - if (fixHiding) { - if (isKeyComboPressed2(keysDown, keysHeld)) { - tsl::Overlay::get()->hide(); - fixHiding = false; - return true; - } - } - - if (keysDown & KEY_B) { - lastSelectedItem = "Other"; - tsl::swapTo(); - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - return true; - } - return false; - } -}; - -//Main Menu -class MainMenu : public tsl::Gui { -public: - MainMenu() { - if (lastMode != "returning") - lastMode = ""; - } - - virtual tsl::elm::Element* createUI() override { - - auto* list = new tsl::elm::List(); - - //list->addItem(new tsl::elm::CategoryHeader("Modes " + ult::DIVIDER_SYMBOL + " \uE0E0 Enter " + ult::DIVIDER_SYMBOL + " \uE0E3 Configure")); - list->addItem(new tsl::elm::CategoryHeader("Modes " + ult::DIVIDER_SYMBOL + " \uE0E3 Configure")); - - auto* Full = new tsl::elm::ListItem("Full"); - Full->disableClickAnimation(); - Full->setClickListener([](uint64_t keys) { - if (keys & KEY_A) { - lastMode = "full"; - tsl::swapTo(); - return true; - } - if (keys & KEY_Y) { - triggerRumbleClick.store(true, std::memory_order_release); - triggerSettingsSound.store(true, std::memory_order_release); - // Launch configurator for Mini mode - tsl::swapTo("Full"); - return true; - } - return false; - }); - list->addItem(Full); - //auto* Mini = new tsl::elm::ListItem("Mini"); - //Mini->setClickListener([](uint64_t keys) { - // if (keys & KEY_A) { - // tsl::swapTo(); - // return true; - // } - // return false; - //}); - //list->addItem(Mini); - - bool fileExist = false; - FILE* test = fopen(std::string(folderpath + filename).c_str(), "rb"); - if (test) { - fclose(test); - fileExist = true; - filepath = folderpath + filename; - } - else { - test = fopen(std::string(folderpath + "Status-Monitor-Overlay.ovl").c_str(), "rb"); - if (test) { - fclose(test); - fileExist = true; - filepath = folderpath + "Status-Monitor-Overlay.ovl"; - } - } - if (fileExist) { - auto* Mini = new tsl::elm::ListItem("Mini"); - Mini->disableClickAnimation(); - Mini->setClickListener([](uint64_t keys) { - if (keys & KEY_A) { - tsl::setNextOverlay(filepath, "-mini_"); - tsl::Overlay::get()->close(); - return true; - } - if (keys & KEY_Y) { - triggerRumbleClick.store(true, std::memory_order_release); - triggerSettingsSound.store(true, std::memory_order_release); - // Launch configurator for Mini mode - tsl::swapTo("Mini"); - return true; - } - return false; - }); - list->addItem(Mini); - - auto* Micro = new tsl::elm::ListItem("Micro"); - Micro->disableClickAnimation(); - Micro->setClickListener([](uint64_t keys) { - if (keys & KEY_A) { - tsl::setNextOverlay(filepath, "-micro_"); - tsl::Overlay::get()->close(); - return true; - } - if (keys & KEY_Y) { - triggerRumbleClick.store(true, std::memory_order_release); - triggerSettingsSound.store(true, std::memory_order_release); - // Launch configurator for Micro mode - tsl::swapTo("Micro"); - return true; - } - return false; - }); - list->addItem(Micro); - } - if (SaltySD) { - //auto* Graphs = new tsl::elm::ListItem("FPS"); - //Graphs->setValue(ult::DROPDOWN_SYMBOL); - //Graphs->setClickListener([](uint64_t keys) { - // if (keys & KEY_A) { - // tsl::swapTo(); - // return true; - // } - // return false; - //}); - //list->addItem(Graphs); - - auto* comFPSGraph = new tsl::elm::ListItem("FPS Graph"); - comFPSGraph->disableClickAnimation(); - comFPSGraph->setClickListener([](uint64_t keys) { - //if (keys & KEY_A) { - // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); - // lastMode = "fps_graph"; - // tsl::swapTo(); - // return true; - //} - if (keys & KEY_A) { - tsl::setNextOverlay(filepath, "-fps_graph_"); - tsl::Overlay::get()->close(); - return true; - } - - if (keys & KEY_Y) { - triggerRumbleClick.store(true, std::memory_order_release); - triggerSettingsSound.store(true, std::memory_order_release); - // Launch configurator for Micro mode - tsl::swapTo("FPS Graph"); - return true; - } - return false; - }); - list->addItem(comFPSGraph); - - auto* comFPSCounter = new tsl::elm::ListItem("FPS Counter"); - comFPSCounter->disableClickAnimation(); - comFPSCounter->setClickListener([](uint64_t keys) { - //if (keys & KEY_A) { - // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); - // lastMode = "fps_counter"; - // tsl::swapTo(); - // return true; - //} - if (keys & KEY_A) { - tsl::setNextOverlay(filepath, "-fps_counter_"); - tsl::Overlay::get()->close(); - return true; - } - - if (keys & KEY_Y) { - triggerRumbleClick.store(true, std::memory_order_release); - triggerSettingsSound.store(true, std::memory_order_release); - // Launch configurator for Micro mode - tsl::swapTo("FPS Counter"); - return true; - } - return false; - }); - list->addItem(comFPSCounter); - - auto* Res = new tsl::elm::ListItem("Game Resolutions"); - Res->disableClickAnimation(); - Res->setClickListener([](uint64_t keys) { - //if (keys & KEY_A) { - // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); - // lastMode = "game_resolutions"; - // tsl::swapTo(); - // return true; - //} - if (keys & KEY_A) { - tsl::setNextOverlay(filepath, "-game_resolutions_"); - tsl::Overlay::get()->close(); - return true; - } - if (keys & KEY_Y) { - triggerRumbleClick.store(true, std::memory_order_release); - triggerSettingsSound.store(true, std::memory_order_release); - // Launch configurator for Micro mode - tsl::swapTo("Game Resolutions"); - return true; - } - return false; - }); - list->addItem(Res); - - } - auto* Other = new tsl::elm::ListItem("Other"); - Other->disableClickAnimation(); - Other->setValue(ult::DROPDOWN_SYMBOL); - Other->setClickListener([](uint64_t keys) { - if (keys & KEY_A) { - triggerRumbleClick.store(true, std::memory_order_release); - triggerEnterSound.store(true, std::memory_order_release); - tsl::swapTo(); - return true; - } - return false; - }); - list->addItem(Other); - - if (!lastSelectedItem.empty()) - list->jumpToItem(lastSelectedItem); - - //list->disableCaching(); - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION); - rootFrame->setContent(list); - - return rootFrame; - } - - virtual void update() override { - if (!ult::useRightAlignment) { - //if ((tsl::cfg::LayerPosX || tsl::cfg::LayerPosY)) { - tsl::gfx::Renderer::get().setLayerPos(0, 0); - //} - } else { - const auto [horizontalUnderscanPixels, verticalUnderscanPixels] = tsl::gfx::getUnderscanPixels(); - tsl::gfx::Renderer::get().setLayerPos(1280-32 - horizontalUnderscanPixels, 0); - } - if (fixForeground) { - fixForeground = false; - tsl::hlp::requestForeground(true); - } - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (disableJumpTo) - disableJumpTo = false; - if (fixHiding) { - if (isKeyComboPressed2(keysDown, keysHeld)) { - tsl::Overlay::get()->hide(); - fixHiding = false; - return true; - } - } - - if (keysDown & KEY_B) { - tsl::goBack(); - return true; - } - return false; - } -}; - -class MonitorOverlay : public tsl::Overlay { -public: - - virtual void initServices() override { - //Initialize services - tsl::hlp::doWithSmSession([this]{ - - apmInitialize(); - - if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); - - if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { - pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001); - } - - if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); - - psmCheck = psmInitialize(); - if (R_SUCCEEDED(psmCheck)) { - psmService = psmGetServiceSession(); - } - i2cCheck = i2cInitialize(); - - SaltySD = CheckPort(); - - if (SaltySD) { - LoadSharedMemoryAndRefreshRate(); - } - if (hocclkIpcRunning() && R_SUCCEEDED(hocclkIpcInitialize())) { - uint32_t hocClkApiVer = 0; - hocclkIpcGetAPIVersion(&hocClkApiVer); - if (hocClkApiVer != HOCCLK_IPC_API_VERSION) { - hocclkIpcExit(); - } - else hocclkCheck = 0; - } - if (R_SUCCEEDED(splInitialize())) { - u64 sku = 0; - splGetConfig(SplConfigItem_HardwareType, &sku); - switch(sku) { - case 2 ... 5: - isMariko = true; - break; - default: - isMariko = false; - } - } - splExit(); - - }); - Hinted = envIsSyscallHinted(0x6F); - } - - virtual void exitServices() override { - CloseThreads(); - if (R_SUCCEEDED(hocclkCheck)) { - hocclkIpcExit(); - } - shmemClose(&_sharedmemory); - //Exit services - tsExit(); - tcExit(); - pwmChannelSessionClose(&g_ICon); - pwmExit(); - nvClose(fd); - nvExit(); - psmExit(); - i2cExit(); - apmExit(); - } - - virtual void onShow() override {} // Called before overlay wants to change from invisible to visible state - virtual void onHide() override {} // Called before overlay wants to change from visible to invisible state - - virtual std::unique_ptr loadInitialGui() override { - return initially(); // Initial Gui to load. It's possible to pass arguments to it's constructor like this - } -}; - -class MicroMode : public tsl::Overlay { -public: - - virtual void initServices() override { - //tsl::hlp::requestForeground(false); - //Initialize services - tsl::hlp::doWithSmSession([this]{ - apmInitialize(); - - if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); - - if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); - - if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { - pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001); - } - - i2cCheck = i2cInitialize(); - - psmCheck = psmInitialize(); - if (R_SUCCEEDED(psmCheck)) { - psmService = psmGetServiceSession(); - } - - SaltySD = CheckPort(); - - if (SaltySD) { - LoadSharedMemory(); - } - if (hocclkIpcRunning() && R_SUCCEEDED(hocclkIpcInitialize())) { - uint32_t hocClkApiVer = 0; - hocclkIpcGetAPIVersion(&hocClkApiVer); - if (hocClkApiVer != HOCCLK_IPC_API_VERSION) { - hocclkIpcExit(); - } - else hocclkCheck = 0; - } - if (R_SUCCEEDED(splInitialize())) { - u64 sku = 0; - splGetConfig(SplConfigItem_HardwareType, &sku); - switch(sku) { - case 2 ... 5: - isMariko = true; - break; - default: - isMariko = false; - } - } - splExit(); - }); - Hinted = envIsSyscallHinted(0x6F); - } - - virtual void exitServices() override { - CloseThreads(); - shmemClose(&_sharedmemory); - if (R_SUCCEEDED(hocclkCheck)) { - hocclkIpcExit(); - } - //Exit services - tsExit(); - tcExit(); - pwmChannelSessionClose(&g_ICon); - pwmExit(); - i2cExit(); - psmExit(); - nvClose(fd); - nvExit(); - apmExit(); - } - - virtual void onShow() override { // Called before overlay wants to change from invisible to visible state - tsl::hlp::requestForeground(false); - } - virtual void onHide() override {} // Called before overlay wants to change from visible to invisible state - - virtual std::unique_ptr loadInitialGui() override { - return initially(); // Initial Gui to load. It's possible to pass arguments to it's constructor like this - } -}; - -class MiniEntryOverlay : public tsl::Overlay { -public: - MiniEntryOverlay() {} - - virtual void initServices() override { - - //tsl::hlp::requestForeground(false); - // Same service‐init as before - tsl::hlp::doWithSmSession([this]{ - apmInitialize(); - - if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); - - if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); - - if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { - pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001); - } - - i2cCheck = i2cInitialize(); - - psmCheck = psmInitialize(); - if (R_SUCCEEDED(psmCheck)) { - psmService = psmGetServiceSession(); - } - - SaltySD = CheckPort(); - - if (SaltySD) { - LoadSharedMemory(); - } - if (hocclkIpcRunning() && R_SUCCEEDED(hocclkIpcInitialize())) { - uint32_t hocClkApiVer = 0; - hocclkIpcGetAPIVersion(&hocClkApiVer); - if (hocClkApiVer != HOCCLK_IPC_API_VERSION) { - hocclkIpcExit(); - } - else hocclkCheck = 0; - } - if (R_SUCCEEDED(splInitialize())) { - u64 sku = 0; - splGetConfig(SplConfigItem_HardwareType, &sku); - switch(sku) { - case 2 ... 5: - isMariko = true; - break; - default: - isMariko = false; - } - } - splExit(); - }); - Hinted = envIsSyscallHinted(0x6F); - - } - - virtual void exitServices() override { - CloseThreads(); - shmemClose(&_sharedmemory); - if (R_SUCCEEDED(hocclkCheck)) { - hocclkIpcExit(); - } - // Exit services - tsExit(); - tcExit(); - pwmChannelSessionClose(&g_ICon); - pwmExit(); - i2cExit(); - psmExit(); - nvClose(fd); - nvExit(); - apmExit(); - } - - // **Override onShow** so that as soon as this Overlay appears, we let input pass through. - virtual void onShow() override { - // Request that Tesla stop grabbing all buttons/touches - tsl::hlp::requestForeground(false); - - // (Optional) hide Tesla’s footer if you don’t want it - //deactivateOriginalFooter = true; - } - - virtual std::unique_ptr loadInitialGui() override { - // Immediately show your MiniOverlay page - return initially(); - } -}; - -class FPSGraphEntryOverlay : public tsl::Overlay { -public: - FPSGraphEntryOverlay() {} - - virtual void initServices() override { - tsl::hlp::doWithSmSession([this]{ - apmInitialize(); - - if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); - - if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); - - if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { - pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001); - } - - i2cCheck = i2cInitialize(); - - psmCheck = psmInitialize(); - if (R_SUCCEEDED(psmCheck)) { - psmService = psmGetServiceSession(); - } - - SaltySD = CheckPort(); - - if (SaltySD) { - LoadSharedMemoryAndRefreshRate(); - } - if (hocclkIpcRunning() && R_SUCCEEDED(hocclkIpcInitialize())) { - uint32_t hocClkApiVer = 0; - hocclkIpcGetAPIVersion(&hocClkApiVer); - if (hocClkApiVer != HOCCLK_IPC_API_VERSION) { - hocclkIpcExit(); - } - else hocclkCheck = 0; - } - if (R_SUCCEEDED(splInitialize())) { - u64 sku = 0; - splGetConfig(SplConfigItem_HardwareType, &sku); - switch(sku) { - case 2 ... 5: - isMariko = true; - break; - default: - isMariko = false; - } - } - splExit(); - }); - Hinted = envIsSyscallHinted(0x6F); - } - - virtual void exitServices() override { - CloseThreads(); - shmemClose(&_sharedmemory); - if (R_SUCCEEDED(hocclkCheck)) { - hocclkIpcExit(); - } - tsExit(); - tcExit(); - pwmChannelSessionClose(&g_ICon); - pwmExit(); - i2cExit(); - psmExit(); - nvClose(fd); - nvExit(); - apmExit(); - } - - virtual void onShow() override { - tsl::hlp::requestForeground(false); - //deactivateOriginalFooter = true; - } - - virtual std::unique_ptr loadInitialGui() override { - return initially(); - } -}; - -class FPSCounterEntryOverlay : public tsl::Overlay { -public: - FPSCounterEntryOverlay() {} - - virtual void initServices() override { - tsl::hlp::doWithSmSession([this]{ - apmInitialize(); - - if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); - - if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); - - if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { - pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001); - } - - i2cCheck = i2cInitialize(); - - psmCheck = psmInitialize(); - if (R_SUCCEEDED(psmCheck)) { - psmService = psmGetServiceSession(); - } - - SaltySD = CheckPort(); - - if (SaltySD) { - LoadSharedMemoryAndRefreshRate(); - } - if (hocclkIpcRunning() && R_SUCCEEDED(hocclkIpcInitialize())) { - uint32_t hocClkApiVer = 0; - hocclkIpcGetAPIVersion(&hocClkApiVer); - if (hocClkApiVer != HOCCLK_IPC_API_VERSION) { - hocclkIpcExit(); - } - else hocclkCheck = 0; - } - if (R_SUCCEEDED(splInitialize())) { - u64 sku = 0; - splGetConfig(SplConfigItem_HardwareType, &sku); - switch(sku) { - case 2 ... 5: - isMariko = true; - break; - default: - isMariko = false; - } - } - splExit(); - }); - Hinted = envIsSyscallHinted(0x6F); - } - - virtual void exitServices() override { - CloseThreads(); - shmemClose(&_sharedmemory); - if (R_SUCCEEDED(hocclkCheck)) { - hocclkIpcExit(); - } - tsExit(); - tcExit(); - pwmChannelSessionClose(&g_ICon); - pwmExit(); - i2cExit(); - psmExit(); - nvClose(fd); - nvExit(); - apmExit(); - } - - virtual void onShow() override { - tsl::hlp::requestForeground(false); - //deactivateOriginalFooter = true; - } - - virtual std::unique_ptr loadInitialGui() override { - return initially(); - } -}; - -class GameResolutionsEntryOverlay : public tsl::Overlay { -public: - GameResolutionsEntryOverlay() {} - - virtual void initServices() override { - tsl::hlp::doWithSmSession([this]{ - apmInitialize(); - - if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu"); - - if (hosversionAtLeast(5,0,0)) tcCheck = tcInitialize(); - - if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) { - pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001); - } - - i2cCheck = i2cInitialize(); - - psmCheck = psmInitialize(); - if (R_SUCCEEDED(psmCheck)) { - psmService = psmGetServiceSession(); - } - - SaltySD = CheckPort(); - - if (SaltySD) { - LoadSharedMemoryAndRefreshRate(); - } - if (hocclkIpcRunning() && R_SUCCEEDED(hocclkIpcInitialize())) { - uint32_t hocClkApiVer = 0; - hocclkIpcGetAPIVersion(&hocClkApiVer); - if (hocClkApiVer != HOCCLK_IPC_API_VERSION) { - hocclkIpcExit(); - } - else hocclkCheck = 0; - } - if (R_SUCCEEDED(splInitialize())) { - u64 sku = 0; - splGetConfig(SplConfigItem_HardwareType, &sku); - switch(sku) { - case 2 ... 5: - isMariko = true; - break; - default: - isMariko = false; - } - } - splExit(); - }); - Hinted = envIsSyscallHinted(0x6F); - } - - virtual void exitServices() override { - CloseThreads(); - shmemClose(&_sharedmemory); - if (R_SUCCEEDED(hocclkCheck)) { - hocclkIpcExit(); - } - tsExit(); - tcExit(); - pwmChannelSessionClose(&g_ICon); - pwmExit(); - i2cExit(); - psmExit(); - nvClose(fd); - nvExit(); - apmExit(); - } - - virtual void onShow() override { - tsl::hlp::requestForeground(false); - //deactivateOriginalFooter = true; - } - - virtual std::unique_ptr loadInitialGui() override { - return initially(); - } -}; - - -// Helper function to check if overlay file exists -bool checkOverlayFile(const std::string& filename) { - struct stat buffer; - return stat(filename.c_str(), &buffer) == 0; -} - -// Helper function to setup micro mode paths -inline void setupMode(const std::string& modeType = "") { - - if (modeType == "micro") { - if (!ult::limitedMemory) { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 720; - } else { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 28; - } - } else { - if (!ult::limitedMemory) { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 720; - } - } - - // Try user-specified filename first, then fallback to default - const std::string primaryPath = folderpath + filename; - - if (checkOverlayFile(primaryPath)) { - filepath = primaryPath; - } else { - const std::string fallbackPath = folderpath + "Status-Monitor-Overlay.ovl"; - if (checkOverlayFile(fallbackPath)) { - filepath = fallbackPath; - } - } -} - -//void setupMicroMode() { -// ult::DefaultFramebufferWidth = 1280; -// //ult::DefaultFramebufferHeight = 28; -// ult::DefaultFramebufferHeight = 720; -// -// // Try user-specified filename first, then fallback to default -// const std::string primaryPath = folderpath + filename; -// -// if (checkOverlayFile(primaryPath)) { -// filepath = primaryPath; -// } else { -// const std::string fallbackPath = folderpath + "Status-Monitor-Overlay.ovl"; -// if (checkOverlayFile(fallbackPath)) { -// filepath = fallbackPath; -// } -// } -//} - - -// This function gets called on startup to create a new Overlay object -int main(int argc, char **argv) { - - // load heap settings outside of loop (only Status Monitor directive) - ult::currentHeapSize = ult::getCurrentHeapSize(); - ult::expandedMemory = ult::currentHeapSize >= ult::OverlayHeapSize::Size_8MB; - ult::limitedMemory = ult::currentHeapSize == ult::OverlayHeapSize::Size_4MB; - - - // Initialize buffer sizes based on expanded memory setting - if (ult::expandedMemory) { - ult::furtherExpandedMemory = ult::currentHeapSize > ult::OverlayHeapSize::Size_8MB; - - if (!ult::furtherExpandedMemory) { - ult::loaderTitle += "+"; - ult::COPY_BUFFER_SIZE = 262144; - ult::HEX_BUFFER_SIZE = 8192; - ult::UNZIP_READ_BUFFER = 262144; - ult::UNZIP_WRITE_BUFFER = 131072; - ult::DOWNLOAD_READ_BUFFER = 131072; - ult::DOWNLOAD_WRITE_BUFFER = 131072; - } else { - ult::loaderTitle += "×"; - ult::COPY_BUFFER_SIZE = 262144*2; - ult::HEX_BUFFER_SIZE = 8192; - ult::UNZIP_READ_BUFFER = 262144*2; - ult::UNZIP_WRITE_BUFFER = 131072*4; - ult::DOWNLOAD_READ_BUFFER = 131072*4; - ult::DOWNLOAD_WRITE_BUFFER = 131072*4; - } - } else if (ult::limitedMemory) { - ult::loaderTitle += "-"; - ult::DOWNLOAD_READ_BUFFER = 16*1024; - ult::UNZIP_READ_BUFFER = 16*1024; - } - - systemtickfrequency = armGetSystemTickFreq(); - ParseIniFile(); // parse INI from file - - if (argc > 0) { - filename = argv[0]; // set global - - { - // Read the entire INI file once - auto iniData = ult::getParsedDataFromIniFile(ult::OVERLAYS_INI_FILEPATH); - - auto sectionIt = iniData.find(filename); - if (sectionIt != iniData.end()) { - auto& section = sectionIt->second; - - // Compare and update if values differ - const std::string expectedArgs = "(-mini, -micro, -fps_graph, -fps_counter, -game_resolutions)"; - - if (section["mode_args"] != expectedArgs) { - section["mode_args"] = expectedArgs; - section["mode_labels"] = "(Mini, Micro, FPS Graph, FPS Counter, Game Resolutions)"; - ult::saveIniFileData(ult::OVERLAYS_INI_FILEPATH, iniData); - } - } else { - // If section doesn't exist, create it with expected values - iniData[filename]["mode_args"] = "(-mini, -micro, -fps_graph, -fps_counter, -game_resolutions)"; - iniData[filename]["mode_labels"] = "(Mini, Micro, FPS Graph, FPS Counter, Game Resolutions)"; - ult::saveIniFileData(ult::OVERLAYS_INI_FILEPATH, iniData); - } - } - - // Process command line arguments - for (u8 arg = 0; arg < argc; arg++) { - const char* argStr = argv[arg]; - if (argStr[0] != '-') continue; - - // Check if ends with underscore and create comparison string without it - const size_t len = strlen(argStr); - const bool hasUnderscore = (len > 1 && argStr[len-1] == '_'); - - // For underscore variants, compare without the trailing underscore - char modeStr[32]; - const char* compareStr; - if (hasUnderscore) { - strncpy(modeStr, argStr, len - 1); - modeStr[len - 1] = '\0'; - compareStr = modeStr; - } else { - compareStr = argStr; - } - - // Micro mode - if (strcasecmp(compareStr, "-micro") == 0) { - FullMode = false; - lastMode = "micro"; - if (hasUnderscore) { - setupMode(lastMode); - } else { - skipMain = true; - - if (!ult::limitedMemory) { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 720; - } else { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 28; - } - } - return tsl::loop(argc, argv); - } - // Mini mode - else if (strcasecmp(compareStr, "-mini") == 0) { - FullMode = false; - lastMode = "mini"; - if (hasUnderscore) { - setupMode(); - } else { - skipMain = true; - if (!ult::limitedMemory) { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 720; - } - } - return tsl::loop(argc, argv); - } - // FPS Graph mode - else if (strcasecmp(compareStr, "-fps_graph") == 0) { - FullMode = false; - lastMode = "fps_graph"; - if (hasUnderscore) { - setupMode(); - } else { - skipMain = true; - if (!ult::limitedMemory) { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 720; - } - } - return tsl::loop(argc, argv); - } - // FPS Counter mode - else if (strcasecmp(compareStr, "-fps_counter") == 0) { - FullMode = false; - lastMode = "fps_counter"; - if (hasUnderscore) { - setupMode(); - } else { - skipMain = true; - if (!ult::limitedMemory) { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 720; - } - } - return tsl::loop(argc, argv); - } - // Game Resolutions mode - else if (strcasecmp(compareStr, "-game_resolutions") == 0) { - FullMode = false; - lastMode = "game_resolutions"; - if (hasUnderscore) { - setupMode(); - } else { - skipMain = true; - if (!ult::limitedMemory) { - ult::DefaultFramebufferWidth = 1280; - ult::DefaultFramebufferHeight = 720; - } - } - return tsl::loop(argc, argv); - } - // Handle --lastSelectedItem (multi-token argument) - else if (strcmp(argStr, "--lastSelectedItem") == 0 && arg + 1 < argc) { - lastSelectedItem.clear(); - - for (++arg; arg < argc; ++arg) { - const char* token = argv[arg]; - - // Stop if we hit another flag - if (token[0] == '-' && !lastSelectedItem.empty()) - break; - - // Add space separator - if (!lastSelectedItem.empty()) - lastSelectedItem += ' '; - - lastSelectedItem += token; - - // Stop if token ends with quote - const char lastChar = token[strlen(token) - 1]; - if (lastChar == '"' || lastChar == '\'') { - ++arg; - break; - } - } - - // Clean up quotes and whitespace - ult::removeQuotes(lastSelectedItem); - - // Trim whitespace - const size_t start = lastSelectedItem.find_first_not_of(" \t"); - if (start != std::string::npos) { - const size_t end = lastSelectedItem.find_last_not_of(" \t"); - lastSelectedItem = lastSelectedItem.substr(start, end - start + 1); - } else { - lastSelectedItem.clear(); - } - } - } - } - - // Default case - return tsl::loop(argc, argv); -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Battery.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/Battery.hpp deleted file mode 100644 index c996ed06..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Battery.hpp +++ /dev/null @@ -1,220 +0,0 @@ -class OtherMenu; - -class BatteryOverlay : public tsl::Gui { -private: - // Separated value buffers - char actualCapacity_c[32] = ""; - char designedCapacity_c[32] = ""; - char batteryTemp_c[32] = ""; - char rawCharge_c[32] = ""; - char batteryAge_c[32] = ""; - char voltageAvg_c[64] = ""; - char currentFlow_c[64] = ""; - char powerFlow_c[64] = ""; - char remainingTime_c[16] = ""; - char inputCurrentLimit_c[32] = ""; - char vbusCurrentLimit_c[32] = ""; - char chargeVoltageLimit_c[32] = ""; - char chargeCurrentLimit_c[32] = ""; - char chargerType_c[32] = ""; - char chargerMaxVoltage_c[32] = ""; - char chargerMaxCurrent_c[32] = ""; - - bool skipOnce = true; - bool runOnce = true; - bool isChargerConnected = false; - FullSettings settings; -public: - BatteryOverlay() { - GetConfigSettings(&settings); - disableJumpTo = true; - mutexInit(&mutex_BatteryChecker); - StartBatteryThread(); - // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); - } - ~BatteryOverlay() { - CloseBatteryThread(); - fixForeground = true; - } - - virtual tsl::elm::Element* createUI() override { - - auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - static constexpr u16 Y_OFFSET = 40; - static constexpr u16 X_OFFSET = 20; - static const u16 LABEL_X = 20 + X_OFFSET; - static const u16 VALUE_X = 240+ X_OFFSET; - static const u16 START_Y = 155 + Y_OFFSET; - static constexpr u16 LINE_HEIGHT = 18; - static constexpr u8 FONT_SIZE = 18; - static const tsl::Color LABEL_COLOR_1= settings.catColor1; - static const tsl::Color LABEL_COLOR_2 = settings.catColor2; - static const tsl::Color VALUE_COLOR = settings.textColor; - - renderer->drawString("Battery Stats", false, LABEL_X, 120 + Y_OFFSET, 20, LABEL_COLOR_1); - - u16 currentY = START_Y; - - // Actual Capacity - renderer->drawString("Actual Capacity", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(actualCapacity_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Designed Capacity - renderer->drawString("Designed Capacity", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(designedCapacity_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Temperature - renderer->drawString("Temperature", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(batteryTemp_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Raw Charge - renderer->drawString("Raw Charge", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(rawCharge_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Age - renderer->drawString("Age", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(batteryAge_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Voltage - renderer->drawString("Voltage", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(voltageAvg_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Current Flow - renderer->drawString("Current Flow", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(currentFlow_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Power Flow - renderer->drawString("Power Flow", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(powerFlow_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Remaining Time - renderer->drawString("Remaining Time", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(remainingTime_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Charger-specific fields (only shown when charger is connected) - if (isChargerConnected) { - currentY += 3*LINE_HEIGHT; - renderer->drawString("Charger Stats", false, LABEL_X, currentY, 20, LABEL_COLOR_1); - currentY += 2*LINE_HEIGHT; - // Input Current Limit - renderer->drawString("Input Current Limit", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(inputCurrentLimit_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // VBUS Current Limit - renderer->drawString("VBUS Current Limit", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(vbusCurrentLimit_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Charge Voltage Limit - renderer->drawString("Voltage Limit", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(chargeVoltageLimit_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Charge Current Limit - renderer->drawString("Current Limit", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(chargeCurrentLimit_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Charger Type - renderer->drawString("Type", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(chargerType_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Charger Max Voltage - renderer->drawString("Max Voltage", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(chargerMaxVoltage_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - currentY += LINE_HEIGHT; - - // Charger Max Current - renderer->drawString("Max Current", false, LABEL_X, currentY, FONT_SIZE, LABEL_COLOR_2); - renderer->drawString(chargerMaxCurrent_c, false, VALUE_X, currentY, FONT_SIZE, VALUE_COLOR); - } - }); - - // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION, true); - rootFrame->setContent(Status); - - return rootFrame; - } - - virtual void update() override { - mutexLock(&mutex_BatteryChecker); - - char tempBatTimeEstimate[8] = "--:--"; - if (batTimeEstimate >= 0) { - snprintf(tempBatTimeEstimate, sizeof(tempBatTimeEstimate), "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); - } - - const BatteryChargeInfoFieldsChargerType ChargerConnected = hosversionAtLeast(17,0,0) ? - ((BatteryChargeInfoFields17*)&_batteryChargeInfoFields)->ChargerType : - _batteryChargeInfoFields.ChargerType; - const int32_t ChargerVoltageLimit = hosversionAtLeast(17,0,0) ? - ((BatteryChargeInfoFields17*)&_batteryChargeInfoFields)->ChargerVoltageLimit : - _batteryChargeInfoFields.ChargerVoltageLimit; - const int32_t ChargerCurrentLimit = hosversionAtLeast(17,0,0) ? - ((BatteryChargeInfoFields17*)&_batteryChargeInfoFields)->ChargerCurrentLimit : - _batteryChargeInfoFields.ChargerCurrentLimit; - - isChargerConnected = (ChargerConnected != 0); - - // Format all values - snprintf(actualCapacity_c, sizeof(actualCapacity_c), "%.0f mAh", actualFullBatCapacity); - snprintf(designedCapacity_c, sizeof(designedCapacity_c), "%.0f mAh", designedFullBatCapacity); - snprintf(batteryTemp_c, sizeof(batteryTemp_c), "%.1f\u00B0C", (float)_batteryChargeInfoFields.BatteryTemperature / 1000); - snprintf(rawCharge_c, sizeof(rawCharge_c), "%.1f%%", (float)_batteryChargeInfoFields.RawBatteryCharge / 1000); - snprintf(batteryAge_c, sizeof(batteryAge_c), "%.1f%%", (float)_batteryChargeInfoFields.BatteryAge / 1000); - snprintf(voltageAvg_c, sizeof(voltageAvg_c), "%.0f mV (%ds)", batVoltageAvg, batteryFiltered ? 45 : 5); - snprintf(currentFlow_c, sizeof(currentFlow_c), "%+.0f mA (%ss)", batCurrentAvg, batteryFiltered ? "11.25" : "5"); - snprintf(powerFlow_c, sizeof(powerFlow_c), "%+.3f W%s", PowerConsumption, batteryFiltered ? "" : " (5s)"); - snprintf(remainingTime_c, sizeof(remainingTime_c), "%s", tempBatTimeEstimate); - - if (isChargerConnected) { - snprintf(inputCurrentLimit_c, sizeof(inputCurrentLimit_c), "%d mA", _batteryChargeInfoFields.InputCurrentLimit); - snprintf(vbusCurrentLimit_c, sizeof(vbusCurrentLimit_c), "%d mA", _batteryChargeInfoFields.VBUSCurrentLimit); - snprintf(chargeVoltageLimit_c, sizeof(chargeVoltageLimit_c), "%d mV", _batteryChargeInfoFields.ChargeVoltageLimit); - snprintf(chargeCurrentLimit_c, sizeof(chargeCurrentLimit_c), "%d mA", _batteryChargeInfoFields.ChargeCurrentLimit); - snprintf(chargerType_c, sizeof(chargerType_c), "%u", ChargerConnected); - snprintf(chargerMaxVoltage_c, sizeof(chargerMaxVoltage_c), "%u mV", ChargerVoltageLimit); - snprintf(chargerMaxCurrent_c, sizeof(chargerMaxCurrent_c), "%u mA", ChargerCurrentLimit); - } - - mutexUnlock(&mutex_BatteryChecker); - - if (!skipOnce) { - if (runOnce) { - isRendering = true; - leventClear(&renderingStopEvent); - runOnce = false; - } - } else { - skipOnce = false; - } - } - - virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { - if (keysDown & KEY_B) { - isRendering = false; - leventSignal(&renderingStopEvent); - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - skipOnce = true; - runOnce = true; - lastSelectedItem = "Battery/Charger"; - lastMode = ""; - tsl::swapTo(); - return true; - } - return false; - } -}; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Configurator.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/Configurator.hpp deleted file mode 100644 index b18c940b..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Configurator.hpp +++ /dev/null @@ -1,2290 +0,0 @@ -/* - * Mode-Specific Configuration Settings - * - * Based on actual settings structures, each mode only shows applicable settings: - * - * Mini Mode: Refresh Rate, Colors (background, focus_background, separator, category, text), - * Toggles, Font Sizes, Elements, DTC Format - * - * Micro Mode: Refresh Rate, Colors (background, separator, category, text), Toggles, - * Font Sizes, Elements, Text Alignment, Vertical Position (Top/Bottom only), DTC Format - * - * Full Mode: Refresh Rate, Toggles (show_real_freqs, show_deltas, etc.), - * Horizontal Position (Left/Right only) - NO colors, fonts, or elements - * - * FPS Counter: Refresh Rate, Colors (background, text only), Font Sizes, - * Horizontal/Vertical Position - * - * FPS Graph: Refresh Rate, Colors (8 graph-specific colors), Toggles (show_info only), - * Horizontal/Vertical Position - NO fonts - * - * Game Resolutions: Refresh Rate, Colors (background, category, text only), - * Horizontal/Vertical Position - NO toggles, fonts, or elements - */ - -#pragma once -#include -#include "../Utils.hpp" - -#include - -// External variables for navigation -extern std::string jumpItemName; -extern std::string jumpItemValue; -extern std::atomic jumpItemExactMatch; -static tsl::elm::ListItem* lastSelectedListItem; - -// Forward declarations -class ConfiguratorOverlay; -class RefreshRateConfig; -class FontSizeConfig; -class FontSizeSelector; -class ColorConfig; -class ColorSelector; -class AlphaSelector; -class ShowConfig; -class TogglesConfig; -class DTCFormatConfig; - -// Helper functions for color manipulation -inline std::string extractColorWithoutAlpha(const std::string& rgba) { - if (rgba.length() >= 5 && rgba[0] == '#') { - return rgba.substr(0, 4); // Return #RGB without alpha - } - return rgba; -} - -inline std::string extractAlphaFromColor(const std::string& rgba) { - if (rgba.length() == 5 && rgba[0] == '#') { - return std::string(1, rgba[4]); // Return just the alpha character - } - return "9"; // Default alpha -} - -inline std::string setAlphaInColor(const std::string& rgba, char alpha) { - if (rgba.length() >= 4 && rgba[0] == '#') { - std::string result = rgba.substr(0, 4); // Get #RGB - result += alpha; // Add new alpha - return result; - } - return rgba; -} - -// Alpha Selector for background colors -class AlphaSelector : public tsl::Gui { -private: - std::string modeName; - std::string colorKey; - std::string title; - bool isMiniMode; - bool isMicroMode; - bool isFPSCounterMode; - bool isFPSGraphMode; - bool isGameResolutionsMode; - -public: - AlphaSelector(const std::string& mode, const std::string& key, const std::string& displayTitle) - : modeName(mode), colorKey(key), title(displayTitle) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - isFPSCounterMode = (mode == "FPS Counter"); - isFPSGraphMode = (mode == "FPS Graph"); - isGameResolutionsMode = (mode == "Game Resolutions"); - } - ~AlphaSelector() { - lastSelectedListItem = nullptr; - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader(title)); - - std::string section; - if (isMiniMode) section = "mini"; - else if (isMicroMode) section = "micro"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - else if (isGameResolutionsMode) section = "game_resolutions"; - - // Get current color value and extract alpha - std::string currentColor = ult::parseValueFromIniSection(configIniPath, section, colorKey); - if (currentColor.empty()) { - currentColor = "#0009"; // Default - } - std::string currentAlpha = extractAlphaFromColor(currentColor); - - // Alpha options - static const std::vector> alphaOptions = { - {"Transparent", '0'}, - {"10%", '1'}, - {"20%", '3'}, - {"30%", '4'}, - {"40%", '6'}, - {"50%", '8'}, - {"60%", '9'}, - {"70%", 'B'}, - {"80%", 'C'}, - {"90%", 'E'}, - {"Opaque", 'F'} - }; - - for (const auto& option : alphaOptions) { - auto* alphaItem = new tsl::elm::ListItem(option.first); - if (currentAlpha[0] == option.second) { - alphaItem->setValue(ult::CHECKMARK_SYMBOL); - lastSelectedListItem = alphaItem; - } - alphaItem->setClickListener([this, alphaItem, option, section, currentColor](uint64_t keys) { - if (keys & KEY_A) { - // Get current color and update only the alpha - std::string color = ult::parseValueFromIniSection(configIniPath, section, colorKey); - if (color.empty()) color = "#0009"; - - std::string newColor = setAlphaInColor(color, option.second); - ult::setIniFileValue(configIniPath, section, colorKey, newColor); - - alphaItem->setValue(ult::CHECKMARK_SYMBOL); - if (lastSelectedListItem && lastSelectedListItem != alphaItem) { - lastSelectedListItem->setValue(""); - } - lastSelectedListItem = alphaItem; - return true; - } - return false; - }); - list->addItem(alphaItem); - } - - list->jumpToItem("", ult::CHECKMARK_SYMBOL, false); - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Alpha"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - jumpItemName = title; - jumpItemValue = ""; - jumpItemExactMatch = false; - - tsl::swapTo(SwapDepth(2), modeName); - return true; - } - return false; - } -}; - - -// Define available DTC format options -static const std::vector> dtcFormats = { - // Special - {"Pretty", "%a, %b %d"+ult::DIVIDER_SYMBOL+"%I:%M %p"}, - {"Compact", "%Y%m%d"+ult::DIVIDER_SYMBOL+"%H:%M:%S"}, - {"FileSafe", "%Y-%m-%d"+ult::DIVIDER_SYMBOL+"%H-%M-%S"}, - {"Day+Time", "%a"+ult::DIVIDER_SYMBOL+"%H:%M"}, - - // Datetime (default included here) - {"Date+Time(s)", "%m-%d-%Y"+ult::DIVIDER_SYMBOL+"%H:%M:%S"}, // default - {"Date+Time AM/PM", "%m-%d-%Y"+ult::DIVIDER_SYMBOL+"%I:%M %p"}, - {"Date+Time(s) AM/PM", "%m-%d-%Y"+ult::DIVIDER_SYMBOL+"%I:%M:%S %p"}, - {"Date+Time EU", "%d/%m/%Y"+ult::DIVIDER_SYMBOL+"%H:%M"}, - {"Date+Time EU AM/PM", "%d/%m/%Y"+ult::DIVIDER_SYMBOL+"%I:%M %p"}, - {"Date+Time(s) EU AM/PM", "%d/%m/%Y"+ult::DIVIDER_SYMBOL+"%I:%M:%S %p"}, - {"Date+Time ISO", "%Y-%m-%dT"+ult::DIVIDER_SYMBOL+"%H:%M:%S"}, - - // Time only - {"Time 24h", "%H:%M"}, - {"Time AM/PM", "%I:%M %p"}, - {"Time(s) 24h", "%H:%M:%S"}, - {"Time(s) AM/PM", "%I:%M:%S %p"}, - - // Date only - {"Date US", "%m-%d-%Y"}, - {"Date EU", "%d/%m/%Y"}, - {"Date ISO", "%Y-%m-%d"}, - {"Date Short", "%m/%d/%y"} -}; - -// DTC Format Configuration (Mini/Micro only) -class DTCFormatConfig : public tsl::Gui { -private: - std::string modeName; - bool isMiniMode; - bool isMicroMode; - -public: - DTCFormatConfig(const std::string& mode) : modeName(mode) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - } - ~DTCFormatConfig() { - lastSelectedListItem = nullptr; - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader("DTC Format")); - - const std::string section = isMiniMode ? "mini" : "micro"; - std::string currentValue = ult::parseValueFromIniSection(configIniPath, section, "dtc_format"); - - // Handle default values - if (currentValue.empty()) { - currentValue = isMiniMode ? "%m-%d-%Y"+ult::DIVIDER_SYMBOL+"%H:%M:%S" : "%H:%M:%S"; - } - - - for (const auto& format : dtcFormats) { - auto* formatItem = new tsl::elm::ListItem(format.first); - //formatItem->setValue(format.second); - if (format.second == currentValue) { - formatItem->setValue(ult::CHECKMARK_SYMBOL); - lastSelectedListItem = formatItem; - } - formatItem->setClickListener([this, formatItem, format, section](uint64_t keys) { - if (keys & KEY_A) { - ult::setIniFileValue(configIniPath, section, "dtc_format", format.second); - formatItem->setValue(ult::CHECKMARK_SYMBOL); - if (lastSelectedListItem && lastSelectedListItem != formatItem) { - lastSelectedListItem->setValue(""); - } - lastSelectedListItem = formatItem; - return true; - } - return false; - }); - list->addItem(formatItem); - } - - // Jump to currently selected item - list->jumpToItem("", ult::CHECKMARK_SYMBOL, false); - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "DTC Format"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - jumpItemName = "DTC Format"; - jumpItemValue = ""; - jumpItemExactMatch = false; - - tsl::swapTo(SwapDepth(2), modeName); - return true; - } - return false; - } -}; - -// Toggles Configuration -class TogglesConfig : public tsl::Gui { -private: - std::string modeName; - bool isMiniMode; - bool isMicroMode; - bool isFullMode; - bool isFPSGraphMode; - bool isGameResolutionsMode; - bool isFPSCounterMode; - -public: - TogglesConfig(const std::string& mode) : modeName(mode) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - isFullMode = (mode == "Full"); - isFPSGraphMode = (mode == "FPS Graph"); - isGameResolutionsMode = (mode == "Game Resolutions"); - isFPSCounterMode = (mode == "FPS Counter"); - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader("Toggles")); - - if (isFPSGraphMode) { - // FPS Graph: show_info and disable_screenshots - auto* showInfo = new tsl::elm::ToggleListItem("Info", getCurrentShowInfo()); - showInfo->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "fps-graph", "show_info", state ? "true" : "false"); - }); - list->addItem(showInfo); - - auto* realTemps = new tsl::elm::ToggleListItem("Real Temperatures", getCurrentFPSGraphRealTemps()); - realTemps->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "fps-graph", "real_temps", state ? "true" : "false"); - }); - list->addItem(realTemps); - - auto* dynamicColors = new tsl::elm::ToggleListItem("Use Dynamic Colors", getCurrentUseDynamicColors()); - dynamicColors->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "fps-graph", "use_dynamic_colors", state ? "true" : "false"); - }); - list->addItem(dynamicColors); - - auto* disableScreenshots = new tsl::elm::ToggleListItem("Disable Screenshots", getCurrentDisableScreenshots("fps-graph")); - disableScreenshots->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "fps-graph", "disable_screenshots", state ? "true" : "false"); - }); - list->addItem(disableScreenshots); - - } else if (isFullMode) { - // Full mode: specific full toggles - auto* realFreqs = new tsl::elm::ToggleListItem("Real Freqs", getCurrentShowRealFreqs()); - realFreqs->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "full", "show_real_freqs", state ? "true" : "false"); - }); - list->addItem(realFreqs); - - auto* realTemps = new tsl::elm::ToggleListItem("Real Temperatures", getCurrentFullRealTemps()); - realTemps->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "full", "real_temps", state ? "true" : "false"); - }); - list->addItem(realTemps); - - auto* showDeltas = new tsl::elm::ToggleListItem("Deltas", getCurrentShowDeltas()); - showDeltas->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "full", "show_deltas", state ? "true" : "false"); - }); - list->addItem(showDeltas); - - auto* targetFreqs = new tsl::elm::ToggleListItem("Target Freqs", getCurrentShowTargetFreqs()); - targetFreqs->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "full", "show_target_freqs", state ? "true" : "false"); - }); - list->addItem(targetFreqs); - - auto* showFPS = new tsl::elm::ToggleListItem("FPS", getCurrentShowFPS()); - showFPS->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "full", "show_fps", state ? "true" : "false"); - }); - list->addItem(showFPS); - - auto* showRES = new tsl::elm::ToggleListItem("RES", getCurrentShowRES()); - showRES->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "full", "show_res", state ? "true" : "false"); - }); - list->addItem(showRES); - - auto* showRDSD = new tsl::elm::ToggleListItem("Read Speed", getCurrentShowRDSD()); - showRDSD->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "full", "show_read_speed", state ? "true" : "false"); - }); - list->addItem(showRDSD); - - { - const std::string curRamInfoMode = getCurrentRamInfoMode("full"); - auto* ramInfoModeItem = new tsl::elm::ListItem("RAM Info Mode"); - ramInfoModeItem->setValue(curRamInfoMode); - ramInfoModeItem->setClickListener([this, ramInfoModeItem](u64 keys) -> bool { - if (!(keys & KEY_A)) return false; - const std::string cur = ult::parseValueFromIniSection(configIniPath, "full", "ram_info_mode"); - const std::string next = cur == "Bandwidth" ? "Load" : "Bandwidth"; - ult::setIniFileValue(configIniPath, "full", "ram_info_mode", next); - ramInfoModeItem->setValue(next); - return true; - }); - list->addItem(ramInfoModeItem); - } - - auto* dynamicColors = new tsl::elm::ToggleListItem("Use Dynamic Colors", getCurrentUseDynamicColors()); - dynamicColors->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "fps-graph", "use_dynamic_colors", state ? "true" : "false"); - }); - list->addItem(dynamicColors); - - auto* disableScreenshots = new tsl::elm::ToggleListItem("Disable Screenshots", getCurrentDisableScreenshots("full")); - disableScreenshots->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "full", "disable_screenshots", state ? "true" : "false"); - }); - list->addItem(disableScreenshots); - - } else if (isMiniMode || isMicroMode) { - // Mini/Micro modes: shared toggles - const std::string section = isMiniMode ? "mini" : "micro"; - - auto* realFreqs = new tsl::elm::ToggleListItem("Real Frequencies", getCurrentRealFreqs()); - realFreqs->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "real_freqs", state ? "true" : "false"); - }); - list->addItem(realFreqs); - - auto* realVolts = new tsl::elm::ToggleListItem("Real Voltages", getCurrentRealVolts()); - realVolts->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "real_volts", state ? "true" : "false"); - }); - list->addItem(realVolts); - - auto* realTemps = new tsl::elm::ToggleListItem("Real Temperatures", getCurrentRealTemps()); - realTemps->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "real_temps", state ? "true" : "false"); - }); - list->addItem(realTemps); - - auto* showFullCPU = new tsl::elm::ToggleListItem("Full CPU", getCurrentShowFullCPU()); - showFullCPU->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "show_full_cpu", state ? "true" : "false"); - }); - list->addItem(showFullCPU); - - auto* showVDDQ = new tsl::elm::ToggleListItem("VDDQ", getCurrentShowVDDQ()); - showVDDQ->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "show_vddq", state ? "true" : "false"); - }); - list->addItem(showVDDQ); - - auto* showVDD2 = new tsl::elm::ToggleListItem("VDD2", getCurrentShowVDD2()); - showVDD2->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "show_vdd2", state ? "true" : "false"); - }); - list->addItem(showVDD2); - - auto* showFullRes = new tsl::elm::ToggleListItem("Full Resolution", getCurrentShowFullRes()); - showFullRes->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "show_full_res", state ? "true" : "false"); - }); - list->addItem(showFullRes); - - auto* socVoltage = new tsl::elm::ToggleListItem("SOC Voltage", getCurrentShowSOCVoltage()); - socVoltage->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "show_soc_voltage", state ? "true" : "false"); - }); - list->addItem(socVoltage); - - if (isMiniMode) { - auto* partLoadCPUGPU = new tsl::elm::ToggleListItem("RAM Load CPU/GPU", getCurrentShowpartLoadCPUGPU()); - partLoadCPUGPU->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "show_RAM_load_CPU_GPU", state ? "true" : "false"); - }); - list->addItem(partLoadCPUGPU); - } - - if (isMiniMode || isMicroMode) { - const std::string curRamInfoMode = getCurrentRamInfoMode(section); - auto* ramInfoModeItem = new tsl::elm::ListItem("RAM Info Mode"); - ramInfoModeItem->setValue(curRamInfoMode); - ramInfoModeItem->setClickListener([this, section, ramInfoModeItem](u64 keys) -> bool { - if (!(keys & KEY_A)) return false; - const std::string cur = ult::parseValueFromIniSection(configIniPath, section, "ram_info_mode"); - const std::string next = cur == "Bandwidth" ? "Load" : "Bandwidth"; - ult::setIniFileValue(configIniPath, section, "ram_info_mode", next); - ramInfoModeItem->setValue(next); - return true; - }); - list->addItem(ramInfoModeItem); - } - - if (isMiniMode || isMicroMode) { - auto* invertBatteryDisplay = new tsl::elm::ToggleListItem("Invert Battery Display", getCurrentInvertBatteryDisplay()); - invertBatteryDisplay->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "invert_battery_display", state ? "true" : "false"); - }); - list->addItem(invertBatteryDisplay); - } - - auto* dtcSymbol = new tsl::elm::ToggleListItem("Use DTC Symbol", getCurrentUseDTCSymbol()); - dtcSymbol->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "use_dtc_symbol", state ? "true" : "false"); - }); - list->addItem(dtcSymbol); - - auto* dynamicColors = new tsl::elm::ToggleListItem("Use Dynamic Colors", getCurrentUseDynamicColors()); - dynamicColors->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "use_dynamic_colors", state ? "true" : "false"); - }); - list->addItem(dynamicColors); - - auto* disableScreenshots = new tsl::elm::ToggleListItem("Disable Screenshots", getCurrentDisableScreenshots(section)); - disableScreenshots->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "disable_screenshots", state ? "true" : "false"); - }); - list->addItem(disableScreenshots); - - auto* sleepExit = new tsl::elm::ToggleListItem("Sleep Exit", getCurrentSleepExit(section)); - sleepExit->setStateChangedListener([this, section](bool state) { - ult::setIniFileValue(configIniPath, section, "sleep_exit", state ? "true" : "false"); - }); - list->addItem(sleepExit); - - } else if (isGameResolutionsMode) { - // Game Resolutions mode: only disable_screenshots - auto* disableScreenshots = new tsl::elm::ToggleListItem("Disable Screenshots", getCurrentDisableScreenshots("game_resolutions")); - disableScreenshots->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "game_resolutions", "disable_screenshots", state ? "true" : "false"); - }); - list->addItem(disableScreenshots); - - } else if (isFPSCounterMode) { - // FPS Counter mode: only disable_screenshots - auto* integerCounter = new tsl::elm::ToggleListItem("Use Integer Counter", getCurrentUseIntegerCounter("fps-counter")); - integerCounter->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "fps-counter", "use_integer_counter", state ? "true" : "false"); - }); - list->addItem(integerCounter); - - // FPS Counter mode: only disable_screenshots - auto* disableScreenshots = new tsl::elm::ToggleListItem("Disable Screenshots", getCurrentDisableScreenshots("fps-counter")); - disableScreenshots->setStateChangedListener([this](bool state) { - ult::setIniFileValue(configIniPath, "fps-counter", "disable_screenshots", state ? "true" : "false"); - }); - list->addItem(disableScreenshots); - } - - list->jumpToItem(jumpItemName, jumpItemValue, jumpItemExactMatch); - { - jumpItemName = ""; - jumpItemValue = ""; - jumpItemExactMatch = false; - } - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Configuration"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - tsl::goBack(); - return true; - } - return false; - } - -private: - // Helper methods for getting current toggle states - bool getCurrentShowInfo() { - std::string value = ult::parseValueFromIniSection(configIniPath, "fps-graph", "show_info"); - if (value.empty()) return true; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentFPSGraphRealTemps() { - std::string value = ult::parseValueFromIniSection(configIniPath, "fps-graph", "real_temps"); - if (value.empty()) return false; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentRealFreqs() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "real_freqs"); - if (value.empty()) return true; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentRealVolts() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "real_volts"); - if (value.empty()) return true; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentRealTemps() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "real_temps"); - if (value.empty()) return true; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentShowFullCPU() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "show_full_cpu"); - if (value.empty()) return false; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentShowVDDQ() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "show_vddq"); - if (value.empty()) return false; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentShowVDD2() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "show_vdd2"); - if (value.empty()) return true; - convertToUpper(value); - return value == "TRUE"; - } - - - bool getCurrentShowFullRes() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "show_full_res"); - if (value.empty()) return true; // Default: true for mini, false for micro - convertToUpper(value); - return value != "FALSE"; - } - - bool getCurrentShowSOCVoltage() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "show_soc_voltage"); - if (value.empty()) return false; // Default: false for mini, true for micro - convertToUpper(value); - return value != "FALSE"; - } - - bool getCurrentShowpartLoadCPUGPU() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "show_RAM_load_CPU_GPU"); - if (value.empty()) return false; // Default: false for mini, true for micro - convertToUpper(value); - return value != "FALSE"; - } - - std::string getCurrentRamInfoMode(const std::string& section) { - const std::string value = ult::parseValueFromIniSection(configIniPath, section, "ram_info_mode"); - return (value == "Bandwidth") ? "Bandwidth" : "Load"; - } - - bool getCurrentInvertBatteryDisplay() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "invert_battery_display"); - if (value.empty()) return isMiniMode ? true : false; // Default: false for mini, true for micro - convertToUpper(value); - return value != "FALSE"; - } - - bool getCurrentUseDTCSymbol() { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "use_dtc_symbol"); - if (value.empty()) return true; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentUseDynamicColors() { - const std::string section = isFPSGraphMode? "fps-graph" : (isMiniMode ? "mini" : "micro"); - std::string value = ult::parseValueFromIniSection(configIniPath, section, "use_dynamic_colors"); - if (value.empty()) return true; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentUseIntegerCounter(const std::string& section) { - std::string value = ult::parseValueFromIniSection(configIniPath, section, "use_integer_counter"); - if (value.empty()) return false; // Default is false (screenshots enabled) - convertToUpper(value); - return value != "FALSE"; // True if not explicitly "FALSE" - } - - bool getCurrentDisableScreenshots(const std::string& section) { - std::string value = ult::parseValueFromIniSection(configIniPath, section, "disable_screenshots"); - if (value.empty()) return false; // Default is false (screenshots enabled) - convertToUpper(value); - return value != "FALSE"; // True if not explicitly "FALSE" - } - - bool getCurrentSleepExit(const std::string& section) { - std::string value = ult::parseValueFromIniSection(configIniPath, section, "sleep_exit"); - if (value.empty()) return false; - convertToUpper(value); - return value != "FALSE"; // True if not explicitly "FALSE" - } - - // Full mode toggle helpers - bool getCurrentShowRealFreqs() { - std::string value = ult::parseValueFromIniSection(configIniPath, "full", "show_real_freqs"); - if (value.empty()) return true; - convertToUpper(value); - return value != "FALSE"; - } - - bool getCurrentFullRealTemps() { - std::string value = ult::parseValueFromIniSection(configIniPath, "full", "real_temps"); - if (value.empty()) return false; - convertToUpper(value); - return value == "TRUE"; - } - - bool getCurrentShowDeltas() { - std::string value = ult::parseValueFromIniSection(configIniPath, "full", "show_deltas"); - if (value.empty()) return true; - convertToUpper(value); - return value != "FALSE"; - } - - bool getCurrentShowTargetFreqs() { - std::string value = ult::parseValueFromIniSection(configIniPath, "full", "show_target_freqs"); - if (value.empty()) return true; - convertToUpper(value); - return value != "FALSE"; - } - - bool getCurrentShowFPS() { - std::string value = ult::parseValueFromIniSection(configIniPath, "full", "show_fps"); - if (value.empty()) return true; - convertToUpper(value); - return value != "FALSE"; - } - - bool getCurrentShowRES() { - std::string value = ult::parseValueFromIniSection(configIniPath, "full", "show_res"); - if (value.empty()) return true; - convertToUpper(value); - return value != "FALSE"; - } - - bool getCurrentShowRDSD() { - std::string value = ult::parseValueFromIniSection(configIniPath, "full", "show_read_speed"); - if (value.empty()) return true; - convertToUpper(value); - return value != "FALSE"; - } -}; - -// Refresh Rate Configuration -class RefreshRateConfig : public tsl::Gui { -private: - std::string modeName; - bool isMiniMode; - bool isMicroMode; - bool isFullMode; - bool isGameResolutionsMode; - bool isFPSCounterMode; - bool isFPSGraphMode; - int currentRate; - -public: - RefreshRateConfig(const std::string& mode) : modeName(mode) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - isFullMode = (mode == "Full"); - isGameResolutionsMode = (mode == "Game Resolutions"); - isFPSCounterMode = (mode == "FPS Counter"); - isFPSGraphMode = (mode == "FPS Graph"); - - std::string section; - if (isMiniMode) section = "mini"; - else if (isMicroMode) section = "micro"; - else if (isFullMode) section = "full"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - const std::string value = ult::parseValueFromIniSection(configIniPath, section, "refresh_rate"); - int defaultRate = (isGameResolutionsMode) ? 10 : ((isFPSCounterMode || isFPSGraphMode) ? 30 : 1); - currentRate = value.empty() ? defaultRate : std::clamp(atoi(value.c_str()), 1, 60); - } - - ~RefreshRateConfig() { - lastSelectedListItem = nullptr; - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader("Refresh Rate")); - - static const std::vector rates = {1, 2, 3, 5, 10, 15, 30, 60}; - for (int rate : rates) { - auto* rateItem = new tsl::elm::ListItem(std::to_string(rate) + " Hz"); - if (rate == currentRate) { - rateItem->setValue(ult::CHECKMARK_SYMBOL); - lastSelectedListItem = rateItem; - } - rateItem->setClickListener([this, rateItem, rate](uint64_t keys) { - if (keys & KEY_A) { - std::string section; - if (isMiniMode) section = "mini"; - else if (isMicroMode) section = "micro"; - else if (isFullMode) section = "full"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - ult::setIniFileValue(configIniPath, section, "refresh_rate", std::to_string(rate)); - rateItem->setValue(ult::CHECKMARK_SYMBOL); - if (lastSelectedListItem && rateItem != lastSelectedListItem) - lastSelectedListItem->setValue(""); - lastSelectedListItem = rateItem; - return true; - } - return false; - }); - list->addItem(rateItem); - } - - list->jumpToItem("", ult::CHECKMARK_SYMBOL, false); - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Configuration"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - jumpItemName = "Refresh Rate"; - jumpItemValue = ""; - jumpItemExactMatch = false; - - tsl::swapTo(SwapDepth(2), modeName); - return true; - } - return false; - } -}; - -// Frame Padding Configuration (Mini only) -class FramePaddingConfig : public tsl::Gui { -private: - std::string modeName; - int currentPadding; - -public: - FramePaddingConfig(const std::string& mode) : modeName(mode) { - const std::string value = ult::parseValueFromIniSection(configIniPath, "mini", "frame_padding"); - currentPadding = value.empty() ? 10 : std::clamp(atoi(value.c_str()), 0, 14); // max value 14 - } - - ~FramePaddingConfig() { - lastSelectedListItem = nullptr; - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader("Frame Padding")); - - static const std::vector paddingValues = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}; - for (int padding : paddingValues) { - auto* paddingItem = new tsl::elm::ListItem(std::to_string(padding) + " px"); - if (padding == currentPadding) { - paddingItem->setValue(ult::CHECKMARK_SYMBOL); - lastSelectedListItem = paddingItem; - } - paddingItem->setClickListener([this, paddingItem, padding](uint64_t keys) { - if (keys & KEY_A) { - ult::setIniFileValue(configIniPath, "mini", "frame_padding", std::to_string(padding)); - paddingItem->setValue(ult::CHECKMARK_SYMBOL); - if (lastSelectedListItem && paddingItem != lastSelectedListItem) - lastSelectedListItem->setValue(""); - lastSelectedListItem = paddingItem; - return true; - } - return false; - }); - list->addItem(paddingItem); - } - - list->jumpToItem("", ult::CHECKMARK_SYMBOL, false); - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Configuration"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - jumpItemName = "Frame Padding"; - jumpItemValue = ""; - jumpItemExactMatch = false; - - tsl::swapTo(SwapDepth(2), modeName); - return true; - } - return false; - } -}; - - -// Font Size Selector -class FontSizeSelector : public tsl::Gui { -private: - std::string modeName; - std::string fontType; - bool isMiniMode; - bool isMicroMode; - bool isFPSCounterMode; - std::string title; - -public: - FontSizeSelector(const std::string& mode, const std::string& type) - : modeName(mode), fontType(type) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - isFPSCounterMode = (mode == "FPS Counter"); - title = fontType; - title[0] = std::toupper(title[0]); - title += " Font Size"; - } - ~FontSizeSelector() { - lastSelectedListItem = nullptr; - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader(title)); - - std::string section; - if (isMiniMode) section = "mini"; - else if (isMicroMode) section = "micro"; - else if (isFPSCounterMode) section = "fps-counter"; - - const std::string keyName = fontType + "_font_size"; - const std::string currentValue = ult::parseValueFromIniSection(configIniPath, section, keyName); - int defaultSize = isFPSCounterMode ? 40 : 15; - const int currentSize = currentValue.empty() ? defaultSize : atoi(currentValue.c_str()); - - // Font size range depends on mode - int minSize = 8; - int maxSize; - if (isFPSCounterMode) maxSize = 150; - else if (isMiniMode) maxSize = 22; - else maxSize = 18; // Micro mode - - for (int size = minSize; size <= maxSize; size++) { - auto* sizeItem = new tsl::elm::ListItem(std::to_string(size) + " pt"); - if (size == currentSize) { - sizeItem->setValue(ult::CHECKMARK_SYMBOL); - lastSelectedListItem = sizeItem; - } - sizeItem->setClickListener([this, sizeItem, size, keyName, section](uint64_t keys) { - if (keys & KEY_A) { - ult::setIniFileValue(configIniPath, section, keyName, std::to_string(size)); - sizeItem->setValue(ult::CHECKMARK_SYMBOL); - if (lastSelectedListItem && lastSelectedListItem != sizeItem) - lastSelectedListItem->setValue(""); - lastSelectedListItem = sizeItem; - return true; - } - return false; - }); - list->addItem(sizeItem); - } - - list->jumpToItem("", ult::CHECKMARK_SYMBOL, false); - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Font Sizes"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - jumpItemName = title; - jumpItemValue = ""; - jumpItemExactMatch = false; - - tsl::swapTo(SwapDepth(2), modeName); - return true; - } - return false; - } -}; - -// Font Size Configuration -class FontSizeConfig : public tsl::Gui { -private: - std::string modeName; - bool isMiniMode; - bool isMicroMode; - bool isFPSCounterMode; - -public: - FontSizeConfig(const std::string& mode) : modeName(mode) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - isFPSCounterMode = (mode == "FPS Counter"); - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader("Font Sizes")); - - std::string section; - if (isMiniMode) section = "mini"; - else if (isMicroMode) section = "micro"; - else if (isFPSCounterMode) section = "fps-counter"; - - const std::string handheldValue = ult::parseValueFromIniSection(configIniPath, section, "handheld_font_size"); - const std::string dockedValue = ult::parseValueFromIniSection(configIniPath, section, "docked_font_size"); - - int defaultSize = isFPSCounterMode ? 40 : 15; - const int handheldSize = handheldValue.empty() ? defaultSize : atoi(handheldValue.c_str()); - const int dockedSize = dockedValue.empty() ? defaultSize : atoi(dockedValue.c_str()); - - auto* handheldItem = new tsl::elm::ListItem("Handheld Font Size"); - handheldItem->setValue(std::to_string(handheldSize) + " pt"); - handheldItem->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "handheld"); - return true; - } - return false; - }); - list->addItem(handheldItem); - - auto* dockedItem = new tsl::elm::ListItem("Docked Font Size"); - dockedItem->setValue(std::to_string(dockedSize) + " pt"); - dockedItem->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "docked"); - return true; - } - return false; - }); - list->addItem(dockedItem); - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Configuration"); - rootFrame->setContent(list); - list->jumpToItem(jumpItemName, jumpItemValue, jumpItemExactMatch); - { - jumpItemName = ""; - jumpItemValue = ""; - jumpItemExactMatch = false; - } - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - tsl::goBack(); - return true; - } - return false; - } -}; - -// Color Selector -class ColorSelector : public tsl::Gui { -private: - std::string modeName; - std::string modeTitle; - std::string colorKey; - std::string defaultValue; - bool isMiniMode; - bool isMicroMode; - bool isFullMode; - bool isGameResolutionsMode; - bool isFPSCounterMode; - bool isFPSGraphMode; - bool isBackgroundColor; - bool isTextBasedColor; - -public: - ColorSelector(const std::string& mode, const std::string& title, const std::string& key, const std::string& def) - : modeName(mode), modeTitle(title), colorKey(key), defaultValue(def) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - isFullMode = (mode == "Full"); - isGameResolutionsMode = (mode == "Game Resolutions"); - isFPSCounterMode = (mode == "FPS Counter"); - isFPSGraphMode = (mode == "FPS Graph"); - - // Determine if this is a background color or text-based color - isBackgroundColor = (key == "background_color" || key == "focus_background_color" || - (isFPSGraphMode && (key == "fps_counter_color" || key == "dashed_line_color"))); - - isTextBasedColor = (key == "text_color" || key == "separator_color" || key == "cat_color" || - (isFPSGraphMode && (key == "border_color" || key == "max_fps_text_color" || - key == "min_fps_text_color" || key == "main_line_color" || - key == "rounded_line_color" || key == "perfect_line_color"))); - } - - ~ColorSelector() { - lastSelectedListItem = nullptr; - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader(modeTitle)); - - std::string section; - if (isMiniMode) section = "mini"; - else if (isMicroMode) section = "micro"; - else if (isFullMode) section = "full"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - std::string currentValue = ult::parseValueFromIniSection(configIniPath, section, colorKey); - if (currentValue.empty()) currentValue = defaultValue; - - // Extract the color without alpha for comparison (for backgrounds and text colors) - std::string currentColorWithoutAlpha = extractColorWithoutAlpha(currentValue); - - // Updated colors list with comprehensive color palette - static const std::vector> colors = { - // Grays & Basics - {"Black", "#000F"}, - {"Dark Gray", "#333F"}, - {"Gray", "#444F"}, - {"Light Gray", "#888F"}, - {"Silver", "#CCCF"}, - {"White", "#FFFF"}, - - // Reds - {"Dark Red", "#800F"}, - {"Red", "#F00F"}, - {"Light Red", "#F88F"}, - {"Pink", "#F8AF"}, - - // Greens - {"Dark Green", "#080F"}, - {"Green", "#0F0F"}, - {"Lime Green", "#0C0F"}, - {"Light Green", "#8F8F"}, - - // Blues - {"Dark Blue", "#003F"}, - {"Blue", "#00FF"}, - {"Light Blue", "#2DFF"}, - {"Sky Blue", "#8CFF"}, - - // Purples - {"Dark Purple", "#808F"}, - {"Purple", "#80FF"}, - {"Light Purple", "#C8FF"}, - {"Violet", "#A0FF"}, - - // Yellows & Oranges - {"Orange", "#F80F"}, - {"Yellow", "#FF0F"}, - {"Light Yellow", "#FFCF"}, - - // Cyans & Teals - {"Teal", "#088F"}, - {"Cyan", "#0FFF"}, - {"Light Cyan", "#8FFF"}, - - // Magentas & Pinks - {"Magenta", "#F0FF"}, - {"Hot Pink", "#F8CF"}, - - // Browns - {"Brown", "#840F"}, - {"Light Brown", "#A86F"} - }; - - std::string _jumpItemValue; - for (const auto& color : colors) { - auto* colorItem = new tsl::elm::ListItem(color.first); - - // For display, show the color code based on type - std::string displayValue; - if (isTextBasedColor || isBackgroundColor) { - // For ALL text-based colors AND background colors, show without the alpha - displayValue = extractColorWithoutAlpha(color.second); - } else { - // For any remaining FPS Graph colors (shouldn't happen now), keep original behavior - displayValue = color.second; - } - - colorItem->setValue(displayValue); - - // Check if this is the selected color - bool isSelected = false; - if (isBackgroundColor || isTextBasedColor) { - // For background and text colors, compare without alpha - isSelected = (extractColorWithoutAlpha(color.second) == currentColorWithoutAlpha); - } else { - // For any remaining FPS Graph colors (shouldn't happen now) - isSelected = (color.second == currentValue); - } - - if (isSelected) { - colorItem->setValue(displayValue + " " + ult::CHECKMARK_SYMBOL); - lastSelectedListItem = colorItem; - _jumpItemValue = displayValue + " " + ult::CHECKMARK_SYMBOL; - } - - colorItem->setClickListener([this, colorItem, color, section, displayValue](uint64_t keys) { - if (keys & KEY_A) { - std::string valueToSave = color.second; - - if (isBackgroundColor) { - // For background colors, preserve existing alpha - std::string existingColor = ult::parseValueFromIniSection(configIniPath, section, colorKey); - if (!existingColor.empty() && existingColor.length() == 5) { - char existingAlpha = existingColor[4]; - valueToSave = setAlphaInColor(color.second, existingAlpha); - } - } else if (isTextBasedColor) { - // For text-based colors, ensure alpha is always F - valueToSave = setAlphaInColor(color.second, 'F'); - } - // For any remaining FPS Graph colors (shouldn't happen now), use as-is - - ult::setIniFileValue(configIniPath, section, colorKey, valueToSave); - - // Update the UI - clear old checkmark and set new one - if (lastSelectedListItem && lastSelectedListItem != colorItem) { - // Get the display value for the old selected item - std::string oldDisplayValue; - for (const auto& c : colors) { - if (lastSelectedListItem->getText() == c.first) { - if (isTextBasedColor || isBackgroundColor) { - oldDisplayValue = extractColorWithoutAlpha(c.second); - } else { - oldDisplayValue = c.second; - } - break; - } - } - lastSelectedListItem->setValue(oldDisplayValue); - } - - // Set new checkmark - colorItem->setValue(displayValue + " " + ult::CHECKMARK_SYMBOL); - lastSelectedListItem = colorItem; - return true; - } - return false; - }); - list->addItem(colorItem); - } - list->jumpToItem("", _jumpItemValue, false); - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Colors"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - jumpItemName = modeTitle; - jumpItemValue = ""; - jumpItemExactMatch = false; - - tsl::swapTo(SwapDepth(2), modeName); - return true; - } - return false; - } -}; - -// Color Configuration -class ColorConfig : public tsl::Gui { -private: - std::string modeName; - bool isMiniMode; - bool isMicroMode; - bool isFullMode; - bool isGameResolutionsMode; - bool isFPSCounterMode; - bool isFPSGraphMode; - -public: - ColorConfig(const std::string& mode) : modeName(mode) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - isFullMode = (mode == "Full"); - isGameResolutionsMode = (mode == "Game Resolutions"); - isFPSCounterMode = (mode == "FPS Counter"); - isFPSGraphMode = (mode == "FPS Graph"); - - // Full mode should never access color configuration - //if (isFullMode) { - // // This should not happen, but if it does, go back - // tsl::goBack(); - //} - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader("Colors")); - - auto getCurrentColor = [this](const std::string& key, const std::string& def) { - std::string section; - if (isMiniMode) section = "mini"; - else if (isMicroMode) section = "micro"; - else if (isFullMode) section = "full"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - std::string value = ult::parseValueFromIniSection(configIniPath, section, key); - return value.empty() ? def : value; - }; - - auto getColorName = [](const std::string& hexColor) -> std::string { - // Extract RGB without alpha for comparison - std::string rgb = hexColor; - if (hexColor.length() == 5 && hexColor[0] == '#') { - rgb = hexColor.substr(0, 4); - } - - // Map of hex colors to names (RGB only, no alpha) - static const std::map colorNames = { - // Grays & Basics - {"#000", "Black"}, - {"#333", "Dark Gray"}, - {"#444", "Gray"}, - {"#888", "Light Gray"}, - {"#CCC", "Silver"}, - {"#FFF", "White"}, - - // Reds - {"#800", "Dark Red"}, - {"#F00", "Red"}, - {"#F88", "Light Red"}, - {"#F8A", "Pink"}, - - // Greens - {"#080", "Dark Green"}, - {"#0F0", "Green"}, - {"#0C0", "Lime Green"}, - {"#8F8", "Light Green"}, - - // Blues - {"#003", "Dark Blue"}, - {"#00F", "Blue"}, - {"#2DF", "Light Blue"}, - {"#8CF", "Sky Blue"}, - - // Purples - {"#808", "Dark Purple"}, - {"#80F", "Purple"}, - {"#C8F", "Light Purple"}, - {"#A0F", "Violet"}, - - // Yellows & Oranges - {"#F80", "Orange"}, - {"#FF0", "Yellow"}, - {"#FFC", "Light Yellow"}, - - // Cyans & Teals - {"#088", "Teal"}, - {"#0FF", "Cyan"}, - {"#8FF", "Light Cyan"}, - - // Magentas & Pinks - {"#F0F", "Magenta"}, - {"#F8C", "Hot Pink"}, - - // Browns - {"#840", "Brown"}, - {"#A86", "Light Brown"} - }; - - auto it = colorNames.find(rgb); - if (it != colorNames.end()) { - // Special case for black/transparent disambiguation - if (rgb == "#000" && hexColor.length() == 5) { - char alpha = hexColor[4]; - if (alpha == '0') return "Transparent"; - else return "Black"; - } - return it->second; - } - return rgb; // Return hex if no name found - }; - - auto getAlphaPercentage = [](const std::string& color) -> std::string { - if (color.length() == 5 && color[0] == '#') { - char alpha = color[4]; - switch(alpha) { - case '0': return "0%"; - case '1': return "10%"; - case '3': return "20%"; - case '4': return "30%"; - case '6': return "40%"; - case '8': return "50%"; - case '9': return "60%"; - case 'B': case 'b': return "70%"; - case 'C': case 'c': return "80%"; - case 'E': case 'e': return "90%"; - case 'F': case 'f': return "100%"; - default: return "60%"; - } - } - return "60%"; - }; - - if (!isFullMode) { - // Background Color (all modes) - auto* bgColor = new tsl::elm::ListItem("Background Color"); - std::string bgDefault = "#0009"; - std::string bgCurrentColor = getCurrentColor("background_color", bgDefault); - // Display color name instead of hex - bgColor->setValue(getColorName(bgCurrentColor)); - bgColor->setClickListener([this, bgDefault](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Background Color", "background_color", bgDefault); - return true; - } - return false; - }); - list->addItem(bgColor); - - // Background Alpha (new) - auto* bgAlpha = new tsl::elm::ListItem("Background Alpha"); - bgAlpha->setValue(getAlphaPercentage(bgCurrentColor)); - bgAlpha->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "background_color", "Background Alpha"); - return true; - } - return false; - }); - list->addItem(bgAlpha); - - if (isMiniMode || isFPSCounterMode || isFPSGraphMode || isGameResolutionsMode) { - // Mini mode: has focus background - auto* focusBgColor = new tsl::elm::ListItem("Focus Color"); - std::string focusCurrentColor = getCurrentColor("focus_background_color", "#000F"); - focusBgColor->setValue(getColorName(focusCurrentColor)); - focusBgColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Focus Color", "focus_background_color", "#000F"); - return true; - } - return false; - }); - list->addItem(focusBgColor); - - // Focus Alpha (new) - auto* focusAlpha = new tsl::elm::ListItem("Focus Alpha"); - focusAlpha->setValue(getAlphaPercentage(focusCurrentColor)); - focusAlpha->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "focus_background_color", "Focus Alpha"); - return true; - } - return false; - }); - list->addItem(focusAlpha); - } - } - - // Text Color (all modes) - auto* textColor = new tsl::elm::ListItem("Text Color"); - std::string textCurrentColor = getCurrentColor("text_color", "#FFFF"); - // Display color name for text colors - textColor->setValue(getColorName(textCurrentColor)); - textColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Text Color", "text_color", "#FFFF"); - return true; - } - return false; - }); - list->addItem(textColor); - - if (isFPSGraphMode) { - // FPS Graph specific colors - struct ColorSetting { - std::string name; - std::string key; - std::string defaultVal; - bool isBackgroundType; // true for colors that allow alpha adjustment - }; - - // Game Resolutions: only category color (no separator) - auto* catColor = new tsl::elm::ListItem("Category Color"); - catColor->setValue(getColorName(getCurrentColor("cat_color", "#0F0F"))); - catColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Category Color", "cat_color", "#0F0F"); - return true; - } - return false; - }); - list->addItem(catColor); - - static const std::vector fpsGraphColors = { - {"FPS Counter", "fps_counter_color", "#888C", true}, // background type - {"Border", "border_color", "#2DFF", false}, // text type - {"Dashed Line", "dashed_line_color", "#8888", true}, // background type - {"Max FPS Text", "max_fps_text_color", "#FFFF", false}, // text type - {"Min FPS Text", "min_fps_text_color", "#FFFF", false}, // text type - {"Main Line", "main_line_color", "#FFFF", false}, // text type - {"Rounded Line", "rounded_line_color", "#F0FF", false}, // text type - {"Perfect Line", "perfect_line_color", "#0C0F", false} // text type - }; - - for (const auto& color : fpsGraphColors) { - auto* colorItem = new tsl::elm::ListItem(color.name + " Color"); - const std::string currentVal = getCurrentColor(color.key, color.defaultVal); - - if (color.isBackgroundType) { - // For background-type colors, show color name - colorItem->setValue(getColorName(currentVal)); - } else { - // For text-type colors, show color name - colorItem->setValue(getColorName(currentVal)); - } - - colorItem->setClickListener([this, color](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, color.name, color.key, color.defaultVal); - return true; - } - return false; - }); - list->addItem(colorItem); - - // Add alpha selector for background-type colors - if (color.isBackgroundType) { - auto* alphaItem = new tsl::elm::ListItem(color.name + " Alpha"); - alphaItem->setValue(getAlphaPercentage(currentVal)); - alphaItem->setClickListener([this, color](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, color.key, color.name + " Alpha"); - return true; - } - return false; - }); - list->addItem(alphaItem); - } - } - - } else if (isFullMode) { - auto* catColor1 = new tsl::elm::ListItem("Category Color 1"); - // Display color name for category colors - catColor1->setValue(getColorName(getCurrentColor("cat_color_1", "#8FFF"))); - catColor1->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Category Color 1", "cat_color_1", "#8FFF"); - return true; - } - return false; - }); - list->addItem(catColor1); - - auto* catColor2 = new tsl::elm::ListItem("Category Color 2"); - // Display color name for category colors - catColor2->setValue(getColorName(getCurrentColor("cat_color_2", "#2DFF"))); - catColor2->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Category Color 2", "cat_color_2", "#2DFF"); - return true; - } - return false; - }); - list->addItem(catColor2); - - auto* sepColor = new tsl::elm::ListItem("Separator Color"); - // Display color name for separator colors - sepColor->setValue(getColorName(getCurrentColor("separator_color", "#888F"))); - sepColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Separator Color", "separator_color", "#888F"); - return true; - } - return false; - }); - list->addItem(sepColor); - } else if (isMiniMode) { - auto* catColor = new tsl::elm::ListItem("Category Color"); - // Display color name for category colors - catColor->setValue(getColorName(getCurrentColor("cat_color", "#2DFF"))); - catColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Category Color", "cat_color", "#2DFF"); - return true; - } - return false; - }); - list->addItem(catColor); - - auto* sepColor = new tsl::elm::ListItem("Separator Color"); - // Display color name for separator colors - sepColor->setValue(getColorName(getCurrentColor("separator_color", "#888F"))); - sepColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Separator Color", "separator_color", "#888F"); - return true; - } - return false; - }); - list->addItem(sepColor); - - } else if (isMicroMode) { - auto* catColor = new tsl::elm::ListItem("Category Color"); - catColor->setValue(getColorName(getCurrentColor("cat_color", "#2DFF"))); - catColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Category Color", "cat_color", "#2DFF"); - return true; - } - return false; - }); - list->addItem(catColor); - - // Micro mode: separator and category colors (no focus background like Mini) - auto* sepColor = new tsl::elm::ListItem("Separator Color"); - sepColor->setValue(getColorName(getCurrentColor("separator_color", "#888F"))); - sepColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Separator Color", "separator_color", "#888F"); - return true; - } - return false; - }); - list->addItem(sepColor); - - - } else if (isGameResolutionsMode) { - // Game Resolutions: only category color (no separator) - auto* catColor = new tsl::elm::ListItem("Category Color"); - catColor->setValue(getColorName(getCurrentColor("cat_color", "#2DFF"))); - catColor->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName, "Category Color", "cat_color", "#2DFF"); - return true; - } - return false; - }); - list->addItem(catColor); - } - // FPS Counter mode: only background and text colors (already added above) - // Full mode: NO color settings at all (excluded from this function) - - list->jumpToItem(jumpItemName, jumpItemValue, jumpItemExactMatch); - { - jumpItemName = ""; - jumpItemValue = ""; - jumpItemExactMatch = false; - } - - //list->disableCaching(); - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Configuration"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - tsl::goBack(); - return true; - } - return false; - } -}; - -// Show Configuration (Mini/Micro only) -class ShowConfig : public tsl::Gui { -private: - std::string modeName; - bool isMiniMode; - bool isMicroMode; - std::vector elementOrder; - std::unordered_set enabledElements; - -public: - ShowConfig(const std::string& mode) : modeName(mode) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader("Elements " + ult::DIVIDER_SYMBOL + " \uE0E3 Move Down " + ult::DIVIDER_SYMBOL + " \uE0E2 Move Up")); - - const std::string section = isMiniMode ? "mini" : "micro"; - std::string showValue = ult::parseValueFromIniSection(configIniPath, section, "show"); - std::string orderValue = ult::parseValueFromIniSection(configIniPath, section, "element_order"); - - if (showValue.empty()) { - showValue = isMiniMode ? "DTC+BAT+CPU+GPU+RAM+TMP+FPS+RES" : "FPS+CPU+GPU+RAM+SOC+BAT+DTC"; - } - convertToUpper(showValue); - - enabledElements.clear(); - ult::StringStream ss(showValue); - std::string item; - while (ss.getline(item, '+')) { - if (!item.empty()) { - enabledElements.insert(item); - } - } - - elementOrder.clear(); - if (!orderValue.empty()) { - convertToUpper(orderValue); - ult::StringStream orderSS(orderValue); - std::string orderItem; - while (orderSS.getline(orderItem, '+')) { - if (!orderItem.empty()) { - elementOrder.push_back(orderItem); - } - } - } else { - ult::StringStream ss2(showValue); - while (ss2.getline(item, '+')) { - if (!item.empty()) { - elementOrder.push_back(item); - } - } - } - - static constexpr std::string_view miniElements[] = { - "DTC","BAT","CPU","GPU","RAM","MEM","READ","SOC","TMP","FPS","RES" - }; - - static constexpr std::string_view microElements[] = { - "FPS","CPU","GPU","RAM","READ","SOC","TMP","RES","BAT","DTC" - }; - - // Use span or array reference instead of pointer - const auto* allElements = isMiniMode ? miniElements : microElements; - const size_t allElementsSize = isMiniMode ? std::size(miniElements) : std::size(microElements); - - elementOrder.clear(); - if (!orderValue.empty()) { - convertToUpper(orderValue); - ult::StringStream orderSS(orderValue); - std::string orderItem; - while (orderSS.getline(orderItem, '+')) { - if (!orderItem.empty()) { - elementOrder.push_back(orderItem); - } - } - } else { - // Initialize with allElements order instead - for (size_t i = 0; i < allElementsSize; i++) { - auto elem = allElements[i]; - if (!isMiniMode && elem == "MEM") - continue; - elementOrder.emplace_back(elem); - } - } - - for (size_t i = 0; i < elementOrder.size(); i++) { - const std::string& element = elementOrder[i]; - const bool isEnabled = enabledElements.find(element) != enabledElements.end(); - - auto* elementItem = new tsl::elm::ListItem(element); - elementItem->setValue(isEnabled ? ult::ON : ult::OFF, !isEnabled); - - elementItem->setClickListener([this, elementItem, element](uint64_t keys) { - static bool hasNotTriggeredAnimation = false; - - if (hasNotTriggeredAnimation) { - elementItem->triggerClickAnimation(); - hasNotTriggeredAnimation = false; - } - - if (keys & KEY_A) { - const bool currentlyEnabled = enabledElements.find(element) != enabledElements.end(); - - if (currentlyEnabled) { - enabledElements.erase(element); - } else { - enabledElements.insert(element); - } - - updateShowAndOrder(); - jumpItemName = element; - jumpItemValue = ""; - jumpItemExactMatch = true; - hasNotTriggeredAnimation = true; - - tsl::swapTo(SwapDepth(1), modeName); - return true; - } - else if (keys & KEY_Y || keys & KEY_X) { - size_t currentPos = 0; - for (size_t j = 0; j < elementOrder.size(); j++) { - if (elementOrder[j] == element) { - currentPos = j; - break; - } - } - - if (keys & KEY_X) { - if (currentPos > 0) { - std::swap(elementOrder[currentPos], elementOrder[currentPos - 1]); - } else { - const std::string temp = elementOrder[0]; - for (size_t j = 0; j < elementOrder.size() - 1; j++) { - elementOrder[j] = elementOrder[j + 1]; - } - elementOrder[elementOrder.size() - 1] = temp; - } - triggerRumbleClick.store(true, std::memory_order_release); - triggerMoveSound.store(true, std::memory_order_release); - } else if (keys & KEY_Y) { - if (currentPos < elementOrder.size() - 1) { - std::swap(elementOrder[currentPos], elementOrder[currentPos + 1]); - } else { - const std::string temp = elementOrder[elementOrder.size() - 1]; - for (size_t j = elementOrder.size() - 1; j > 0; j--) { - elementOrder[j] = elementOrder[j - 1]; - } - elementOrder[0] = temp; - } - triggerRumbleClick.store(true, std::memory_order_release); - triggerMoveSound.store(true, std::memory_order_release); - } - - updateShowAndOrder(); - jumpItemName = element; - jumpItemValue = ""; - jumpItemExactMatch = true; - - tsl::swapTo(SwapDepth(1), modeName); - return true; - } - return false; - }); - - list->addItem(elementItem); - } - - list->jumpToItem(jumpItemName, jumpItemValue, jumpItemExactMatch); - { - jumpItemName = ""; - jumpItemValue = ""; - jumpItemExactMatch = false; - } - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", "Configuration"); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - tsl::goBack(); - return true; - } - return false; - } - -private: - void updateShowAndOrder() { - std::string newShowValue; - std::string newOrderValue; - bool showFirst = true; - bool orderFirst = true; - - for (const std::string& element : elementOrder) { - if (!orderFirst) { - newOrderValue += "+"; - } - newOrderValue += element; - orderFirst = false; - - if (enabledElements.find(element) != enabledElements.end()) { - if (!showFirst) { - newShowValue += "+"; - } - newShowValue += element; - showFirst = false; - } - } - - const std::string section = isMiniMode ? "mini" : "micro"; - ult::setIniFileValue(configIniPath, section, "show", newShowValue); - ult::setIniFileValue(configIniPath, section, "element_order", newOrderValue); - } -}; - -// Main Configurator -class ConfiguratorOverlay : public tsl::Gui { -private: - std::string modeName; - bool isMiniMode; - bool isMicroMode; - bool isFullMode; - bool isGameResolutionsMode; - bool isFPSCounterMode; - bool isFPSGraphMode; - -public: - ConfiguratorOverlay(const std::string& mode) : modeName(mode) { - isMiniMode = (mode == "Mini"); - isMicroMode = (mode == "Micro"); - isFullMode = (mode == "Full"); - isGameResolutionsMode = (mode == "Game Resolutions"); - isFPSCounterMode = (mode == "FPS Counter"); - isFPSGraphMode = (mode == "FPS Graph"); - } - - virtual tsl::elm::Element* createUI() override { - auto* list = new tsl::elm::List(); - list->addItem(new tsl::elm::CategoryHeader("Configuration")); - - // 5. Elements (Mini/Micro only) - if (isMiniMode || isMicroMode) { - auto* showSettings = new tsl::elm::ListItem("Elements"); - showSettings->setValue(ult::DROPDOWN_SYMBOL); - showSettings->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName); - return true; - } - return false; - }); - list->addItem(showSettings); - } - - // 3. Toggles (All modes) - //if (isMiniMode || isMicroMode || isFullMode || isFPSGraphMode) { - auto* toggles = new tsl::elm::ListItem("Toggles"); - toggles->setValue(ult::DROPDOWN_SYMBOL); - toggles->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName); - return true; - } - return false; - }); - list->addItem(toggles); - //} - - // 2. Colors (not Full mode - it has no color settings) - //if (!isFullMode) { - auto* colors = new tsl::elm::ListItem("Colors"); - colors->setValue(ult::DROPDOWN_SYMBOL); - colors->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName); - return true; - } - return false; - }); - list->addItem(colors); - //} - - - // 4. Font Sizes (Mini/Micro/FPS Counter only) - if (isMiniMode || isMicroMode || isFPSCounterMode) { - auto* fontSizes = new tsl::elm::ListItem("Font Sizes"); - fontSizes->setValue(ult::DROPDOWN_SYMBOL); - fontSizes->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName); - return true; - } - return false; - }); - list->addItem(fontSizes); - } - - // 1. Refresh Rate (all modes) - auto* refreshRate = new tsl::elm::ListItem("Refresh Rate"); - refreshRate->setValue(std::to_string(getCurrentRefreshRate()) + " Hz"); - refreshRate->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName); - return true; - } - return false; - }); - list->addItem(refreshRate); - - // 6. DTC Format (Mini/Micro only) - NEW ADDITION - if (isMiniMode || isMicroMode) { - auto* dtcFormat = new tsl::elm::ListItem("DTC Format"); - dtcFormat->setValue(getCurrentDTCFormat()); - dtcFormat->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName); - return true; - } - return false; - }); - list->addItem(dtcFormat); - } - - // 7. Frame Padding (Mini only) - NEW ADDITION - if (isMiniMode || isGameResolutionsMode || isFPSCounterMode || isFPSGraphMode) { - auto* framePadding = new tsl::elm::ListItem("Frame Padding"); - framePadding->setValue(std::to_string(getCurrentFramePadding()) + " px"); - framePadding->setClickListener([this](uint64_t keys) { - if (keys & KEY_A) { - tsl::changeTo(modeName); - return true; - } - return false; - }); - list->addItem(framePadding); - } - - // 7. Mode-specific positioning settings - if (isMicroMode) { - // Text Alignment for Micro - auto* textAlign = new tsl::elm::ListItem("Text Alignment"); - textAlign->setValue(getCurrentTextAlign()); - textAlign->setClickListener([this, textAlign](uint64_t keys) { - if (keys & KEY_A) { - const std::string next = cycleTextAlign(); - textAlign->setValue(next); - return true; - } - return false; - }); - list->addItem(textAlign); - - // Vertical Position for Micro (Top/Bottom only) - auto* layerPos = new tsl::elm::ListItem("Vertical Position"); - layerPos->setValue(getCurrentLayerPosBottom()); - layerPos->setClickListener([this, layerPos](uint64_t keys) { - if (keys & KEY_A) { - const std::string next = cycleLayerPosBottom(); - layerPos->setValue(next); - return true; - } - return false; - }); - list->addItem(layerPos); - - } else if (isFullMode) { - // Horizontal Position for Full (Left/Right only) - auto* layerPos = new tsl::elm::ListItem("Horizontal Position"); - layerPos->setValue(getCurrentLayerPosRight()); - layerPos->setClickListener([this, layerPos](uint64_t keys) { - if (keys & KEY_A) { - const std::string next = cycleLayerPosRight(); - layerPos->setValue(next); - return true; - } - return false; - }); - list->addItem(layerPos); - - //} else if (isGameResolutionsMode || isFPSCounterMode || isFPSGraphMode) { - // // Both horizontal and vertical positioning - // auto* layerPosH = new tsl::elm::ListItem("Horizontal Position"); - // layerPosH->setValue(getCurrentLayerPosRight()); - // layerPosH->setClickListener([this, layerPosH](uint64_t keys) { - // if (keys & KEY_A) { - // const std::string next = cycleLayerPosRight(); - // layerPosH->setValue(next); - // return true; - // } - // return false; - // }); - // list->addItem(layerPosH); - // - // auto* layerPosV = new tsl::elm::ListItem("Vertical Position"); - // layerPosV->setValue(getCurrentLayerPosBottom()); - // layerPosV->setClickListener([this, layerPosV](uint64_t keys) { - // if (keys & KEY_A) { - // const std::string next = cycleLayerPosBottom(); - // layerPosV->setValue(next); - // return true; - // } - // return false; - // }); - // list->addItem(layerPosV); - } - - list->jumpToItem(jumpItemName, jumpItemValue, jumpItemExactMatch.load(std::memory_order_acquire)); - { - jumpItemName = ""; - jumpItemValue = ""; - jumpItemExactMatch = false; - } - - tsl::elm::OverlayFrame* rootFrame = new tsl::elm::OverlayFrame("Horizon OC Monitor", modeName); - rootFrame->setContent(list); - return rootFrame; - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysDown & KEY_B) { - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - lastSelectedItem = modeName; - tsl::swapTo(); - return true; - } - return false; - } - -private: - int getCurrentRefreshRate() { - std::string section; - if (isMiniMode) section = "mini"; - else if (isMicroMode) section = "micro"; - else if (isFullMode) section = "full"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - std::string value = ult::parseValueFromIniSection(configIniPath, section, "refresh_rate"); - int defaultRate = (isGameResolutionsMode) ? 10 : ((isFPSCounterMode || isFPSGraphMode) ? 30 : 1); - return value.empty() ? defaultRate : atoi(value.c_str()); - } - - // NEW METHOD: Get current DTC format for display - std::string getCurrentDTCFormat() { - if (isMiniMode || isMicroMode) { - const std::string section = isMiniMode ? "mini" : "micro"; - std::string value = ult::parseValueFromIniSection(configIniPath, section, "dtc_format"); - - // Handle defaults properly - if (value.empty()) { - value = isMiniMode ? "%m-%d-%Y"+ult::DIVIDER_SYMBOL+"%H:%M:%S" : "%H:%M:%S"; - } - - // Convert format string to display name - return getDTCFormatName(value); - } - return ""; - } - - // Helper function to convert format string to display name - std::string getDTCFormatName(const std::string& formatStr) { - - for (const auto& format : dtcFormats) { - if (format.second == formatStr) { - return format.first; - } - } - - // Return the format string itself if no match found - return formatStr; - } - - int getCurrentFramePadding() { - if (isMiniMode) { - std::string value = ult::parseValueFromIniSection(configIniPath, "mini", "frame_padding"); - return value.empty() ? 10 : atoi(value.c_str()); - } - return 10; - } - - std::string getCurrentTextAlign() { - if (isMicroMode) { - std::string value = ult::parseValueFromIniSection(configIniPath, "micro", "text_align"); - convertToUpper(value); - if (value == "LEFT") return "Left"; - if (value == "RIGHT") return "Right"; - return "Center"; - } - return ""; - } - - std::string getCurrentLayerPosRight() { - std::string section; - if (isFullMode) section = "full"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - std::string value = ult::parseValueFromIniSection(configIniPath, section, "layer_width_align"); - convertToUpper(value); - - if (isFullMode) { - // Full mode: only Left and Right allowed - if (value == "RIGHT") return "Right"; - return "Left"; - } else { - // Other modes: allow Center - if (value == "RIGHT") return "Right"; - if (value == "CENTER") return "Center"; - return "Left"; - } - } - - std::string getCurrentLayerPosBottom() { - std::string section; - if (isMicroMode) section = "micro"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - std::string value = ult::parseValueFromIniSection(configIniPath, section, "layer_height_align"); - convertToUpper(value); - - if (isMicroMode) { - // Micro mode: only Top and Bottom allowed - if (value == "BOTTOM") return "Bottom"; - return "Top"; - } else { - // Other modes: allow Center - if (value == "BOTTOM") return "Bottom"; - if (value == "CENTER") return "Center"; - return "Top"; - } - } - - std::string cycleTextAlign() { - if (isMicroMode) { - const std::string current = getCurrentTextAlign(); - std::string next; - if (current == "Left") next = "Center"; - else if (current == "Center") next = "Right"; - else if (current == "Right") next = "Left"; - else next = "Center"; - - ult::setIniFileValue(configIniPath, "micro", "text_align", next); - return next; - } - return ""; - } - - std::string cycleLayerPosRight() { - std::string section; - if (isFullMode) section = "full"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - const std::string current = getCurrentLayerPosRight(); - std::string next; - - if (isFullMode) { - // Full mode: only Left and Right - if (current == "Left") next = "Right"; - else next = "Left"; - } else { - // Other modes: Left -> Center -> Right -> Left - if (current == "Left") next = "Center"; - else if (current == "Center") next = "Right"; - else next = "Left"; - } - - const std::string value = (next == "Right") ? "right" : (next == "Center" ? "center" : "left"); - ult::setIniFileValue(configIniPath, section, "layer_width_align", value); - return next; - } - - std::string cycleLayerPosBottom() { - std::string section; - if (isMicroMode) section = "micro"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - - const std::string current = getCurrentLayerPosBottom(); - std::string next; - - if (isMicroMode) { - // Micro mode: only Top and Bottom - if (current == "Top") next = "Bottom"; - else next = "Top"; - } else { - // Other modes: Top -> Center -> Bottom -> Top - if (current == "Top") next = "Center"; - else if (current == "Center") next = "Bottom"; - else next = "Top"; - } - - const std::string value = (next == "Bottom") ? "bottom" : (next == "Center" ? "center" : "top"); - ult::setIniFileValue(configIniPath, section, "layer_height_align", value); - return next; - } -}; diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/FPS_Counter.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/FPS_Counter.hpp deleted file mode 100644 index 56ee9ba6..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/FPS_Counter.hpp +++ /dev/null @@ -1,525 +0,0 @@ -class MainMenu; - -class com_FPS : public tsl::Gui { -private: - char FPSavg_c[8]; - FpsCounterSettings settings; - size_t fontsize = 0; - ApmPerformanceMode performanceMode = ApmPerformanceMode_Invalid; - bool skipOnce = true; - bool runOnce = true; - - // Repositioning variables - int frameOffsetX = 0; - int frameOffsetY = 0; - bool isDragging = false; - size_t framePadding = 10; - static constexpr int screenWidth = 1280; - static constexpr int screenHeight = 720; - static constexpr int border = 8; - - bool originalUseRightAlignment = ult::useRightAlignment; - - struct ButtonState { - std::atomic minusDragActive{false}; - std::atomic plusDragActive{false}; - } buttonState; - - Thread touchPollThread; - std::atomic touchPollRunning{false}; - - // Store actual rendered dimensions - size_t actualTextWidth = 0; - size_t actualTotalWidth = 0; - size_t actualTotalHeight = 0; - -public: - com_FPS() { - tsl::hlp::requestForeground(false); - disableJumpTo = true; - GetConfigSettings(&settings); - apmGetPerformanceMode(&performanceMode); - if (performanceMode == ApmPerformanceMode_Normal) { - fontsize = settings.handheldFontSize; - } - else if (performanceMode == ApmPerformanceMode_Boost) { - fontsize = settings.dockedFontSize; - } - - // Load saved frame offsets - frameOffsetX = settings.frameOffsetX; - frameOffsetY = settings.frameOffsetY; - framePadding = settings.framePadding; - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - - FullMode = false; - TeslaFPS = settings.refreshRate; - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().removeScreenshotStacks(); - } - deactivateOriginalFooter = true; - StartFPSCounterThread(); - - // Start touch polling thread for instant response at low FPS - touchPollRunning.store(true, std::memory_order_release); - threadCreate(&touchPollThread, [](void* arg) -> void { - com_FPS* overlay = static_cast(arg); - - // Allow only Player 1 and handheld mode - const HidNpadIdType id_list[2] = { HidNpadIdType_No1, HidNpadIdType_Handheld }; - - // Configure HID system to only listen to these IDs - hidSetSupportedNpadIdType(id_list, 2); - - // Configure input for up to 2 supported controllers (P1 + Handheld) - padConfigureInput(2, HidNpadStyleSet_NpadStandard | HidNpadStyleTag_NpadSystemExt); - - // Initialize separate pad states for both controllers - PadState pad_p1; - PadState pad_handheld; - padInitialize(&pad_p1, HidNpadIdType_No1); - padInitialize(&pad_handheld, HidNpadIdType_Handheld); - - u64 minusHoldStart = 0; - u64 plusHoldStart = 0; - static constexpr u64 HOLD_THRESHOLD_NS = 500'000'000ULL; - - HidTouchScreenState state = {0}; - bool inputDetected; - - while (overlay->touchPollRunning.load(std::memory_order_acquire)) { - // Only poll when rendering and not dragging - { - inputDetected = false; - - // Check touch in bounds - if (hidGetTouchScreenStates(&state, 1) && state.count > 0) { - const int touchX = state.touches[0].x; - const int touchY = state.touches[0].y; - - // Use actual dimensions, fallback to estimate if not yet rendered - size_t totalWidth = overlay->actualTotalWidth; - size_t totalHeight = overlay->actualTotalHeight; - - if (totalWidth == 0) { - // Fallback calculation - size_t approxFontSize = overlay->fontsize; - if (approxFontSize == 0) approxFontSize = 50; - const size_t textWidth = approxFontSize * 4; - const size_t margin = (approxFontSize / 8); - const size_t innerWidth = textWidth + margin; - const size_t innerHeight = approxFontSize; - totalWidth = innerWidth + (2 * border); - totalHeight = innerHeight + (2 * border); - } - - // Apply frame offsets - const int overlayX = overlay->frameOffsetX; - const int overlayY = overlay->frameOffsetY; - - // Touch padding - const int touchPadding = 4; - const int touchableX = overlayX - touchPadding; - const int touchableY = overlayY - touchPadding; - const int touchableWidth = totalWidth + (touchPadding * 2); - const int touchableHeight = totalHeight + (touchPadding * 2); - - // Check if touch is within bounds - if (touchX >= touchableX && touchX <= touchableX + touchableWidth && - touchY >= touchableY && touchY <= touchableY + touchableHeight) { - inputDetected = true; - } - } - - // Poll buttons from both controllers - padUpdate(&pad_p1); - padUpdate(&pad_handheld); - - // Combine input from both controllers - const u64 keysHeld = padGetButtons(&pad_p1) | padGetButtons(&pad_handheld); - const u64 now = armTicksToNs(armGetSystemTick()); - - // Track MINUS hold duration - if ((keysHeld & KEY_MINUS) && !(keysHeld & ~KEY_MINUS & ALL_KEYS_MASK)) { - if (minusHoldStart == 0) { - minusHoldStart = now; - } - if (now - minusHoldStart >= HOLD_THRESHOLD_NS) { - inputDetected = true; - overlay->buttonState.minusDragActive.exchange(true, std::memory_order_acq_rel); - } - } - - // Track PLUS hold duration - else if ((keysHeld & KEY_PLUS) && !(keysHeld & ~KEY_PLUS & ALL_KEYS_MASK)) { - if (plusHoldStart == 0) { - plusHoldStart = now; - } - if (now - plusHoldStart >= HOLD_THRESHOLD_NS) { - inputDetected = true; - overlay->buttonState.plusDragActive.exchange(true, std::memory_order_acq_rel); - } - } - - else { - minusHoldStart = plusHoldStart = 0; - overlay->buttonState.minusDragActive.exchange(false, std::memory_order_acq_rel); - overlay->buttonState.plusDragActive.exchange(false, std::memory_order_acq_rel); - } - - // Disable rendering on any input, re-enable when no input - static bool resetOnce = true; - if (inputDetected) { - if (resetOnce && isRendering) { - isRendering = false; - leventSignal(&renderingStopEvent); - resetOnce = false; - } - } else { - resetOnce = true; - } - } - - if (ult::limitedMemory) { - static auto lastUnderscanPixels = std::make_pair(0, 0); - - if (lastUnderscanPixels != tsl::impl::currentUnderscanPixels) { - for (int i = 0; i < 2; i++) { - tsl::gfx::Renderer::get().updateLayerSize(); - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(overlay->frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - } - lastUnderscanPixels = tsl::impl::currentUnderscanPixels; - } - - svcSleepThread(16000000ULL*2); // 16ms polling - } - }, this, NULL, 0x1000, 0x2B, -2); - threadStart(&touchPollThread); - } - - ~com_FPS() { - // Stop touch polling thread - touchPollRunning.store(false, std::memory_order_release); - threadWaitForExit(&touchPollThread); - threadClose(&touchPollThread); - - TeslaFPS = 60; - EndFPSCounterThread(); - FullMode = true; - fixForeground = true; - ult::useRightAlignment = originalUseRightAlignment; - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().addScreenshotStacks(); - } - deactivateOriginalFooter = false; - } - - virtual tsl::elm::Element* createUI() override { - - auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - // Calculate text dimensions - const auto [textWidth, textHeight] = renderer->getTextDimensions( - (FPSavg != 254.0) ? FPSavg_c : "--", false, fontsize - ); - - const size_t margin = (fontsize / 8); - - // Inner rectangle dimensions (content area) - const size_t innerWidth = textWidth + margin; - const size_t innerHeight = textHeight; - - // Total dimensions including border - const size_t totalWidth = innerWidth + (2 * border); - const size_t totalHeight = innerHeight + (2 * border); - - // Store actual dimensions for input handling - actualTextWidth = textWidth; - actualTotalWidth = totalWidth; - actualTotalHeight = totalHeight; - - // Calculate position with frame offsets - //int posX = frameOffsetX; - //int posY = frameOffsetY; - - int _frameOffsetX = ult::limitedMemory ? std::max(0, frameOffsetX - (1280-448)) : frameOffsetX; - - // Clamp to screen bounds (accounting for total size including border) - const int posX = std::max(int(framePadding), std::min(_frameOffsetX, static_cast(screenWidth - totalWidth - framePadding))); - const int posY = std::max(int(framePadding), std::min(frameOffsetY, static_cast(screenHeight - totalHeight - framePadding))); - - // Draw the rounded rectangle (background) - const tsl::Color bgColor = !isDragging - ? settings.backgroundColor - : settings.focusBackgroundColor; - - renderer->drawRoundedRectSingleThreaded( - posX, - posY, - totalWidth, - totalHeight, - 16, - aWithOpacity(bgColor) - ); - - // Calculate centered text position within the bordered area - const int textX = posX + border + (margin / 2); - const int textY = posY + border + (fontsize - margin); - - // Draw the text - renderer->drawString( - (FPSavg != 254.0) ? FPSavg_c : "--", - false, - textX, - textY, - fontsize, - settings.textColor - ); - }); - - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("", ""); - rootFrame->setContent(Status); - - return rootFrame; - } - - virtual void update() override { - apmGetPerformanceMode(&performanceMode); - if (performanceMode == ApmPerformanceMode_Normal) { - fontsize = settings.handheldFontSize; - } - else if (performanceMode == ApmPerformanceMode_Boost) { - fontsize = settings.dockedFontSize; - } - if (settings.useIntegerCounter) { - snprintf(FPSavg_c, sizeof FPSavg_c, "%d", (int)round(useOldFPSavg ? FPSavg_old : FPSavg)); - } else { - snprintf(FPSavg_c, sizeof FPSavg_c, "%2.1f", useOldFPSavg ? FPSavg_old : FPSavg); - } - - if (!skipOnce) { - if (runOnce) { - isRendering = true; - leventClear(&renderingStopEvent); - runOnce = false; - } - } else { - skipOnce = false; - } - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - // Static variables to maintain drag state between function calls - static bool oldTouchDetected = false; - static bool oldMinusHeld = false; - static bool oldPlusHeld = false; - static HidTouchState initialTouchPos = {0}; - static int initialFrameOffsetX = 0; - static int initialFrameOffsetY = 0; - static constexpr int TOUCH_THRESHOLD = 8; - static bool hasMoved = false; - - // Touch detection - const bool currentTouchDetected = (touchPos.x > 0 && touchPos.y > 0 && - touchPos.x < screenWidth && touchPos.y < screenHeight); - - static bool clearOnRelease = false; - - if (clearOnRelease && !isRendering) { - clearOnRelease = false; - isRendering = true; - leventClear(&renderingStopEvent); - } - - // Use actual dimensions from last render, fallback to estimate if not available - size_t totalWidth = actualTotalWidth; - size_t totalHeight = actualTotalHeight; - - if (totalWidth == 0) { - // Fallback calculation if not yet rendered - const size_t textWidth = fontsize * 4; - const size_t margin = (fontsize / 8); - const size_t innerWidth = textWidth + margin; - const size_t innerHeight = fontsize + (margin / 2); - totalWidth = innerWidth + (2 * border); - totalHeight = innerHeight + (2 * border); - } - - // Current overlay position - const int overlayX = frameOffsetX; - const int overlayY = frameOffsetY; - - // Touch detection area (with padding for easier interaction) - static constexpr int touchPadding = 4; - const int touchableX = overlayX - touchPadding; - const int touchableY = overlayY - touchPadding; - const int touchableWidth = totalWidth + (touchPadding * 2); - const int touchableHeight = totalHeight + (touchPadding * 2); - - // Screen boundaries for clamping (accounting for total size) - const int minX = framePadding; - const int maxX = screenWidth - totalWidth - framePadding; - const int minY = framePadding; - const int maxY = screenHeight - totalHeight - framePadding; - - const bool minusDragReady = buttonState.minusDragActive.load(std::memory_order_acquire); - const bool plusDragReady = buttonState.plusDragActive.load(std::memory_order_acquire); - - // Check button states - const bool currentMinusHeld = (keysHeld & KEY_MINUS) && !(keysHeld & ~KEY_MINUS & ALL_KEYS_MASK) && minusDragReady; - const bool currentPlusHeld = (keysHeld & KEY_PLUS) && !(keysHeld & ~KEY_PLUS & ALL_KEYS_MASK) && plusDragReady; - - // Handle touch dragging - if (currentTouchDetected && !isDragging) { - const int touchX = touchPos.x; - const int touchY = touchPos.y; - - if (!oldTouchDetected) { - // Touch just started - check if within overlay bounds - if (touchX >= touchableX && touchX <= touchableX + touchableWidth && - touchY >= touchableY && touchY <= touchableY + touchableHeight) { - - // Start touch dragging - isDragging = true; - triggerRumbleClick.store(true, std::memory_order_release); - triggerOnSound.store(true, std::memory_order_release); - hasMoved = false; - initialTouchPos = touchPos; - initialFrameOffsetX = frameOffsetX; - initialFrameOffsetY = frameOffsetY; - } - } - } else if (currentTouchDetected && isDragging && !currentMinusHeld && !currentPlusHeld) { - // Continue touch dragging - const int touchX = touchPos.x; - const int touchY = touchPos.y; - const int deltaX = touchX - initialTouchPos.x; - const int deltaY = touchY - initialTouchPos.y; - - // Check if we've moved enough to consider this a drag - if (!hasMoved) { - const int totalMovement = abs(deltaX) + abs(deltaY); - if (totalMovement >= TOUCH_THRESHOLD) { - hasMoved = true; - } - } - - if (hasMoved) { - // Update frame offsets with boundary checking - frameOffsetX = std::max(minX, std::min(maxX, initialFrameOffsetX + deltaX)); - frameOffsetY = std::max(minY, std::min(maxY, initialFrameOffsetY + deltaY)); - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - } - } else if (!currentTouchDetected && oldTouchDetected && isDragging && !currentMinusHeld && !currentPlusHeld) { - // Touch just released - if (hasMoved) { - // Save position when touch drag ends - auto iniData = ult::getParsedDataFromIniFile(configIniPath); - iniData["fps-counter"]["frame_offset_x"] = std::to_string(frameOffsetX); - iniData["fps-counter"]["frame_offset_y"] = std::to_string(frameOffsetY); - ult::saveIniFileData(configIniPath, iniData); - } - - // Reset touch drag state - isDragging = false; - hasMoved = false; - clearOnRelease = true; - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerOffSound.store(true, std::memory_order_release); - } - - // Handle joystick dragging (MINUS + right joystick OR PLUS + left joystick) - if ((currentMinusHeld || currentPlusHeld) && !isDragging) { - // Start joystick dragging - isDragging = true; - triggerRumbleClick.store(true, std::memory_order_release); - triggerOnSound.store(true, std::memory_order_release); - } else if ((currentMinusHeld || currentPlusHeld) && isDragging) { - // Continue joystick dragging - static constexpr int JOYSTICK_DEADZONE = 20; - - // Choose the appropriate joystick based on which button is held - const HidAnalogStickState& activeJoystick = currentMinusHeld ? joyStickPosRight : joyStickPosLeft; - - // Only move if joystick is outside deadzone - if (abs(activeJoystick.x) > JOYSTICK_DEADZONE || abs(activeJoystick.y) > JOYSTICK_DEADZONE) { - // Calculate joystick magnitude - const float magnitude = sqrt((float)(activeJoystick.x * activeJoystick.x + activeJoystick.y * activeJoystick.y)); - const float normalizedMagnitude = magnitude / 32767.0f; - - // Smooth curve for sensitivity - static constexpr float baseSensitivity = 0.00008f; - static constexpr float maxSensitivity = 0.0005f; - - const float curveValue = pow(normalizedMagnitude, 8.0f); - const float currentSensitivity = baseSensitivity + (maxSensitivity - baseSensitivity) * curveValue; - - // Calculate movement delta with fractional accumulation - static float accumulatedX = 0.0f; - static float accumulatedY = 0.0f; - - accumulatedX += (float)activeJoystick.x * currentSensitivity; - accumulatedY += -(float)activeJoystick.y * currentSensitivity; - - const int deltaX = (int)accumulatedX; - const int deltaY = (int)accumulatedY; - accumulatedX -= deltaX; - accumulatedY -= deltaY; - - // Update frame offsets with boundary checking - frameOffsetX = std::max(minX, std::min(maxX, frameOffsetX + deltaX)); - frameOffsetY = std::max(minY, std::min(maxY, frameOffsetY + deltaY)); - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - } - } else if (((!currentMinusHeld && oldMinusHeld) || (!currentPlusHeld && oldPlusHeld)) && isDragging) { - // Button just released - stop joystick dragging - auto iniData = ult::getParsedDataFromIniFile(configIniPath); - iniData["fps-counter"]["frame_offset_x"] = std::to_string(frameOffsetX); - iniData["fps-counter"]["frame_offset_y"] = std::to_string(frameOffsetY); - ult::saveIniFileData(configIniPath, iniData); - isDragging = false; - clearOnRelease = true; - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerOffSound.store(true, std::memory_order_release); - } - - // Update state for next frame - oldTouchDetected = currentTouchDetected; - oldMinusHeld = currentMinusHeld; - oldPlusHeld = currentPlusHeld; - - // Handle existing key input logic (but don't interfere with dragging) - if (!isDragging) { - if (isKeyComboPressed(keysHeld, keysDown)) { - isRendering = false; - leventSignal(&renderingStopEvent); - runOnce = true; - skipOnce = true; - TeslaFPS = 60; - lastSelectedItem = "FPS Counter"; - lastMode = ""; - if (skipMain) { - lastMode = "return"; - tsl::goBack(); - } - else { - tsl::setNextOverlay(filepath.c_str(), "--lastSelectedItem 'FPS Counter'"); - tsl::Overlay::get()->close(); - } - return true; - } - } - - // Return true if we handled the input (during dragging) - return isDragging; - } -}; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/FPS_Graph.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/FPS_Graph.hpp deleted file mode 100644 index aa90a055..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/FPS_Graph.hpp +++ /dev/null @@ -1,757 +0,0 @@ -class MainMenu; - -class com_FPSGraph : public tsl::Gui { -private: - uint8_t refreshRate = 0; - char FPSavg_c[8]; - FpsGraphSettings settings; - uint64_t systemtickfrequency_impl = systemtickfrequency; - uint32_t cnt = 0; - char CPU_Load_c[12] = " -"; - char GPU_Load_c[12] = " -"; - char RAM_Load_c[12] = " -"; - char SOC_TEMP_c[12] = " -"; - char PCB_TEMP_c[12] = " -"; - char SKIN_TEMP_c[12] = " -"; - char CPU_TEMP_c[12] = " -"; - char GPU_TEMP_c[12] = " -"; - char RAM_TEMP_c[12] = " -"; - bool skipOnce = true; - bool runOnce = true; - - // Repositioning variables (matching Mini) - int frameOffsetX = 0; - int frameOffsetY = 0; - bool isDragging = false; - size_t framePadding = 10; - static constexpr int screenWidth = 1280; - static constexpr int screenHeight = 720; - static constexpr int border = 8; - - bool originalUseRightAlignment = ult::useRightAlignment; - - struct ButtonState { - std::atomic minusDragActive{false}; - std::atomic plusDragActive{false}; - } buttonState; - - Thread touchPollThread; - std::atomic touchPollRunning{false}; - - // Store actual rendered dimensions (including border) - size_t actualTotalWidth = 0; - size_t actualTotalHeight = 0; - -public: - bool isStarted = false; - com_FPSGraph() { - tsl::hlp::requestForeground(false); - disableJumpTo = true; - GetConfigSettings(&settings); - - if (R_SUCCEEDED(SaltySD_Connect())) { - if (R_FAILED(SaltySD_GetDisplayRefreshRate(&refreshRate))) - refreshRate = 0; - svcSleepThread(100'000); - SaltySD_Term(); - } - - // Load saved frame offsets - frameOffsetX = settings.frameOffsetX; - frameOffsetY = settings.frameOffsetY; - framePadding = settings.framePadding; - - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - - FullMode = false; - TeslaFPS = settings.refreshRate; - systemtickfrequency_impl /= settings.refreshRate; - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().removeScreenshotStacks(); - } - deactivateOriginalFooter = true; - mutexInit(&mutex_Misc); - StartInfoThread(); - StartFPSCounterThread(); - - // Start touch polling thread for instant response at low FPS - touchPollRunning.store(true, std::memory_order_release); - threadCreate(&touchPollThread, [](void* arg) -> void { - com_FPSGraph* overlay = static_cast(arg); - - // Allow only Player 1 and handheld mode - const HidNpadIdType id_list[2] = { HidNpadIdType_No1, HidNpadIdType_Handheld }; - - // Configure HID system to only listen to these IDs - hidSetSupportedNpadIdType(id_list, 2); - - // Configure input for up to 2 supported controllers (P1 + Handheld) - padConfigureInput(2, HidNpadStyleSet_NpadStandard | HidNpadStyleTag_NpadSystemExt); - - // Initialize separate pad states for both controllers - PadState pad_p1; - PadState pad_handheld; - padInitialize(&pad_p1, HidNpadIdType_No1); - padInitialize(&pad_handheld, HidNpadIdType_Handheld); - - u64 minusHoldStart = 0; - u64 plusHoldStart = 0; - static constexpr u64 HOLD_THRESHOLD_NS = 500'000'000ULL; - - HidTouchScreenState state = {0}; - bool inputDetected; - - while (overlay->touchPollRunning.load(std::memory_order_acquire)) { - // Only poll when rendering and not dragging - { - inputDetected = false; - - // Check touch in bounds - if (hidGetTouchScreenStates(&state, 1) && state.count > 0) { - const int touchX = state.touches[0].x; - const int touchY = state.touches[0].y; - - // Use actual dimensions, fallback to estimate if not yet rendered - size_t totalWidth = overlay->actualTotalWidth; - size_t totalHeight = overlay->actualTotalHeight; - - if (totalWidth == 0) { - // Fallback calculation - const s16 refresh_rate_offset = (overlay->refreshRate < 100) ? 21 : 28; - const s16 info_width = overlay->settings.showInfo ? (6 + overlay->rectangle_width/2 - 4) : 0; - const s16 content_width = overlay->rectangle_width + refresh_rate_offset + info_width; - const s16 content_height = overlay->rectangle_height + 12; - totalWidth = content_width + (2 * border); - totalHeight = content_height + (2 * border); - } - - // Apply frame offsets (base position already includes border offset) - const int overlayX = overlay->base_x + overlay->frameOffsetX - border; - const int overlayY = overlay->base_y + overlay->frameOffsetY - border; - - // Touch padding - const int touchPadding = 4; - const int touchableX = overlayX - touchPadding; - const int touchableY = overlayY - touchPadding; - const int touchableWidth = totalWidth + (touchPadding * 2); - const int touchableHeight = totalHeight + (touchPadding * 2); - - // Check if touch is within bounds - if (touchX >= touchableX && touchX <= touchableX + touchableWidth && - touchY >= touchableY && touchY <= touchableY + touchableHeight) { - inputDetected = true; - } - } - - // Poll buttons from both controllers - padUpdate(&pad_p1); - padUpdate(&pad_handheld); - - // Combine input from both controllers - const u64 keysHeld = padGetButtons(&pad_p1) | padGetButtons(&pad_handheld); - const u64 now = armTicksToNs(armGetSystemTick()); - - // Track MINUS hold duration - if ((keysHeld & KEY_MINUS) && !(keysHeld & ~KEY_MINUS & ALL_KEYS_MASK)) { - if (minusHoldStart == 0) { - minusHoldStart = now; - } - if (now - minusHoldStart >= HOLD_THRESHOLD_NS) { - inputDetected = true; - overlay->buttonState.minusDragActive.exchange(true, std::memory_order_acq_rel); - } - } - - // Track PLUS hold duration - else if ((keysHeld & KEY_PLUS) && !(keysHeld & ~KEY_PLUS & ALL_KEYS_MASK)) { - if (plusHoldStart == 0) { - plusHoldStart = now; - } - if (now - plusHoldStart >= HOLD_THRESHOLD_NS) { - inputDetected = true; - overlay->buttonState.plusDragActive.exchange(true, std::memory_order_acq_rel); - } - } - - else { - minusHoldStart = plusHoldStart = 0; - overlay->buttonState.minusDragActive.exchange(false, std::memory_order_acq_rel); - overlay->buttonState.plusDragActive.exchange(false, std::memory_order_acq_rel); - } - - // Disable rendering on any input, re-enable when no input - static bool resetOnce = true; - if (inputDetected) { - if (resetOnce && isRendering) { - isRendering = false; - leventSignal(&renderingStopEvent); - resetOnce = false; - } - } else { - resetOnce = true; - } - } - - if (ult::limitedMemory) { - static auto lastUnderscanPixels = std::make_pair(0, 0); - - if (lastUnderscanPixels != tsl::impl::currentUnderscanPixels) { - for (int i = 0; i < 2; i++) { - tsl::gfx::Renderer::get().updateLayerSize(); - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(overlay->frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - } - lastUnderscanPixels = tsl::impl::currentUnderscanPixels; - } - - svcSleepThread(16000000ULL*2); // 16ms polling - } - }, this, NULL, 0x1000, 0x2B, -2); - threadStart(&touchPollThread); - } - - ~com_FPSGraph() { - // Stop touch polling thread - touchPollRunning.store(false, std::memory_order_release); - threadWaitForExit(&touchPollThread); - threadClose(&touchPollThread); - - EndInfoThread(); - EndFPSCounterThread(); - FullMode = true; - fixForeground = true; - ult::useRightAlignment = originalUseRightAlignment; - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().addScreenshotStacks(); - } - deactivateOriginalFooter = false; - } - - struct stats { - s16 value; - bool zero_rounded; - }; - - std::vector readings; - - s16 base_y = 0; - s16 base_x = 0; - s16 rectangle_width = 180; - s16 rectangle_height = 60; - s16 rectangle_x = 15; - s16 rectangle_y = 5; - s16 rectangle_range_max = 60; - s16 rectangle_range_min = 0; - char legend_max[4] = "60"; - char legend_min[2] = "0"; - s32 range = std::abs(rectangle_range_max - rectangle_range_min) + 1; - s16 x_end = rectangle_x + rectangle_width; - s16 y_old = rectangle_y+rectangle_height; - s16 y_30FPS = rectangle_y+(rectangle_height / 2); - s16 y_60FPS = rectangle_y; - bool isAbove = false; - - virtual tsl::elm::Element* createUI() override { - - auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - - // Calculate content dimensions (what goes inside the border) - const s16 refresh_rate_offset = (refreshRate < 100) ? 21 : 28; - const s16 info_width = settings.showInfo ? (6 + rectangle_width/2 - 4) : 6; - const s16 content_width = rectangle_width + refresh_rate_offset + info_width; - const s16 content_height = rectangle_height + 12; - - // Total dimensions including border - const size_t totalWidth = content_width + (2 * border); - const size_t totalHeight = content_height + (2 * border); - - // Store actual dimensions for input handling - actualTotalWidth = totalWidth; - actualTotalHeight = totalHeight; - - if (refreshRate && refreshRate < 240) { - rectangle_height = refreshRate; - rectangle_range_max = refreshRate; - if (refreshRate < 100) { - rectangle_x = 15; - legend_max[0] = 0x30 + (refreshRate / 10); - legend_max[1] = 0x30 + (refreshRate % 10); - legend_max[2] = 0; - } - else { - rectangle_x = 22; - legend_max[0] = 0x30 + (refreshRate / 100); - legend_max[1] = 0x30 + ((refreshRate / 10) % 10); - legend_max[2] = 0x30 + (refreshRate % 10); - } - y_30FPS = rectangle_y+(rectangle_height / 2); - range = std::abs(rectangle_range_max - rectangle_range_min) + 1; - }; - - int _frameOffsetX = ult::limitedMemory ? std::max(0, frameOffsetX - (1280-448)) : frameOffsetX; - - // Calculate position with frame offsets (for the rounded rect, which includes border) - int posX = base_x + _frameOffsetX - border; - int posY = base_y + frameOffsetY - border; - - // Clamp to screen bounds (accounting for total size including border) - posX = std::max(int(framePadding), std::min(posX, static_cast(screenWidth - totalWidth - framePadding))); - posY = std::max(int(framePadding), std::min(posY, static_cast(screenHeight - totalHeight - framePadding))); - - // Draw the rounded rectangle (background) - const tsl::Color bgColor = !isDragging - ? settings.backgroundColor - : settings.focusBackgroundColor; - - renderer->drawRoundedRectSingleThreaded( - posX, - posY, - totalWidth, - totalHeight, - 16, - aWithOpacity(bgColor) - ); - - posX += 4; - - // Content drawing position (inside the border) - const int final_base_x = posX + border; - const int final_base_y = posY + border; - - const s16 size = (refreshRate > 60 || !refreshRate) ? 63 : (s32)(63.0/(60.0/refreshRate)); - const auto width = renderer->getTextDimensions(FPSavg_c, false, size).first; - - const s16 pos_y = size + final_base_y + rectangle_y + ((rectangle_height - size) / 2); - const s16 pos_x = final_base_x + rectangle_x + ((rectangle_width - width) / 2); - - if (FPSavg != 254.0) - renderer->drawString(FPSavg_c, false, pos_x, pos_y-5, size, settings.fpsColor); - renderer->drawEmptyRect(final_base_x+(rectangle_x - 1)+2, final_base_y+(rectangle_y - 1), rectangle_width + 2, rectangle_height + 4, aWithOpacity(settings.borderColor)); - renderer->drawDashedLine(final_base_x+rectangle_x+2, final_base_y+y_30FPS, final_base_x+rectangle_x+rectangle_width, final_base_y+y_30FPS, 6, aWithOpacity(settings.dashedLineColor)); - renderer->drawString(&legend_max[0], false, final_base_x+(rectangle_x-((refreshRate < 100) ? 15 : 22)), final_base_y+(rectangle_y+7), 10, (settings.maxFPSTextColor)); - renderer->drawString(&legend_min[0], false, final_base_x+(rectangle_x-10), final_base_y+(rectangle_y+rectangle_height+3), 10, settings.minFPSTextColor); - - size_t last_element = readings.size() - 1; - - s16 offset = 0; - if (refreshRate >= 100) offset = 7; - - static s32 y_on_range; - static tsl::Color color = {0}; - for (s16 x = x_end; x > static_cast(x_end-readings.size()); x--) { - y_on_range = readings[last_element].value + std::abs(rectangle_range_min) + 1; - if (y_on_range < 0) { - y_on_range = 0; - } - else if (y_on_range > range) { - isAbove = true; - y_on_range = range; - } - - const s16 y = rectangle_y + static_cast(std::lround((float)rectangle_height * ((float)(range - y_on_range) / (float)range))); - color = (settings.mainLineColor); - if (y == y_old && !isAbove && readings[last_element].zero_rounded) { - if ((y == y_30FPS || y == y_60FPS)) - color = (settings.perfectLineColor); - else - color = (settings.dashedLineColor); - } - - if (x == x_end) { - y_old = y; - } - - renderer->drawLine(final_base_x+x+offset, final_base_y+y, final_base_x+x+offset, final_base_y+y_old, color); - isAbove = false; - y_old = y; - last_element--; - } - - if (settings.showInfo) { - const s16 info_x = final_base_x+rectangle_width+rectangle_x + 6 +8; - const s16 info_y = final_base_y + 3; - const s16 fontSize = 11; - - // Get line height from font size (we'll use the actual rendered height) - const auto testDimensions = renderer->getTextDimensions("A", false, fontSize); - const s16 lineHeight = testDimensions.second; - - // Starting Y position for first line - const s16 startY = info_y + lineHeight; - - // Value X position (offset from labels) - const s16 value_x = info_x + 40; - - static constexpr s16 SPACING = 1; - - // Compute gradient colors for temperatures - const tsl::Color socColor = settings.useDynamicColors ? tsl::GradientColor(SOC_temperatureF) : settings.textColor; - const tsl::Color pcbColor = settings.useDynamicColors ? tsl::GradientColor(PCB_temperatureF) : settings.textColor; - const tsl::Color skinColor = settings.useDynamicColors ? tsl::GradientColor(static_cast(skin_temperaturemiliC) / 1000.0f) : settings.textColor; - - // Draw each label and value pair on the same baseline - // Line 0: CPU - renderer->drawString("CPU", false, info_x, startY, fontSize, settings.catColor); - renderer->drawString(CPU_Load_c, false, value_x, startY, fontSize, settings.textColor); - - // Line 1: GPU - renderer->drawString("GPU", false, info_x, startY + lineHeight+SPACING, fontSize, settings.catColor); - renderer->drawString(GPU_Load_c, false, value_x, startY + lineHeight+SPACING, fontSize, settings.textColor); - - // Line 2: RAM - renderer->drawString("RAM", false, info_x, startY + lineHeight * 2+2*SPACING, fontSize, settings.catColor); - renderer->drawString(RAM_Load_c, false, value_x, startY + lineHeight * 2+2*SPACING, fontSize, settings.textColor); - - // Line 3: CPU or SOC (with gradient color) - if (settings.realTemps && realCPU_Temp != 0) { - const tsl::Color cpuTempColor = settings.useDynamicColors ? tsl::GradientColor(realCPU_Temp / 1000.0f) : settings.textColor; - renderer->drawString("CPU", false, info_x, startY + lineHeight * 3+3*SPACING, fontSize, settings.catColor); - renderer->drawString(CPU_TEMP_c, false, value_x, startY + lineHeight * 3+3*SPACING, fontSize, cpuTempColor); - } else { - renderer->drawString("SOC", false, info_x, startY + lineHeight * 3+3*SPACING, fontSize, settings.catColor); - renderer->drawString(SOC_TEMP_c, false, value_x, startY + lineHeight * 3+3*SPACING, fontSize, socColor); - } - - // Line 4: GPU or PCB (with gradient color) - if (settings.realTemps && realGPU_Temp != 0) { - const tsl::Color gpuTempColor = settings.useDynamicColors ? tsl::GradientColor(realGPU_Temp / 1000.0f) : settings.textColor; - renderer->drawString("GPU", false, info_x, startY + lineHeight * 4+4*SPACING, fontSize, settings.catColor); - renderer->drawString(GPU_TEMP_c, false, value_x, startY + lineHeight * 4+4*SPACING, fontSize, gpuTempColor); - } else { - renderer->drawString("PCB", false, info_x, startY + lineHeight * 4+4*SPACING, fontSize, settings.catColor); - renderer->drawString(PCB_TEMP_c, false, value_x, startY + lineHeight * 4+4*SPACING, fontSize, pcbColor); - } - - // Line 5: RAM or SKIN (with gradient color) - if (settings.realTemps && realRAM_Temp != 0) { - const tsl::Color ramTempColor = settings.useDynamicColors ? tsl::GradientColor(realRAM_Temp / 1000.0f) : settings.textColor; - renderer->drawString("RAM", false, info_x, startY + lineHeight * 5+5*SPACING, fontSize, settings.catColor); - renderer->drawString(RAM_TEMP_c, false, value_x, startY + lineHeight * 5+5*SPACING, fontSize, ramTempColor); - } else { - renderer->drawString("Skin", false, info_x, startY + lineHeight * 5+5*SPACING, fontSize, settings.catColor); - renderer->drawString(SKIN_TEMP_c, false, value_x, startY + lineHeight * 5+5*SPACING, fontSize, skinColor); - } - } - }); - - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("", ""); - rootFrame->setContent(Status); - - return rootFrame; - } - - virtual void update() override { - cnt++; - if (cnt >= TeslaFPS) - cnt = 0; - - ///FPS - stats temp = {0, false}; - static uint64_t lastFrame = 0; - - snprintf(FPSavg_c, sizeof FPSavg_c, "%2.1f", FPSavg); - const uint8_t SaltySharedDisplayRefreshRate = *(uint8_t*)((uintptr_t)shmemGetAddr(&_sharedmemory) + 1); - if (SaltySharedDisplayRefreshRate) - refreshRate = SaltySharedDisplayRefreshRate; - else refreshRate = 60; - if (FPSavg < 254) { - snprintf(FPSavg_c, sizeof(FPSavg_c), "%.1f", useOldFPSavg ? FPSavg_old : FPSavg); - - if (lastFrame == lastFrameNumber) return; - else lastFrame = lastFrameNumber; - if ((s16)(readings.size()) >= rectangle_width) { - readings.erase(readings.begin()); - } - const float whole = std::round(useOldFPSavg ? FPSavg_old : FPSavg); - temp.value = static_cast(std::lround(useOldFPSavg ? FPSavg_old : FPSavg)); - if ((useOldFPSavg ? FPSavg_old : FPSavg) < whole+0.04 && (useOldFPSavg ? FPSavg_old : FPSavg) > whole-0.05) { - temp.zero_rounded = true; - } - readings.push_back(temp); - } - else { - if (readings.size()) { - readings.clear(); - readings.shrink_to_fit(); - lastFrame = 0; - } - FPSavg_c[0] = 0; - } - - if (cnt) - return; - - mutexLock(&mutex_Misc); - - // Format temperature strings separately for proper alignment - snprintf(SOC_TEMP_c, sizeof SOC_TEMP_c, "%2.1f\u00B0C", SOC_temperatureF); - snprintf(PCB_TEMP_c, sizeof PCB_TEMP_c, "%2.1f\u00B0C", PCB_temperatureF); - snprintf(SKIN_TEMP_c, sizeof SKIN_TEMP_c, "%2d.%d\u00B0C", - skin_temperaturemiliC / 1000, (skin_temperaturemiliC / 100) % 10); - - if (realCPU_Temp != 0) { - snprintf(CPU_TEMP_c, sizeof(CPU_TEMP_c), "%.1f\u00B0C", realCPU_Temp / 1000.0f); - } - if (realGPU_Temp != 0) { - snprintf(GPU_TEMP_c, sizeof(GPU_TEMP_c), "%.1f\u00B0C", realGPU_Temp / 1000.0f); - } - if (realRAM_Temp != 0) { - snprintf(RAM_TEMP_c, sizeof(RAM_TEMP_c), "%.1f\u00B0C", realRAM_Temp / 1000.0f); - } - - // Atomically snapshot each idle tick once - const uint64_t idle0 = idletick0.load(std::memory_order_acquire); - const uint64_t idle1 = idletick1.load(std::memory_order_acquire); - const uint64_t idle2 = idletick2.load(std::memory_order_acquire); - const uint64_t idle3 = idletick3.load(std::memory_order_acquire); - - // Clamp values to systemtickfrequency_impl (avoid div-by-zero / runaway) - const uint64_t safe0 = std::min(idle0, systemtickfrequency_impl); - const uint64_t safe1 = std::min(idle1, systemtickfrequency_impl); - const uint64_t safe2 = std::min(idle2, systemtickfrequency_impl); - const uint64_t safe3 = std::min(idle3, systemtickfrequency_impl); - - // Compute per-core CPU usage - const double cpu_usage0 = (1.0 - (static_cast(safe0) / systemtickfrequency_impl)) * 100.0; - const double cpu_usage1 = (1.0 - (static_cast(safe1) / systemtickfrequency_impl)) * 100.0; - const double cpu_usage2 = (1.0 - (static_cast(safe2) / systemtickfrequency_impl)) * 100.0; - const double cpu_usage3 = (1.0 - (static_cast(safe3) / systemtickfrequency_impl)) * 100.0; - - // Compute max core load (the highest usage) - const double cpu_usageM = std::max({cpu_usage0, cpu_usage1, cpu_usage2, cpu_usage3}); - - // Format output strings - snprintf(CPU_Load_c, sizeof(CPU_Load_c), "%.1f%%", cpu_usageM); - snprintf(GPU_Load_c, sizeof(GPU_Load_c), "%d.%d%%", GPU_Load_u / 10, GPU_Load_u % 10); - snprintf(RAM_Load_c, sizeof(RAM_Load_c), "%hu.%hhu%%", - partLoad[HocClkPartLoad_EMC] / 10, - partLoad[HocClkPartLoad_EMC] % 10); - - mutexUnlock(&mutex_Misc); - - if (!skipOnce) { - if (runOnce) { - isRendering = true; - leventClear(&renderingStopEvent); - runOnce = false; - } - } else { - skipOnce = false; - } - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - // Static variables to maintain drag state between function calls - static bool oldTouchDetected = false; - static bool oldMinusHeld = false; - static bool oldPlusHeld = false; - static HidTouchState initialTouchPos = {0}; - static int initialFrameOffsetX = 0; - static int initialFrameOffsetY = 0; - static constexpr int TOUCH_THRESHOLD = 8; - static bool hasMoved = false; - - // Touch detection - const bool currentTouchDetected = (touchPos.x > 0 && touchPos.y > 0 && - touchPos.x < screenWidth && touchPos.y < screenHeight); - - static bool clearOnRelease = false; - - if (clearOnRelease && !isRendering) { - clearOnRelease = false; - isRendering = true; - leventClear(&renderingStopEvent); - } - - // Use actual dimensions from last render, fallback to estimate if not available - size_t totalWidth = actualTotalWidth; - size_t totalHeight = actualTotalHeight; - - if (totalWidth == 0) { - // Fallback calculation if not yet rendered - const s16 refresh_rate_offset = (refreshRate < 100) ? 21 : 28; - const s16 info_width = settings.showInfo ? (6 + rectangle_width/2 - 4) : 0; - const s16 content_width = rectangle_width + refresh_rate_offset + info_width; - const s16 content_height = rectangle_height + 12; - totalWidth = content_width + (2 * border); - totalHeight = content_height + (2 * border); - } - - // Current overlay position (top-left of rounded rect) - const int overlayX = base_x + frameOffsetX - border; - const int overlayY = base_y + frameOffsetY - border; - - // Touch detection area (with padding for easier interaction) - static constexpr int touchPadding = 4; - const int touchableX = overlayX - touchPadding; - const int touchableY = overlayY - touchPadding; - const int touchableWidth = totalWidth + (touchPadding * 2); - const int touchableHeight = totalHeight + (touchPadding * 2); - - // Screen boundaries for clamping (accounting for total size) - const int minX = -(base_x - border) + framePadding; - const int maxX = screenWidth - totalWidth - (base_x - border) - framePadding; - const int minY = -(base_y - border) + framePadding; - const int maxY = screenHeight - totalHeight - (base_y - border) - framePadding; - - const bool minusDragReady = buttonState.minusDragActive.load(std::memory_order_acquire); - const bool plusDragReady = buttonState.plusDragActive.load(std::memory_order_acquire); - - // Check button states - const bool currentMinusHeld = (keysHeld & KEY_MINUS) && !(keysHeld & ~KEY_MINUS & ALL_KEYS_MASK) && minusDragReady; - const bool currentPlusHeld = (keysHeld & KEY_PLUS) && !(keysHeld & ~KEY_PLUS & ALL_KEYS_MASK) && plusDragReady; - - // Handle touch dragging - if (currentTouchDetected && !isDragging) { - const int touchX = touchPos.x; - const int touchY = touchPos.y; - - if (!oldTouchDetected) { - // Touch just started - check if within overlay bounds - if (touchX >= touchableX && touchX <= touchableX + touchableWidth && - touchY >= touchableY && touchY <= touchableY + touchableHeight) { - - // Start touch dragging - isDragging = true; - triggerRumbleClick.store(true, std::memory_order_release); - triggerOnSound.store(true, std::memory_order_release); - hasMoved = false; - initialTouchPos = touchPos; - initialFrameOffsetX = frameOffsetX; - initialFrameOffsetY = frameOffsetY; - } - } - } else if (currentTouchDetected && isDragging && !currentMinusHeld && !currentPlusHeld) { - // Continue touch dragging - const int touchX = touchPos.x; - const int touchY = touchPos.y; - const int deltaX = touchX - initialTouchPos.x; - const int deltaY = touchY - initialTouchPos.y; - - // Check if we've moved enough to consider this a drag - if (!hasMoved) { - const int totalMovement = abs(deltaX) + abs(deltaY); - if (totalMovement >= TOUCH_THRESHOLD) { - hasMoved = true; - } - } - - if (hasMoved) { - // Update frame offsets with boundary checking - frameOffsetX = std::max(minX, std::min(maxX, initialFrameOffsetX + deltaX)); - frameOffsetY = std::max(minY, std::min(maxY, initialFrameOffsetY + deltaY)); - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - } - } else if (!currentTouchDetected && oldTouchDetected && isDragging && !currentMinusHeld && !currentPlusHeld) { - // Touch just released - if (hasMoved) { - // Save position when touch drag ends - auto iniData = ult::getParsedDataFromIniFile(configIniPath); - iniData["fps-graph"]["frame_offset_x"] = std::to_string(frameOffsetX); - iniData["fps-graph"]["frame_offset_y"] = std::to_string(frameOffsetY); - ult::saveIniFileData(configIniPath, iniData); - } - - // Reset touch drag state - isDragging = false; - hasMoved = false; - clearOnRelease = true; - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerOffSound.store(true, std::memory_order_release); - } - - // Handle joystick dragging (MINUS + right joystick OR PLUS + left joystick) - if ((currentMinusHeld || currentPlusHeld) && !isDragging) { - // Start joystick dragging - isDragging = true; - triggerRumbleClick.store(true, std::memory_order_release); - triggerOnSound.store(true, std::memory_order_release); - } else if ((currentMinusHeld || currentPlusHeld) && isDragging) { - // Continue joystick dragging - static constexpr int JOYSTICK_DEADZONE = 20; - - // Choose the appropriate joystick based on which button is held - const HidAnalogStickState& activeJoystick = currentMinusHeld ? joyStickPosRight : joyStickPosLeft; - - // Only move if joystick is outside deadzone - if (abs(activeJoystick.x) > JOYSTICK_DEADZONE || abs(activeJoystick.y) > JOYSTICK_DEADZONE) { - // Calculate joystick magnitude - const float magnitude = sqrt((float)(activeJoystick.x * activeJoystick.x + activeJoystick.y * activeJoystick.y)); - const float normalizedMagnitude = magnitude / 32767.0f; - - // Smooth curve for sensitivity - static constexpr float baseSensitivity = 0.00008f; - static constexpr float maxSensitivity = 0.0005f; - - const float curveValue = pow(normalizedMagnitude, 8.0f); - const float currentSensitivity = baseSensitivity + (maxSensitivity - baseSensitivity) * curveValue; - - // Calculate movement delta with fractional accumulation - static float accumulatedX = 0.0f; - static float accumulatedY = 0.0f; - - accumulatedX += (float)activeJoystick.x * currentSensitivity; - accumulatedY += -(float)activeJoystick.y * currentSensitivity; - - const int deltaX = (int)accumulatedX; - const int deltaY = (int)accumulatedY; - accumulatedX -= deltaX; - accumulatedY -= deltaY; - - // Update frame offsets with boundary checking - frameOffsetX = std::max(minX, std::min(maxX, frameOffsetX + deltaX)); - frameOffsetY = std::max(minY, std::min(maxY, frameOffsetY + deltaY)); - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - } - } else if (((!currentMinusHeld && oldMinusHeld) || (!currentPlusHeld && oldPlusHeld)) && isDragging) { - // Button just released - stop joystick dragging - auto iniData = ult::getParsedDataFromIniFile(configIniPath); - iniData["fps-graph"]["frame_offset_x"] = std::to_string(frameOffsetX); - iniData["fps-graph"]["frame_offset_y"] = std::to_string(frameOffsetY); - ult::saveIniFileData(configIniPath, iniData); - isDragging = false; - clearOnRelease = true; - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerOffSound.store(true, std::memory_order_release); - } - - // Update state for next frame - oldTouchDetected = currentTouchDetected; - oldMinusHeld = currentMinusHeld; - oldPlusHeld = currentPlusHeld; - - // Handle existing key input logic (but don't interfere with dragging) - if (!isDragging) { - if (isKeyComboPressed(keysHeld, keysDown)) { - isRendering = false; - leventSignal(&renderingStopEvent); - runOnce = true; - skipOnce = true; - TeslaFPS = 60; - lastSelectedItem = "FPS Graph"; - lastMode = ""; - if (skipMain) { - lastMode = "return"; - tsl::goBack(); - } - else { - tsl::setNextOverlay(filepath.c_str(), "--lastSelectedItem 'FPS Graph'"); - tsl::Overlay::get()->close(); - } - return true; - } - } - - // Return true if we handled the input (during dragging) - return isDragging; - } -}; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Full.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/Full.hpp deleted file mode 100644 index 06965099..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Full.hpp +++ /dev/null @@ -1,727 +0,0 @@ -class MainMenu; - -class FullOverlay : public tsl::Gui { -private: - char DeltaCPU_c[12] = ""; - char DeltaGPU_c[12] = ""; - char DeltaRAM_c[12] = ""; - char RealCPU_Hz_c[64] = ""; - char RealGPU_Hz_c[64] = ""; - char RealRAM_Hz_c[64] = ""; - char GPU_Load_c[32] = ""; - char Rotation_SpeedLevel_c[64] = ""; - char RAM_compressed_c[64] = ""; - char RAM_var_compressed_c[128] = ""; - char RAM_percentage_var_compressed_c[128] = ""; - char CPU_Hz_c[64] = ""; - char GPU_Hz_c[64] = ""; - char RAM_Hz_c[64] = ""; - char CPU_compressed_c[160] = ""; - char SOC_temperature_c[32] = ""; - char PCB_temperature_c[32] = ""; - char skin_temperature_c[32] = ""; - char CPU_temp_c[32] = ""; - char GPU_temp_c[32] = ""; - char RAM_temp_c[32] = ""; - char BatteryDraw_c[64] = ""; - char FPS_var_compressed_c[64] = ""; - char RAM_load_c[64] = ""; - char RAM_load2_c[64] = ""; - char RAM_bw_peak_c[16] = ""; - char RAM_bw_total_c[16] = ""; - char RAM_bw_gpu_c[16] = ""; - char RAM_bw_cpu_c[16] = ""; - char Resolutions_c[64] = ""; - char readSpeed_c[32] = ""; - - // New separated value buffers for CPU cores - char CPU_Core0_c[16] = ""; - char CPU_Core1_c[16] = ""; - char CPU_Core2_c[16] = ""; - char CPU_Core3_c[16] = ""; - - // New separated value buffers for FPS - char PFPS_value_c[16] = ""; - char FPS_value_c[16] = ""; - - static constexpr uint8_t COMMON_MARGIN = 20; - FullSettings settings; - uint64_t systemtickfrequency_impl = systemtickfrequency; - std::string formattedKeyCombo = keyCombo; - std::string message; - const std::vector KEY_SYMBOLS = { - "\uE0E4", "\uE0E5", "\uE0E6", "\uE0E7", - "\uE0E8", "\uE0E9", "\uE0ED", "\uE0EB", - "\uE0EE", "\uE0EC", "\uE0E0", "\uE0E1", - "\uE0E2", "\uE0E3", "\uE08A", "\uE08B", - "\uE0B6", "\uE0B5" - }; - - bool skipOnce = true; - bool runOnce = true; - - bool originalUseRightAlignment = ult::useRightAlignment; -public: - FullOverlay() { - disableJumpTo = true; - GetConfigSettings(&settings); - mutexInit(&mutex_BatteryChecker); - mutexInit(&mutex_Misc); - tsl::hlp::requestForeground(false); - TeslaFPS = settings.refreshRate; - systemtickfrequency_impl /= settings.refreshRate; - idletick0.store(systemtickfrequency_impl, std::memory_order_relaxed); - idletick1.store(systemtickfrequency_impl, std::memory_order_relaxed); - idletick2.store(systemtickfrequency_impl, std::memory_order_relaxed); - idletick3.store(systemtickfrequency_impl, std::memory_order_relaxed); - if (settings.setPosRight) { - const auto [horizontalUnderscanPixels, verticalUnderscanPixels] = tsl::gfx::getUnderscanPixels(); - tsl::gfx::Renderer::get().setLayerPos(1280-32 - horizontalUnderscanPixels, 0); - ult::useRightAlignment = true; - } else { - tsl::gfx::Renderer::get().setLayerPos(0, 0); - ult::useRightAlignment = false; - } - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().removeScreenshotStacks(); - } - deactivateOriginalFooter = true; - formatButtonCombination(formattedKeyCombo); - //message = "Press " + formattedKeyCombo + " to Exit"; - - realVoltsPolling = false; - StartThreads(); - } - ~FullOverlay() { - CloseThreads(); - fixForeground = true; - ult::useRightAlignment = originalUseRightAlignment; - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().addScreenshotStacks(); - } - deactivateOriginalFooter = false; - } - - resolutionCalls m_resolutionRenderCalls[8] = {0}; - resolutionCalls m_resolutionViewportCalls[8] = {0}; - resolutionCalls m_resolutionOutput[8] = {0}; - uint8_t resolutionLookup = 0; - - virtual tsl::elm::Element* createUI() override { - - - auto Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - //static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency", false, 15).first; - //static auto realFreqWidth = renderer->getTextDimensions("Real Frequency", false, 15).first; - //static auto freqWidth = std::max(targetFreqWidth, realFreqWidth); - - //static auto batteryLabelWidth = renderer->getTextDimensions("Battery Power Flow", false, 15).first; - //static auto fanLabelWidth = renderer->getTextDimensions("Fan Rotation Level", false, 15).first; - //static auto boardWidth = std::max(batteryLabelWidth, fanLabelWidth); - - static constexpr size_t valueOffset = 150+10; - static constexpr size_t deltaOffset = 246+10; - static constexpr size_t ramPercentageOffset = 350+10; - - //Print strings - ///CPU - if (1) { - - uint32_t height_offset = 155; - if (realCPU_Hz && settings.showRealFreqs) { - height_offset = 162; - } - renderer->drawString("CPU Usage", false, COMMON_MARGIN, 120, 20, (settings.catColor1)); - if (settings.showTargetFreqs) { - //static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first; - renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2)); - renderer->drawString(CPU_Hz_c, false, COMMON_MARGIN + valueOffset, height_offset, 15, (settings.textColor)); - } - if (realCPU_Hz && settings.showRealFreqs) { - //static auto realFreqWidth = renderer->getTextDimensions("Real Frequency: ", false, 15).first; - renderer->drawString("Real Frequency", false, COMMON_MARGIN, height_offset - 15, 15, (settings.catColor2)); - renderer->drawString(RealCPU_Hz_c, false, COMMON_MARGIN + valueOffset, height_offset - 15, 15, (settings.textColor)); - if (settings.showDeltas && settings.showTargetFreqs) { - renderer->drawString(DeltaCPU_c, false, COMMON_MARGIN + deltaOffset, height_offset - 7, 15, (settings.textColor)); - } - else if (settings.showDeltas && !settings.showTargetFreqs) { - renderer->drawString(DeltaCPU_c, false, COMMON_MARGIN + deltaOffset, height_offset - 15, 15, (settings.textColor)); - } - } - else if (realCPU_Hz && settings.showDeltas && (settings.showRealFreqs || settings.showTargetFreqs)) { - renderer->drawString(DeltaCPU_c, false, COMMON_MARGIN + deltaOffset, height_offset, 15, (settings.textColor)); - } - - // CPU Core labels and values - static auto core0Width = renderer->getTextDimensions("Core 0 ", false, 15).first; - static auto core1Width = renderer->getTextDimensions("Core 1 ", false, 15).first; - static auto core2Width = renderer->getTextDimensions("Core 2 ", false, 15).first; - static auto core3Width = renderer->getTextDimensions("Core 3 ", false, 15).first; - - const uint32_t core_height = height_offset + 30; - renderer->drawString("Core 0 ", false, COMMON_MARGIN, core_height, 15, (settings.catColor2)); - renderer->drawString(CPU_Core0_c, false, COMMON_MARGIN + core0Width, core_height, 15, (settings.textColor)); - - renderer->drawString("Core 1 ", false, COMMON_MARGIN, core_height + 15, 15, (settings.catColor2)); - renderer->drawString(CPU_Core1_c, false, COMMON_MARGIN + core1Width, core_height + 15, 15, (settings.textColor)); - - renderer->drawString("Core 2 ", false, COMMON_MARGIN, core_height + 30, 15, (settings.catColor2)); - renderer->drawString(CPU_Core2_c, false, COMMON_MARGIN + core2Width, core_height + 30, 15, (settings.textColor)); - - renderer->drawString("Core 3 ", false, COMMON_MARGIN, core_height + 45, 15, (settings.catColor2)); - renderer->drawString(CPU_Core3_c, false, COMMON_MARGIN + core3Width, core_height + 45, 15, (settings.textColor)); - } - - ///GPU - if (R_SUCCEEDED(nvCheck)) { - - uint32_t height_offset = 320-8; - if (realGPU_Hz && settings.showRealFreqs) { - height_offset = 327-8; - } - - renderer->drawString("GPU Usage", false, COMMON_MARGIN, 285-8, 20, (settings.catColor1)); - if (1) { - if (settings.showTargetFreqs) { - //static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first; - renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2)); - renderer->drawString(GPU_Hz_c, false, COMMON_MARGIN + valueOffset, height_offset, 15, (settings.textColor)); - } - if (realCPU_Hz && settings.showRealFreqs) { - //static auto realFreqWidth = renderer->getTextDimensions("Real Frequency: ", false, 15).first; - renderer->drawString("Real Frequency", false, COMMON_MARGIN, height_offset - 15, 15, (settings.catColor2)); - renderer->drawString(RealGPU_Hz_c, false, COMMON_MARGIN + valueOffset, height_offset - 15, 15, (settings.textColor)); - if (settings.showDeltas && settings.showTargetFreqs) { - renderer->drawString(DeltaGPU_c, false, COMMON_MARGIN + deltaOffset, height_offset - 7, 15, (settings.textColor)); - } - else if (settings.showDeltas && !settings.showTargetFreqs) { - renderer->drawString(DeltaGPU_c, false, COMMON_MARGIN + deltaOffset, height_offset - 15, 15, (settings.textColor)); - } - } - else if (realGPU_Hz && settings.showDeltas && (settings.showRealFreqs || settings.showTargetFreqs)) { - renderer->drawString(DeltaGPU_c, false, COMMON_MARGIN + deltaOffset, height_offset, 15, (settings.textColor)); - } - } - if (R_SUCCEEDED(nvCheck)) { - //static auto loadWidth = renderer->getTextDimensions("Load: ", false, 15).first; - renderer->drawString("Load", false, COMMON_MARGIN, height_offset + 15, 15, (settings.catColor2)); - renderer->drawString(GPU_Load_c, false, COMMON_MARGIN + valueOffset, height_offset + 15, 15, (settings.textColor)); - } - - } - - static std::vector specialChars = {""}; - - ///RAM - if (R_SUCCEEDED(Hinted)) { - - uint32_t height_offset = 410; - if (realRAM_Hz && settings.showRealFreqs) { - height_offset += 7; - } - - renderer->drawString("RAM Usage", false, COMMON_MARGIN, 375, 20, (settings.catColor1)); - if (1) { - if (settings.showTargetFreqs) { - //static auto targetFreqWidth = renderer->getTextDimensions("Target Frequency: ", false, 15).first; - renderer->drawString("Target Frequency", false, COMMON_MARGIN, height_offset, 15, (settings.catColor2)); - renderer->drawString(RAM_Hz_c, false, COMMON_MARGIN + valueOffset, height_offset, 15, (settings.textColor)); - } - if (realRAM_Hz && settings.showRealFreqs) { - //static auto realFreqWidth = renderer->getTextDimensions("Real Frequency: ", false, 15).first; - renderer->drawString("Real Frequency", false, COMMON_MARGIN, height_offset - 15, 15, (settings.catColor2)); - renderer->drawString(RealRAM_Hz_c, false, COMMON_MARGIN + valueOffset, height_offset - 15, 15, (settings.textColor)); - if (settings.showDeltas && settings.showTargetFreqs) { - renderer->drawString(DeltaRAM_c, false, COMMON_MARGIN + deltaOffset, height_offset - 7, 15, (settings.textColor)); - } - else if (settings.showDeltas && !settings.showTargetFreqs) { - renderer->drawString(DeltaRAM_c, false, COMMON_MARGIN + deltaOffset, height_offset - 15, 15, (settings.textColor)); - } - } - else if (realRAM_Hz && settings.showDeltas && (settings.showRealFreqs || settings.showTargetFreqs)) { - renderer->drawString(DeltaRAM_c, false, COMMON_MARGIN + deltaOffset, height_offset, 15, (settings.textColor)); - } - if (R_SUCCEEDED(hocclkCheck)) { - if (settings.ramInfoMode == "Bandwidth") { - // Fixed column layout: labels at fixed x, values at fixed x after max label width - // Col1: Peak/GPU labels, Col2: Total/CPU labels - // Values start at a fixed offset so columns don't shift with different digit counts - static const uint32_t bwLbl1W = renderer->getTextDimensions("Peak ", false, 15).first; - static const uint32_t bwLbl2W = renderer->getTextDimensions("Total ", false, 15).first; - static const uint32_t bwValW = renderer->getTextDimensions("99.9 GB/s", false, 15).first; - static const uint32_t bwGap = renderer->getTextDimensions(" ", false, 15).first; - const uint32_t xV1 = COMMON_MARGIN + bwLbl1W; - const uint32_t xL2 = xV1 + bwValW + bwGap; - const uint32_t xV2 = xL2 + bwLbl2W; - // Row 1: Peak ... Total - renderer->drawString("Peak", false, COMMON_MARGIN, height_offset+15, 15, settings.catColor2); - renderer->drawString(RAM_bw_peak_c, false, xV1, height_offset+15, 15, settings.textColor); - renderer->drawString("Total", false, xL2, height_offset+15, 15, settings.catColor2); - renderer->drawString(RAM_bw_total_c, false, xV2, height_offset+15, 15, settings.textColor); - // Row 2: GPU ... CPU - renderer->drawString("GPU", false, COMMON_MARGIN, height_offset+30, 15, settings.catColor2); - renderer->drawString(RAM_bw_gpu_c, false, xV1, height_offset+30, 15, settings.textColor); - renderer->drawString("CPU", false, xL2, height_offset+30, 15, settings.catColor2); - renderer->drawString(RAM_bw_cpu_c, false, xV2, height_offset+30, 15, settings.textColor); - } else { - static std::vector partLoadColoredChars = {"CPU", "GPU"}; - renderer->drawString("Load", false, COMMON_MARGIN, height_offset+15, 15, (settings.catColor2)); - renderer->drawStringWithColoredSections(RAM_load_c, false, partLoadColoredChars, COMMON_MARGIN + valueOffset, height_offset+15, 15, (settings.textColor), settings.catColor2); - } - } - } - if (R_SUCCEEDED(Hinted)) { - const uint32_t ramUsageOffset = (R_SUCCEEDED(hocclkCheck) && settings.ramInfoMode == "Bandwidth") ? height_offset + 50 : height_offset + 40; - //static auto textWidth = renderer->getTextDimensions("Total \nApplication \nApplet \nSystem \nSystem Unsafe ", false, 15).first; - renderer->drawString("Total\nApplication\nApplet\nSystem\nSystem Unsafe", false, COMMON_MARGIN, ramUsageOffset, 15, (settings.catColor2)); - renderer->drawString(RAM_var_compressed_c, false, COMMON_MARGIN + valueOffset, ramUsageOffset, 15, (settings.textColor)); - renderer->drawString(RAM_percentage_var_compressed_c, false, ramPercentageOffset, ramUsageOffset, 15, (settings.textColor)); - } - } - - ///Thermal - if (R_SUCCEEDED(i2cCheck) || R_SUCCEEDED(tcCheck) || R_SUCCEEDED(pwmCheck)) { - renderer->drawString("Board", false, 20, 550+2, 20, (settings.catColor1)); - if (R_SUCCEEDED(i2cCheck)) { - renderer->drawString("Battery Power Flow", false, COMMON_MARGIN, 575+2, 15, (settings.catColor2)); - renderer->drawStringWithColoredSections(BatteryDraw_c, false, specialChars, COMMON_MARGIN + valueOffset, 575+2, 15, (settings.textColor), settings.separatorColor); - } - if (R_SUCCEEDED(pwmCheck)) { - renderer->drawString("Fan Rotation Level", false, COMMON_MARGIN, 590+2, 15, (settings.catColor2)); - renderer->drawString(Rotation_SpeedLevel_c, false, COMMON_MARGIN + valueOffset, 590+2, 15, (settings.textColor)); - } - if (R_SUCCEEDED(i2cCheck) || R_SUCCEEDED(tcCheck)) { - static auto socLabelWidth = renderer->getTextDimensions("SOC ", false, 15).first; - static auto pcbLabelWidth = renderer->getTextDimensions("PCB ", false, 15).first; - static auto maxLabelWidth = std::max(socLabelWidth, pcbLabelWidth); - static auto skinLabelWidth = renderer->getTextDimensions("Skin ", false, 15).first; - - // Compute gradient colors for temperatures - const tsl::Color socColor = settings.useDynamicColors ? tsl::GradientColor(SOC_temperatureF) : settings.textColor; - const tsl::Color pcbColor = settings.useDynamicColors ? tsl::GradientColor(PCB_temperatureF) : settings.textColor; - const tsl::Color skinColor = settings.useDynamicColors ? tsl::GradientColor(static_cast(skin_temperaturemiliC) / 1000.0f) : settings.textColor; - - renderer->drawString("Temperatures", false, COMMON_MARGIN, 605+2, 15, (settings.catColor2)); - - // SOC - starts at valueOffset next to "Temperatures" - uint32_t current_x = COMMON_MARGIN + valueOffset; - renderer->drawString("SOC ", false, current_x, 605+2, 15, (settings.catColor2)); - current_x += maxLabelWidth; - renderer->drawString(SOC_temperature_c, false, current_x, 605+2, 15, socColor); - - // SKIN - same spacing to the right - current_x += renderer->getTextDimensions(SOC_temperature_c, false, 15).first + 15; - renderer->drawString("Skin ", false, current_x, 605+2, 15, (settings.catColor2)); - current_x += skinLabelWidth; - renderer->drawString(skin_temperature_c, false, current_x, 605+2, 15, skinColor); - - // PCB - below SOC on next line - current_x = COMMON_MARGIN + valueOffset; - renderer->drawString("PCB ", false, current_x, 620+2, 15, (settings.catColor2)); - current_x += maxLabelWidth; - renderer->drawString(PCB_temperature_c, false, current_x, 620+2, 15, pcbColor); - } - } - - // Real temps - CPU, GPU, RAM - if (settings.realTemps && (realCPU_Temp != 0 || realGPU_Temp != 0 || realRAM_Temp != 0)) { - static auto cpuTempLabelWidth = renderer->getTextDimensions("CPU ", false, 15).first; - static auto gpuTempLabelWidth = renderer->getTextDimensions("GPU ", false, 15).first; - static auto ramTempLabelWidth = renderer->getTextDimensions("RAM ", false, 15).first; - - uint32_t current_x = COMMON_MARGIN + 58;; - - // CPU temp - if (realCPU_Temp != 0) { - const tsl::Color cpuTempColor = settings.useDynamicColors ? tsl::GradientColor(realCPU_Temp / 1000.0f) : settings.textColor; - renderer->drawString("CPU ", false, current_x, 635+2, 15, (settings.catColor2)); - current_x += cpuTempLabelWidth; - renderer->drawString(CPU_temp_c, false, current_x, 635+2, 15, cpuTempColor); - current_x += renderer->getTextDimensions(CPU_temp_c, false, 15).first + 15; - } - - // GPU temp - if (realGPU_Temp != 0) { - const tsl::Color gpuTempColor = settings.useDynamicColors ? tsl::GradientColor(realGPU_Temp / 1000.0f) : settings.textColor; - renderer->drawString("GPU ", false, current_x, 635+2, 15, (settings.catColor2)); - current_x += gpuTempLabelWidth; - renderer->drawString(GPU_temp_c, false, current_x, 635+2, 15, gpuTempColor); - current_x += renderer->getTextDimensions(GPU_temp_c, false, 15).first + 15; - } - - // RAM temp - if (realRAM_Temp != 0) { - const tsl::Color ramTempColor = settings.useDynamicColors ? tsl::GradientColor(realRAM_Temp / 1000.0f) : settings.textColor; - renderer->drawString("RAM ", false, current_x, 635+2, 15, (settings.catColor2)); - current_x += ramTempLabelWidth; - renderer->drawString(RAM_temp_c, false, current_x, 635+2, 15, ramTempColor); - } - } - - ///FPS - if (GameRunning) { - const uint32_t width_offset = valueOffset; - if (settings.showFPS || settings.showRES || settings.showRDSD) { - renderer->drawString("Game", false, COMMON_MARGIN + width_offset, 185+12, 20, (settings.catColor1)); - } - uint32_t height = 210+12; - if (settings.showFPS == true) { - static auto pfpsWidth = renderer->getTextDimensions("PFPS ", false, 15).first; - static auto fpsWidth = renderer->getTextDimensions("FPS ", false, 15).first; - - renderer->drawString("PFPS ", false, COMMON_MARGIN + width_offset, height, 15, (settings.catColor2)); - renderer->drawString(PFPS_value_c, false, COMMON_MARGIN + width_offset + pfpsWidth, height, 15, (settings.textColor)); - - // Calculate position for "FPS " label - add some spacing - const uint32_t fps_x_offset = COMMON_MARGIN + width_offset + pfpsWidth + renderer->getTextDimensions(PFPS_value_c, false, 15).first + 15; - renderer->drawString("FPS ", false, fps_x_offset, height, 15, (settings.catColor2)); - renderer->drawString(FPS_value_c, false, fps_x_offset + fpsWidth, height, 15, (settings.textColor)); - - height += 15; - } - if ((settings.showRES == true) && NxFps && SharedMemoryUsed && (NxFps -> API >= 1)) { - static auto resLabelWidth = renderer->getTextDimensions("Resolutions ", false, 15).first; - renderer->drawString("Resolutions ", false, COMMON_MARGIN + width_offset, height, 15, (settings.catColor2)); - - renderer->drawStringWithColoredSections(Resolutions_c, false, specialChars, COMMON_MARGIN + width_offset + resLabelWidth, height, 15, (settings.textColor), settings.separatorColor); - height += 15; - } - if (settings.showRDSD == true) { - static auto readLabelWidth = renderer->getTextDimensions("Read Speed ", false, 15).first; - renderer->drawString("Read Speed ", false, COMMON_MARGIN + width_offset, height, 15, (settings.catColor2)); - renderer->drawString(readSpeed_c, false, COMMON_MARGIN + width_offset + readLabelWidth, height, 15, (settings.textColor)); - } - } - - //renderer->drawStringWithColoredSections(message, false, KEY_SYMBOLS, 30, 693, 23, a(tsl::bottomTextColor), a(tsl::buttonColor)); - - - static const auto pressWidth = renderer->getTextDimensions("Press ", false, 23).first; - static const auto keyComboWidth = renderer->getTextDimensions(formattedKeyCombo.c_str(), false, 23).first; - - static constexpr u16 baseX = 30; - static constexpr u16 baseY = 693; - static constexpr u8 fontSize = 23; - - // Draw "Press " - renderer->drawString("Press ", false, baseX, baseY, fontSize, (tsl::bottomTextColor)); - - // Draw formatted key combo with colored sections - renderer->drawStringWithColoredSections(formattedKeyCombo, false, KEY_SYMBOLS, baseX + pressWidth, baseY, fontSize, (tsl::bottomTextColor), (tsl::buttonColor)); - - // Draw " to Exit" - renderer->drawString(" to Exit", false, baseX + pressWidth + keyComboWidth, baseY, fontSize, (tsl::bottomTextColor)); - }); - - auto rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION); - rootFrame->setContent(Status); - - return rootFrame; - } - - virtual void update() override { - //Make stuff ready to print - ///CPU - if (systemtickfrequency_impl > 0) { - const uint64_t idle0_val = std::min(idletick0.load(std::memory_order_acquire), systemtickfrequency_impl); - const uint64_t idle1_val = std::min(idletick1.load(std::memory_order_acquire), systemtickfrequency_impl); - const uint64_t idle2_val = std::min(idletick2.load(std::memory_order_acquire), systemtickfrequency_impl); - const uint64_t idle3_val = std::min(idletick3.load(std::memory_order_acquire), systemtickfrequency_impl); - - const float usage0 = std::clamp(100.0f * (1.0f - float(idle0_val) / systemtickfrequency_impl), 0.0f, 100.0f); - const float usage1 = std::clamp(100.0f * (1.0f - float(idle1_val) / systemtickfrequency_impl), 0.0f, 100.0f); - const float usage2 = std::clamp(100.0f * (1.0f - float(idle2_val) / systemtickfrequency_impl), 0.0f, 100.0f); - const float usage3 = std::clamp(100.0f * (1.0f - float(idle3_val) / systemtickfrequency_impl), 0.0f, 100.0f); - - // Format individual core values - snprintf(CPU_Core0_c, sizeof(CPU_Core0_c), "%.2f%%", usage0); - snprintf(CPU_Core1_c, sizeof(CPU_Core1_c), "%.2f%%", usage1); - snprintf(CPU_Core2_c, sizeof(CPU_Core2_c), "%.2f%%", usage2); - snprintf(CPU_Core3_c, sizeof(CPU_Core3_c), "%.2f%%", usage3); - } - - mutexLock(&mutex_Misc); - snprintf(CPU_Hz_c, sizeof(CPU_Hz_c), "%u.%u MHz", CPU_Hz / 1000000, (CPU_Hz / 100000) % 10); - if (realCPU_Hz) { - snprintf(RealCPU_Hz_c, sizeof(RealCPU_Hz_c), "%u.%u MHz", realCPU_Hz / 1000000, (realCPU_Hz / 100000) % 10); - const int32_t deltaCPU = (int32_t)(realCPU_Hz / 1000) - (CPU_Hz / 1000); - snprintf(DeltaCPU_c, sizeof(DeltaCPU_c), "Δ %d.%u", deltaCPU / 1000, abs(deltaCPU / 100) % 10); - } - - ///GPU - snprintf(GPU_Hz_c, sizeof GPU_Hz_c, "%u.%u MHz", GPU_Hz / 1000000, (GPU_Hz / 100000) % 10); - if (realGPU_Hz) { - snprintf(RealGPU_Hz_c, sizeof(RealGPU_Hz_c), "%u.%u MHz", realGPU_Hz / 1000000, (realGPU_Hz / 100000) % 10); - const int32_t deltaGPU = (int32_t)(realGPU_Hz / 1000) - (GPU_Hz / 1000); - snprintf(DeltaGPU_c, sizeof(DeltaGPU_c), "Δ %d.%u", deltaGPU / 1000, abs(deltaGPU / 100) % 10); - } - snprintf(GPU_Load_c, sizeof GPU_Load_c, "%u.%u%%", GPU_Load_u / 10, GPU_Load_u % 10); - - ///RAM - snprintf(RAM_Hz_c, sizeof RAM_Hz_c, "%u.%u MHz", RAM_Hz / 1000000, (RAM_Hz / 100000) % 10); - if (realRAM_Hz) { - snprintf(RealRAM_Hz_c, sizeof(RealRAM_Hz_c), "%u.%u MHz", realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10); - const int32_t deltaRAM = (int32_t)(realRAM_Hz / 1000) - (RAM_Hz / 1000); - snprintf(DeltaRAM_c, sizeof(DeltaRAM_c), "Δ %d.%u", deltaRAM / 1000, abs(deltaRAM / 100) % 10); - } - - const float RAM_Total_application_f = (float)RAM_Total_application_u / 1024 / 1024; - const float RAM_Total_applet_f = (float)RAM_Total_applet_u / 1024 / 1024; - const float RAM_Total_system_f = (float)RAM_Total_system_u / 1024 / 1024; - const float RAM_Total_systemunsafe_f = (float)RAM_Total_systemunsafe_u / 1024 / 1024; - const float RAM_Total_all_f = RAM_Total_application_f + RAM_Total_applet_f + RAM_Total_system_f + RAM_Total_systemunsafe_f; - - const float RAM_Used_application_f = (float)RAM_Used_application_u / 1024 / 1024; - const float RAM_Used_applet_f = (float)RAM_Used_applet_u / 1024 / 1024; - const float RAM_Used_system_f = (float)RAM_Used_system_u / 1024 / 1024; - const float RAM_Used_systemunsafe_f = (float)RAM_Used_systemunsafe_u / 1024 / 1024; - const float RAM_Used_all_f = RAM_Used_application_f + RAM_Used_applet_f + RAM_Used_system_f + RAM_Used_systemunsafe_f; - - // Compute percentages - const int RAMPct_all = (int)((RAM_Used_all_f / RAM_Total_all_f) * 100.0f ); - const int RAMPct_app = (int)((RAM_Used_application_f / RAM_Total_application_f) * 100.0f ); - const int RAMPct_applet = (int)((RAM_Used_applet_f / RAM_Total_applet_f) * 100.0f ); - const int RAMPct_system = (int)((RAM_Used_system_f / RAM_Total_system_f) * 100.0f ); - const int RAMPct_systemunsafe = (int)((RAM_Used_systemunsafe_f/ RAM_Total_systemunsafe_f)* 100.0f ); - - snprintf(RAM_var_compressed_c, sizeof(RAM_var_compressed_c), - "%.1f MB / %.1f MB\n" - "%.1f MB / %.1f MB\n" - "%.1f MB / %.1f MB\n" - "%.1f MB / %.1f MB\n" - "%.1f MB / %.1f MB", - RAM_Used_all_f, RAM_Total_all_f, - RAM_Used_application_f, RAM_Total_application_f, - RAM_Used_applet_f, RAM_Total_applet_f, - RAM_Used_system_f, RAM_Total_system_f, - RAM_Used_systemunsafe_f, RAM_Total_systemunsafe_f - ); - - // 2. Percentages only (newlines preserved) - snprintf(RAM_percentage_var_compressed_c, sizeof(RAM_percentage_var_compressed_c), - "(%d%%)\n" - "(%d%%)\n" - "(%d%%)\n" - "(%d%%)\n" - "(%d%%)", - RAMPct_all, - RAMPct_app, - RAMPct_applet, - RAMPct_system, - RAMPct_systemunsafe - ); - - if (R_SUCCEEDED(hocclkCheck)) { - if (settings.ramInfoMode == "Bandwidth") { - const unsigned bwAll = partLoad[HocClkPartLoad_RamBWAll] / 1000; - const unsigned bwAllD = (partLoad[HocClkPartLoad_RamBWAll] % 1000) / 100; - const unsigned bwPeak = partLoad[HocClkPartLoad_RamBWPeak] / 1000; - const unsigned bwPeakD= (partLoad[HocClkPartLoad_RamBWPeak]% 1000) / 100; - const unsigned bwCpu = partLoad[HocClkPartLoad_RamBWCpu] / 1000; - const unsigned bwCpuD = (partLoad[HocClkPartLoad_RamBWCpu] % 1000) / 100; - const unsigned bwGpu = partLoad[HocClkPartLoad_RamBWGpu] / 1000; - const unsigned bwGpuD = (partLoad[HocClkPartLoad_RamBWGpu] % 1000) / 100; - snprintf(RAM_bw_peak_c, sizeof RAM_bw_peak_c, "%u.%u GB/s", bwPeak, bwPeakD); - snprintf(RAM_bw_total_c, sizeof RAM_bw_total_c, "%u.%u GB/s", bwAll, bwAllD); - snprintf(RAM_bw_gpu_c, sizeof RAM_bw_gpu_c, "%u.%u GB/s", bwGpu, bwGpuD); - snprintf(RAM_bw_cpu_c, sizeof RAM_bw_cpu_c, "%u.%u GB/s", bwCpu, bwCpuD); - } else { - const int RAM_GPU_Load = partLoad[HocClkPartLoad_EMC] - partLoad[HocClkPartLoad_EMCCpu]; - snprintf(RAM_load_c, sizeof RAM_load_c, - "%u.%u%% CPU %u.%u%% GPU %u.%u%%", - partLoad[HocClkPartLoad_EMC] / 10, partLoad[HocClkPartLoad_EMC] % 10, - partLoad[HocClkPartLoad_EMCCpu] / 10, partLoad[HocClkPartLoad_EMCCpu] % 10, - RAM_GPU_Load / 10, RAM_GPU_Load % 10); - } - } - ///Thermal - snprintf(SOC_temperature_c, sizeof SOC_temperature_c, "%.1f\u00B0C", SOC_temperatureF); - snprintf(PCB_temperature_c, sizeof PCB_temperature_c, "%.1f\u00B0C", PCB_temperatureF); - snprintf(skin_temperature_c, sizeof skin_temperature_c, "%d.%d\u00B0C", skin_temperaturemiliC / 1000, (skin_temperaturemiliC / 100) % 10); - - snprintf(Rotation_SpeedLevel_c, sizeof Rotation_SpeedLevel_c, "%.1f%%", Rotation_Duty); - - if (settings.realTemps) { - if (realCPU_Temp != 0) { - snprintf(CPU_temp_c, sizeof(CPU_temp_c), "%.1f°C", realCPU_Temp / 1000.0f); - } - if (realGPU_Temp != 0) { - snprintf(GPU_temp_c, sizeof(GPU_temp_c), "%.1f°C", realGPU_Temp / 1000.0f); - } - if (realRAM_Temp != 0) { - snprintf(RAM_temp_c, sizeof(RAM_temp_c), "%.1f°C", realRAM_Temp / 1000.0f); - } - } - ///FPS - if (settings.showFPS == true) { - snprintf(PFPS_value_c, sizeof PFPS_value_c, "%1u", FPS); - snprintf(FPS_value_c, sizeof FPS_value_c, "%.1f", useOldFPSavg ? FPSavg_old : FPSavg); - } - - //Resolutions - if ((settings.showRES == true) && GameRunning && NxFps) { - if (!resolutionLookup) { - (NxFps -> renderCalls[0].calls) = 0xFFFF; - resolutionLookup = 1; - } - else if (resolutionLookup == 1) { - if ((NxFps -> renderCalls[0].calls) != 0xFFFF) resolutionLookup = 2; - } - else { - if (NxFps && SharedMemoryUsed) { - memcpy(&m_resolutionRenderCalls, &(NxFps -> renderCalls), sizeof(m_resolutionRenderCalls)); - memcpy(&m_resolutionViewportCalls, &(NxFps -> viewportCalls), sizeof(m_resolutionViewportCalls)); - } else { - memset(&m_resolutionRenderCalls, 0, sizeof(m_resolutionRenderCalls)); - memset(&m_resolutionViewportCalls, 0, sizeof(m_resolutionViewportCalls)); - } - qsort(m_resolutionRenderCalls, 8, sizeof(resolutionCalls), compare); - qsort(m_resolutionViewportCalls, 8, sizeof(resolutionCalls), compare); - memset(&m_resolutionOutput, 0, sizeof(m_resolutionOutput)); - size_t out_iter = 0; - bool found = false; - for (size_t i = 0; i < 8; i++) { - for (size_t x = 0; x < 8; x++) { - if (m_resolutionRenderCalls[i].width == 0) { - break; - } - if ((m_resolutionRenderCalls[i].width == m_resolutionViewportCalls[x].width) && (m_resolutionRenderCalls[i].height == m_resolutionViewportCalls[x].height)) { - m_resolutionOutput[out_iter].width = m_resolutionRenderCalls[i].width; - m_resolutionOutput[out_iter].height = m_resolutionRenderCalls[i].height; - m_resolutionOutput[out_iter].calls = (m_resolutionRenderCalls[i].calls > m_resolutionViewportCalls[x].calls) ? m_resolutionRenderCalls[i].calls : m_resolutionViewportCalls[x].calls; - out_iter++; - found = true; - break; - } - } - if (!found && m_resolutionRenderCalls[i].width != 0) { - m_resolutionOutput[out_iter].width = m_resolutionRenderCalls[i].width; - m_resolutionOutput[out_iter].height = m_resolutionRenderCalls[i].height; - m_resolutionOutput[out_iter].calls = m_resolutionRenderCalls[i].calls; - out_iter++; - } - found = false; - if (out_iter == 8) break; - } - if (out_iter < 8) { - const size_t out_iter_s = out_iter; - for (size_t x = 0; x < 8; x++) { - for (size_t y = 0; y < out_iter_s; y++) { - if (m_resolutionViewportCalls[x].width == 0) { - break; - } - if ((m_resolutionViewportCalls[x].width == m_resolutionOutput[y].width) && (m_resolutionViewportCalls[x].height == m_resolutionOutput[y].height)) { - found = true; - break; - } - } - if (!found && m_resolutionViewportCalls[x].width != 0) { - m_resolutionOutput[out_iter].width = m_resolutionViewportCalls[x].width; - m_resolutionOutput[out_iter].height = m_resolutionViewportCalls[x].height; - m_resolutionOutput[out_iter].calls = m_resolutionViewportCalls[x].calls; - out_iter++; - } - found = false; - if (out_iter == 8) break; - } - } - qsort(m_resolutionOutput, 8, sizeof(resolutionCalls), compare); - static std::pair old_res[2]; - - // Only swap if BOTH resolutions exist (prevent swapping with empty slot) - if (m_resolutionOutput[0].width && m_resolutionOutput[1].width) { - if ((m_resolutionOutput[0].width == old_res[1].first && m_resolutionOutput[0].height == old_res[1].second) || - (m_resolutionOutput[1].width == old_res[0].first && m_resolutionOutput[1].height == old_res[0].second)) { - const uint16_t swap_width = m_resolutionOutput[0].width; - const uint16_t swap_height = m_resolutionOutput[0].height; - m_resolutionOutput[0].width = m_resolutionOutput[1].width; - m_resolutionOutput[0].height = m_resolutionOutput[1].height; - m_resolutionOutput[1].width = swap_width; - m_resolutionOutput[1].height = swap_height; - } - } - - //if (!m_resolutionOutput[1].width) { - // snprintf(Resolutions_c, sizeof(Resolutions_c), "%dx%d", m_resolutionOutput[0].width, m_resolutionOutput[0].height); - //} - //else { - // snprintf(Resolutions_c, sizeof(Resolutions_c), "%dx%d%dx%d", m_resolutionOutput[0].width, m_resolutionOutput[0].height, m_resolutionOutput[1].width, m_resolutionOutput[1].height); - //} - - if (!m_resolutionOutput[1].width || !m_resolutionOutput[0].width) { - if (!m_resolutionOutput[1].width) - snprintf(Resolutions_c, sizeof(Resolutions_c), "%dx%d", m_resolutionOutput[0].width, m_resolutionOutput[0].height); - else snprintf(Resolutions_c, sizeof(Resolutions_c), "%dx%d", m_resolutionOutput[1].width, m_resolutionOutput[1].height); - } - else snprintf(Resolutions_c, sizeof(Resolutions_c),"%dx%d%dx%d", m_resolutionOutput[0].width, m_resolutionOutput[0].height, m_resolutionOutput[1].width, m_resolutionOutput[1].height); - - old_res[0] = std::make_pair(m_resolutionOutput[0].width, m_resolutionOutput[0].height); - old_res[1] = std::make_pair(m_resolutionOutput[1].width, m_resolutionOutput[1].height); - } - if (settings.showRDSD == true && GameRunning && NxFps) { - if ((NxFps -> readSpeedPerSecond) != 0.f) snprintf(readSpeed_c, sizeof(readSpeed_c), "%.2f MiB/s", (NxFps -> readSpeedPerSecond) / 1048576.f); - else snprintf(readSpeed_c, sizeof(readSpeed_c), "n/d"); - } - } - else if (!GameRunning && resolutionLookup != 0) { - resolutionLookup = 0; - } - - mutexUnlock(&mutex_Misc); - - /* ── Battery / power draw ───────────────────────────────────── */ - char remainingBatteryLife[8]; - - /* Normalise "-0.00" → "0.00" W */ - const float drawW = (fabsf(PowerConsumption) < 0.01f) ? 0.0f - : PowerConsumption; - - mutexLock(&mutex_BatteryChecker); - - /* keep "--:--" whenever estimate is negative */ - if (batTimeEstimate >= 0 && !(drawW <= 0.01f && drawW >= -0.01f)) { - snprintf(remainingBatteryLife, sizeof(remainingBatteryLife), - "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); - } else { - strcpy(remainingBatteryLife, "--:--"); - } - - const float batteryPercent = (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f; - - snprintf(BatteryDraw_c, sizeof(BatteryDraw_c), - "%.2f W%.0f%% [%s]", - drawW, - batteryPercent, - remainingBatteryLife); - - mutexUnlock(&mutex_BatteryChecker); - - if (!skipOnce) { - if (runOnce) { - isRendering = true; - leventClear(&renderingStopEvent); - runOnce = false; - } - } else { - skipOnce = false; - } - } - - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (isKeyComboPressed(keysHeld, keysDown)) { - isRendering = false; - leventSignal(&renderingStopEvent); - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - skipOnce = true; - runOnce = true; - TeslaFPS = 60; - lastSelectedItem = "Full"; - lastMode = ""; - tsl::swapTo(); - return true; - } - return false; - } -}; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Micro.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/Micro.hpp deleted file mode 100644 index 9c999d13..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Micro.hpp +++ /dev/null @@ -1,1300 +0,0 @@ -class MainMenu; - -class MicroOverlay : public tsl::Gui { -private: - char GPU_Load_c[32]; - char RAM_var_compressed_c[128]; - char CPU_compressed_c[160]; - char CPU_Usage0[32]; - char CPU_Usage1[32]; - char CPU_Usage2[32]; - char CPU_Usage3[32]; - char CPU_UsageM[32]; - char soc_temperature_c[32]; - char skin_temperature_c[32]; - char FPS_var_compressed_c[64]; - char Battery_c[32]; - char CPU_volt_c[16]; - char GPU_volt_c[16]; - char RAM_volt_c[32]; - char SOC_volt_c[16]; - char CPU_temp_c[32]; - char GPU_temp_c[32]; - char RAM_temp_c[32]; - char RES_var_compressed_c[32]; - char READ_var_compressed_c[32]; - char DTC_c[32]; - - static constexpr uint32_t margin = 4; - - // Performance optimization members - bool Initialized = false; - MicroSettings settings; - size_t text_width = 0; - size_t fps_width = 0; - ApmPerformanceMode performanceMode = ApmPerformanceMode_Invalid; - size_t fontsize = 0; - bool showFPS = false; - uint64_t systemtickfrequency_impl = systemtickfrequency; - - // Pre-compiled render data structures - struct RenderItem { - uint8_t type; - const char* label; - const char* data_ptr; - const char* volt_ptr; - bool has_voltage; - }; - - // Resolution tracking - resolutionCalls m_resolutionRenderCalls[8] = {0}; - resolutionCalls m_resolutionViewportCalls[8] = {0}; - resolutionCalls m_resolutionOutput[8] = {0}; - uint8_t resolutionLookup = 0; - bool resolutionShow = false; - - std::vector renderItems; - uint32_t cachedMargin = 0; - tsl::Color catColorA = 0; - tsl::Color textColorA = 0; - uint32_t base_y = 0; - bool renderDataDirty = true; - - bool skipOnce = true; - bool runOnce = true; - - // Fixed spacing system - calculate actual widths at render time - struct LayoutMetrics { - uint32_t label_data_gap = 8; // Fixed gap between label and data - uint32_t volt_separator_gap = 0; // Fixed gap before voltage separator - uint32_t volt_data_gap = 0; // Fixed gap after voltage separator - uint32_t item_spacing = 16; // Minimum spacing between complete items - uint32_t side_margin = 3; // Margins on left and right - bool calculated = false; - } layout; - - // Lookup table for difference symbols - static constexpr const char* diffSymbols[4] = {"△", "@", "▽", "≠"}; - - inline const char* getDifferenceSymbol(int32_t delta) { - if (delta > 20000) return diffSymbols[0]; // △ - if (delta > -20000) return diffSymbols[1]; // @ - if (delta < -50000) return diffSymbols[3]; // ≠ - return diffSymbols[2]; // ▽ - } - - void calculateLayoutMetrics(tsl::gfx::Renderer *renderer) { - if (layout.calculated) return; - - // Use font size to determine appropriate spacing - if (fontsize <= 16) { - layout.label_data_gap = 6; - layout.volt_separator_gap = 0; - layout.volt_data_gap = 0; - layout.item_spacing = 12; - } else if (fontsize <= 20) { - layout.label_data_gap = 8; - layout.volt_separator_gap = 0; - layout.volt_data_gap = 0; - layout.item_spacing = 16; - } else { - layout.label_data_gap = 10; - layout.volt_separator_gap = 0; - layout.volt_data_gap = 0; - layout.item_spacing = 20; - } - - layout.calculated = true; - } - -public: - MicroOverlay() { - CPU_temp_c[0] = '\0'; - GPU_temp_c[0] = '\0'; - RAM_temp_c[0] = '\0'; - - tsl::hlp::requestForeground(false); - disableJumpTo = true; - //tsl::initializeUltrahandSettings(); - GetConfigSettings(&settings); - apmGetPerformanceMode(&performanceMode); - if (performanceMode == ApmPerformanceMode_Normal) { - fontsize = settings.handheldFontSize; - } - else fontsize = settings.dockedFontSize; - - if (ult::limitedMemory && settings.setPosBottom) { - const auto [horizontalUnderscanPixels, verticalUnderscanPixels] = tsl::gfx::getUnderscanPixels(); - tsl::gfx::Renderer::get().setLayerPos(0, !verticalUnderscanPixels ? 1038 : 1038- (tsl::cfg::ScreenHeight/720. * verticalUnderscanPixels) +0.5); - } - - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().removeScreenshotStacks(); - } - mutexInit(&mutex_BatteryChecker); - mutexInit(&mutex_Misc); - TeslaFPS = settings.refreshRate; - systemtickfrequency_impl /= settings.refreshRate; - FullMode = false; - //alphabackground = 0x0; - deactivateOriginalFooter = true; - StartThreads(); - - // Pre-allocate render items vector - //renderItems.reserve(8); - realVoltsPolling = settings.realVolts; - - // Get initial battery readings BEFORE starting threads - if (R_SUCCEEDED(psmCheck) && R_SUCCEEDED(i2cCheck)) { - uint16_t data = 0; - float tempA = 0.0; - - // Get initial power consumption - Max17050ReadReg(MAX17050_AvgCurrent, &data); - tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; - PowerConsumption = tempA * batVoltageAvg / 1000000.0; // Rough initial estimate - - // Get initial battery info - psmGetBatteryChargeInfoFields(psmService, &_batteryChargeInfoFields); - - // Get initial time estimate - if (tempA >= 0) { - batTimeEstimate = -1; - } else { - Max17050ReadReg(MAX17050_TTE, &data); - const float batteryTimeEstimateInMinutes = (5.625 * data) / 60; - if (batteryTimeEstimateInMinutes > (99.0*60.0)+59.0) { - batTimeEstimate = (99*60)+59; - } else { - batTimeEstimate = (int16_t)batteryTimeEstimateInMinutes; - } - } - } else { - // Fallback if checks failed - PowerConsumption = 0.0f; - batTimeEstimate = -1; - _batteryChargeInfoFields = {0}; - } - - // Now format the initial Battery_c string - char remainingBatteryLife[8]; - const float drawW = (fabsf(PowerConsumption) < 0.01f) ? 0.0f : PowerConsumption; - - if (batTimeEstimate >= 0 && !(drawW <= 0.01f && drawW >= -0.01f)) { - snprintf(remainingBatteryLife, sizeof(remainingBatteryLife), - "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); - } else { - strcpy(remainingBatteryLife, "--:--"); - } - - if (!settings.invertBatteryDisplay) { - snprintf(Battery_c, sizeof(Battery_c), - "%.2f W%.1f%% [%s]", - drawW, - (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f, - remainingBatteryLife); - } else { - snprintf(Battery_c, sizeof(Battery_c), - "%.1f%% [%s]%.2f W", - (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f, - remainingBatteryLife, - drawW); - } - - - } - - ~MicroOverlay() { - CloseThreads(); - fixForeground = true; - FullMode = true; - } - - // Fast parsing and render item preparation - void prepareRenderItems() { - if (!renderDataDirty) return; - - renderItems.clear(); - - // Fast manual parsing of settings.show - const std::string& show = settings.show; - size_t start = 0, end = 0; - uint8_t seen_flags = 0; - - static size_t len; - static uint32_t key3; - while (start < show.length()) { - end = show.find('+', start); - if (end == std::string::npos) end = show.length(); - - len = end - start; - if (len >= 3) { - const char* key = &show[start]; - - // Use first 3 chars for fast comparison - key3 = (key[0] << 16) | (key[1] << 8) | key[2]; - - switch (key3) { - case 0x435055: // "CPU" - if (!(seen_flags & 1)) { - renderItems.push_back({0, "CPU", CPU_compressed_c, CPU_volt_c, settings.realVolts}); - seen_flags |= 1; - } - break; - case 0x475055: // "GPU" - if (!(seen_flags & 2)) { - renderItems.push_back({1, "GPU", GPU_Load_c, GPU_volt_c, settings.realVolts}); - seen_flags |= 2; - } - break; - case 0x52414D: // "RAM" - if (!(seen_flags & 4)) { - renderItems.push_back({2, "RAM", RAM_var_compressed_c, RAM_volt_c, settings.realVolts}); - seen_flags |= 4; - } - break; - case 0x534F43: // "SOC" - if (!(seen_flags & 8)) { - renderItems.push_back({3, "SOC", soc_temperature_c, SOC_volt_c, settings.realVolts && settings.showSOCVoltage}); - seen_flags |= 8; - } - break; - case 0x544D50: // "TMP" - if (!(seen_flags & 16)) { - renderItems.push_back({4, "TMP", skin_temperature_c, SOC_volt_c, settings.realVolts && settings.showSOCVoltage}); - seen_flags |= 16; - } - break; - case 0x524553: // "RES" - if (!(seen_flags & 128)) { - renderItems.push_back({7, "RES", RES_var_compressed_c, nullptr, false}); // We'll reuse FPS buffer temporarily - seen_flags |= 128; - resolutionShow = true; - } - break; - case 0x465053: // "FPS" - if (!(seen_flags & 32)) { - renderItems.push_back({5, "FPS", FPS_var_compressed_c, nullptr, false}); - seen_flags |= 32; - } - break; - case 0x424154: // "BAT" - if (!(seen_flags & 64)) { - renderItems.push_back({6, "BAT", Battery_c, nullptr, false}); - seen_flags |= 64; - } - break; - case 0x524541: // "REA" (for READ) - if (len >= 4 && key[3] == 'D' && !(seen_flags & 512)) { - renderItems.push_back({9, "READ", READ_var_compressed_c, nullptr, false}); - seen_flags |= 512; - } - break; - case 0x445443: // "DTC" - if (!(seen_flags & 256) && settings.showDTC) { - renderItems.push_back({8, settings.useDTCSymbol ? "\uE007" : "DTC", DTC_c, nullptr, false}); - seen_flags |= 256; - } - break; - } - } - start = end + 1; - } - - renderDataDirty = false; - } - - virtual tsl::elm::Element* createUI() override { - - auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - cachedMargin = renderer->getTextDimensions("CPUGPURAMSOCBAT[]", false, fontsize).second; - if (!Initialized) { - //cachedMargin = renderer->drawString(" ", false, 0, 0, fontsize, renderer->a(0x0000)).first; - - catColorA = settings.catColor; - textColorA = settings.textColor; - base_y = settings.setPosBottom ? - tsl::cfg::FramebufferHeight - (fontsize + (fontsize / 4)) +1: 0; - Initialized = true; - renderDataDirty = true; - layout.calculated = false; // Force recalculation - tsl::hlp::requestForeground(false); - } - - //renderer->drawRect(0, 0, tsl::cfg::FramebufferWidth, cachedMargin + 4, a(settings.backgroundColor)); - renderer->drawRect(0, settings.setPosBottom ? base_y-1 : 0, tsl::cfg::FramebufferWidth, cachedMargin + 4, a(settings.backgroundColor)); - - // Prepare render items if settings changed - prepareRenderItems(); - calculateLayoutMetrics(renderer); - - // Separate battery from other items - std::vector main_items; - //RenderItem* battery_item = nullptr; - - for (auto& item : renderItems) { - //if (item.type == 6) { // BAT - // battery_item = &item; - if (item.type == 5 && (!GameRunning || (strcmp(FPS_var_compressed_c, "254.0") == 0))) { - // Skip FPS if no game running - continue; - } else if (item.type == 7 && (!GameRunning || !m_resolutionOutput[0].width)) { - // Skip RES if no game running or no resolution data yet - continue; - } else if (item.type == 8 && !settings.showDTC) { - // Skip DTC if disabled in settings - continue; - } else if (item.type == 9 && (!GameRunning || !NxFps)) { - // Skip READ if no game running or no NxFps available - continue; - } else { - main_items.push_back(item); - } - } - - // Calculate actual widths for all main items - struct ItemLayout { - uint32_t label_width; - uint32_t data_width; - uint32_t volt_width; - uint32_t total_width; - }; - - std::vector item_layouts; - uint32_t total_main_width = 0; - - static const auto sep_width = renderer->getTextDimensions("", false, fontsize).first; - - static ItemLayout item_layout; - for (const auto& item : main_items) { - item_layout = {}; - - // Calculate actual label width - //auto label_dim = renderer->drawString(item.label, false, 0, 0, fontsize, renderer->a(0x0000)); - //auto label_dim = renderer->getTextDimensions(item.label, fontsize); - item_layout.label_width = renderer->getTextDimensions(item.label, false, fontsize).first; - - // Calculate actual data width - //auto data_dim = renderer->drawString(item.data_ptr, false, 0, 0, fontsize, renderer->a(0x0000)); - //auto data_dim = renderer->getTextDimensions(item.data_ptr, fontsize); - item_layout.data_width = renderer->getTextDimensions(item.data_ptr, false, fontsize).first; - - // Calculate voltage width if present - if (item.has_voltage && item.volt_ptr) { - //uto volt_dim = renderer->drawString(item.volt_ptr, false, 0, 0, fontsize, renderer->a(0x0000)); - //auto volt_dim = renderer->getTextDimensions(item.volt_ptr, fontsize); - item_layout.volt_width = renderer->getTextDimensions(item.volt_ptr, false, fontsize).first; - - // Total: label + gap + data + gap + "|" + gap + voltage - //auto sep_width = renderer->drawString("", false, 0, 0, fontsize, renderer->a(0x0000)); - item_layout.total_width = item_layout.label_width + layout.label_data_gap + - item_layout.data_width + layout.volt_separator_gap + - sep_width + layout.volt_data_gap + item_layout.volt_width; - } else { - // Total: label + gap + data - item_layout.total_width = item_layout.label_width + layout.label_data_gap + item_layout.data_width; - } - - item_layouts.push_back(item_layout); - total_main_width += item_layout.total_width; - } - - - - // Determine if we have battery and handle it as the rightmost item - std::vector all_items_ordered; - std::vector all_layouts_ordered; - - // Add main items first - for (size_t i = 0; i < main_items.size(); i++) { - all_items_ordered.push_back(main_items[i]); - all_layouts_ordered.push_back(item_layouts[i]); - } - - // Add battery as the last item if present - //if (battery_item) { - // //auto bat_label_dim = renderer->drawString("BAT", false, 0, 0, fontsize, renderer->a(0x0000)); - // //auto bat_label_dim = renderer->getTextDimensions("BAT", fontsize); - // //auto bat_data_dim = renderer->drawString(battery_item->data_ptr, false, 0, 0, fontsize, renderer->a(0x0000)); - // //auto bat_data_dim = renderer->getTextDimensions(battery_item->data_ptr, fontsize); - // - // ItemLayout battery_layout = {}; - // battery_layout.label_width = renderer->getTextDimensions("BAT", false, fontsize).first; - // battery_layout.data_width = renderer->getTextDimensions(battery_item->data_ptr, false, fontsize).first; - // battery_layout.volt_width = 0; - // battery_layout.total_width = battery_layout.label_width + layout.label_data_gap + battery_layout.data_width; - // - // all_items_ordered.push_back(*battery_item); - // all_layouts_ordered.push_back(battery_layout); - //} - - // Calculate total width of all items - uint32_t total_all_width = 0; - for (const auto& item_layout : all_layouts_ordered) { - total_all_width += item_layout.total_width; - } - - // Calculate available space for distribution - //uint32_t available_width = tsl::cfg::FramebufferWidth - (2 * layout.side_margin); - //uint32_t remaining_space = available_width - total_all_width; - - // Calculate positions based on alignment mode - std::vector item_positions; - const size_t N = all_items_ordered.size(); - if (N == 0) return; - - if (N == 1) { - // Single item positioning based on alignment - if (settings.alignTo == 2) { // RIGHT - const uint32_t total_width = all_layouts_ordered[0].total_width; - item_positions.push_back(tsl::cfg::FramebufferWidth - layout.side_margin - total_width); - } else { // LEFT or CENTER - item_positions.push_back(layout.side_margin); - } - } else { - uint32_t total_widths = 0; - for (const auto& layout : all_layouts_ordered) { - total_widths += layout.total_width; - } - - if (settings.alignTo == 0) { // LEFT alignment - // All items except last positioned from left with small gaps - // Last item (battery if present) positioned at far right - const uint32_t small_gap = layout.item_spacing; - - // Position items from left - uint32_t current_x = layout.side_margin; - for (size_t i = 0; i < N - 1; ++i) { - item_positions.push_back(current_x); - current_x += all_layouts_ordered[i].total_width + small_gap; - } - - // Position last item at far right - const uint32_t last_width = all_layouts_ordered[N-1].total_width; - item_positions.push_back(tsl::cfg::FramebufferWidth - layout.side_margin - last_width); - - } else if (settings.alignTo == 2) { // RIGHT alignment - // First item at far left, remaining items packed at right - const uint32_t small_gap = layout.item_spacing; - - // Resize vector to hold all positions - item_positions.resize(N); - - // Position first item at far left - item_positions[0] = layout.side_margin; - - // Calculate total width of items 1 to N-1 plus gaps between them - uint32_t right_group_width = 0; - for (size_t i = 1; i < N; ++i) { - right_group_width += all_layouts_ordered[i].total_width; - if (i < N - 1) right_group_width += small_gap; // Gap after each item except the last - } - - // Start positioning from right margin minus total width of right group - uint32_t current_x = tsl::cfg::FramebufferWidth - layout.side_margin - right_group_width; - - // Position items 1 to N-1 sequentially from left to right within the right group - for (size_t i = 1; i < N; ++i) { - item_positions[i] = current_x; - current_x += all_layouts_ordered[i].total_width + small_gap; - } - } else { // CENTER alignment (default behavior) - // Total available width for spacing = framebuffer width minus total item widths minus margins - const int32_t total_spacing = (int32_t)tsl::cfg::FramebufferWidth - (2 * (int32_t)layout.side_margin) - (int32_t)total_widths; - - // Number of gaps between items is N-1 - const uint32_t gap = total_spacing > 0 ? (uint32_t)(total_spacing / (N - 1)) : 0; - - // Position first item flush left - item_positions.push_back(layout.side_margin); - static uint32_t prev_pos, prev_width; - // Position subsequent items - for (size_t i = 1; i < N; ++i) { - prev_pos = item_positions[i - 1]; - prev_width = all_layouts_ordered[i - 1].total_width; - item_positions.push_back(prev_pos + prev_width + gap); - } - - // Fix any rounding error for center alignment - const int32_t last_item_end = item_positions.back() + all_layouts_ordered.back().total_width; - const int32_t overflow = (int32_t)tsl::cfg::FramebufferWidth - layout.side_margin - last_item_end; - - if (overflow != 0) { - for (size_t i = 1; i < item_positions.size(); ++i) { - item_positions[i] += overflow; - } - } - } - } - - - uint32_t current_x; - static std::vector specialChars = {""}; - - // Render all items at calculated positions - for (size_t i = 0; i < all_items_ordered.size(); i++) { - const auto& item = all_items_ordered[i]; - const auto& item_layout = all_layouts_ordered[i]; - current_x = item_positions[i]; - - // Draw label - renderer->drawString(item.label, false, current_x, base_y + cachedMargin, fontsize, catColorA); - current_x += item_layout.label_width + layout.label_data_gap; - - // Draw data - //renderer->drawString(item.data_ptr, false, current_x, base_y + fontsize, fontsize, textColorA); - - if (settings.useDynamicColors) { - // Draw data with temperature gradient support - if (item.type == 0) { // CPU - std::string dataStr(item.data_ptr); - const size_t degreesPos = dataStr.find("°"); - if (degreesPos != std::string::npos && settings.realTemps && realCPU_Temp != 0) { - size_t tempStart = dataStr.rfind(' ', degreesPos); - if (tempStart != std::string::npos) { - tempStart++; - const size_t cPos = dataStr.find("C", degreesPos); - if (cPos != std::string::npos) { - const size_t tempEnd = cPos + 1; - - const std::string preTempPart = dataStr.substr(0, tempStart); - const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart); - const std::string postTempPart = dataStr.substr(tempEnd); - - const float temp = realCPU_Temp / 1000.0f; - const tsl::Color tempColor = tsl::GradientColor(temp); - - uint32_t renderX = current_x; - if (!preTempPart.empty()) { - renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first; - } - - renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor)); - - if (!postTempPart.empty()) { - renderX += renderer->getTextDimensions(tempPart, false, fontsize).first; - renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - - } else if (item.type == 1) { // GPU - std::string dataStr(item.data_ptr); - const size_t degreesPos = dataStr.find("°"); - if (degreesPos != std::string::npos && settings.realTemps && realGPU_Temp != 0) { - size_t tempStart = dataStr.rfind(' ', degreesPos); - if (tempStart != std::string::npos) { - tempStart++; - const size_t cPos = dataStr.find("C", degreesPos); - if (cPos != std::string::npos) { - const size_t tempEnd = cPos + 1; - - const std::string preTempPart = dataStr.substr(0, tempStart); - const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart); - const std::string postTempPart = dataStr.substr(tempEnd); - - const float temp = realGPU_Temp / 1000.0f; - const tsl::Color tempColor = tsl::GradientColor(temp); - - uint32_t renderX = current_x; - if (!preTempPart.empty()) { - renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first; - } - - renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor)); - - if (!postTempPart.empty()) { - renderX += renderer->getTextDimensions(tempPart, false, fontsize).first; - renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - - } else if (item.type == 2) { // RAM - std::string dataStr(item.data_ptr); - const size_t degreesPos = dataStr.find("°"); - if (degreesPos != std::string::npos && settings.realTemps && realRAM_Temp != 0) { - size_t tempStart = dataStr.rfind(' ', degreesPos); - if (tempStart != std::string::npos) { - tempStart++; - const size_t cPos = dataStr.find("C", degreesPos); - if (cPos != std::string::npos) { - const size_t tempEnd = cPos + 1; - - const std::string preTempPart = dataStr.substr(0, tempStart); - const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart); - const std::string postTempPart = dataStr.substr(tempEnd); - - const float temp = realRAM_Temp / 1000.0f; - const tsl::Color tempColor = tsl::GradientColor(temp); - - uint32_t renderX = current_x; - if (!preTempPart.empty()) { - renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first; - } - - renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor)); - - if (!postTempPart.empty()) { - renderX += renderer->getTextDimensions(tempPart, false, fontsize).first; - renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - - } else if (item.type == 3) { // SOC temperature - // Parse SOC temperature: "XX°C (XX%)" - std::string dataStr(item.data_ptr); - const size_t degreesPos = dataStr.find("°"); - if (degreesPos != std::string::npos) { - const size_t cPos = dataStr.find("C", degreesPos); - if (cPos != std::string::npos) { - const size_t tempEnd = cPos + 1; // Include the 'C' - - // Extract temperature value and apply gradient - const int temp = atoi(item.data_ptr); - const tsl::Color tempColor = tsl::GradientColor((float)temp); - - // Split into temperature part and remaining part - const std::string tempPart = dataStr.substr(0, tempEnd); - const std::string restPart = dataStr.substr(tempEnd); - - // Render temperature with gradient color - renderer->drawString(tempPart, false, current_x, base_y + cachedMargin, fontsize, tempColor); - - // Render remaining text with normal color - if (!restPart.empty()) { - const uint32_t tempPartWidth = renderer->getTextDimensions(tempPart, false, fontsize).first; - renderer->drawStringWithColoredSections(restPart, false, specialChars, current_x + tempPartWidth, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - // Fallback: render normally - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - // Fallback: render normally - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - - } else if (item.type == 4) { // TMP multiple temperatures - // Parse TMP temperatures: "XX°C XX°C XX°C (XX%)" - std::string dataStr(item.data_ptr); - uint32_t renderX = current_x; - size_t pos = 0; - bool parseSuccess = true; - - // Parse up to 3 temperatures - for (int tempCount = 0; tempCount < 3 && parseSuccess && pos < dataStr.length(); tempCount++) { - // Skip any leading spaces - while (pos < dataStr.length() && dataStr[pos] == ' ') { - renderer->drawString(" ", false, renderX, base_y + cachedMargin, fontsize, textColorA); - renderX += renderer->getTextDimensions(" ", false, fontsize).first; - pos++; - } - - if (pos >= dataStr.length()) break; - - // Find degrees symbol - const size_t degreesPos = dataStr.find("°", pos); - if (degreesPos == std::string::npos) { - parseSuccess = false; - break; - } - - // Find 'C' after degrees symbol - const size_t cPos = dataStr.find("C", degreesPos); - if (cPos == std::string::npos) { - parseSuccess = false; - break; - } - - const size_t tempEnd = cPos + 1; // Include the 'C' - - // Extract and render temperature with gradient - const std::string tempPart = dataStr.substr(pos, tempEnd - pos); - const int temp = atoi(tempPart.c_str()); - const tsl::Color tempColor = tsl::GradientColor((float)temp); - - renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor)); - renderX += renderer->getTextDimensions(tempPart, false, fontsize).first; - - pos = tempEnd; - } - - // Render any remaining text (like " (50%)") - if (pos < dataStr.length()) { - const std::string restPart = dataStr.substr(pos); - renderer->drawStringWithColoredSections(restPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - - // If parsing failed, fall back to normal rendering - if (!parseSuccess) { - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - - } else { - // Normal rendering for all other item types - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } else { - // Normal rendering for all other item types - renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - current_x += item_layout.data_width; - - // Draw voltage if present - if (item.has_voltage && item.volt_ptr) { - current_x += layout.volt_separator_gap; - renderer->drawString("", false, current_x, base_y + cachedMargin, fontsize, a(settings.separatorColor)); - //auto sep_width = renderer->drawString("", false, 0, 0, fontsize, renderer->a(0x0000)); - //auto sep_width = renderer->getTextDimensions("", fontsize); - current_x += sep_width + layout.volt_data_gap; - renderer->drawStringWithColoredSections(item.volt_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor)); - } - } - }); - - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("", ""); - rootFrame->setContent(Status); - return rootFrame; - } - - virtual void update() override { - if (triggerExitNow) - return; - - if (!SaltySD) { - SaltySD = CheckPort(); - - if (SaltySD) { - LoadSharedMemory(); - //Assign NX-FPS to default core - threadCreate(&t6, CheckIfGameRunning, NULL, NULL, 0x1000, 0x38, -2); - threadStart(&t6); - } - } - - //static bool triggerExit = false; - //if (triggerExit) { - // ult::setIniFileValue( - // ult::ULTRAHAND_CONFIG_INI_PATH, - // ult::ULTRAHAND_PROJECT_NAME, - // ult::IN_OVERLAY_STR, - // ult::FALSE_STR - // ); - // tsl::setNextOverlay( - // ult::OVERLAY_PATH + "ovlmenu.ovl" - // ); - // tsl::Overlay::get()->close(); - // return; - //} - - apmGetPerformanceMode(&performanceMode); - if (performanceMode == ApmPerformanceMode_Normal) { - if (fontsize != settings.handheldFontSize) { - Initialized = false; - layout.calculated = false; // Recalculate layout for new font size - fontsize = settings.handheldFontSize; - } - } - else if (performanceMode == ApmPerformanceMode_Boost) { - if (fontsize != settings.dockedFontSize) { - Initialized = false; - layout.calculated = false; // Recalculate layout for new font size - fontsize = settings.dockedFontSize; - } - } - - // CPU usage calculations - optimized with fewer conditionals - const double inv_freq = 1.0 / systemtickfrequency_impl; - - // Capture systemtickfrequency_impl and inv_freq safely - const auto formatUsage = [this](char* buf, size_t size, uint64_t idletick, double inv_freq) { - if (idletick > systemtickfrequency_impl) { - strcpy(buf, "0%"); - } else { - snprintf(buf, size, "%.0f%%", (1.0 - (idletick * inv_freq)) * 100.0); - } - }; - - // Atomically load idle ticks before using them - const uint64_t idle0 = idletick0.load(std::memory_order_acquire); - const uint64_t idle1 = idletick1.load(std::memory_order_acquire); - const uint64_t idle2 = idletick2.load(std::memory_order_acquire); - const uint64_t idle3 = idletick3.load(std::memory_order_acquire); - - formatUsage(CPU_Usage0, sizeof(CPU_Usage0), idle0, inv_freq); - formatUsage(CPU_Usage1, sizeof(CPU_Usage1), idle1, inv_freq); - formatUsage(CPU_Usage2, sizeof(CPU_Usage2), idle2, inv_freq); - formatUsage(CPU_Usage3, sizeof(CPU_Usage3), idle3, inv_freq); - - mutexLock(&mutex_Misc); - - // CPU frequency and voltage - const char* cpuDiff = "@"; - if (realCPU_Hz) { - const int32_t deltaCPU = (int32_t)(realCPU_Hz / 1000) - (CPU_Hz / 1000); - cpuDiff = getDifferenceSymbol(deltaCPU); - } - - const uint32_t cpuFreq = settings.realFrequencies && realCPU_Hz ? realCPU_Hz : CPU_Hz; - - if (settings.showFullCPU) { - snprintf(CPU_compressed_c, sizeof(CPU_compressed_c), - "[%s,%s,%s,%s]%s%u.%u", - CPU_Usage0, CPU_Usage1, CPU_Usage2, CPU_Usage3, - cpuDiff, cpuFreq / 1000000, (cpuFreq / 100000) % 10); - } else { - // Find max CPU usage across all cores - const auto extractUsage = [](const char* usage_str) -> double { - return strtod(usage_str, nullptr); - }; - - const double usage0 = extractUsage(CPU_Usage0); - const double usage1 = extractUsage(CPU_Usage1); - const double usage2 = extractUsage(CPU_Usage2); - const double usage3 = extractUsage(CPU_Usage3); - - const double maxUsage = std::max({usage0, usage1, usage2, usage3}); - - snprintf(CPU_compressed_c, sizeof(CPU_compressed_c), - "%.0f%%%s%u.%u", - maxUsage, cpuDiff, cpuFreq / 1000000, (cpuFreq / 100000) % 10); - } - - if (settings.realTemps && realCPU_Temp != 0 && CPU_temp_c[0] != '\0') { - char temp_buffer[48]; - snprintf(temp_buffer, sizeof(temp_buffer), " %s", CPU_temp_c); - strncat(CPU_compressed_c, temp_buffer, sizeof(CPU_compressed_c) - strlen(CPU_compressed_c) - 1); - } - - //if (settings.realVolts) { - // snprintf(CPU_volt_c, sizeof(CPU_volt_c), "%u.%u mV", - // realCPU_mV/1000, (isMariko ? (realCPU_mV/100)%10 : (realCPU_mV/10)%100)); - //} - - /* ── CPU voltage ───────────────────────────── */ - if (settings.realVolts) { - const uint32_t mv = realCPU_mV / 1000; // µV → mV - snprintf(CPU_volt_c, sizeof(CPU_volt_c), "%u mV", mv); - } - - // GPU frequency and voltage - const char* gpuDiff = "@"; - if (realGPU_Hz) { - const int32_t deltaGPU = (int32_t)(realGPU_Hz / 1000) - (GPU_Hz / 1000); - gpuDiff = getDifferenceSymbol(deltaGPU); - } - - const uint32_t gpuFreq = settings.realFrequencies && realGPU_Hz ? realGPU_Hz : GPU_Hz; - snprintf(GPU_Load_c, sizeof(GPU_Load_c), - "%u%%%s%u.%u", - GPU_Load_u / 10, - gpuDiff, gpuFreq / 1000000, (gpuFreq / 100000) % 10); - - if (settings.realTemps && realGPU_Temp != 0 && GPU_temp_c[0] != '\0') { - char temp_buffer[48]; - snprintf(temp_buffer, sizeof(temp_buffer), " %s", GPU_temp_c); - strncat(GPU_Load_c, temp_buffer, sizeof(GPU_Load_c) - strlen(GPU_Load_c) - 1); - } - - //if (settings.realVolts) { - // snprintf(GPU_volt_c, sizeof(GPU_volt_c), "%u.%u mV", - // realGPU_mV/1000, (isMariko ? (realGPU_mV/100)%10 : (realGPU_mV/10)%100)); - //} - - // For properly handling sleep exit - if (settings.sleepExit) { - const auto GPU_Hz_int = int(GPU_Hz / 1000000); - static auto lastGPU_Hz_int = GPU_Hz_int; - if (GPU_Hz_int == 0 && lastGPU_Hz_int != 0) { - isRendering = false; - leventSignal(&renderingStopEvent); - - triggerExitNow = true; - return; - } - lastGPU_Hz_int = GPU_Hz_int; - } - - - /* ── GPU voltage ───────────────────────────── */ - if (settings.realVolts) { - const uint32_t mv = realGPU_mV / 1000; - snprintf(GPU_volt_c, sizeof(GPU_volt_c), "%u mV", mv); - } - - // RAM usage and frequency - char MICRO_RAM_all_c[16]; - if (!settings.showpartLoad) { - // User wants GB display - const float RAM_Total_all_f = (RAM_Total_application_u + RAM_Total_applet_u + RAM_Total_system_u + RAM_Total_systemunsafe_u) / (1024.0f * 1024.0f * 1024.0f); - const float RAM_Used_all_f = (RAM_Used_application_u + RAM_Used_applet_u + RAM_Used_system_u + RAM_Used_systemunsafe_u) / (1024.0f * 1024.0f * 1024.0f); - snprintf(MICRO_RAM_all_c, sizeof(MICRO_RAM_all_c), "%.0f%.0fGB", RAM_Used_all_f, RAM_Total_all_f); - } else if (settings.ramInfoMode == "Bandwidth" && R_SUCCEEDED(hocclkCheck)) { - // Bandwidth mode: show GB/s from context (partLoad values are in MB/s) - const unsigned bwAll = partLoad[HocClkPartLoad_RamBWAll] / 1000; - const unsigned bwAllD = (partLoad[HocClkPartLoad_RamBWAll] % 1000) / 100; - snprintf(MICRO_RAM_all_c, sizeof(MICRO_RAM_all_c), "%u.%uGB/s", bwAll, bwAllD); - } else { - // User wants percentage display - if (R_SUCCEEDED(hocclkCheck)) { - // Use sys-clk's RAM load if available - snprintf(MICRO_RAM_all_c, sizeof(MICRO_RAM_all_c), "%hu%%", - partLoad[HocClkPartLoad_EMC] / 10); - } else { - // Calculate percentage manually when sys-clk isn't available - const uint64_t RAM_Total_all = RAM_Total_application_u + RAM_Total_applet_u + RAM_Total_system_u + RAM_Total_systemunsafe_u; - const uint64_t RAM_Used_all = RAM_Used_application_u + RAM_Used_applet_u + RAM_Used_system_u + RAM_Used_systemunsafe_u; - const unsigned partLoadPercent = (RAM_Total_all > 0) ? (unsigned)((RAM_Used_all * 100) / RAM_Total_all) : 0; - snprintf(MICRO_RAM_all_c, sizeof(MICRO_RAM_all_c), "%u%%", partLoadPercent); - } - } - - const char* ramDiff = "@"; - if (realRAM_Hz) { - const int32_t deltaRAM = (int32_t)(realRAM_Hz / 1000) - (RAM_Hz / 1000); - ramDiff = getDifferenceSymbol(deltaRAM); - } - - const uint32_t ramFreq = settings.realFrequencies && realRAM_Hz ? realRAM_Hz : RAM_Hz; - snprintf(RAM_var_compressed_c, sizeof(RAM_var_compressed_c), - "%s%s%u.%u", MICRO_RAM_all_c, ramDiff, - ramFreq / 1000000, (ramFreq / 100000) % 10); - - if (settings.realTemps && realRAM_Temp != 0 && RAM_temp_c[0] != '\0') { - char temp_buffer[48]; - snprintf(temp_buffer, sizeof(temp_buffer), " %s", RAM_temp_c); - strncat(RAM_var_compressed_c, temp_buffer, sizeof(RAM_var_compressed_c) - strlen(RAM_var_compressed_c) - 1); - } - - //if (settings.realVolts) { - // uint32_t vdd2 = realRAM_mV / 10000; - // uint32_t vddq = realRAM_mV % 10000; - // if (isMariko) { - // snprintf(RAM_volt_c, sizeof(RAM_volt_c), "%u.%u%u.%u mV", - // vdd2/10, vdd2%10, vddq/10, vddq%10); - // } else { - // snprintf(RAM_volt_c, sizeof(RAM_volt_c), "%u.%u mV", vdd2/10, vdd2%10); - // } - //} - - /* ── RAM voltage ───────────────────────────── */ - if (settings.realVolts && (settings.showVDD2 || settings.showVDDQ)) { - /* realRAM_mV packs VDD2 | VDDQ in 10-µV units * - * → split, convert to mV - */ - const float mv_vdd2 = realVDD2_mV / 1000.0f; // VDD2 - const uint32_t mv_vddq = realVDDQ_mV / 1000; // VDDQ - - // Build voltage string based on settings - RAM_volt_c[0] = '\0'; // Start with empty string - char temp_buffer[16]; - - if (settings.showVDD2) { - if (settings.decimalVDD2) { - snprintf(temp_buffer, sizeof(temp_buffer), "%.1f mV", mv_vdd2); - } else { - snprintf(temp_buffer, sizeof(temp_buffer), "%u mV", (uint32_t)mv_vdd2); - } - strcat(RAM_volt_c, temp_buffer); - } - - if (settings.showVDDQ && isMariko) { - if (RAM_volt_c[0] != '\0') { - strcat(RAM_volt_c, ""); - } - snprintf(temp_buffer, sizeof(temp_buffer), "%u mV", mv_vddq); - strcat(RAM_volt_c, temp_buffer); - } - } else { - RAM_volt_c[0] = '\0'; // Empty if voltages disabled - } - - /* ── Battery / power draw ───────────────────────────── */ - char remainingBatteryLife[8]; - - /* Normalise “-0.00” → “0.00” W */ - const float drawW = (fabsf(PowerConsumption) < 0.01f) ? 0.0f - : PowerConsumption; - - mutexLock(&mutex_BatteryChecker); - - /* show a time only when the estimate is valid **and** draw ≥ 0.01 W */ - if (batTimeEstimate >= 0 && !(drawW <= 0.01f && drawW >= -0.01f)) { - snprintf(remainingBatteryLife, sizeof remainingBatteryLife, - "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); - } else { - strcpy(remainingBatteryLife, "--:--"); - } - - if (!settings.invertBatteryDisplay) { - snprintf(Battery_c, sizeof Battery_c, - "%.2f W%.1f%% [%s]", - drawW, - (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f, - remainingBatteryLife); - } else { - snprintf(Battery_c, sizeof Battery_c, - "%.1f%% [%s]%.2f W", - (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f, - remainingBatteryLife, - drawW); - } - - mutexUnlock(&mutex_BatteryChecker); - - - // Format current datetime for DTC - if (settings.showDTC) { - time_t rawtime = time(NULL); - struct tm *timeinfo = localtime(&rawtime); - strftime(DTC_c, sizeof(DTC_c), settings.dtcFormat.c_str(), timeinfo); - } - - // Thermal info - const int duty = safeFanDuty((int)Rotation_Duty); - - /* Integer SoC temperature + duty */ - snprintf(soc_temperature_c, sizeof soc_temperature_c, - "%d°C %d%%", - (int)SOC_temperatureF, // SoC °C, no decimals - duty); // fan % - - /* Integer SOC, PCB and skin temperatures + duty * - * skin_temperaturemiliC is in milli-degrees C → divide by 1000 */ - snprintf(skin_temperature_c, sizeof skin_temperature_c, - "%d°C %d°C %hu°C %d%%", - (int)SOC_temperatureF, // SoC - (int)PCB_temperatureF, // PCB - (uint16_t)(skin_temperaturemiliC / 1000), // skin - duty); - - //if (settings.realVolts) { - // snprintf(SOC_volt_c, sizeof(SOC_volt_c), "%u.%u mV", - // realSOC_mV/1000, (realSOC_mV/100)%10); - //} - - /* ── SoC voltage ───────────────────────────── */ - if (settings.realVolts && settings.showSOCVoltage) { - const uint32_t mv = realSOC_mV / 1000; - snprintf(SOC_volt_c, sizeof(SOC_volt_c), "%u mV", mv); - } else { - SOC_volt_c[0] = '\0'; // Clear the buffer when disabled - } - - if (settings.realTemps) { - if (realCPU_Temp != 0) { - snprintf(CPU_temp_c, sizeof(CPU_temp_c), "%u°C", static_cast(realCPU_Temp / 1000.0)); - } - if (realGPU_Temp != 0) { - snprintf(GPU_temp_c, sizeof(GPU_temp_c), "%u°C", static_cast(realGPU_Temp / 1000.0)); - } - if (realRAM_Temp != 0) { - snprintf(RAM_temp_c, sizeof(RAM_temp_c), "%u°C", static_cast(realRAM_Temp / 1000.0)); - } - } - - // Resolution processing - //char RES_var_compressed_c[32] = ""; - if (GameRunning && NxFps && resolutionShow) { - if (!resolutionLookup) { - if (NxFps && SharedMemoryUsed) { - (NxFps -> renderCalls[0].calls) = 0xFFFF; - resolutionLookup = 1; - } - } - else if (resolutionLookup == 1) { - if (NxFps && SharedMemoryUsed && (NxFps -> renderCalls[0].calls) != 0xFFFF) { - resolutionLookup = 2; - } - } - else { - if (NxFps && SharedMemoryUsed) { - memcpy(&m_resolutionRenderCalls, &(NxFps -> renderCalls), sizeof(m_resolutionRenderCalls)); - memcpy(&m_resolutionViewportCalls, &(NxFps -> viewportCalls), sizeof(m_resolutionViewportCalls)); - } else { - memset(&m_resolutionRenderCalls, 0, sizeof(m_resolutionRenderCalls)); - memset(&m_resolutionViewportCalls, 0, sizeof(m_resolutionViewportCalls)); - } - qsort(m_resolutionRenderCalls, 8, sizeof(resolutionCalls), compare); - qsort(m_resolutionViewportCalls, 8, sizeof(resolutionCalls), compare); - memset(&m_resolutionOutput, 0, sizeof(m_resolutionOutput)); - size_t out_iter = 0; - bool found = false; - for (size_t i = 0; i < 8; i++) { - for (size_t x = 0; x < 8; x++) { - if (m_resolutionRenderCalls[i].width == 0) { - break; - } - if ((m_resolutionRenderCalls[i].width == m_resolutionViewportCalls[x].width) && (m_resolutionRenderCalls[i].height == m_resolutionViewportCalls[x].height)) { - m_resolutionOutput[out_iter].width = m_resolutionRenderCalls[i].width; - m_resolutionOutput[out_iter].height = m_resolutionRenderCalls[i].height; - m_resolutionOutput[out_iter].calls = (m_resolutionRenderCalls[i].calls > m_resolutionViewportCalls[x].calls) ? m_resolutionRenderCalls[i].calls : m_resolutionViewportCalls[x].calls; - out_iter++; - found = true; - break; - } - } - if (!found && m_resolutionRenderCalls[i].width != 0) { - m_resolutionOutput[out_iter].width = m_resolutionRenderCalls[i].width; - m_resolutionOutput[out_iter].height = m_resolutionRenderCalls[i].height; - m_resolutionOutput[out_iter].calls = m_resolutionRenderCalls[i].calls; - out_iter++; - } - found = false; - if (out_iter == 8) break; - } - if (out_iter < 8) { - const size_t out_iter_s = out_iter; - for (size_t x = 0; x < 8; x++) { - for (size_t y = 0; y < out_iter_s; y++) { - if (m_resolutionViewportCalls[x].width == 0) { - break; - } - if ((m_resolutionViewportCalls[x].width == m_resolutionOutput[y].width) && (m_resolutionViewportCalls[x].height == m_resolutionOutput[y].height)) { - found = true; - break; - } - } - if (!found && m_resolutionViewportCalls[x].width != 0) { - m_resolutionOutput[out_iter].width = m_resolutionViewportCalls[x].width; - m_resolutionOutput[out_iter].height = m_resolutionViewportCalls[x].height; - m_resolutionOutput[out_iter].calls = m_resolutionViewportCalls[x].calls; - out_iter++; - } - found = false; - if (out_iter == 8) break; - } - } - qsort(m_resolutionOutput, 8, sizeof(resolutionCalls), compare); - - // Anti-flicker swap logic - static std::pair old_res[2]; - - // Only swap if BOTH resolutions exist (prevent swapping with empty slot) - if (m_resolutionOutput[0].width && m_resolutionOutput[1].width) { - if ((m_resolutionOutput[0].width == old_res[1].first && m_resolutionOutput[0].height == old_res[1].second) || - (m_resolutionOutput[1].width == old_res[0].first && m_resolutionOutput[1].height == old_res[0].second)) { - const uint16_t swap_width = m_resolutionOutput[0].width; - const uint16_t swap_height = m_resolutionOutput[0].height; - m_resolutionOutput[0].width = m_resolutionOutput[1].width; - m_resolutionOutput[0].height = m_resolutionOutput[1].height; - m_resolutionOutput[1].width = swap_width; - m_resolutionOutput[1].height = swap_height; - } - } - - // Format resolution string - if (m_resolutionOutput[0].width) { - if (settings.showFullResolution) { - if (!m_resolutionOutput[1].width) { - snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dx%d", - m_resolutionOutput[0].width, m_resolutionOutput[0].height); - } - else { - snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dx%d%dx%d", - m_resolutionOutput[0].width, m_resolutionOutput[0].height, - m_resolutionOutput[1].width, m_resolutionOutput[1].height); - } - } else { - if (!m_resolutionOutput[1].width) { - snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dp", - m_resolutionOutput[0].height); - } - else { - snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dp%dp", - m_resolutionOutput[0].height, m_resolutionOutput[1].height); - } - } - } - - // Always store current resolutions for next frame comparison - old_res[0] = std::make_pair(m_resolutionOutput[0].width, m_resolutionOutput[0].height); - old_res[1] = std::make_pair(m_resolutionOutput[1].width, m_resolutionOutput[1].height); - } - } - else if (!GameRunning && resolutionLookup != 0) { - resolutionLookup = 0; - } - - // FPS - snprintf(FPS_var_compressed_c, sizeof FPS_var_compressed_c, "%2.1f", useOldFPSavg ? FPSavg_old : FPSavg); - - - // Read Speed - if (GameRunning && NxFps && SharedMemoryUsed) { - float readSpeed = 0.0f; - memcpy(&readSpeed, &(NxFps->readSpeedPerSecond), sizeof(float)); - if (readSpeed != 0.f) { - snprintf(READ_var_compressed_c, sizeof(READ_var_compressed_c), "%.2f MiB/s", readSpeed / 1048576.f); - } else { - strcpy(READ_var_compressed_c, "n/d"); - } - } else { - strcpy(READ_var_compressed_c, "n/d"); - } - - mutexUnlock(&mutex_Misc); - - //static bool skipOnce = true; - - if (!skipOnce) { - //static bool runOnce = true; - if (runOnce) { - isRendering = true; - leventClear(&renderingStopEvent); - runOnce = false; // Add this to prevent repeated calls - } - } else { - skipOnce = false; - } - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (isKeyComboPressed(keysHeld, keysDown)) { - isRendering = false; - leventSignal(&renderingStopEvent); - //triggerRumbleDoubleClick.store(true, std::memory_order_release); - skipOnce = true; - runOnce = true; - //TeslaFPS = 60; - if (skipMain) { - //lastSelectedItem = "Micro"; - lastMode = "returning"; - //tsl::swapTo(); - tsl::goBack(); - } - else { - tsl::setNextOverlay(filepath.c_str(), "--lastSelectedItem Micro"); - tsl::Overlay::get()->close(); - } - return true; - } - return false; - } -}; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Mini.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/Mini.hpp deleted file mode 100644 index 5d97ccc1..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Mini.hpp +++ /dev/null @@ -1,1853 +0,0 @@ -class MainMenu; - -class MiniOverlay : public tsl::Gui { -private: - char GPU_Load_c[32] = ""; - char Rotation_SpeedLevel_c[64] = ""; - char RAM_var_compressed_c[128] = ""; - char Battery_c[64] = ""; - char soc_temperature_c[64] = ""; - char skin_temperature_c[64] = ""; - char CPU_temp_c[32]; - char GPU_temp_c[32]; - char RAM_temp_c[32]; - - uint32_t rectangleWidth; - char Variables[512]; - size_t fontsize; - MiniSettings settings; - bool Initialized = false; - ApmPerformanceMode performanceMode = ApmPerformanceMode_Invalid; - uint64_t systemtickfrequency_impl = systemtickfrequency; - int frameOffsetX, frameOffsetY; - int topPadding, bottomPadding; - bool isDragging = false; - - bool skipOnce = true; - bool runOnce = true; - - size_t framePadding = 10; - static constexpr int screenWidth = 1280; - static constexpr int screenHeight = 720; - - struct ButtonState { - std::atomic minusDragActive{false}; - std::atomic plusDragActive{false}; - } buttonState; - - Thread touchPollThread; - std::atomic touchPollRunning{false}; -public: - MiniOverlay() { - CPU_temp_c[0] = '\0'; - GPU_temp_c[0] = '\0'; - RAM_temp_c[0] = '\0'; - - tsl::hlp::requestForeground(false); - disableJumpTo = true; - //tsl::initializeUltrahandSettings(); - PowerConsumption = 0.0f; - batTimeEstimate = -1; - strcpy(Battery_c, "-.-- W-.-% [--:--]"); // Default display - - GetConfigSettings(&settings); - apmGetPerformanceMode(&performanceMode); - if (performanceMode == ApmPerformanceMode_Normal) { - fontsize = settings.handheldFontSize; - } - else fontsize = settings.dockedFontSize; - - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().removeScreenshotStacks(); - } - mutexInit(&mutex_BatteryChecker); - mutexInit(&mutex_Misc); - //alphabackground = 0x0; - frameOffsetX = settings.frameOffsetX; - frameOffsetY = settings.frameOffsetY; - framePadding = settings.framePadding; - topPadding = 5; - bottomPadding = 2; - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - - FullMode = false; - TeslaFPS = settings.refreshRate; - systemtickfrequency_impl /= settings.refreshRate; - deactivateOriginalFooter = true; - realVoltsPolling = settings.realVolts; - StartThreads(); - - // Get initial battery readings BEFORE starting threads - if (R_SUCCEEDED(psmCheck) && R_SUCCEEDED(i2cCheck)) { - uint16_t data = 0; - float tempA = 0.0; - - // Get initial power consumption - Max17050ReadReg(MAX17050_AvgCurrent, &data); - tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data; - PowerConsumption = tempA * batVoltageAvg / 1000000.0; // Rough initial estimate - - // Get initial battery info - psmGetBatteryChargeInfoFields(psmService, &_batteryChargeInfoFields); - - // Get initial time estimate - if (tempA >= 0) { - batTimeEstimate = -1; - } else { - Max17050ReadReg(MAX17050_TTE, &data); - const float batteryTimeEstimateInMinutes = (5.625 * data) / 60; - if (batteryTimeEstimateInMinutes > (99.0*60.0)+59.0) { - batTimeEstimate = (99*60)+59; - } else { - batTimeEstimate = (int16_t)batteryTimeEstimateInMinutes; - } - } - } else { - // Fallback if checks failed - PowerConsumption = 0.0f; - batTimeEstimate = -1; - _batteryChargeInfoFields = {0}; - } - - // Now format the initial Battery_c string - char remainingBatteryLife[8]; - const float drawW = (fabsf(PowerConsumption) < 0.01f) ? 0.0f : PowerConsumption; - - if (batTimeEstimate >= 0 && !(drawW <= 0.01f && drawW >= -0.01f)) { - snprintf(remainingBatteryLife, sizeof(remainingBatteryLife), - "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); - } else { - strcpy(remainingBatteryLife, "--:--"); - } - - if (!settings.invertBatteryDisplay) { - snprintf(Battery_c, sizeof(Battery_c), - "%.2f W%.1f%% [%s]", - drawW, - (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f, - remainingBatteryLife); - } else { - snprintf(Battery_c, sizeof(Battery_c), - "%.1f%% [%s]%.2f W", - (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f, - remainingBatteryLife, - drawW); - } - - - - - // Start touch polling thread for instant response at low FPS - touchPollRunning.store(true, std::memory_order_release); - threadCreate(&touchPollThread, [](void* arg) -> void { - MiniOverlay* overlay = static_cast(arg); - - // Allow only Player 1 and handheld mode - const HidNpadIdType id_list[2] = { HidNpadIdType_No1, HidNpadIdType_Handheld }; - - // Configure HID system to only listen to these IDs - hidSetSupportedNpadIdType(id_list, 2); - - // Configure input for up to 2 supported controllers (P1 + Handheld) - padConfigureInput(2, HidNpadStyleSet_NpadStandard | HidNpadStyleTag_NpadSystemExt); - - // Initialize separate pad states for both controllers - PadState pad_p1; - PadState pad_handheld; - padInitialize(&pad_p1, HidNpadIdType_No1); - padInitialize(&pad_handheld, HidNpadIdType_Handheld); - - u64 minusHoldStart = 0; - u64 plusHoldStart = 0; - static constexpr u64 HOLD_THRESHOLD_NS = 500'000'000ULL; - - HidTouchScreenState state = {0}; - bool inputDetected; - size_t actualEntryCount; - - while (overlay->touchPollRunning.load(std::memory_order_acquire)) { - // Only poll when rendering and not dragging - { - inputDetected = false; - - // Check touch in bounds - if (hidGetTouchScreenStates(&state, 1) && state.count > 0) { - const int touchX = state.touches[0].x; - const int touchY = state.touches[0].y; - - // Calculate bounds (same logic as handleInput) - const uint32_t margin = (overlay->fontsize * 4); - const int overlayX = overlay->frameOffsetX; - const int overlayY = overlay->frameOffsetY; - const int overlayWidth = margin + overlay->rectangleWidth + (overlay->fontsize / 3); - - // Calculate height from Variables string - actualEntryCount = 1; - for (size_t i = 0; overlay->Variables[i] != '\0'; i++) { - if (overlay->Variables[i] == '\n') { - actualEntryCount++; - } - } - const int overlayHeight = ((overlay->fontsize + overlay->settings.spacing) * actualEntryCount) + - (overlay->fontsize / 3) + overlay->settings.spacing + - overlay->topPadding + overlay->bottomPadding; - - // Add touch padding - const int touchPadding = 4; - const int touchableX = overlayX - touchPadding; - const int touchableY = overlayY - touchPadding; - const int touchableWidth = overlayWidth + (touchPadding * 2); - const int touchableHeight = overlayHeight + (touchPadding * 2); - - // Check if touch is within bounds - if (touchX >= touchableX && touchX <= touchableX + touchableWidth && - touchY >= touchableY && touchY <= touchableY + touchableHeight) { - inputDetected = true; - } - } - - // Poll buttons from both controllers - padUpdate(&pad_p1); - padUpdate(&pad_handheld); - //const u64 keysHeld_p1 = padGetButtons(&pad_p1); - //const u64 keysHeld_handheld = padGetButtons(&pad_handheld); - - // Combine input from both controllers - const u64 keysHeld = padGetButtons(&pad_p1) | padGetButtons(&pad_handheld); - const u64 now = armTicksToNs(armGetSystemTick()); - - // Track MINUS hold duration - if ((keysHeld & KEY_MINUS) && !(keysHeld & ~KEY_MINUS & ALL_KEYS_MASK)) { - if (minusHoldStart == 0) { - minusHoldStart = now; - } - if (now - minusHoldStart >= HOLD_THRESHOLD_NS) { - // Long enough to start drag - inputDetected = true; - overlay->buttonState.minusDragActive.exchange(true, std::memory_order_acq_rel); - } - } - - // Track PLUS hold duration - else if ((keysHeld & KEY_PLUS) && !(keysHeld & ~KEY_PLUS & ALL_KEYS_MASK)) { - if (plusHoldStart == 0) { - plusHoldStart = now; - } - if (now - plusHoldStart >= HOLD_THRESHOLD_NS) { - // Long enough to start drag - inputDetected = true; - overlay->buttonState.plusDragActive.exchange(true, std::memory_order_acq_rel); - } - } - - else { - minusHoldStart = plusHoldStart = 0; - overlay->buttonState.minusDragActive.exchange(false, std::memory_order_acq_rel); - overlay->buttonState.plusDragActive.exchange(false, std::memory_order_acq_rel); - } - - // Disable rendering on any input, re-enable when no input - static bool resetOnce = true; - if (inputDetected) { - if (resetOnce && isRendering) { - isRendering = false; - leventSignal(&renderingStopEvent); - resetOnce = false; - } - } else { - resetOnce = true; - } - } - - if (ult::limitedMemory) { - static auto lastUnderscanPixels = std::make_pair(0, 0); - - if (lastUnderscanPixels != tsl::impl::currentUnderscanPixels) { - for (int i = 0; i < 2; i++) { - tsl::gfx::Renderer::get().updateLayerSize(); - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(overlay->frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - } - lastUnderscanPixels = tsl::impl::currentUnderscanPixels; - } - - svcSleepThread(32000000ULL); // 32ms polling - } - }, this, NULL, 0x1000, 0x2B, -2); - threadStart(&touchPollThread); - } - ~MiniOverlay() { - // Stop touch polling thread - touchPollRunning.store(false, std::memory_order_release); - threadWaitForExit(&touchPollThread); - threadClose(&touchPollThread); - - CloseThreads(); - FullMode = true; - fixForeground = true; - //tsl::hlp::requestForeground(true); - //alphabackground = 0xD; - deactivateOriginalFooter = false; - } - - resolutionCalls m_resolutionRenderCalls[8] = {0}; - resolutionCalls m_resolutionViewportCalls[8] = {0}; - resolutionCalls m_resolutionOutput[8] = {0}; - uint8_t resolutionLookup = 0; - bool resolutionShow = false; - - virtual tsl::elm::Element* createUI() override { - - auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - //static constexpr u16 frameWidth = 448; - - // Cache parsed settings and calculations - static std::vector showKeys; - static std::string lastShowSetting; - static bool needsRecalc = true; - static std::vector labelLines; // Store individual label lines - static std::string lastVariables; // Track changes in Variables content - static size_t entryCount = 0; - static uint32_t cachedHeight = 0; - static int cachedBaseX = 0, cachedBaseY = 0; - static bool lastGameRunning = false; // Track game state changes - - // Check if we need to recalculate due to content changes - const bool contentChanged = (std::string(Variables) != lastVariables) || - (GameRunning != lastGameRunning); - - // Only recalculate if settings changed or content changed - if (settings.show != lastShowSetting || !Initialized || contentChanged) { - showKeys.clear(); - - // Parse once and cache - size_t start = 0, end = 0; - const std::string& show = settings.show; - while ((end = show.find('+', start)) != std::string::npos) { - showKeys.emplace_back(show.substr(start, end - start)); - start = end + 1; - } - if (start < show.length()) { - showKeys.emplace_back(show.substr(start)); - } - - lastShowSetting = settings.show; - lastVariables = Variables; - lastGameRunning = GameRunning; - needsRecalc = true; - } - - // Initial width calculation (only once) - if (!Initialized) { - - rectangleWidth = 0; - //std::pair dimensions; - u32 width; - - for (const auto& key : showKeys) { - if (key == "CPU") { - //dimensions = renderer->drawString("[100%,100%,100%,100%]@4444.4", false, 0, 0, fontsize, renderer->a(0x0000)); - if (!settings.realVolts) { - if (settings.showFullCPU) - width = renderer->getTextDimensions("[100%,100%,100%,100%]@4444.4", false, fontsize).first; - else - width = renderer->getTextDimensions("100%@4444.4", false, fontsize).first; - } else { - if (settings.showFullCPU) - width = renderer->getTextDimensions("[100%,100%,100%,100%]@4444.4444 mV", false, fontsize).first; - else - width = renderer->getTextDimensions("100%@4444.4444 mV", false, fontsize).first; - } - if (settings.realTemps) { - width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first; - } - } else if (key == "RAM" && settings.ramInfoMode == "Bandwidth" && R_SUCCEEDED(hocclkCheck)) { - width = renderer->getTextDimensions("99.9GB/s@4444.4", false, fontsize).first; - if (settings.realVolts) { - if (isMariko) { - if (settings.showVDD2 && settings.decimalVDD2 && settings.showVDDQ) - width += renderer->getTextDimensions("4444.4444 mV 4444 mV", false, fontsize).first; - else if (settings.showVDD2 && !settings.decimalVDD2 && settings.showVDDQ) - width += renderer->getTextDimensions("4444 mV 4444 mV", false, fontsize).first; - else if (settings.showVDD2 && settings.decimalVDD2) - width += renderer->getTextDimensions("4444.4 mV", false, fontsize).first; - else if (settings.showVDD2 && !settings.decimalVDD2) - width += renderer->getTextDimensions("4444 mV", false, fontsize).first; - else if (settings.showVDDQ) - width += renderer->getTextDimensions("4444 mV", false, fontsize).first; - } else { - if (settings.decimalVDD2) - width += renderer->getTextDimensions("4444.44 mV", false, fontsize).first; - else - width += renderer->getTextDimensions("4444 mV", false, fontsize).first; - } - } - if (settings.realTemps) { - width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first; - } - } else if (key == "GPU" || (key == "RAM" && settings.showpartLoad && R_SUCCEEDED(hocclkCheck))) { - //dimensions = renderer->drawString("100.0%@4444.4", false, 0, 0, fontsize, renderer->a(0x0000)); - - if (!settings.showpartLoadCPUGPU) { - if (!settings.realVolts) { - width = renderer->getTextDimensions("100%@4444.4", false, fontsize).first; - } else { - width = renderer->getTextDimensions("100%@4444.4444 mV", false, fontsize).first; - } - } else { - if (!settings.realVolts) { - width = renderer->getTextDimensions("100%[100%,100%]@4444.4", false, fontsize).first; - } else { - width = renderer->getTextDimensions("100%[100%,100%]@4444.4444 mV", false, fontsize).first; - } - } - if (settings.realTemps) { - width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first; - } - } else if (key == "RAM" && (!settings.showpartLoad || R_FAILED(hocclkCheck))) { - //dimensions = renderer->drawString("44444444MB@4444.4", false, 0, 0, fontsize, renderer->a(0x0000)); - if (!settings.realVolts) { - width = renderer->getTextDimensions("100%@4444.4", false, fontsize).first; - if (settings.realTemps) { - width += renderer->getTextDimensions(" 88.8°C ", false, fontsize).first; - } - } else { - if (isMariko) { - if (settings.showVDD2 && settings.decimalVDD2 && settings.showVDDQ) - width = renderer->getTextDimensions("100%@4444.44444.4444 mV", false, fontsize).first; - else if (settings.showVDD2 && !settings.decimalVDD2 && settings.showVDDQ) - width = renderer->getTextDimensions("100%@4444.44444444 mV", false, fontsize).first; - else if (settings.showVDD2 && settings.decimalVDD2) - width = renderer->getTextDimensions("100%@4444.44444.4 mV", false, fontsize).first; - else if (settings.showVDD2 && !settings.decimalVDD2) - width = renderer->getTextDimensions("100%@4444.44444 mV", false, fontsize).first; - else if (settings.showVDDQ) - width = renderer->getTextDimensions("100%@4444.4444 mV", false, fontsize).first; - } else { - if (settings.decimalVDD2) - width = renderer->getTextDimensions("100%@4444.44444.4 mV", false, fontsize).first; - else - width = renderer->getTextDimensions("100%@4444.44444 mV", false, fontsize).first; - } - } - } else if (key == "SOC") { // new block - if (!settings.realVolts) - if (settings.showFanPercentage) - width = renderer->getTextDimensions("88°C (100%)", false, fontsize).first; - else - width = renderer->getTextDimensions("88°C", false, fontsize).first; - else - if (settings.showSOCVoltage) { - if (settings.showFanPercentage) - width = renderer->getTextDimensions("88°C 100%444 mV", false, fontsize).first; - else - width = renderer->getTextDimensions("88°C444 mV", false, fontsize).first; - } else { - if (settings.showFanPercentage) - width = renderer->getTextDimensions("88°C 100%", false, fontsize).first; - else - width = renderer->getTextDimensions("88°C", false, fontsize).first; - } - } else if (key == "TMP") { - //dimensions = renderer->drawString("88.8\u00B0C88.8\u00B0C88.8\u00B0C (100%)", false, 0, 0, fontsize, renderer->a(0x0000)); - if (!settings.realVolts) { - if (settings.showFanPercentage) - width = renderer->getTextDimensions("88\u00B0C 88\u00B0C 88\u00B0C 100%", false, fontsize).first; - else - width = renderer->getTextDimensions("88\u00B0C 88\u00B0C 88\u00B0C", false, fontsize).first; - } else { - if (settings.showSOCVoltage) { - if (settings.showFanPercentage) - width = renderer->getTextDimensions("88\u00B0C 88\u00B0C 88\u00B0C 100%444 mV", false, fontsize).first; - else - width = renderer->getTextDimensions("88\u00B0C 88\u00B0C 88\u00B0C444 mV", false, fontsize).first; - } else { - if (settings.showFanPercentage) - width = renderer->getTextDimensions("88\u00B0C 88\u00B0C 88\u00B0C 100%", false, fontsize).first; - else - width = renderer->getTextDimensions("88\u00B0C 88\u00B0C 88\u00B0C", false, fontsize).first; - } - } - } else if (key == "BAT") { - //dimensions = renderer->drawString("-44.44 W100.0% [44:44]", false, 0, 0, fontsize, renderer->a(0x0000)); - width = renderer->getTextDimensions("-44.44 W100.0% [44:44]", false, fontsize).first; - } else if (key == "FPS") { - //dimensions = renderer->drawString("444.4", false, 0, 0, fontsize, renderer->a(0x0000)); - width = renderer->getTextDimensions("444.4", false, fontsize).first; - } else if (key == "RES") { - //dimensions = renderer->drawString("3840x21603840x2160", false, 0, 0, fontsize, renderer->a(0x0000)); - if (settings.showFullResolution) - width = renderer->getTextDimensions("3840x21603840x2160", false, fontsize).first; - else - width = renderer->getTextDimensions("2160p2160p", false, fontsize).first; - } else if (key == "READ") { - // Calculate width for read speed display - width = renderer->getTextDimensions("999.99 MiB/s", false, fontsize).first; - } else if (key == "MEM") { - // Calculate width for system memory display (System + divider + memory value) - const u32 memValueWidth = renderer->getTextDimensions("999.9 MB "+ult::FREE, false, fontsize).first; - const u32 dividerWidth = renderer->getTextDimensions(ult::DIVIDER_SYMBOL, false, fontsize).first; - const u32 systemWidth = renderer->getTextDimensions("System", false, fontsize).first; - width = memValueWidth + dividerWidth + systemWidth; - } else if (key == "DTC" && settings.showDTC) { - // Calculate width based on the datetime format - // Use multiple sample dates to ensure longest possible textual output - - char sampleDateTime[64]; - size_t maxWidth = 0; - - // Representative dates that produce long names in most locales - constexpr int testDays[][3] = { - {2025, 11, 26}, // Wednesday – longest weekday - {2025, 9, 30}, // September – long month - {2025, 12, 31}, // December – another long month - {2025, 2, 28}, // February – to cover locales where it's long - }; - - struct tm t = {}; - for (auto &d : testDays) { - - t.tm_year = d[0] - 1900; - t.tm_mon = d[1] - 1; - t.tm_mday = d[2]; - t.tm_hour = 23; - t.tm_min = 59; - t.tm_sec = 59; - mktime(&t); // normalize (sets weekday, etc.) - - strftime(sampleDateTime, sizeof(sampleDateTime), settings.dtcFormat.c_str(), &t); - const size_t w = renderer->getTextDimensions(std::string(sampleDateTime) + " ", false, fontsize).first; - if (w > maxWidth) - maxWidth = w; - } - - width = maxWidth; - - } else { - continue; - } - - if (rectangleWidth < width) { - rectangleWidth = width; - } - } - Initialized = true; - needsRecalc = true; - } - - // Recalculate layout when needed (including content changes) - if (needsRecalc) { - // Build label lines array for individual centering - labelLines.clear(); - entryCount = 0; - uint16_t flags = 0; - - bool shouldAdd; - std::string labelText; - for (const auto& key : showKeys) { - shouldAdd = false; - labelText = ""; - - if (key == "CPU" && !(flags & 1)) { - shouldAdd = true; - labelText = "CPU"; - flags |= 1; - } else if (key == "GPU" && !(flags & 2)) { - shouldAdd = true; - labelText = "GPU"; - flags |= 2; - } else if (key == "RAM" && !(flags & 4)) { - shouldAdd = true; - labelText = "RAM"; - flags |= 4; - } else if (key == "SOC" && !(flags & 8)) { - shouldAdd = true; - labelText = "SOC"; - flags |= 8; - } else if (key == "TMP" && !(flags & 16)) { - shouldAdd = true; - labelText = "TMP"; - flags |= 16; - } else if ((key == "BAT" || key == "DRAW") && !(flags & 32)) { - shouldAdd = true; - labelText = "BAT"; - flags |= 32; - } else if (key == "FPS" && !(flags & 64) && GameRunning) { - shouldAdd = true; - labelText = "FPS"; - flags |= 64; - } else if (key == "RES" && !(flags & 128) && GameRunning) { - shouldAdd = true; - labelText = "RES"; - flags |= 128; - resolutionShow = true; - } else if (key == "READ" && !(flags & 512) && GameRunning) { - shouldAdd = true; - labelText = "READ"; - flags |= 512; - } else if (key == "DTC" && !(flags & 256) && settings.showDTC) { - shouldAdd = true; - labelText = settings.useDTCSymbol ? "\uE007" : "DTC"; - flags |= 256; - } else if (key == "MEM" && !(flags & 1024)) { - shouldAdd = true; - labelText = "MEM"; - flags |= 1024; - } - - - if (shouldAdd) { - labelLines.push_back(labelText); - entryCount++; - - //if (settings.realVolts && key != "BAT" && key != "DRAW" && key != "FPS" && key != "RES") { - // labelLines.push_back(""); // Empty line for voltage info - // entryCount++; - //} - } - } - - // Calculate actual entry count from Variables string - size_t actualEntryCount = 1; // Start with 1 for the first line - for (size_t i = 0; Variables[i] != '\0'; i++) { - if (Variables[i] == '\n') { - actualEntryCount++; - } - } - - // Use the actual entry count for height calculation - cachedHeight = ((fontsize + settings.spacing) * actualEntryCount) + (fontsize / 3) + settings.spacing + topPadding + bottomPadding; - //const uint32_t margin = (fontsize * 4); - - cachedBaseX = 0; - cachedBaseY = 0; - - needsRecalc = false; - } - - // Fast rendering using cached values - const uint32_t margin = (fontsize * 4); - - // Draw background - const tsl::Color bgColor = !isDragging - ? settings.backgroundColor // full opacity - : settings.focusBackgroundColor; - - int clippingOffsetX = 0, clippingOffsetY = 0; - - int _frameOffsetX = ult::limitedMemory ? std::max(0, frameOffsetX - (1280-448)) : frameOffsetX; - - // Check X bounds and calculate clipping offset - if (cachedBaseX + _frameOffsetX < int(framePadding)) { - clippingOffsetX = framePadding - (cachedBaseX + _frameOffsetX); - } else if ((cachedBaseX + _frameOffsetX + margin + rectangleWidth + (fontsize / 3)) > screenWidth - framePadding) { - clippingOffsetX = (screenWidth - framePadding) - (cachedBaseX + _frameOffsetX + margin + rectangleWidth + (fontsize / 3)); - } - - // Check Y bounds and calculate clipping offset - if (cachedBaseY + frameOffsetY < int(framePadding)) { - clippingOffsetY = framePadding - (cachedBaseY + frameOffsetY); - } else if ((cachedBaseY + frameOffsetY + cachedHeight) > screenHeight - framePadding) { - clippingOffsetY = (screenHeight - framePadding) - (cachedBaseY + frameOffsetY + cachedHeight); - } - - // Apply to all drawing calls - renderer->drawRoundedRectSingleThreaded( - cachedBaseX + _frameOffsetX + clippingOffsetX, - cachedBaseY + frameOffsetY + clippingOffsetY, - margin + rectangleWidth + (fontsize / 3), - cachedHeight, - 16, - a(bgColor) - ); - - - // Split Variables into lines for individual positioning - std::vector variableLines; - const std::string variablesStr(Variables); - size_t start = 0; - size_t pos = 0; - while ((pos = variablesStr.find('\n', start)) != std::string::npos) { - variableLines.push_back(variablesStr.substr(start, pos - start)); - start = pos + 1; - } - if (start < variablesStr.length()) { - variableLines.push_back(variablesStr.substr(start)); - } - - // Draw each label and variable line individually - uint32_t currentY = cachedBaseY + fontsize + settings.spacing + topPadding; - size_t labelIndex = 0; - - static const std::vector specialChars = {""}; - static uint32_t labelWidth, labelCenterX; - static std::vector _variableLines; - if (!delayUpdate) - _variableLines = variableLines; - for (size_t i = 0; i < _variableLines.size() && labelIndex < labelLines.size(); i++) { - // Check for RES label without corresponding RES data - if (labelIndex < labelLines.size() && labelLines[labelIndex] == "RES") { - //const std::string& currentLine = _variableLines[i]; - // Check if this data line looks like resolution data (contains 'x' or 'p') - bool isResolutionData = m_resolutionOutput[0].width; - - if (!isResolutionData) { - // This is RES label but data isn't resolution data - skip the label - ++labelIndex; - // Don't increment i, so the current data line gets paired with the next label - --i; - continue; - } - } - - // Draw label (centered in label region) - if (!labelLines[labelIndex].empty()) { - labelWidth = renderer->getTextDimensions(labelLines[labelIndex], false, fontsize).first; - labelCenterX = cachedBaseX + (margin / 2) - (labelWidth / 2); - renderer->drawString(labelLines[labelIndex], false, labelCenterX + _frameOffsetX + clippingOffsetX, currentY + frameOffsetY + clippingOffsetY, fontsize, settings.catColor); - } - - // Determine rendering method based on label type - const std::string& currentLine = _variableLines[i]; - const int baseX = cachedBaseX + margin + _frameOffsetX + clippingOffsetX; - const int baseY = currentY + frameOffsetY + clippingOffsetY; - - if (settings.useDynamicColors) { - if (labelIndex < labelLines.size() && labelLines[labelIndex] == "CPU") { - std::string dataStr = currentLine; - - const size_t degreesPos = dataStr.find("°"); - if (degreesPos != std::string::npos && settings.realTemps && realCPU_Temp != 0) { - size_t tempStart = dataStr.rfind(' ', degreesPos); - if (tempStart != std::string::npos) { - tempStart++; - const size_t cPos = dataStr.find("C", degreesPos); - if (cPos != std::string::npos) { - const size_t tempEnd = cPos + 1; - - const std::string preTempPart = dataStr.substr(0, tempStart); - const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart); - const std::string postTempPart = dataStr.substr(tempEnd); - - const float temp = realCPU_Temp / 1000.0f; - const tsl::Color tempColor = tsl::GradientColor(temp); - - int currentX = baseX; - if (!preTempPart.empty()) { - renderer->drawStringWithColoredSections(preTempPart, false, specialChars, currentX, baseY, fontsize, settings.textColor, settings.separatorColor); - currentX += renderer->getTextDimensions(preTempPart, false, fontsize).first; - } - - renderer->drawStringWithColoredSections(tempPart, false, specialChars, currentX, baseY, fontsize, tempColor, settings.separatorColor); - - if (!postTempPart.empty()) { - currentX += renderer->getTextDimensions(tempPart, false, fontsize).first; - renderer->drawStringWithColoredSections(postTempPart, false, specialChars, currentX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - - } else if (labelIndex < labelLines.size() && labelLines[labelIndex] == "GPU") { - std::string dataStr = currentLine; - - const size_t degreesPos = dataStr.find("°"); - if (degreesPos != std::string::npos && settings.realTemps && realGPU_Temp != 0) { - size_t tempStart = dataStr.rfind(' ', degreesPos); - if (tempStart != std::string::npos) { - tempStart++; - const size_t cPos = dataStr.find("C", degreesPos); - if (cPos != std::string::npos) { - const size_t tempEnd = cPos + 1; - - const std::string preTempPart = dataStr.substr(0, tempStart); - const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart); - const std::string postTempPart = dataStr.substr(tempEnd); - - const float temp = realGPU_Temp / 1000.0f; - const tsl::Color tempColor = tsl::GradientColor(temp); - - int currentX = baseX; - if (!preTempPart.empty()) { - renderer->drawStringWithColoredSections(preTempPart, false, specialChars, currentX, baseY, fontsize, settings.textColor, settings.separatorColor); - currentX += renderer->getTextDimensions(preTempPart, false, fontsize).first; - } - - renderer->drawStringWithColoredSections(tempPart, false, specialChars, currentX, baseY, fontsize, tempColor, settings.separatorColor); - - if (!postTempPart.empty()) { - currentX += renderer->getTextDimensions(tempPart, false, fontsize).first; - renderer->drawStringWithColoredSections(postTempPart, false, specialChars, currentX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - - } else if (labelIndex < labelLines.size() && labelLines[labelIndex] == "RAM") { - std::string dataStr = currentLine; - - const size_t degreesPos = dataStr.find("°"); - if (degreesPos != std::string::npos && settings.realTemps && realRAM_Temp != 0) { - size_t tempStart = dataStr.rfind(' ', degreesPos); - if (tempStart != std::string::npos) { - tempStart++; - const size_t cPos = dataStr.find("C", degreesPos); - if (cPos != std::string::npos) { - const size_t tempEnd = cPos + 1; - - const std::string preTempPart = dataStr.substr(0, tempStart); - const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart); - const std::string postTempPart = dataStr.substr(tempEnd); - - const float temp = realRAM_Temp / 1000.0f; - const tsl::Color tempColor = tsl::GradientColor(temp); - - int currentX = baseX; - if (!preTempPart.empty()) { - renderer->drawStringWithColoredSections(preTempPart, false, specialChars, currentX, baseY, fontsize, settings.textColor, settings.separatorColor); - currentX += renderer->getTextDimensions(preTempPart, false, fontsize).first; - } - - renderer->drawStringWithColoredSections(tempPart, false, specialChars, currentX, baseY, fontsize, tempColor, settings.separatorColor); - - if (!postTempPart.empty()) { - currentX += renderer->getTextDimensions(tempPart, false, fontsize).first; - renderer->drawStringWithColoredSections(postTempPart, false, specialChars, currentX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - - } else if (labelIndex < labelLines.size() && labelLines[labelIndex] == "SOC") { - // SOC temperature rendering with gradient - const size_t degreesPos = currentLine.find("°"); - if (degreesPos != std::string::npos) { - // Find the 'C' after the degrees symbol - const size_t cPos = currentLine.find("C", degreesPos); - if (cPos != std::string::npos) { - const size_t tempEnd = cPos + 1; // Include the 'C' - - // Extract temperature value and apply gradient - const int temp = atoi(currentLine.c_str()); - const tsl::Color tempColor = tsl::GradientColor((float)temp); - - // Split into temperature part and remaining part - const std::string tempPart = currentLine.substr(0, tempEnd); - const std::string restPart = currentLine.substr(tempEnd); - - // Render temperature with gradient color - int currentX = baseX; - renderer->drawString(tempPart, false, currentX, baseY, fontsize, tempColor); - - // Render remaining text with normal color - if (!restPart.empty()) { - currentX += renderer->getTextDimensions(tempPart, false, fontsize).first; - renderer->drawStringWithColoredSections(restPart, false, specialChars, currentX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - // Fallback: no C found after degrees, render normally - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - // Fallback: no degrees symbol found, render normally - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - - } else if (labelIndex < labelLines.size() && labelLines[labelIndex] == "TMP") { - // TMP multiple temperatures rendering with gradients - int currentX = baseX; - size_t pos = 0; - bool parseSuccess = true; - - // Parse up to 3 temperatures in the format "XX°C XX°C XX°C (XX%)" - for (int tempCount = 0; tempCount < 3 && parseSuccess && pos < currentLine.length(); tempCount++) { - // Find start of current temperature (skip any leading spaces) - while (pos < currentLine.length() && currentLine[pos] == ' ') { - renderer->drawString(" ", false, currentX, baseY, fontsize, settings.textColor); - currentX += renderer->getTextDimensions(" ", false, fontsize).first; - pos++; - } - - if (pos >= currentLine.length()) break; - - // Find degrees symbol - const size_t degreesPos = currentLine.find("°", pos); - if (degreesPos == std::string::npos) { - parseSuccess = false; - break; - } - - // Find 'C' after degrees symbol - const size_t cPos = currentLine.find("C", degreesPos); - if (cPos == std::string::npos) { - parseSuccess = false; - break; - } - - const size_t tempEnd = cPos + 1; // Include the 'C' - - // Extract and render temperature with gradient - const std::string tempPart = currentLine.substr(pos, tempEnd - pos); - const int temp = atoi(tempPart.c_str()); - const tsl::Color tempColor = tsl::GradientColor((float)temp); - - renderer->drawString(tempPart, false, currentX, baseY, fontsize, tempColor); - currentX += renderer->getTextDimensions(tempPart, false, fontsize).first; - - pos = tempEnd; - } - - // Render any remaining text (like " (50%)" or voltage info) - if (pos < currentLine.length()) { - std::string restPart = currentLine.substr(pos); - renderer->drawStringWithColoredSections(restPart, false, specialChars, currentX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - - // If parsing failed, fall back to normal rendering - if (!parseSuccess) { - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else if (labelIndex < labelLines.size() && labelLines[labelIndex] == "MEM") { - // MEM memory rendering with gradient color - // Extract numeric value for color determination - float sysValue = 0.0f; - sscanf(currentLine.c_str(), "%f", &sysValue); - - // Determine unit from string - const bool isGB = (currentLine.find("GB") != std::string::npos); - const float sysValueMB = isGB ? (sysValue * 1024.0f) : sysValue; - - // Apply same color scheme as in drawMemoryWidget - tsl::Color sysColor = settings.textColor; - if (sysValueMB >= 9.0f) { - sysColor = settings.useDynamicColors ? tsl::healthyRamTextColor : settings.textColor; - } else if (sysValueMB >= 3.0f) { - sysColor = settings.useDynamicColors ? tsl::neutralRamTextColor : settings.textColor; - } else { - sysColor = settings.useDynamicColors ? tsl::badRamTextColor : settings.textColor; - } - - // Draw the memory value with color on the left - int currentX = baseX; - renderer->drawStringWithColoredSections(currentLine, false, specialChars, currentX, baseY, fontsize, sysColor, settings.separatorColor); - currentX += renderer->getTextDimensions(currentLine, false, fontsize).first; - - // Draw separator " | " - renderer->drawString(ult::DIVIDER_SYMBOL, false, currentX, baseY, fontsize, settings.separatorColor); - currentX += renderer->getTextDimensions(ult::DIVIDER_SYMBOL, false, fontsize).first; - - // Draw "System" on the right - renderer->drawString("System", false, currentX, baseY, fontsize, settings.textColor); - } else { - // Normal rendering for all other line types (CPU, GPU, RAM, BAT, FPS, RES, DTC) - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - } else { - // Normal rendering for all other line types (CPU, GPU, RAM, BAT, FPS, RES, DTC) - renderer->drawStringWithColoredSections(currentLine, false, specialChars, baseX, baseY, fontsize, settings.textColor, settings.separatorColor); - } - - currentY += fontsize + settings.spacing; - ++labelIndex; - } - }); - - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("", ""); - rootFrame->setContent(Status); - return rootFrame; - } - - virtual void update() override { - if (triggerExitNow) - return; - - if (!SaltySD) { - SaltySD = CheckPort(); - if (SaltySD) { - LoadSharedMemory(); - threadCreate(&t6, CheckIfGameRunning, NULL, NULL, 0x1000, 0x38, -2); - threadStart(&t6); - } - } - - // Handle performance mode changes - apmGetPerformanceMode(&performanceMode); - if (performanceMode == ApmPerformanceMode_Normal) { - if (fontsize != settings.handheldFontSize) { - Initialized = false; - fontsize = settings.handheldFontSize; - } - } - else if (performanceMode == ApmPerformanceMode_Boost) { - if (fontsize != settings.dockedFontSize) { - Initialized = false; - fontsize = settings.dockedFontSize; - } - } - - // Parse show settings to determine what to calculate - std::vector showKeys; - { - size_t start = 0, end = 0; - const std::string& show = settings.show; - while ((end = show.find('+', start)) != std::string::npos) { - showKeys.emplace_back(show.substr(start, end - start)); - start = end + 1; - } - if (start < show.length()) { - showKeys.emplace_back(show.substr(start)); - } - } - - // Helper to check if a key is active - static auto isActive = [&showKeys](const std::string& key) { - return std::find(showKeys.begin(), showKeys.end(), key) != showKeys.end(); - }; - - mutexLock(&mutex_Misc); - - // Variables to store formatted strings - char MINI_CPU_compressed_c[42] = ""; - char MINI_CPU_volt_c[16] = ""; - char MINI_GPU_Load_c[32] = ""; - char MINI_GPU_volt_c[20] = ""; - char MINI_RAM_var_compressed_c[35] = ""; - char MINI_RAM_volt_c[32] = ""; - char MINI_MEM_RAM_c[32] = ""; - char MINI_SOC_volt_c[16] = ""; - - // Only process CPU if needed - if (isActive("CPU")) { - char MINI_CPU_Usage0[7], MINI_CPU_Usage1[7], MINI_CPU_Usage2[7], MINI_CPU_Usage3[7]; - - const uint64_t idle0 = idletick0.load(std::memory_order_acquire); - const uint64_t idle1 = idletick1.load(std::memory_order_acquire); - const uint64_t idle2 = idletick2.load(std::memory_order_acquire); - const uint64_t idle3 = idletick3.load(std::memory_order_acquire); - - auto formatMiniUsage = [this](char* buf, size_t size, uint64_t idletick) { - if (idletick > systemtickfrequency_impl) { - strcpy(buf, "0%"); - } else { - snprintf(buf, size, "%.0f%%", - (1.0 - (static_cast(idletick) / systemtickfrequency_impl)) * 100.0); - } - }; - - formatMiniUsage(MINI_CPU_Usage0, sizeof(MINI_CPU_Usage0), idle0); - formatMiniUsage(MINI_CPU_Usage1, sizeof(MINI_CPU_Usage1), idle1); - formatMiniUsage(MINI_CPU_Usage2, sizeof(MINI_CPU_Usage2), idle2); - formatMiniUsage(MINI_CPU_Usage3, sizeof(MINI_CPU_Usage3), idle3); - - if (settings.showFullCPU) { - if (settings.realFrequencies && realCPU_Hz) { - snprintf(MINI_CPU_compressed_c, sizeof(MINI_CPU_compressed_c), - "[%s,%s,%s,%s]@%hu.%hhu", - MINI_CPU_Usage0, MINI_CPU_Usage1, MINI_CPU_Usage2, MINI_CPU_Usage3, - realCPU_Hz / 1000000, (realCPU_Hz / 100000) % 10); - } else { - snprintf(MINI_CPU_compressed_c, sizeof(MINI_CPU_compressed_c), - "[%s,%s,%s,%s]@%hu.%hhu", - MINI_CPU_Usage0, MINI_CPU_Usage1, MINI_CPU_Usage2, MINI_CPU_Usage3, - CPU_Hz / 1000000, (CPU_Hz / 100000) % 10); - } - } else { - double usage0 = 0, usage1 = 0, usage2 = 0, usage3 = 0; - sscanf(MINI_CPU_Usage0, "%lf%%", &usage0); - sscanf(MINI_CPU_Usage1, "%lf%%", &usage1); - sscanf(MINI_CPU_Usage2, "%lf%%", &usage2); - sscanf(MINI_CPU_Usage3, "%lf%%", &usage3); - - double maxUsage = std::max({usage0, usage1, usage2, usage3}); - - if (settings.realFrequencies && realCPU_Hz) { - snprintf(MINI_CPU_compressed_c, sizeof(MINI_CPU_compressed_c), - "%.0f%%@%hu.%hhu", maxUsage, - realCPU_Hz / 1000000, (realCPU_Hz / 100000) % 10); - } else { - snprintf(MINI_CPU_compressed_c, sizeof(MINI_CPU_compressed_c), - "%.0f%%@%hu.%hhu", maxUsage, - CPU_Hz / 1000000, (CPU_Hz / 100000) % 10); - } - } - - if (settings.realVolts) { - const uint32_t mv = realCPU_mV / 1000; - snprintf(MINI_CPU_volt_c, sizeof(MINI_CPU_volt_c), "%u mV", mv); - } - } - - if (settings.realTemps && realCPU_Temp != 0 && CPU_temp_c[0] != '\0') { - char temp_buffer[48]; - snprintf(temp_buffer, sizeof(temp_buffer), " %s", CPU_temp_c); - strncat(MINI_CPU_compressed_c, temp_buffer, sizeof(MINI_CPU_compressed_c) - strlen(MINI_CPU_compressed_c) - 1); - } - - // Only process GPU if needed - if (isActive("GPU")) { - if (settings.realFrequencies && realGPU_Hz) { - snprintf(MINI_GPU_Load_c, sizeof(MINI_GPU_Load_c), - "%hu%%%s%hu.%hhu", - GPU_Load_u / 10, "@", - realGPU_Hz / 1000000, (realGPU_Hz / 100000) % 10); - } else { - snprintf(MINI_GPU_Load_c, sizeof(MINI_GPU_Load_c), - "%hu%%%s%hu.%hhu", - GPU_Load_u / 10, "@", - GPU_Hz / 1000000, (GPU_Hz / 100000) % 10); - } - - // Handle sleep exit - if (settings.sleepExit) { - const auto GPU_Hz_int = int(GPU_Hz / 1000000); - static auto lastGPU_Hz_int = GPU_Hz_int; - if (GPU_Hz_int == 0 && lastGPU_Hz_int != 0) { - isRendering = false; - leventSignal(&renderingStopEvent); - triggerExitNow = true; - mutexUnlock(&mutex_Misc); - return; - } - lastGPU_Hz_int = GPU_Hz_int; - } - - if (settings.realVolts) { - const uint32_t mv = realGPU_mV / 1000; - snprintf(MINI_GPU_volt_c, sizeof(MINI_GPU_volt_c), "%u mV", mv); - } - } - - if (settings.realTemps && realGPU_Temp != 0 && GPU_temp_c[0] != '\0') { - char temp_buffer[48]; - snprintf(temp_buffer, sizeof(temp_buffer), " %s", GPU_temp_c); - strncat(MINI_GPU_Load_c, temp_buffer, sizeof(MINI_GPU_Load_c) - strlen(MINI_GPU_Load_c) - 1); - } - - // Only process RAM if needed - if (isActive("RAM")) { - if (!settings.showpartLoad) { - const float ramTotalGiB = (RAM_Total_application_u + RAM_Total_applet_u + - RAM_Total_system_u + RAM_Total_systemunsafe_u) / - (1024.0f * 1024.0f); - const float ramUsedGiB = (RAM_Used_application_u + RAM_Used_applet_u + - RAM_Used_system_u + RAM_Used_systemunsafe_u) / - (1024.0f * 1024.0f); - - if (settings.realFrequencies && realRAM_Hz) { - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%.0f/%.0fMB@%hu.%hhu", - ramUsedGiB, ramTotalGiB, - realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10); - } else { - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%.0f/%.0fMB@%hu.%hhu", - ramUsedGiB, ramTotalGiB, - RAM_Hz / 1000000, (RAM_Hz / 100000) % 10); - } - } else { - if (settings.ramInfoMode == "Bandwidth" && R_SUCCEEDED(hocclkCheck)) { - // Bandwidth mode: show GB/s from context (partLoad values are in MB/s) - const uint32_t ramFreq = settings.realFrequencies && realRAM_Hz ? realRAM_Hz : RAM_Hz; - const unsigned bwAll = partLoad[HocClkPartLoad_RamBWAll] / 1000; - const unsigned bwAllD = (partLoad[HocClkPartLoad_RamBWAll] % 1000) / 100; - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%u.%uGB/s@%hu.%hhu", - bwAll, bwAllD, - ramFreq / 1000000, (ramFreq / 100000) % 10); - } else { - unsigned partLoadInt; - - if (R_SUCCEEDED(hocclkCheck)) { - partLoadInt = partLoad[HocClkPartLoad_EMC] / 10; - - if (settings.showpartLoadCPUGPU) { - unsigned ramCpuLoadInt = partLoad[HocClkPartLoad_EMCCpu] / 10; - int RAM_GPU_Load = partLoad[HocClkPartLoad_EMC] - partLoad[HocClkPartLoad_EMCCpu]; - unsigned ramGpuLoadInt = RAM_GPU_Load / 10; - - if (settings.realFrequencies && realRAM_Hz) { - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%u%%[%u%%,%u%%]@%hu.%hhu", - partLoadInt, ramCpuLoadInt, ramGpuLoadInt, - realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10); - } else { - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%u%%[%u%%,%u%%]@%hu.%hhu", - partLoadInt, ramCpuLoadInt, ramGpuLoadInt, - RAM_Hz / 1000000, (RAM_Hz / 100000) % 10); - } - } else { - if (settings.realFrequencies && realRAM_Hz) { - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%u%%@%hu.%hhu", partLoadInt, - realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10); - } else { - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%u%%@%hu.%hhu", partLoadInt, - RAM_Hz / 1000000, (RAM_Hz / 100000) % 10); - } - } - } else { - const uint64_t RAM_Total_all = RAM_Total_application_u + RAM_Total_applet_u + - RAM_Total_system_u + RAM_Total_systemunsafe_u; - const uint64_t RAM_Used_all = RAM_Used_application_u + RAM_Used_applet_u + - RAM_Used_system_u + RAM_Used_systemunsafe_u; - partLoadInt = (RAM_Total_all > 0) ? (unsigned)((RAM_Used_all * 100) / RAM_Total_all) : 0; - - if (settings.realFrequencies && realRAM_Hz) { - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%u%%@%hu.%hhu", partLoadInt, - realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10); - } else { - snprintf(MINI_RAM_var_compressed_c, sizeof(MINI_RAM_var_compressed_c), - "%u%%@%hu.%hhu", partLoadInt, - RAM_Hz / 1000000, (RAM_Hz / 100000) % 10); - } - } - } - } - - if (settings.realVolts) { - const float mv_vdd2_f = realVDD2_mV / 1000.0f; // VDD2 - const uint32_t mv_vddq = realVDDQ_mV / 1000; // VDDQ - const uint32_t mv_vdd2_i = realVDD2_mV / 1000; - - if (isMariko) { - if (settings.showVDDQ && settings.showVDD2) { - if (settings.decimalVDD2) - snprintf(MINI_RAM_volt_c, sizeof(MINI_RAM_volt_c), - "%.1f mV%u mV", mv_vdd2_f, mv_vddq); - else - snprintf(MINI_RAM_volt_c, sizeof(MINI_RAM_volt_c), - "%u mV%u mV", mv_vdd2_i, mv_vddq); - } else if (settings.showVDDQ) { - snprintf(MINI_RAM_volt_c, sizeof(MINI_RAM_volt_c), "%u mV", mv_vddq); - } else if (settings.showVDD2) { - if (settings.decimalVDD2) - snprintf(MINI_RAM_volt_c, sizeof(MINI_RAM_volt_c), "%.1f mV", mv_vdd2_f); - else - snprintf(MINI_RAM_volt_c, sizeof(MINI_RAM_volt_c), "%u mV", mv_vdd2_i); - } - } else { - if (settings.decimalVDD2) - snprintf(MINI_RAM_volt_c, sizeof(MINI_RAM_volt_c), "%.1f mV", mv_vdd2_f); - else - snprintf(MINI_RAM_volt_c, sizeof(MINI_RAM_volt_c), "%u mV", mv_vdd2_i); - } - } - } - - if (settings.realTemps && realRAM_Temp != 0 && RAM_temp_c[0] != '\0') { - char temp_buffer[48]; - snprintf(temp_buffer, sizeof(temp_buffer), " %s", RAM_temp_c); - strncat(MINI_RAM_var_compressed_c, temp_buffer, sizeof(MINI_RAM_var_compressed_c) - strlen(MINI_RAM_var_compressed_c) - 1); - } - - // Only process MEM if needed - if (isActive("MEM")) { - const u64 freeRamBytes = RAM_Total_system_u - RAM_Used_system_u; - - float value; - const char* unit; - - if (freeRamBytes >= 1024ULL * 1024 * 1024) { - value = static_cast(freeRamBytes) / (1024.0f * 1024.0f * 1024.0f); - unit = "GB"; - } else { - value = static_cast(freeRamBytes) / (1024.0f * 1024.0f); - unit = "MB"; - } - - int decimalPlaces; - if (value >= 1000.0f) { - decimalPlaces = 0; - } else if (value >= 100.0f) { - decimalPlaces = 1; - } else if (value >= 10.0f) { - decimalPlaces = 2; - } else { - decimalPlaces = 3; - } - - snprintf(MINI_MEM_RAM_c, sizeof(MINI_MEM_RAM_c), "%.*f %s %s", - decimalPlaces, value, unit, ult::FREE.c_str()); - } - - // Only process temperature/fan data if SOC or TMP is active - if (isActive("TMP") || isActive("SOC")) { - const int duty = safeFanDuty((int)Rotation_Duty); - - if (settings.realVolts && settings.showSOCVoltage) { - const uint32_t mv = realSOC_mV / 1000; - snprintf(MINI_SOC_volt_c, sizeof(MINI_SOC_volt_c), "%u mV", mv); - } - - if (isActive("SOC")) { - if (settings.showFanPercentage) { - snprintf(soc_temperature_c, sizeof(soc_temperature_c), - "%d°C %d%%", (int)SOC_temperatureF, duty); - } else { - snprintf(soc_temperature_c, sizeof(soc_temperature_c), - "%d°C", (int)SOC_temperatureF); - } - } - - if (isActive("TMP")) { - if (settings.showFanPercentage) { - snprintf(skin_temperature_c, sizeof(skin_temperature_c), - "%d\u00B0C %d\u00B0C %hu\u00B0C %d%%", - (int)SOC_temperatureF, (int)PCB_temperatureF, - skin_temperaturemiliC / 1000, duty); - } else { - snprintf(skin_temperature_c, sizeof(skin_temperature_c), - "%d\u00B0C %d\u00B0C %hu\u00B0C", - (int)SOC_temperatureF, (int)PCB_temperatureF, - skin_temperaturemiliC / 1000); - } - } - } - - if (settings.realTemps) { - if (realCPU_Temp != 0) { - snprintf(CPU_temp_c, sizeof(CPU_temp_c), "%u°C", static_cast(realCPU_Temp / 1000.0)); - } - if (realGPU_Temp != 0) { - snprintf(GPU_temp_c, sizeof(GPU_temp_c), "%u°C", static_cast(realGPU_Temp / 1000.0)); - } - if (realRAM_Temp != 0) { - snprintf(RAM_temp_c, sizeof(RAM_temp_c), "%u°C", static_cast(realRAM_Temp / 1000.0)); - } - } - - // Only process resolution if RES is active and game is running - if (isActive("RES") && GameRunning && NxFps) { - if (!resolutionLookup) { - (NxFps->renderCalls[0].calls) = 0xFFFF; - resolutionLookup = 1; - } else if (resolutionLookup == 1) { - if ((NxFps->renderCalls[0].calls) != 0xFFFF) resolutionLookup = 2; - } else { - memcpy(&m_resolutionRenderCalls, &(NxFps->renderCalls), sizeof(m_resolutionRenderCalls)); - memcpy(&m_resolutionViewportCalls, &(NxFps->viewportCalls), sizeof(m_resolutionViewportCalls)); - qsort(m_resolutionRenderCalls, 8, sizeof(resolutionCalls), compare); - qsort(m_resolutionViewportCalls, 8, sizeof(resolutionCalls), compare); - memset(&m_resolutionOutput, 0, sizeof(m_resolutionOutput)); - size_t out_iter = 0; - bool found = false; - for (size_t i = 0; i < 8; i++) { - for (size_t x = 0; x < 8; x++) { - if (m_resolutionRenderCalls[i].width == 0) break; - if ((m_resolutionRenderCalls[i].width == m_resolutionViewportCalls[x].width) && - (m_resolutionRenderCalls[i].height == m_resolutionViewportCalls[x].height)) { - m_resolutionOutput[out_iter].width = m_resolutionRenderCalls[i].width; - m_resolutionOutput[out_iter].height = m_resolutionRenderCalls[i].height; - m_resolutionOutput[out_iter].calls = (m_resolutionRenderCalls[i].calls > m_resolutionViewportCalls[x].calls) - ? m_resolutionRenderCalls[i].calls : m_resolutionViewportCalls[x].calls; - out_iter++; - found = true; - break; - } - } - if (!found && m_resolutionRenderCalls[i].width != 0) { - m_resolutionOutput[out_iter].width = m_resolutionRenderCalls[i].width; - m_resolutionOutput[out_iter].height = m_resolutionRenderCalls[i].height; - m_resolutionOutput[out_iter].calls = m_resolutionRenderCalls[i].calls; - out_iter++; - } - found = false; - if (out_iter == 8) break; - } - if (out_iter < 8) { - const size_t out_iter_s = out_iter; - for (size_t x = 0; x < 8; x++) { - for (size_t y = 0; y < out_iter_s; y++) { - if (m_resolutionViewportCalls[x].width == 0) break; - if ((m_resolutionViewportCalls[x].width == m_resolutionOutput[y].width) && - (m_resolutionViewportCalls[x].height == m_resolutionOutput[y].height)) { - found = true; - break; - } - } - if (!found && m_resolutionViewportCalls[x].width != 0) { - m_resolutionOutput[out_iter].width = m_resolutionViewportCalls[x].width; - m_resolutionOutput[out_iter].height = m_resolutionViewportCalls[x].height; - m_resolutionOutput[out_iter].calls = m_resolutionViewportCalls[x].calls; - out_iter++; - } - found = false; - if (out_iter == 8) break; - } - } - qsort(m_resolutionOutput, 8, sizeof(resolutionCalls), compare); - } - } else if (!GameRunning && resolutionLookup != 0) { - resolutionLookup = 0; - } - - mutexUnlock(&mutex_Misc); - - // Battery/power draw - always update since BAT/DRAW might be displayed - if (isActive("BAT") || isActive("DRAW")) { - char remainingBatteryLife[8]; - const float drawW = (fabsf(PowerConsumption) < 0.01f) ? 0.0f : PowerConsumption; - - mutexLock(&mutex_BatteryChecker); - - if (batTimeEstimate >= 0 && !(drawW <= 0.01f && drawW >= -0.01f)) { - snprintf(remainingBatteryLife, sizeof(remainingBatteryLife), - "%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60); - } else { - strcpy(remainingBatteryLife, "--:--"); - } - - if (!settings.invertBatteryDisplay) { - snprintf(Battery_c, sizeof(Battery_c), - "%.2f W%.1f%% [%s]", - drawW, - (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f, - remainingBatteryLife); - } else { - snprintf(Battery_c, sizeof(Battery_c), - "%.1f%% [%s]%.2f W", - (float)_batteryChargeInfoFields.RawBatteryCharge / 1000.0f, - remainingBatteryLife, - drawW); - } - - mutexUnlock(&mutex_BatteryChecker); - } - - // Build Variables string - char Temp[512] = ""; - uint16_t flags = 0; - - for (const auto& key : showKeys) { - if (key == "CPU" && !(flags & 1)) { - if (Temp[0]) strcat(Temp, "\n"); - strcat(Temp, MINI_CPU_compressed_c); - if (settings.realVolts && MINI_CPU_volt_c[0]) { - strcat(Temp, ""); - strcat(Temp, MINI_CPU_volt_c); - } - flags |= 1; - } - else if (key == "GPU" && !(flags & 2)) { - if (Temp[0]) strcat(Temp, "\n"); - strcat(Temp, MINI_GPU_Load_c); - if (settings.realVolts && MINI_GPU_volt_c[0]) { - strcat(Temp, ""); - strcat(Temp, MINI_GPU_volt_c); - } - flags |= 2; - } - else if (key == "RAM" && !(flags & 4)) { - if (Temp[0]) strcat(Temp, "\n"); - strcat(Temp, MINI_RAM_var_compressed_c); - if (settings.realVolts && MINI_RAM_volt_c[0]) { - strcat(Temp, ""); - strcat(Temp, MINI_RAM_volt_c); - } - flags |= 4; - } - else if (key == "SOC" && !(flags & 8)) { - if (Temp[0]) strcat(Temp, "\n"); - strcat(Temp, soc_temperature_c); - if (settings.realVolts && settings.showSOCVoltage && MINI_SOC_volt_c[0]) { - strcat(Temp, ""); - strcat(Temp, MINI_SOC_volt_c); - } - flags |= 8; - } - else if (key == "TMP" && !(flags & 16)) { - if (Temp[0]) strcat(Temp, "\n"); - strcat(Temp, skin_temperature_c); - if (settings.realVolts && settings.showSOCVoltage && MINI_SOC_volt_c[0]) { - strcat(Temp, ""); - strcat(Temp, MINI_SOC_volt_c); - } - flags |= 16; - } - else if ((key == "BAT" || key == "DRAW") && !(flags & 32)) { - if (Temp[0]) strcat(Temp, "\n"); - strcat(Temp, Battery_c); - flags |= 32; - } - else if (key == "FPS" && !(flags & 64) && GameRunning) { - if (Temp[0]) strcat(Temp, "\n"); - char Temp_s[24]; - snprintf(Temp_s, sizeof(Temp_s), "%2.1f [%2.1f - %2.1f]", FPSavg, FPSmin, FPSmax); - strcat(Temp, Temp_s); - flags |= 64; - } - else if (key == "RES" && !(flags & 128) && GameRunning && m_resolutionOutput[0].width) { - if (Temp[0]) strcat(Temp, "\n"); - char Temp_s[32] = ""; - static std::pair old_res[2]; - - uint16_t w0 = m_resolutionOutput[0].width; - uint16_t h0 = m_resolutionOutput[0].height; - uint16_t w1 = m_resolutionOutput[1].width; - uint16_t h1 = m_resolutionOutput[1].height; - - if (w0 || w1) { - if (w0 && w1) { - if ((w0 == old_res[1].first && h0 == old_res[1].second) || - (w1 == old_res[0].first && h1 == old_res[0].second)) { - std::swap(w0, w1); - std::swap(h0, h1); - } - } - - - // Format based on whether we show full resolution or just height (p) - if (settings.showFullResolution) { - if (!w1 || !h1) - snprintf(Temp_s, sizeof(Temp_s), "%dx%d", w0 ? w0 : w1, h0 ? h0 : h1); - else - snprintf(Temp_s, sizeof(Temp_s), "%dx%d%dx%d", w0, h0, w1, h1); - } else { - if (!w1 || !h1) - snprintf(Temp_s, sizeof(Temp_s), "%dp", h0 ? h0 : h1); - else - snprintf(Temp_s, sizeof(Temp_s), "%dp%dp", h0, h1); - } - - // Update last-frame cache - old_res[0] = {m_resolutionOutput[0].width, m_resolutionOutput[0].height}; - old_res[1] = {m_resolutionOutput[1].width, m_resolutionOutput[1].height}; - - strcat(Temp, Temp_s); - flags |= 128; - } - } - else if (key == "READ" && !(flags & 512) && GameRunning && NxFps) { - if (Temp[0]) strcat(Temp, "\n"); - char Temp_s[24]; - if ((NxFps->readSpeedPerSecond) != 0.f) { - snprintf(Temp_s, sizeof(Temp_s), "%.2f MiB/s", (NxFps->readSpeedPerSecond) / 1048576.f); - } else { - strcpy(Temp_s, "n/d"); - } - strcat(Temp, Temp_s); - flags |= 512; - } - else if (key == "DTC" && !(flags & 256) && settings.showDTC) { - if (Temp[0]) strcat(Temp, "\n"); - char dateTimeStr[64]; - time_t rawtime = time(NULL); - struct tm *timeinfo = localtime(&rawtime); - strftime(dateTimeStr, sizeof(dateTimeStr), settings.dtcFormat.c_str(), timeinfo); - strcat(Temp, dateTimeStr); - flags |= 256; - } - else if (key == "MEM" && !(flags & 1024)) { - if (Temp[0]) strcat(Temp, "\n"); - strcat(Temp, MINI_MEM_RAM_c); - flags |= 1024; - } - } - - strcpy(Variables, Temp); - - // Enable rendering if needed - if (!skipOnce) { - if (runOnce) { - isRendering = true; - leventClear(&renderingStopEvent); - runOnce = false; - } - } else { - skipOnce = false; - } - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - // Static variables to maintain drag state between function calls - static bool oldTouchDetected = false; - static bool oldMinusHeld = false; - static bool oldPlusHeld = false; - - static HidTouchState initialTouchPos = {0}; - static int initialFrameOffsetX = 0; - static int initialFrameOffsetY = 0; - static constexpr int TOUCH_THRESHOLD = 8; - static bool hasMoved = false; - //static u64 lastTouchTime = 0; - //static constexpr u64 TOUCH_DEBOUNCE_NS = 16000000ULL; // 16ms debounce - - // Get current time for debouncing - //const u64 currentTime = armTicksToNs(armGetSystemTick()); - - // Better touch detection - check if coordinates are within reasonable screen bounds - const bool currentTouchDetected = (touchPos.x > 0 && touchPos.y > 0 && - touchPos.x < screenWidth && touchPos.y < screenHeight); - - // Debounce touch detection - //if (currentTouchDetected && !oldTouchDetected) { - // if (currentTime - lastTouchTime < TOUCH_DEBOUNCE_NS) { - // currentTouchDetected = false; // Ignore rapid touch changes - // } else { - // lastTouchTime = currentTime; - // } - //} - - static bool clearOnRelease = false; - - if (clearOnRelease && !isRendering) { - clearOnRelease = false; - isRendering = true; - leventClear(&renderingStopEvent); - } - - // Calculate overlay bounds - const uint32_t margin = (fontsize * 4); - - // Cache bounds calculation - static int cachedBaseX = 0; - static int cachedBaseY = 0; - static uint32_t cachedOverlayHeight = 0; - static bool boundsNeedUpdate = true; - static std::string lastVariables = ""; - - // Only recalculate bounds when Variables change or first time - if (boundsNeedUpdate || std::string(Variables) != lastVariables) { - // Calculate actual entry count from Variables string - size_t actualEntryCount = 1; - for (size_t i = 0; Variables[i] != '\0'; i++) { - if (Variables[i] == '\n') { - actualEntryCount++; - } - } - - cachedOverlayHeight = ((fontsize + settings.spacing) * actualEntryCount) + - (fontsize / 3) + settings.spacing + topPadding + bottomPadding; - - // Position calculation based on settings - cachedBaseX = 0; - cachedBaseY = 0; - - boundsNeedUpdate = false; - lastVariables = Variables; - } - - const int overlayX = frameOffsetX;//ult::limitedMemory ? cachedBaseX + std::max(0, frameOffsetX - (1280-448)) : cachedBaseX + frameOffsetX; - const int overlayY = cachedBaseY + frameOffsetY; - const int overlayWidth = margin + rectangleWidth + (fontsize / 3); - const int overlayHeight = cachedOverlayHeight; - - // Add padding to make touch detection more forgiving - static constexpr int touchPadding = 4; - const int touchableX = overlayX - touchPadding; - const int touchableY = overlayY - touchPadding; - const int touchableWidth = overlayWidth + (touchPadding * 2); - const int touchableHeight = overlayHeight + (touchPadding * 2); - - // Screen boundaries for clamping - const int minX = -cachedBaseX + framePadding; - const int maxX = screenWidth - overlayWidth - cachedBaseX - framePadding; - const int minY = -cachedBaseY + framePadding; - const int maxY = screenHeight - overlayHeight - cachedBaseY - framePadding; - - const bool minusDragReady = buttonState.minusDragActive.load(std::memory_order_acquire); - const bool plusDragReady = buttonState.plusDragActive.load(std::memory_order_acquire); - - // Check button states - const bool currentMinusHeld = (keysHeld & KEY_MINUS) && !(keysHeld & ~KEY_MINUS & ALL_KEYS_MASK) && minusDragReady; - const bool currentPlusHeld = (keysHeld & KEY_PLUS) && !(keysHeld & ~KEY_PLUS & ALL_KEYS_MASK) && plusDragReady; - - // Handle touch dragging - if (currentTouchDetected && !isDragging) { - // Touch detected and not currently dragging - check if we should start - const int touchX = touchPos.x; - const int touchY = touchPos.y; - - if (!oldTouchDetected) { - // Touch just started - check if within overlay bounds - if (touchX >= touchableX && touchX <= touchableX + touchableWidth && - touchY >= touchableY && touchY <= touchableY + touchableHeight) { - - // Start touch dragging - isDragging = true; - //isRendering = false; - //leventSignal(&renderingStopEvent); - triggerRumbleClick.store(true, std::memory_order_release); - triggerOnSound.store(true, std::memory_order_release); - hasMoved = false; - initialTouchPos = touchPos; - initialFrameOffsetX = frameOffsetX; - initialFrameOffsetY = frameOffsetY; - } - } - } else if (currentTouchDetected && isDragging && !currentMinusHeld && !currentPlusHeld) { - // Continue touch dragging (only if neither MINUS nor PLUS is held) - const int touchX = touchPos.x; - const int touchY = touchPos.y; - const int deltaX = touchX - initialTouchPos.x; - const int deltaY = touchY - initialTouchPos.y; - - // Check if we've moved enough to consider this a drag - if (!hasMoved) { - const int totalMovement = abs(deltaX) + abs(deltaY); - if (totalMovement >= TOUCH_THRESHOLD) { - hasMoved = true; - } - } - - if (hasMoved) { - // Update frame offsets with boundary checking - const int newFrameOffsetX = std::max(minX, std::min(maxX, initialFrameOffsetX + deltaX)); - const int newFrameOffsetY = std::max(minY, std::min(maxY, initialFrameOffsetY + deltaY)); - - frameOffsetX = newFrameOffsetX; - frameOffsetY = newFrameOffsetY; - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - boundsNeedUpdate = true; - } - } else if (!currentTouchDetected && oldTouchDetected && isDragging && !currentMinusHeld && !currentPlusHeld) { - // Touch just released and we were touch dragging - if (hasMoved) { - // Save position when touch drag ends - auto iniData = ult::getParsedDataFromIniFile(configIniPath); - iniData["mini"]["frame_offset_x"] = std::to_string(frameOffsetX); - iniData["mini"]["frame_offset_y"] = std::to_string(frameOffsetY); - ult::saveIniFileData(configIniPath, iniData); - } - - // Reset touch drag state - isDragging = false; - hasMoved = false; - //isRendering = true; - //leventClear(&renderingStopEvent); - clearOnRelease = true; - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerOffSound.store(true, std::memory_order_release); - } - - - // Handle joystick dragging (MINUS + right joystick OR PLUS + left joystick) - if ((currentMinusHeld || currentPlusHeld) && !isDragging) { - // Start joystick dragging - isDragging = true; - //isRendering = false; - //leventSignal(&renderingStopEvent); - triggerRumbleClick.store(true, std::memory_order_release); - triggerOnSound.store(true, std::memory_order_release); - } else if ((currentMinusHeld || currentPlusHeld) && isDragging) { - // Continue joystick dragging - static constexpr int JOYSTICK_DEADZONE = 20; - - // Choose the appropriate joystick based on which button is held - const HidAnalogStickState& activeJoystick = currentMinusHeld ? joyStickPosRight : joyStickPosLeft; - - // Only move if joystick is outside deadzone - if (abs(activeJoystick.x) > JOYSTICK_DEADZONE || abs(activeJoystick.y) > JOYSTICK_DEADZONE) { - // Calculate joystick magnitude (distance from center) - const float magnitude = sqrt((float)(activeJoystick.x * activeJoystick.x + activeJoystick.y * activeJoystick.y)); - const float normalizedMagnitude = magnitude / 32767.0f; // Normalize to 0-1 range - - // Single smooth curve: stays very slow for wide range, then accelerates - static constexpr float baseSensitivity = 0.00008f; // Higher so small movements register - static constexpr float maxSensitivity = 0.0005f; - - // Use x^8 curve - stays very low until ~70% then curves up sharply - const float curveValue = pow(normalizedMagnitude, 8.0f); - const float currentSensitivity = baseSensitivity + (maxSensitivity - baseSensitivity) * curveValue; - - // Calculate movement delta with fractional accumulation - static float accumulatedX = 0.0f; - static float accumulatedY = 0.0f; - - accumulatedX += (float)activeJoystick.x * currentSensitivity; - accumulatedY += -(float)activeJoystick.y * currentSensitivity; - - // Extract integer movement and keep fractional part - const int deltaX = (int)accumulatedX; - const int deltaY = (int)accumulatedY; - accumulatedX -= deltaX; - accumulatedY -= deltaY; - - // Update frame offsets with boundary checking - const int newFrameOffsetX = std::max(minX, std::min(maxX, frameOffsetX + deltaX)); - const int newFrameOffsetY = std::max(minY, std::min(maxY, frameOffsetY + deltaY)); - - frameOffsetX = newFrameOffsetX; - frameOffsetY = newFrameOffsetY; - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - boundsNeedUpdate = true; - } - } else if (((!currentMinusHeld && oldMinusHeld) || (!currentPlusHeld && oldPlusHeld)) && isDragging) { - // Button just released - stop joystick dragging - auto iniData = ult::getParsedDataFromIniFile(configIniPath); - iniData["mini"]["frame_offset_x"] = std::to_string(frameOffsetX); - iniData["mini"]["frame_offset_y"] = std::to_string(frameOffsetY); - ult::saveIniFileData(configIniPath, iniData); - isDragging = false; - //isRendering = true; - //leventClear(&renderingStopEvent); - clearOnRelease = true; - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerOffSound.store(true, std::memory_order_release); - } - - // Update state for next frame - oldTouchDetected = currentTouchDetected; - oldMinusHeld = currentMinusHeld; - oldPlusHeld = currentPlusHeld; - - // Handle existing key input logic (but don't interfere with dragging) - if (!isDragging) { - if (isKeyComboPressed(keysHeld, keysDown)) { - isRendering = false; - leventSignal(&renderingStopEvent); - //triggerRumbleDoubleClick.store(true, std::memory_order_release); - skipOnce = true; - runOnce = true; - //TeslaFPS = 60; - if (skipMain) { - //lastSelectedItem = "Mini"; - lastMode = "returning"; - tsl::goBack(); - } - else { - tsl::setNextOverlay(filepath.c_str(), "--lastSelectedItem Mini"); - tsl::Overlay::get()->close(); - } - return true; - } - else if (((keysDown & KEY_L) && (keysDown & KEY_ZL)) || ((keysDown & KEY_L) && (keysHeld & KEY_ZL)) || ((keysHeld & KEY_L) && (keysDown & KEY_ZL))) { - FPSmin = 254; - FPSmax = 0; - } - } - - // Return true if we handled the input (during dragging) - return isDragging; - } -}; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Misc.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/Misc.hpp deleted file mode 100644 index 98f52528..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Misc.hpp +++ /dev/null @@ -1,189 +0,0 @@ -class OtherMenu; - -void StartMiscThread() { - // Wait for existing thread to exit - threadWaitForExit(&t0); - - // Clear the thread exit event for new thread - leventClear(&threadexit); - - // Close and recreate thread - threadClose(&t0); - threadCreate(&t0, Misc2, NULL, NULL, 0x1000, 0x3F, 3); - threadStart(&t0); -} - -void EndMiscThread() { - // Signal the thread exit event - leventSignal(&threadexit); - - // Wait for thread to exit - threadWaitForExit(&t0); - - // Close thread handle - threadClose(&t0); -} - -class MiscOverlay : public tsl::Gui { -private: - char DSP_Load_c[16]; - // Separated value buffers for NV clocks - char NVDEC_value_c[16] = ""; - char NVENC_value_c[16] = ""; - char NVJPG_value_c[16] = ""; - char Nifm_pass[96]; - FullSettings settings; -public: - MiscOverlay() { - GetConfigSettings(&settings); - disableJumpTo = true; - smInitialize(); - nifmCheck = nifmInitialize(NifmServiceType_Admin); - if (R_SUCCEEDED(mmuInitialize())) { - nvdecCheck = mmuRequestInitialize(&nvdecRequest, MmuModuleId(5), 8, false); - nvencCheck = mmuRequestInitialize(&nvencRequest, MmuModuleId(6), 8, false); - nvjpgCheck = mmuRequestInitialize(&nvjpgRequest, MmuModuleId(7), 8, false); - } - - if (R_SUCCEEDED(audsnoopInitialize())) - audsnoopCheck = audsnoopEnableDspUsageMeasurement(); - - smExit(); - StartMiscThread(); - // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); - } - - ~MiscOverlay() { - EndMiscThread(); - nifmExit(); - mmuRequestFinalize(&nvdecRequest); - mmuRequestFinalize(&nvencRequest); - mmuRequestFinalize(&nvjpgRequest); - mmuExit(); - if (R_SUCCEEDED(audsnoopCheck)) { - audsnoopDisableDspUsageMeasurement(); - } - audsnoopExit(); - } - - virtual tsl::elm::Element* createUI() override { - - auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - static constexpr u16 X_OFFSET = 30; - static constexpr u16 NV_VALUE_X = 120; // Aligned X position for NV values - - ///DSP - if (R_SUCCEEDED(audsnoopCheck)) { - renderer->drawString(DSP_Load_c, false, X_OFFSET, 120, 20, (settings.textColor)); - } - - //Multimedia engines - if (R_SUCCEEDED(nvdecCheck | nvencCheck | nvjpgCheck)) { - renderer->drawString("Multimedia Clock Rates", false, X_OFFSET, 165, 20, (settings.catColor1)); - - u16 currentY = 185; - - if (R_SUCCEEDED(nvdecCheck)) { - renderer->drawString("NVDEC", false, X_OFFSET+15, currentY, 15, (settings.catColor2)); - renderer->drawString(NVDEC_value_c, false, NV_VALUE_X, currentY, 15, (settings.textColor)); - currentY += 15; - } - if (R_SUCCEEDED(nvencCheck)) { - renderer->drawString("NVENC", false, X_OFFSET+15, currentY, 15, (settings.catColor2)); - renderer->drawString(NVENC_value_c, false, NV_VALUE_X, currentY, 15, (settings.textColor)); - currentY += 15; - } - if (R_SUCCEEDED(nvjpgCheck)) { - renderer->drawString("NVJPG", false, X_OFFSET+15, currentY, 15, (settings.catColor2)); - renderer->drawString(NVJPG_value_c, false, NV_VALUE_X, currentY, 15, (settings.textColor)); - } - } - - if (R_SUCCEEDED(nifmCheck)) { - renderer->drawString("Network", false, X_OFFSET, 255, 20, (settings.catColor1)); - if (!Nifm_internet_rc) { - if (NifmConnectionType == NifmInternetConnectionType_WiFi) { - renderer->drawString("Type: Wi-Fi", false, X_OFFSET, 280, 18, (settings.catColor2)); - if (!Nifm_profile_rc) { - if (Nifm_showpass) - renderer->drawString(Nifm_pass, false, X_OFFSET, 305, 15, (settings.textColor)); - else - renderer->drawString("Press Y to show password", false, X_OFFSET, 305, 15, (settings.textColor)); - } - } - else if (NifmConnectionType == NifmInternetConnectionType_Ethernet) - renderer->drawString("Type: Ethernet", false, X_OFFSET, 280, 18, (settings.textColor)); - } - else - renderer->drawString("Type: Not connected", false, X_OFFSET, 280, 18, (settings.textColor)); - } - - - }); - - // tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release); - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION, true); - rootFrame->setContent(Status); - - return rootFrame; - } - - virtual void update() override { - - snprintf(DSP_Load_c, sizeof DSP_Load_c, "DSP usage: %u%%", DSP_Load_u); - - // Format just the values for NV clocks - snprintf(NVDEC_value_c, sizeof(NVDEC_value_c), "%.1f MHz", (float)NVDEC_Hz / 1000000); - snprintf(NVENC_value_c, sizeof(NVENC_value_c), "%.1f MHz", (float)NVENC_Hz / 1000000); - snprintf(NVJPG_value_c, sizeof(NVJPG_value_c), "%.1f MHz", (float)NVJPG_Hz / 1000000); - - char pass_temp1[25] = ""; - char pass_temp2[25] = ""; - char pass_temp3[17] = ""; - if (Nifm_profile.wireless_setting_data.passphrase_len > 48) { - memcpy(&pass_temp1, &(Nifm_profile.wireless_setting_data.passphrase[0]), 24); - memcpy(&pass_temp2, &(Nifm_profile.wireless_setting_data.passphrase[24]), 24); - memcpy(&pass_temp3, &(Nifm_profile.wireless_setting_data.passphrase[48]), 16); - } - else if (Nifm_profile.wireless_setting_data.passphrase_len > 24) { - memcpy(&pass_temp1, &(Nifm_profile.wireless_setting_data.passphrase[0]), 24); - memcpy(&pass_temp2, &(Nifm_profile.wireless_setting_data.passphrase[24]), 24); - } - else { - memcpy(&pass_temp1, &(Nifm_profile.wireless_setting_data.passphrase[0]), 24); - } - snprintf(Nifm_pass, sizeof Nifm_pass, "%s\n%s\n%s", pass_temp1, pass_temp2, pass_temp3); - - static bool skipOnce = true; - - if (!skipOnce) { - static bool runOnce = true; - if (runOnce) { - isRendering = true; - leventClear(&renderingStopEvent); - runOnce = false; - } - } else { - skipOnce = false; - } - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - if (keysHeld & KEY_Y) { - Nifm_showpass = true; - } - else Nifm_showpass = false; - - if (keysDown & KEY_B) { - isRendering = false; - leventSignal(&renderingStopEvent); - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerExitSound.store(true, std::memory_order_release); - lastSelectedItem = "Miscellaneous"; - lastMode = ""; - tsl::swapTo(); - return true; - } - return false; - } -}; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Resolutions.hpp b/Source/Horizon-OC-Monitor (deprecated)/source/modes/Resolutions.hpp deleted file mode 100644 index aca519b7..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/modes/Resolutions.hpp +++ /dev/null @@ -1,581 +0,0 @@ -class MainMenu; - -class ResolutionsOverlay : public tsl::Gui { -private: - char Resolutions_c[512] = {0}; - char Resolutions2_c[512] = {0}; - ResolutionSettings settings; - bool skipOnce = true; - bool runOnce = true; - - // Repositioning variables (matching Mini) - int frameOffsetX = 0; - int frameOffsetY = 0; - bool isDragging = false; - size_t framePadding = 10; - static constexpr int screenWidth = 1280; - static constexpr int screenHeight = 720; - - bool originalUseRightAlignment = ult::useRightAlignment; - - struct ButtonState { - std::atomic minusDragActive{false}; - std::atomic plusDragActive{false}; - } buttonState; - - Thread touchPollThread; - std::atomic touchPollRunning{false}; - - std::atomic inputDetected{false}; - -public: - ResolutionsOverlay() { - tsl::hlp::requestForeground(false); - disableJumpTo = true; - GetConfigSettings(&settings); - - // Load saved frame offsets - frameOffsetX = settings.frameOffsetX; - frameOffsetY = settings.frameOffsetY; - framePadding = settings.framePadding; - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().removeScreenshotStacks(); - } - deactivateOriginalFooter = true; - FullMode = false; - TeslaFPS = settings.refreshRate; - StartFPSCounterThread(); - - // Start touch polling thread for instant response at low FPS - touchPollRunning.store(true, std::memory_order_release); - threadCreate(&touchPollThread, [](void* arg) -> void { - ResolutionsOverlay* overlay = static_cast(arg); - - // Allow only Player 1 and handheld mode - const HidNpadIdType id_list[2] = { HidNpadIdType_No1, HidNpadIdType_Handheld }; - - // Configure HID system to only listen to these IDs - hidSetSupportedNpadIdType(id_list, 2); - - // Configure input for up to 2 supported controllers (P1 + Handheld) - padConfigureInput(2, HidNpadStyleSet_NpadStandard | HidNpadStyleTag_NpadSystemExt); - - // Initialize separate pad states for both controllers - PadState pad_p1; - PadState pad_handheld; - padInitialize(&pad_p1, HidNpadIdType_No1); - padInitialize(&pad_handheld, HidNpadIdType_Handheld); - - u64 minusHoldStart = 0; - u64 plusHoldStart = 0; - static constexpr u64 HOLD_THRESHOLD_NS = 500'000'000ULL; - - HidTouchScreenState state = {0}; - - - while (overlay->touchPollRunning.load(std::memory_order_acquire)) { - // Only poll when rendering and not dragging - { - overlay->inputDetected.store(false, std::memory_order_release); - - // Check touch in bounds - if (hidGetTouchScreenStates(&state, 1) && state.count > 0) { - const int touchX = state.touches[0].x; - const int touchY = state.touches[0].y; - - // Calculate bounds (same logic as handleInput) - const int overlayX = overlay->frameOffsetX; - const int overlayY = overlay->frameOffsetY; - - // Overlay dimensions based on game state - int overlayWidth, overlayHeight; - overlayWidth = 360-20; - overlayHeight = 200; - - // Add touch padding - const int touchPadding = 4; - const int touchableX = overlayX - touchPadding; - const int touchableY = overlayY - touchPadding; - const int touchableWidth = overlayWidth + (touchPadding * 2); - const int touchableHeight = overlayHeight + (touchPadding * 2); - - // Check if touch is within bounds - if (touchX >= touchableX && touchX <= touchableX + touchableWidth && - touchY >= touchableY && touchY <= touchableY + touchableHeight) { - overlay->inputDetected.store(true, std::memory_order_release); - } - } - - // Poll buttons from both controllers - padUpdate(&pad_p1); - padUpdate(&pad_handheld); - - // Combine input from both controllers - const u64 keysHeld = padGetButtons(&pad_p1) | padGetButtons(&pad_handheld); - const u64 now = armTicksToNs(armGetSystemTick()); - - // Track MINUS hold duration - if ((keysHeld & KEY_MINUS) && !(keysHeld & ~KEY_MINUS & ALL_KEYS_MASK)) { - if (minusHoldStart == 0) { - minusHoldStart = now; - } - if (now - minusHoldStart >= HOLD_THRESHOLD_NS) { - // Long enough to start drag - overlay->inputDetected.store(true, std::memory_order_release); - overlay->buttonState.minusDragActive.exchange(true, std::memory_order_acq_rel); - } - } - - // Track PLUS hold duration - else if ((keysHeld & KEY_PLUS) && !(keysHeld & ~KEY_PLUS & ALL_KEYS_MASK)) { - if (plusHoldStart == 0) { - plusHoldStart = now; - } - if (now - plusHoldStart >= HOLD_THRESHOLD_NS) { - // Long enough to start drag - overlay->inputDetected.store(true, std::memory_order_release); - overlay->buttonState.plusDragActive.exchange(true, std::memory_order_acq_rel); - } - } - - else { - minusHoldStart = plusHoldStart = 0; - overlay->buttonState.minusDragActive.exchange(false, std::memory_order_acq_rel); - overlay->buttonState.plusDragActive.exchange(false, std::memory_order_acq_rel); - } - - // Disable rendering on any input, re-enable when no input - static bool resetOnce = true; - if (overlay->inputDetected.load(std::memory_order_acquire)) { - if (resetOnce && isRendering) { - isRendering = false; - leventSignal(&renderingStopEvent); - resetOnce = false; - } - } else { - resetOnce = true; - } - } - - if (ult::limitedMemory) { - static auto lastUnderscanPixels = std::make_pair(0, 0); - - if (lastUnderscanPixels != tsl::impl::currentUnderscanPixels) { - for (int i = 0; i < 2; i++) { - tsl::gfx::Renderer::get().updateLayerSize(); - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(overlay->frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - } - lastUnderscanPixels = tsl::impl::currentUnderscanPixels; - } - - svcSleepThread(16000000ULL*2); // 16ms polling - } - }, this, NULL, 0x1000, 0x2B, -2); - threadStart(&touchPollThread); - } - - ~ResolutionsOverlay() { - // Stop touch polling thread - touchPollRunning.store(false, std::memory_order_release); - threadWaitForExit(&touchPollThread); - threadClose(&touchPollThread); - - EndFPSCounterThread(); - TeslaFPS = 60; - if (settings.disableScreenshots) { - tsl::gfx::Renderer::get().addScreenshotStacks(); - } - deactivateOriginalFooter = false; - ult::useRightAlignment = originalUseRightAlignment; - fixForeground = true; - FullMode = true; - } - - resolutionCalls m_resolutionRenderCalls[8] = {0}; - resolutionCalls m_resolutionViewportCalls[8] = {0}; - bool gameStart = false; - uint8_t resolutionLookup = 0; - u64 lastGameSeenTick = 0; - bool waitingForGame = true; - - virtual tsl::elm::Element* createUI() override { - - auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) { - int base_y = 0; - int base_x = 0; - int clippingOffsetX = 0, clippingOffsetY = 0; - - int total_width = 360 - 20; - int total_height = 200; - - // Check clipping bounds (same as before) - if (base_x + frameOffsetX < int(framePadding)) - clippingOffsetX = framePadding - (base_x + frameOffsetX); - else if ((base_x + frameOffsetX + total_width) > static_cast(screenWidth - framePadding)) - clippingOffsetX = (screenWidth - framePadding) - (base_x + frameOffsetX + total_width); - - if (base_y + frameOffsetY < int(framePadding)) - clippingOffsetY = framePadding - (base_y + frameOffsetY); - else if ((base_y + frameOffsetY + total_height) > static_cast(screenHeight - framePadding)) - clippingOffsetY = (screenHeight - framePadding) - (base_y + frameOffsetY + total_height); - - int _frameOffsetX = ult::limitedMemory ? std::max(0, frameOffsetX - (1280-448)) : frameOffsetX; - - const int final_base_x = base_x + _frameOffsetX + clippingOffsetX; - const int final_base_y = base_y + frameOffsetY + clippingOffsetY; - - const tsl::Color bgColor = !isDragging ? settings.backgroundColor : settings.focusBackgroundColor; - - const u64 curTick = armGetSystemTick(); - - // guard: ensure lastGameSeenTick is initialized to something reasonable - if (lastGameSeenTick == 0) lastGameSeenTick = curTick; - - // threshold in ns (100 ms) - static constexpr u64 CHECK_NS = 2000000000ULL; - - // Game detected - if (gameStart && NxFps && NxFps->API >= 1 && (Resolutions_c[0] != '\0' && Resolutions2_c[0] != '\0')) { - lastGameSeenTick = curTick; - waitingForGame = true; // reset waiting state so next missing cycle shows "Checking..." - renderer->drawRoundedRectSingleThreaded(final_base_x, final_base_y, total_width, total_height, 16, aWithOpacity(bgColor)); - - int xOffset = 10; - int yOffset = 10; - renderer->drawString("Depth", false, xOffset + final_base_x + 20, yOffset + final_base_y + 20, 20, settings.catColor); - renderer->drawString(Resolutions_c, false, xOffset + final_base_x + 20, yOffset + final_base_y + 55, 18, settings.textColor); - renderer->drawString("Viewport", false, xOffset + final_base_x + 180, yOffset + final_base_y + 20, 20, settings.catColor); - renderer->drawString(Resolutions2_c, false, xOffset + final_base_x + 180, yOffset + final_base_y + 55, 18, settings.textColor); - } - // Game not detected - else { - renderer->drawRoundedRectSingleThreaded(final_base_x, final_base_y, total_width, total_height, 16, aWithOpacity(bgColor)); - - // Check elapsed time since last game detection - u64 elapsed_ns = armTicksToNs(curTick - lastGameSeenTick); - const bool under100ms = (elapsed_ns < CHECK_NS); // 100ms - - std::string msg; - if (under100ms && waitingForGame) - msg = "Checking for game..."; - else { - msg = "Game is not running\nor is incompatible."; - waitingForGame = false; - } - - const auto [textWidth, textHeight] = renderer->getTextDimensions(msg, false, 20); - const int text_x = final_base_x + (total_width - textWidth) / 2; - const int text_y = final_base_y + (total_height) / 2; - - renderer->drawString(msg, false, text_x, (under100ms && waitingForGame) ? text_y+textHeight/2 : text_y, 20, (under100ms && waitingForGame) ? 0xFFFF : 0xF00F); - } - }); - - tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("", ""); - rootFrame->setContent(Status); - - return rootFrame; - } - - virtual void update() override { - - if (gameStart && NxFps) { - if (!resolutionLookup) { - NxFps -> renderCalls[0].calls = 0xFFFF; - resolutionLookup = 1; - } - else if (resolutionLookup == 1) { - if ((NxFps -> renderCalls[0].calls) != 0xFFFF) resolutionLookup = 2; - else return; - } - memcpy(&m_resolutionRenderCalls, &(NxFps -> renderCalls), sizeof(m_resolutionRenderCalls)); - memcpy(&m_resolutionViewportCalls, &(NxFps -> viewportCalls), sizeof(m_resolutionViewportCalls)); - qsort(m_resolutionRenderCalls, 8, sizeof(resolutionCalls), compare); - qsort(m_resolutionViewportCalls, 8, sizeof(resolutionCalls), compare); - snprintf(Resolutions_c, sizeof Resolutions_c, - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d", - m_resolutionRenderCalls[0].width, m_resolutionRenderCalls[0].height, m_resolutionRenderCalls[0].calls, - m_resolutionRenderCalls[1].width, m_resolutionRenderCalls[1].height, m_resolutionRenderCalls[1].calls, - m_resolutionRenderCalls[2].width, m_resolutionRenderCalls[2].height, m_resolutionRenderCalls[2].calls, - m_resolutionRenderCalls[3].width, m_resolutionRenderCalls[3].height, m_resolutionRenderCalls[3].calls, - m_resolutionRenderCalls[4].width, m_resolutionRenderCalls[4].height, m_resolutionRenderCalls[4].calls, - m_resolutionRenderCalls[5].width, m_resolutionRenderCalls[5].height, m_resolutionRenderCalls[5].calls, - m_resolutionRenderCalls[6].width, m_resolutionRenderCalls[6].height, m_resolutionRenderCalls[6].calls, - m_resolutionRenderCalls[7].width, m_resolutionRenderCalls[7].height, m_resolutionRenderCalls[7].calls - ); - snprintf(Resolutions2_c, sizeof Resolutions2_c, - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d\n" - "%dx%d, %d", - m_resolutionViewportCalls[0].width, m_resolutionViewportCalls[0].height, m_resolutionViewportCalls[0].calls, - m_resolutionViewportCalls[1].width, m_resolutionViewportCalls[1].height, m_resolutionViewportCalls[1].calls, - m_resolutionViewportCalls[2].width, m_resolutionViewportCalls[2].height, m_resolutionViewportCalls[2].calls, - m_resolutionViewportCalls[3].width, m_resolutionViewportCalls[3].height, m_resolutionViewportCalls[3].calls, - m_resolutionViewportCalls[4].width, m_resolutionViewportCalls[4].height, m_resolutionViewportCalls[4].calls, - m_resolutionViewportCalls[5].width, m_resolutionViewportCalls[5].height, m_resolutionViewportCalls[5].calls, - m_resolutionViewportCalls[6].width, m_resolutionViewportCalls[6].height, m_resolutionViewportCalls[6].calls, - m_resolutionViewportCalls[7].width, m_resolutionViewportCalls[7].height, m_resolutionViewportCalls[7].calls - ); - } - if (FPSavg < 254) { - gameStart = true; - } - else { - gameStart = false; - resolutionLookup = false; - } - - if (!skipOnce) { - if (runOnce) { - isRendering = true; - leventClear(&renderingStopEvent); - runOnce = false; - } - } else { - skipOnce = false; - } - } - - virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override { - // Static variables to maintain drag state between function calls - static bool oldTouchDetected = false; - static bool oldMinusHeld = false; - static bool oldPlusHeld = false; - static HidTouchState initialTouchPos = {0}; - static int initialFrameOffsetX = 0; - static int initialFrameOffsetY = 0; - static constexpr int TOUCH_THRESHOLD = 8; - static bool hasMoved = false; - - // Better touch detection - check if coordinates are within reasonable screen bounds - const bool currentTouchDetected = (touchPos.x > 0 && touchPos.y > 0 && - touchPos.x < screenWidth && touchPos.y < screenHeight); - - static bool clearOnRelease = false; - - if (clearOnRelease && !isRendering) { - clearOnRelease = false; - isRendering = true; - leventClear(&renderingStopEvent); - } - - // Calculate overlay bounds - // Cache bounds calculation - static int cachedBaseX = 0; - static int cachedBaseY = 0; - static bool boundsNeedUpdate = true; - - // Only recalculate bounds when needed - if (boundsNeedUpdate) { - cachedBaseX = 0; - cachedBaseY = 0; - boundsNeedUpdate = false; - } - - const int overlayX = cachedBaseX + frameOffsetX; - const int overlayY = cachedBaseY + frameOffsetY; - - // Overlay dimensions based on game state - int overlayWidth, overlayHeight; - overlayWidth = 360-20; - overlayHeight = 200; - - // Add padding to make touch detection more forgiving - static constexpr int touchPadding = 4; - const int touchableX = overlayX - touchPadding; - const int touchableY = overlayY - touchPadding; - const int touchableWidth = overlayWidth + (touchPadding * 2); - const int touchableHeight = overlayHeight + (touchPadding * 2); - - // Screen boundaries for clamping - const int minX = -cachedBaseX + framePadding; - const int maxX = screenWidth - overlayWidth - cachedBaseX - framePadding; - const int minY = -cachedBaseY + framePadding; - const int maxY = screenHeight - overlayHeight - cachedBaseY - framePadding; - - const bool minusDragReady = buttonState.minusDragActive.load(std::memory_order_acquire); - const bool plusDragReady = buttonState.plusDragActive.load(std::memory_order_acquire); - - // Check button states - const bool currentMinusHeld = (keysHeld & KEY_MINUS) && !(keysHeld & ~KEY_MINUS & ALL_KEYS_MASK) && minusDragReady; - const bool currentPlusHeld = (keysHeld & KEY_PLUS) && !(keysHeld & ~KEY_PLUS & ALL_KEYS_MASK) && plusDragReady; - - // Handle touch dragging - if (currentTouchDetected && !isDragging) { - const int touchX = touchPos.x; - const int touchY = touchPos.y; - - if (!oldTouchDetected) { - // Touch just started - check if within overlay bounds - if (touchX >= touchableX && touchX <= touchableX + touchableWidth && - touchY >= touchableY && touchY <= touchableY + touchableHeight) { - - // Start touch dragging - isDragging = true; - triggerRumbleClick.store(true, std::memory_order_release); - triggerOnSound.store(true, std::memory_order_release); - hasMoved = false; - initialTouchPos = touchPos; - initialFrameOffsetX = frameOffsetX; - initialFrameOffsetY = frameOffsetY; - } - } - } else if (currentTouchDetected && isDragging && !currentMinusHeld && !currentPlusHeld) { - // Continue touch dragging - const int touchX = touchPos.x; - const int touchY = touchPos.y; - const int deltaX = touchX - initialTouchPos.x; - const int deltaY = touchY - initialTouchPos.y; - - // Check if we've moved enough to consider this a drag - if (!hasMoved) { - const int totalMovement = abs(deltaX) + abs(deltaY); - if (totalMovement >= TOUCH_THRESHOLD) { - hasMoved = true; - } - } - - if (hasMoved) { - // Update frame offsets with boundary checking - const int newFrameOffsetX = std::max(minX, std::min(maxX, initialFrameOffsetX + deltaX)); - const int newFrameOffsetY = std::max(minY, std::min(maxY, initialFrameOffsetY + deltaY)); - - frameOffsetX = newFrameOffsetX; - frameOffsetY = newFrameOffsetY; - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - - boundsNeedUpdate = true; - } - } else if (!currentTouchDetected && oldTouchDetected && isDragging && !currentMinusHeld && !currentPlusHeld) { - // Touch just released - if (hasMoved) { - // Save position when touch drag ends - auto iniData = ult::getParsedDataFromIniFile(configIniPath); - iniData["game_resolutions"]["frame_offset_x"] = std::to_string(frameOffsetX); - iniData["game_resolutions"]["frame_offset_y"] = std::to_string(frameOffsetY); - ult::saveIniFileData(configIniPath, iniData); - } - - // Reset touch drag state - isDragging = false; - hasMoved = false; - clearOnRelease = true; - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerOffSound.store(true, std::memory_order_release); - } - - // Handle joystick dragging (MINUS + right joystick OR PLUS + left joystick) - if ((currentMinusHeld || currentPlusHeld) && !isDragging) { - // Start joystick dragging - isDragging = true; - triggerRumbleClick.store(true, std::memory_order_release); - triggerOnSound.store(true, std::memory_order_release); - } else if ((currentMinusHeld || currentPlusHeld) && isDragging) { - // Continue joystick dragging - static constexpr int JOYSTICK_DEADZONE = 20; - - // Choose the appropriate joystick based on which button is held - const HidAnalogStickState& activeJoystick = currentMinusHeld ? joyStickPosRight : joyStickPosLeft; - - // Only move if joystick is outside deadzone - if (abs(activeJoystick.x) > JOYSTICK_DEADZONE || abs(activeJoystick.y) > JOYSTICK_DEADZONE) { - // Calculate joystick magnitude - const float magnitude = sqrt((float)(activeJoystick.x * activeJoystick.x + activeJoystick.y * activeJoystick.y)); - const float normalizedMagnitude = magnitude / 32767.0f; - - // Smooth curve for sensitivity - static constexpr float baseSensitivity = 0.00008f; - static constexpr float maxSensitivity = 0.0005f; - - const float curveValue = pow(normalizedMagnitude, 8.0f); - const float currentSensitivity = baseSensitivity + (maxSensitivity - baseSensitivity) * curveValue; - - // Calculate movement delta with fractional accumulation - static float accumulatedX = 0.0f; - static float accumulatedY = 0.0f; - - accumulatedX += (float)activeJoystick.x * currentSensitivity; - accumulatedY += -(float)activeJoystick.y * currentSensitivity; - - const int deltaX = (int)accumulatedX; - const int deltaY = (int)accumulatedY; - accumulatedX -= deltaX; - accumulatedY -= deltaY; - - // Update frame offsets with boundary checking - const int newFrameOffsetX = std::max(minX, std::min(maxX, frameOffsetX + deltaX)); - const int newFrameOffsetY = std::max(minY, std::min(maxY, frameOffsetY + deltaY)); - - frameOffsetX = newFrameOffsetX; - frameOffsetY = newFrameOffsetY; - - if (ult::limitedMemory) { - tsl::gfx::Renderer::get().setLayerPos(std::max(std::min((int)(frameOffsetX*1.5 + 0.5) - tsl::impl::currentUnderscanPixels.first, 1280-32 - tsl::impl::currentUnderscanPixels.first), 0), 0); - } - - boundsNeedUpdate = true; - } - } else if (((!currentMinusHeld && oldMinusHeld) || (!currentPlusHeld && oldPlusHeld)) && isDragging) { - // Button just released - stop joystick dragging - auto iniData = ult::getParsedDataFromIniFile(configIniPath); - iniData["game_resolutions"]["frame_offset_x"] = std::to_string(frameOffsetX); - iniData["game_resolutions"]["frame_offset_y"] = std::to_string(frameOffsetY); - ult::saveIniFileData(configIniPath, iniData); - isDragging = false; - clearOnRelease = true; - triggerRumbleDoubleClick.store(true, std::memory_order_release); - triggerOffSound.store(true, std::memory_order_release); - } - - // Update state for next frame - oldTouchDetected = currentTouchDetected; - oldMinusHeld = currentMinusHeld; - oldPlusHeld = currentPlusHeld; - - // Handle existing key input logic (but don't interfere with dragging) - if (!isDragging) { - if (isKeyComboPressed(keysHeld, keysDown)) { - isRendering = false; - leventSignal(&renderingStopEvent); - runOnce = true; - skipOnce = true; - TeslaFPS = 60; - lastSelectedItem = "Game Resolutions"; - lastMode = ""; - if (skipMain) { - lastMode = "return"; - tsl::goBack(); - } - else { - tsl::setNextOverlay(filepath.c_str(), "--lastSelectedItem 'Game Resolutions'"); - tsl::Overlay::get()->close(); - } - return true; - } - } - - // Return true if we handled the input (during dragging) - return isDragging; - } -}; \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/pwm.c b/Source/Horizon-OC-Monitor (deprecated)/source/pwm.c deleted file mode 100644 index d556e7ca..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/pwm.c +++ /dev/null @@ -1,35 +0,0 @@ -#define NX_SERVICE_ASSUME_NON_DOMAIN -#include -#include -#include "pwm.h" - -static Service g_pwmSrv; - -NX_GENERATE_SERVICE_GUARD(pwm); - -Result _pwmInitialize(void) { - return smGetService(&g_pwmSrv, "pwm"); -} - -void _pwmCleanup(void) { - serviceClose(&g_pwmSrv); -} - -Service* pwmGetServiceSession(void) { - return &g_pwmSrv; -} - -Result pwmOpenSession2(PwmChannelSession *out, u32 device_code) { - return serviceDispatchIn(&g_pwmSrv, 2, device_code, - .out_num_objects = 1, - .out_objects = &out->s, - ); -} - -Result pwmChannelSessionGetDutyCycle(PwmChannelSession *c, double* out) { - return serviceDispatchOut(&c->s, 7, *out); -} - -void pwmChannelSessionClose(PwmChannelSession *c) { - serviceClose(&c->s); -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/rgltr_services.cpp b/Source/Horizon-OC-Monitor (deprecated)/source/rgltr_services.cpp deleted file mode 100644 index 5f2160db..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/rgltr_services.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// rgltr_services.cpp (no changes needed here—just compile it once) -#include -#include "rgltr.h" -#include "rgltr_services.h" // for extern Service g_rgltrSrv, etc. - -// Global service handle -Service g_rgltrSrv; - -Result rgltrInitialize(void) { - if (hosversionBefore(8, 0, 0)) { - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - } - return smGetService(&g_rgltrSrv, "rgltr"); -} - -void rgltrExit(void) { - serviceClose(&g_rgltrSrv); -} - -Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id) { - const u32 in = (u32)module_id; - return serviceDispatchIn( - &g_rgltrSrv, - 0, - in, - .out_num_objects = 1, - .out_objects = &session_out->s - ); -} - -Result rgltrGetVoltage(RgltrSession* session, u32* out_volt) { - // Service returns µV (microvolts) in a local u32: - u32 temp = 0; - Result rc = serviceDispatchOut(&session->s, 4, temp); - if (R_SUCCEEDED(rc)) { - *out_volt = temp; - } - return rc; -} - -void rgltrCloseSession(RgltrSession* session) { - serviceClose(&session->s); -} diff --git a/Source/Horizon-OC-Monitor (deprecated)/source/sysclk_ipc.c b/Source/Horizon-OC-Monitor (deprecated)/source/sysclk_ipc.c deleted file mode 100644 index 6d3172b3..00000000 --- a/Source/Horizon-OC-Monitor (deprecated)/source/sysclk_ipc.c +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors - * - * 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 . - * - */ - -/* -------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * , , - * wrote this file. As long as you retain this notice you can do whatever you - * want with this stuff. If you meet any of us some day, and you think this - * stuff is worth it, you can buy us a beer in return. - The sys-clk authors - * -------------------------------------------------------------------------- - */ - - -#define NX_SERVICE_ASSUME_NON_DOMAIN -#include -#include -#include -#include - -static Service g_hocclkSrv; -static atomic_size_t g_refCnt; - -bool hocclkIpcRunning() -{ - Handle handle; - bool running = R_FAILED(smRegisterService(&handle, smEncodeName(HOCCLK_IPC_SERVICE_NAME), false, 1)); - - if (!running) - { - smUnregisterService(smEncodeName(HOCCLK_IPC_SERVICE_NAME)); - } - - return running; -} - -Result hocclkIpcInitialize(void) -{ - Result rc = 0; - - g_refCnt++; - - if (serviceIsActive(&g_hocclkSrv)) - return 0; - - rc = smGetService(&g_hocclkSrv, HOCCLK_IPC_SERVICE_NAME); - - if (R_FAILED(rc)) hocclkIpcExit(); - - return rc; -} - -void hocclkIpcExit(void) -{ - if (--g_refCnt == 0) - { - serviceClose(&g_hocclkSrv); - } -} - -Result hocclkIpcGetAPIVersion(u32* out_ver) -{ - return serviceDispatchOut(&g_hocclkSrv, HocClkIpcCmd_GetApiVersion, *out_ver); -} - -Result hocclkIpcGetVersionString(char* out, size_t len) -{ - return serviceDispatch(&g_hocclkSrv, HocClkIpcCmd_GetVersionString, - .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out }, - .buffers = {{out, len}}, - ); -} - -Result hocclkIpcGetCurrentContext(HocClkContext* out_context) -{ - return serviceDispatch(&g_hocclkSrv, HocClkIpcCmd_GetCurrentContext, - .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out }, - .buffers = {{out_context, sizeof(HocClkContext)}}, - ); -} - -Result hocclkIpcGetProfileCount(u64 tid, u8* out_count) -{ - return serviceDispatchInOut(&g_hocclkSrv, HocClkIpcCmd_GetProfileCount, tid, *out_count); -} - -Result hocclkIpcSetEnabled(bool enabled) -{ - u8 enabledRaw = (u8)enabled; - return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_SetEnabled, enabledRaw); -} - -Result hocclkIpcSetOverride(HocClkModule module, u32 hz) -{ - HocClkIpc_SetOverride_Args args = { - .module = module, - .hz = hz - }; - return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_SetOverride, args); -} - -Result hocclkIpcGetProfiles(u64 tid, HocClkTitleProfileList* out_profiles) -{ - return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_GetProfiles, tid, - .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out }, - .buffers = {{out_profiles, sizeof(HocClkTitleProfileList)}}, - ); -} - -Result hocclkIpcSetProfiles(u64 tid, HocClkTitleProfileList* profiles) -{ - HocClkIpc_SetProfiles_Args args; - args.tid = tid; - memcpy(&args.profiles, profiles, sizeof(HocClkTitleProfileList)); - return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_SetProfiles, args); -} - -Result hocclkIpcGetConfigValues(HocClkConfigValueList* out_configValues) -{ - return serviceDispatch(&g_hocclkSrv, HocClkIpcCmd_GetConfigValues, - .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out }, - .buffers = {{out_configValues, sizeof(HocClkConfigValueList)}}, - ); -} - -Result hocclkIpcSetConfigValues(HocClkConfigValueList* configValues) -{ - return serviceDispatch(&g_hocclkSrv, HocClkIpcCmd_SetConfigValues, - .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In }, - .buffers = {{configValues, sizeof(HocClkConfigValueList)}}, - ); -} - -Result hocclkIpcGetFreqList(HocClkModule module, u32* list, u32 maxCount, u32* outCount) -{ - HocClkIpc_GetFreqList_Args args = { - .module = module, - .maxCount = maxCount - }; - return serviceDispatchInOut(&g_hocclkSrv, HocClkIpcCmd_GetFreqList, args, *outCount, - .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out }, - .buffers = {{list, maxCount * sizeof(u32)}}, - ); -} - -Result hocClkIpcSetKipData() -{ - u32 temp = 0; - return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_SetKipData, temp); -} - -Result hocClkIpcGetKipData() -{ - u32 temp = 0; - return serviceDispatchIn(&g_hocclkSrv, HocClkIpcCmd_GetKipData, temp); -} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.elf b/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.elf deleted file mode 100644 index d0cbd027..00000000 Binary files a/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.elf and /dev/null differ diff --git a/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.nacp b/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.nacp deleted file mode 100644 index 146958db..00000000 Binary files a/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.nacp and /dev/null differ diff --git a/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.ovl b/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.ovl deleted file mode 100644 index 95495b80..00000000 Binary files a/Source/Horizon-OC-Monitor/Horizon-OC-Monitor.ovl and /dev/null differ diff --git a/Source/Horizon-OC-Monitor/out/switch/.overlays/Horizon-OC-Monitor.ovl b/Source/Horizon-OC-Monitor/out/switch/.overlays/Horizon-OC-Monitor.ovl deleted file mode 100644 index 95495b80..00000000 Binary files a/Source/Horizon-OC-Monitor/out/switch/.overlays/Horizon-OC-Monitor.ovl and /dev/null differ diff --git a/Source/Old-Atmosphere-Patches/ldr_process_creation_1_12_0.cpp b/Source/Old-Atmosphere-Patches/ldr_process_creation_1_12_0.cpp new file mode 100644 index 00000000..fd96684e --- /dev/null +++ b/Source/Old-Atmosphere-Patches/ldr_process_creation_1_12_0.cpp @@ -0,0 +1,973 @@ +/* + * 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 . + */ + +#include +#include "ldr_capabilities.hpp" +#include "ldr_content_management.hpp" +#include "ldr_development_manager.hpp" +#include "ldr_launch_record.hpp" +#include "ldr_meta.hpp" +#include "ldr_patcher.hpp" +#include "ldr_process_creation.hpp" +#include "ldr_ro_manager.hpp" +#include "oc/oc_loader.hpp" + +namespace ams::ldr { + + namespace { + + /* Convenience defines. */ + constexpr size_t SystemResourceSizeMax = 0x1FE00000; + constexpr size_t AutoLoadModuleSizeMax = 0x800000000; + + /* Types. */ + enum NsoIndex { + Nso_Rtld = 0, + Nso_Main = 1, + Nso_Wkc0 = 2, + Nso_Wkc1 = 3, + Nso_Wkc2 = 4, + Nso_Wkc3 = 5, + Nso_Wkc4 = 6, + Nso_Wkc5 = 7, + Nso_Wkc6 = 8, + Nso_Wkc7 = 9, + Nso_Wkc8 = 10, + Nso_Wkc9 = 11, + Nso_SubSdk0 = 12, + Nso_SubSdk1 = 13, + Nso_SubSdk2 = 14, + Nso_SubSdk3 = 15, + Nso_SubSdk4 = 16, + Nso_SubSdk5 = 17, + Nso_SubSdk6 = 18, + Nso_SubSdk7 = 19, + Nso_SubSdk8 = 20, + Nso_SubSdk9 = 21, + Nso_Sdk = 22, + Nso_Count, + }; + + constexpr inline const char *NsoPaths[Nso_Count] = { + ENCODE_ATMOSPHERE_CODE_PATH("/rtld"), + ENCODE_ATMOSPHERE_CODE_PATH("/main"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc0"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc1"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc2"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc3"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc4"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc5"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc6"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc7"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc8"), + ENCODE_ATMOSPHERE_BDLL_PATH("/wkc9"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk0"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk1"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk2"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk3"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk4"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk5"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk6"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk7"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk8"), + ENCODE_ATMOSPHERE_CODE_PATH("/subsdk9"), + ENCODE_ATMOSPHERE_CODE_PATH("/sdk"), + }; + + constexpr const char *GetNsoPath(size_t idx) { + AMS_ABORT_UNLESS(idx < Nso_Count); + return NsoPaths[idx]; + } + + struct ProcessInfo { + os::NativeHandle process_handle; + uintptr_t code_address; + size_t total_size; + uintptr_t args_address; + size_t args_size; + uintptr_t nso_address[Nso_Count]; + size_t nso_size[Nso_Count]; + }; + + struct AutoLoadModuleInfo { + bool has_rtld; + bool has_main; + bool has_sdk; + bool has_subsdk; + s8 nso_indices[Nso_Count]; + }; + + struct AutoLoadModuleContext { + NsoHeader *headers; + int nso_count; + int rtld_idx; + int main_nso_idx; + int sdk_nso_idx; + AutoLoadModuleInfo ali; + }; + + /* Global NSO header cache. */ + NsoHeader g_nso_headers[Nso_Count]; + + /* Pcv/Ptm check cache */ + bool g_is_pcv; + bool g_is_ptm; + + /* Global Zstd decompression context. */ + alignas(8) u8 g_zstd_dctx_workspace[util::DecompressZstdWithBicWorkBufferSizeDefault]; + + Result ValidateProgramVersion(ncm::ProgramId program_id, u32 version) { + /* No version verification is done before 8.1.0. */ + R_SUCCEED_IF(hos::GetVersion() < hos::Version_8_1_0); + + /* No verification is done if development. */ + R_SUCCEED_IF(IsDevelopmentForAntiDowngradeCheck()); + + /* TODO: Anti-downgrade checking does not make very much sense for us. Should we do anything? */ + AMS_UNUSED(program_id, version); + + R_SUCCEED(); + } + + /* Helpers. */ + Result GetProgramInfoFromMeta(ProgramInfo *out, const Meta *meta) { + /* Copy basic info. */ + out->main_thread_priority = meta->npdm->main_thread_priority; + out->default_cpu_id = meta->npdm->default_cpu_id; + out->main_thread_stack_size = meta->npdm->main_thread_stack_size; + out->program_id = meta->aci->program_id; + + /* Copy access controls. */ + size_t offset = 0; +#define COPY_ACCESS_CONTROL(source, which) \ + ({ \ + const size_t size = meta->source->which##_size; \ + R_UNLESS(offset + size <= sizeof(out->ac_buffer), ldr::ResultInternalError()); \ + out->source##_##which##_size = size; \ + std::memcpy(out->ac_buffer + offset, meta->source##_##which, size); \ + offset += size; \ + }) + + /* Copy all access controls to buffer. */ + COPY_ACCESS_CONTROL(acid, sac); + COPY_ACCESS_CONTROL(aci, sac); + COPY_ACCESS_CONTROL(acid, fac); + COPY_ACCESS_CONTROL(aci, fah); +#undef COPY_ACCESS_CONTROL + + /* Copy flags. */ + out->flags = MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)); + R_SUCCEED(); + } + + bool IsApplet(const Meta *meta) { + return (MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet; + } + + bool IsApplication(const Meta *meta) { + return (MakeProgramInfoFlag(static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32)) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Application; + } + + Npdm::ProcessAddressSpace GetProcessAddressSpace(const Meta *meta) { + return static_cast((meta->npdm->flags0 & Npdm::MetaFlag0_ProcessAddressSpaceMask) >> Npdm::MetaFlag0_ProcessAddressSpaceShift); + } + + Acid::PoolPartition GetPoolPartition(const Meta *meta) { + return static_cast((meta->acid->flags & Acid::AcidFlag_PoolPartitionMask) >> Acid::AcidFlag_PoolPartitionShift); + } + + Result LoadAutoLoadHeaders(AutoLoadModuleContext &ctx, u32 acid_flags) { + /* Clear NSOs. */ + std::memset(g_nso_headers, 0, sizeof(g_nso_headers)); + ctx.headers = g_nso_headers; + ctx.nso_count = 0; + ctx.rtld_idx = -1; + ctx.main_nso_idx = -1; + ctx.sdk_nso_idx = -1; + ctx.ali = {}; + + for (size_t i = 0; i < Nso_Count; i++) { + /* Only load browser DLLs if acid flags say to do so. */ + switch (i) { + case Nso_Wkc0: + case Nso_Wkc1: + case Nso_Wkc2: + case Nso_Wkc3: + case Nso_Wkc4: + case Nso_Wkc5: + case Nso_Wkc6: + case Nso_Wkc7: + case Nso_Wkc8: + case Nso_Wkc9: + if ((acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) == 0) { + continue; + } + break; + } + + fs::FileHandle file; + if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), GetNsoPath(i), fs::OpenMode_Read))) { + ON_SCOPE_EXIT { fs::CloseFile(file); }; + + /* Read NSO header. */ + size_t read_size; + R_TRY(fs::ReadFile(std::addressof(read_size), file, 0, g_nso_headers + ctx.nso_count, sizeof(NsoHeader))); + R_UNLESS_LOG(read_size == sizeof(NsoHeader), ldr::ResultInvalidNso(), "[ldr] NSO header truncated!\n"); + + /* Note nso is present. */ + switch (i) { + case Nso_Rtld: + ctx.rtld_idx = ctx.nso_count; + ctx.ali.has_rtld = true; + break; + case Nso_Main: + ctx.main_nso_idx = ctx.nso_count; + ctx.ali.has_main = true; + break; + case Nso_SubSdk0: + case Nso_SubSdk1: + case Nso_SubSdk2: + case Nso_SubSdk3: + case Nso_SubSdk4: + case Nso_SubSdk5: + case Nso_SubSdk6: + case Nso_SubSdk7: + case Nso_SubSdk8: + case Nso_SubSdk9: + ctx.ali.has_subsdk = true; + break; + case Nso_Sdk: + ctx.sdk_nso_idx = ctx.nso_count; + ctx.ali.has_sdk = true; + break; + } + ctx.ali.nso_indices[ctx.nso_count] = static_cast(i); + ctx.nso_count++; + } + } + + R_SUCCEED(); + } + + Result CheckAutoLoad(const AutoLoadModuleContext &ctx, u32 acid_flags) { + /* We must always have a main. */ + R_UNLESS_LOG(ctx.ali.has_main, ldr::ResultInvalidNso(), "[ldr] Missing main!\n"); + + /* Validate flags and extents for all present NSOs. */ + for (int i = 0; i < ctx.nso_count; ++i) { + const auto &hdr = ctx.headers[i]; + + /* All NSOs must not be --X. */ + /* This is "probably" not checked on Ounce? */ + R_UNLESS_LOG((hdr.flags & NsoHeader::Flag_PreventCodeReads) == 0, ldr::ResultInvalidNso(), "[ldr] NSO[%d] --x not allowed!\n", i); + + /* Zstd compression only allowed on main, and only when both rtld+sdk are present. */ + if (i != ctx.main_nso_idx || ctx.rtld_idx < 0 || ctx.sdk_nso_idx < 0) { + R_UNLESS_LOG((hdr.flags & NsoHeader::Flag_UseZbicCompression) == 0, ldr::ResultInvalidNso(), "[ldr] NSO[%d] zbic not allowed!\n", i); + } + + /* NSOs must have page-aligned segments. */ + R_UNLESS(util::IsAligned(hdr.text_dst_offset, os::MemoryPageSize), ldr::ResultInvalidNso()); + R_UNLESS(util::IsAligned(hdr.ro_dst_offset, os::MemoryPageSize), ldr::ResultInvalidNso()); + R_UNLESS(util::IsAligned(hdr.rw_dst_offset, os::MemoryPageSize), ldr::ResultInvalidNso()); + + /* NSOs must have zero text offset. */ + R_UNLESS(hdr.text_dst_offset == 0, ldr::ResultInvalidNso()); + + /* NSO .text must precede .rodata. */ + const size_t text_end = static_cast(hdr.text_dst_offset) + static_cast(hdr.text_size); + R_UNLESS(text_end <= static_cast(hdr.ro_dst_offset), ldr::ResultInvalidNso()); + + /* NSO .rodata must precede .rwdata. */ + const size_t ro_end = static_cast(hdr.ro_dst_offset) + static_cast(hdr.ro_size); + R_UNLESS(ro_end <= static_cast(hdr.rw_dst_offset), ldr::ResultInvalidNso()); + } + + const bool has_browser_dll = (acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) != 0; + if (ctx.ali.has_rtld || ctx.ali.has_sdk) { + /* If we have sdk we must have rtld. */ + R_UNLESS_LOG(ctx.ali.has_rtld, ldr::ResultInvalidNso(), "[ldr] Missing rtld!\n"); + + /* If we have rtld, we must not have browser core dll. */ + R_UNLESS_LOG(!has_browser_dll, ldr::ResultInvalidNso(), "[ldr] BrowserCoreDll must not be present!\n"); + } else { + /* We must not have both subsdk and browser dll. */ + R_UNLESS_LOG(!(ctx.ali.has_subsdk && has_browser_dll), ldr::ResultInvalidNso(), "[ldr] Can't have both subsdk and BrowserCoreDll!\n"); + } + + R_SUCCEED(); + } + + constexpr const ncm::ProgramId UnqualifiedApprovalProgramIds[] = { + { 0x010003F003A34000 }, /* Pokemon: Let's Go, Pikachu! */ + { 0x0100152000022000 }, /* Mario Kart 8 Deluxe */ + { 0x0100165003504000 }, /* Nintendo Labo Toy-Con 04: VR Kit */ + { 0x0100187003A36000 }, /* Pokemon: Let's Go, Eevee! */ + { 0x01002E5008C56000 }, /* Pokemon Sword [Live Tournament] */ + { 0x01002FF008C24000 }, /* Ring Fit Adventure */ + { 0x010049900F546001 }, /* Super Mario 3D All-Stars: Super Mario 64 */ + { 0x010057D00ECE4000 }, /* Nintendo Switch Online (Nintendo 64) [for Japan] */ + { 0x01006F8002326000 }, /* Animal Crossing: New Horizons */ + { 0x01006FB00F50E000 }, /* 宝可梦 走吧!伊布 [Pokemon: Let's Go, Eevee! for China] */ + { 0x010070300F50C000 }, /* 宝可梦 走吧!皮卡丘 [Pokemon: Let's Go, Pikachu! for China] */ + { 0x010075100E8EC000 }, /* 马力欧卡丁车8 豪华版 [Mario Kart 8 Deluxe for China] */ + { 0x01008DB008C2C000 }, /* Pokemon Shield */ + { 0x01009AD008C4C000 }, /* Pokemon: Let's Go, Pikachu! [Kiosk] */ + { 0x0100A66003384000 }, /* Hulu */ + { 0x0100ABF008968000 }, /* Pokemon Sword */ + { 0x0100C9A00ECE6000 }, /* Nintendo Switch Online (Nintendo 64) [for America] */ + { 0x0100ED100BA3A000 }, /* Mario Kart Live: Home Circuit */ + { 0x0100F38011CFE000 }, /* Animal Crossing: New Horizons Island Transfer Tool */ + { 0x0100F6B011028000 }, /* 健身环大冒险 [Ring Fit Adventure for China] */ + }; + + /* Check that the unqualified approval programs are sorted. */ + static_assert([]() -> bool { + for (size_t i = 0; i < util::size(UnqualifiedApprovalProgramIds) - 1; ++i) { + if (UnqualifiedApprovalProgramIds[i].value >= UnqualifiedApprovalProgramIds[i + 1].value) { + return false; + } + } + + return true; + }()); + + bool IsUnqualifiedApprovalProgramId(ncm::ProgramId program_id) { + /* Check if the program id is one with unqualified approval. */ + return std::binary_search(std::begin(UnqualifiedApprovalProgramIds), std::end(UnqualifiedApprovalProgramIds), program_id); + } + + bool IsUnqualifiedApproval(const Meta *meta) { + /* If the meta has unqualified approval flag, it's unqualified approval. */ + if (meta->acid->flags & ldr::Acid::AcidFlag_UnqualifiedApproval) { + return true; + } + + /* If the unqualified approval flag is not set, the program must be an application. */ + if (!IsApplication(meta)) { + return false; + } + + /* The program id must be a force unqualified approval program id. */ + return IsUnqualifiedApprovalProgramId(meta->acid->program_id_min) && meta->acid->program_id_min == meta->acid->program_id_max; + } + + Result ValidateMeta(const Meta *meta, const ncm::ProgramLocation &loc, const fs::CodeVerificationData &code_verification_data) { + /* Validate version. */ + R_TRY(ValidateProgramVersion(loc.program_id, meta->npdm->version)); + + /* Validate program id. */ + R_UNLESS(meta->aci->program_id >= meta->acid->program_id_min, ldr::ResultInvalidProgramId()); + R_UNLESS(meta->aci->program_id <= meta->acid->program_id_max, ldr::ResultInvalidProgramId()); + + /* Validate the kernel capabilities. */ + R_TRY(TestCapability(static_cast(meta->acid_kac), meta->acid->kac_size / sizeof(util::BitPack32), static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32))); + + /* Check if NCA is PCV or PTM */ + g_is_pcv = meta->aci->program_id == ncm::SystemProgramId::Pcv; + g_is_ptm = meta->aci->program_id == ncm::SystemProgramId::Ptm; + + /* If we have data to validate, validate it. */ + if (meta->check_verification_data) { + const u8 *sig = code_verification_data.signature; + const size_t sig_size = sizeof(code_verification_data.signature); + const u8 *mod = static_cast(meta->modulus); + const size_t mod_size = crypto::Rsa2048PssSha256Verifier::ModulusSize; + const u8 *exp = fssystem::GetAcidSignatureKeyPublicExponent(); + const size_t exp_size = fssystem::AcidSignatureKeyPublicExponentSize; + const u8 *hsh = code_verification_data.target_hash; + const size_t hsh_size = sizeof(code_verification_data.target_hash); + const bool is_signature_valid = crypto::VerifyRsa2048PssSha256WithHash(sig, sig_size, mod, mod_size, exp, exp_size, hsh, hsh_size); + + /* If the signature check fails, we need to check if this is allowable. */ + if (!is_signature_valid) { + AMS_LOG("[ldr] invalid signature!\n"); + + /* We have to enforce signature checks on prod and when we have a signature to check on dev. */ + R_UNLESS(IsDevelopmentForAcidProductionCheck(), ldr::ResultInvalidNcaSignature()); + R_UNLESS(!code_verification_data.has_data, ldr::ResultInvalidNcaSignature()); + + /* There was no signature to check on dev. Check if this is acceptable. */ + R_UNLESS(IsUnqualifiedApproval(meta), ldr::ResultInvalidNcaSignature()); + } + } + + /* All good. */ + R_SUCCEED(); + } + + Result GetCreateProcessParameterFlags(u32 *out, const Meta *meta, const u32 ldr_flags) { + const u8 meta_flags0 = meta->npdm->flags0; + const u8 meta_flags1 = meta->npdm->flags1; + + u32 flags = 0; + + /* Set Is64Bit. */ + if (meta_flags0 & Npdm::MetaFlag0_Is64BitInstruction) { + flags |= svc::CreateProcessParameterFlag_64Bit; + } + + /* Set ProcessAddressSpace. */ + switch (GetProcessAddressSpace(meta)) { + case Npdm::ProcessAddressSpace_32Bit: + flags |= svc::CreateProcessParameterFlag_AddressSpace32Bit; + break; + case Npdm::ProcessAddressSpace_64Bit36: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit36; + break; + case Npdm::ProcessAddressSpace_32BitNoReserved: + flags |= svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved; + break; + case Npdm::ProcessAddressSpace_64Bit39: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit39; + break; + case Npdm::ProcessAddressSpace_64Bit42: + flags |= svc::CreateProcessParameterFlag_AddressSpace64Bit42; + break; + default: + R_THROW(ldr::ResultInvalidMeta()); + } + + /* Set Enable Debug. */ + if (ldr_flags & CreateProcessParameterFlag_EnableJitDebug) { + flags |= svc::CreateProcessParameterFlag_EnableJitDebug; + } + + /* Set Enable ASLR. */ + if (!(ldr_flags & CreateProcessParameterFlag_DisableAslr)) { + flags |= svc::CreateProcessParameterFlag_EnableAslr; + } + + /* Set Is Application. */ + if (IsApplication(meta)) { + flags |= svc::CreateProcessParameterFlag_IsApplication; + + /* 7.0.0+: Set OptimizeMemoryAllocation if relevant. */ + if (hos::GetVersion() >= hos::Version_7_0_0) { + if (meta_flags0 & Npdm::MetaFlag0_OptimizeMemoryAllocation) { + flags |= svc::CreateProcessParameterFlag_OptimizeMemoryAllocation; + } + } + } + + /* 5.0.0+ Set Pool Partition. */ + if (hos::GetVersion() >= hos::Version_5_0_0) { + /* TODO: Nintendo no longer accepts Applet when pool partition == application. Would this break hbl/anything else in the hb ecosystem? */ + /* TODO: Nintendo uses a helper bool MakeSvcPoolPartitionFlag(u32 *out, Acid::PoolPartition partition); */ + switch (GetPoolPartition(meta)) { + case Acid::PoolPartition_Application: + if (IsApplet(meta)) { + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplet; + } else { + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplication; + } + break; + case Acid::PoolPartition_Applet: + flags |= svc::CreateProcessParameterFlag_PoolPartitionApplet; + break; + case Acid::PoolPartition_System: + flags |= svc::CreateProcessParameterFlag_PoolPartitionSystem; + break; + case Acid::PoolPartition_SystemNonSecure: + flags |= svc::CreateProcessParameterFlag_PoolPartitionSystemNonSecure; + break; + default: + R_THROW(ldr::ResultInvalidMeta()); + } + } else if (hos::GetVersion() >= hos::Version_4_0_0) { + /* On 4.0.0+, the corresponding bit was simply "UseSecureMemory". */ + if (meta->acid->flags & Acid::AcidFlag_DeprecatedUseSecureMemory) { + flags |= svc::CreateProcessParameterFlag_DeprecatedUseSecureMemory; + } + } + + /* 11.0.0+/meso Set Disable DAS Merge. */ + if (meta_flags0 & Npdm::MetaFlag0_DisableDeviceAddressSpaceMerge) { + flags |= svc::CreateProcessParameterFlag_DisableDeviceAddressSpaceMerge; + } + + /* 18.0.0+/meso Set Enable Address Sanitizer . */ + if (meta_flags0 & Npdm::MetaFlag0_EnableAddressSanitizer) { + flags |= svc::CreateProcessParameterFlag_EnableAddressSanitizer; + } + + /* 23.0.0+/meso Set Enable Shadow Stack. */ + if (meta_flags1 & Npdm::MetaFlag1_EnableShadowStack) { + flags |= svc::CreateProcessParameterFlag_EnableShadowStack; + } + + *out = flags; + R_SUCCEED(); + } + + Result GetCreateProcessParameter(svc::CreateProcessParameter *out, const Meta *meta, u32 flags, os::NativeHandle resource_limit) { + /* Clear output. */ + std::memset(out, 0, sizeof(*out)); + + /* Set name, version, program id, resource limit handle. */ + std::memcpy(out->name, meta->npdm->program_name, sizeof(out->name) - 1); + out->version = meta->npdm->version; + out->program_id = meta->aci->program_id.value; + out->reslimit = resource_limit; + + /* Set flags. */ + R_TRY(GetCreateProcessParameterFlags(std::addressof(out->flags), meta, flags)); + + /* 3.0.0+ System Resource Size. */ + if (hos::GetVersion() >= hos::Version_3_0_0) { + /* Validate size is aligned. */ + R_UNLESS(util::IsAligned(meta->npdm->system_resource_size, os::MemoryBlockUnitSize), ldr::ResultInvalidSize()); + + /* Validate system resource usage. */ + if (meta->npdm->system_resource_size) { + /* Process must be 64-bit. */ + R_UNLESS((out->flags & svc::CreateProcessParameterFlag_AddressSpace64Bit39), ldr::ResultInvalidMeta()); + + /* Process must be application or applet. */ + R_UNLESS(IsApplication(meta) || IsApplet(meta), ldr::ResultInvalidMeta()); + + /* Size must be less than or equal to max. */ + R_UNLESS(meta->npdm->system_resource_size <= SystemResourceSizeMax, ldr::ResultInvalidMeta()); + } + out->system_resource_num_pages = meta->npdm->system_resource_size >> 12; + } + + R_SUCCEED(); + } + + u64 GenerateSecureRandom(u64 max) { + /* Generate a cryptographically random number. */ + u64 rand; + crypto::GenerateCryptographicallyRandomBytes(std::addressof(rand), sizeof(rand)); + + /* Coerce into range. */ + return rand % (max + 1); + } + + Result DecideAddressSpaceLayout(ProcessInfo *out, svc::CreateProcessParameter *out_param, const AutoLoadModuleContext &ctx, const ArgumentStore::Entry *argument) { + /* Clear output. */ + out->args_address = 0; + out->args_size = 0; + std::memset(out->nso_address, 0, sizeof(out->nso_address)); + std::memset(out->nso_size, 0, sizeof(out->nso_size)); + + size_t total_size = 0; + bool argument_allocated = false; + + /* Calculate base offsets. */ + for (int i = 0; i < ctx.nso_count; i++) { + out->nso_address[i] = total_size; + const size_t text_end = static_cast(ctx.headers[i].text_dst_offset) + static_cast(ctx.headers[i].text_size); + const size_t ro_end = static_cast(ctx.headers[i].ro_dst_offset) + static_cast(ctx.headers[i].ro_size); + const size_t rw_end = static_cast(ctx.headers[i].rw_dst_offset) + static_cast(ctx.headers[i].rw_size); + out->nso_size[i] = text_end; + out->nso_size[i] = std::max(out->nso_size[i], ro_end); + out->nso_size[i] = std::max(out->nso_size[i], rw_end); + out->nso_size[i] += static_cast(ctx.headers[i].bss_size); + + /* Reserve hook arena memory past pcv's bss. */ + if (g_is_pcv && i == ctx.main_nso_idx) { + out->nso_size[i] = util::AlignUp(out->nso_size[i], os::MemoryPageSize) + hoc::pcv::PcvDataArenaSize; + } + + const size_t aligned_up_size = util::AlignUp(out->nso_size[i], os::MemoryPageSize) & (AutoLoadModuleSizeMax - 1); + R_UNLESS(out->nso_size[i] <= aligned_up_size, ldr::ResultInvalidNso()); + R_UNLESS(aligned_up_size > 0, ldr::ResultInvalidNso()); + + out->nso_size[i] = aligned_up_size; + + R_UNLESS(util::CanAddWithoutOverflow(total_size, out->nso_size[i]), ldr::ResultInvalidNso()); + total_size += out->nso_size[i]; + + if (!argument_allocated && argument != nullptr) { + out->args_address = total_size; + out->args_size = util::AlignUp(2 * sizeof(u32) + argument->argument_size * 2 + ArgumentStore::ArgumentBufferSize, os::MemoryPageSize); + + R_UNLESS(util::CanAddWithoutOverflow(total_size, out->args_size), ldr::ResultInvalidNso()); + total_size += out->args_size; + + argument_allocated = true; + } + } + + /* Calculate ASLR. */ + uintptr_t aslr_start = 0; + size_t aslr_size = 0; + if (hos::GetVersion() >= hos::Version_2_0_0) { + switch (out_param->flags & svc::CreateProcessParameterFlag_AddressSpaceMask) { + case svc::CreateProcessParameterFlag_AddressSpace32Bit: + case svc::CreateProcessParameterFlag_AddressSpace32BitNoReserved: + aslr_start = svc::AddressSmallMap32Start; + aslr_size = svc::AddressSmallMap32Size; + break; + case svc::CreateProcessParameterFlag_AddressSpace64Bit36: + aslr_start = svc::AddressSmallMap36Start; + aslr_size = svc::AddressSmallMap36Size; + break; + case svc::CreateProcessParameterFlag_AddressSpace64Bit39: + aslr_start = svc::AddressMap39Start; + aslr_size = svc::AddressMap39Size; + break; + case svc::CreateProcessParameterFlag_AddressSpace64Bit42: + aslr_start = svc::AddressMap42Start; + aslr_size = svc::AddressMap42Size; + break; + AMS_UNREACHABLE_DEFAULT_CASE(); + } + } else { + /* On 1.0.0, only 2 address space types existed. */ + if (out_param->flags & svc::CreateProcessParameterFlag_AddressSpace64Bit36) { + aslr_start = svc::AddressSmallMap36Start; + aslr_size = svc::AddressSmallMap36Size; + } else { + aslr_start = svc::AddressSmallMap32Start; + aslr_size = svc::AddressSmallMap32Size; + } + } + R_UNLESS(total_size <= aslr_size, svc::ResultOutOfMemory()); + + /* Set Create Process output. */ + uintptr_t aslr_slide = 0; + size_t free_size = (aslr_size - total_size); + if (out_param->flags & svc::CreateProcessParameterFlag_EnableAslr) { + aslr_slide = GenerateSecureRandom(free_size / os::MemoryBlockUnitSize) * os::MemoryBlockUnitSize; + } + + /* Set out. */ + aslr_start += aslr_slide; + for (int i = 0; i < ctx.nso_count; i++) { + R_UNLESS(util::CanAddWithoutOverflow(out->nso_address[i], aslr_start), ldr::ResultInvalidNso()); + out->nso_address[i] += aslr_start; + } + if (out->args_address) { + R_UNLESS(util::CanAddWithoutOverflow(out->args_address, aslr_start), ldr::ResultInvalidNso()); + out->args_address += aslr_start; + } + + out_param->code_address = aslr_start; + out_param->code_num_pages = total_size >> 12; + out->total_size = total_size; + + R_SUCCEED(); + } + + Result LoadAutoLoadModuleSegment(fs::FileHandle file, size_t file_offset, size_t compressed_size, size_t segment_size, bool is_compressed, bool is_zbic, uintptr_t map_base, uintptr_t map_end) { + /* Select read size based on compression. */ + size_t file_size = is_compressed ? compressed_size : segment_size; + + AMS_LOG("[ldr] Loading segment @ 0x%016lx: compressed=%d, file_size=0x%08lx, compressed_size=0x%08lx, segment_size=0x%08lx\n", + map_base, is_compressed, file_size, compressed_size, segment_size); + + /* Validate size. */ + R_UNLESS(file_size <= segment_size, ldr::ResultInvalidNso()); + R_UNLESS(file_size <= std::numeric_limits::max(), ldr::ResultInvalidNso()); + R_UNLESS(segment_size <= std::numeric_limits::max(), ldr::ResultInvalidNso()); + + /* Load data from file. */ + uintptr_t load_address = is_compressed ? map_end - compressed_size : map_base; + size_t read_size; + R_TRY(fs::ReadFile(std::addressof(read_size), file, file_offset, reinterpret_cast(load_address), file_size)); + R_UNLESS_LOG(read_size == file_size, ldr::ResultInvalidNso(), "[ldr] Couldn't read segment from file!\n"); + + /* Uncompress if necessary. */ + R_SUCCEED_IF(!is_compressed); + + auto compressed_data_buf = reinterpret_cast(load_address); + + if (is_zbic) { + bool decompressed = util::DecompressZstdWithBic(reinterpret_cast(g_zstd_dctx_workspace), sizeof(g_zstd_dctx_workspace), reinterpret_cast(map_base), static_cast(map_end - map_base), segment_size, compressed_data_buf, file_size); + R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with zbic!\n"); + } else { + bool decompressed = (util::DecompressLZ4(reinterpret_cast(map_base), segment_size, compressed_data_buf, file_size) == static_cast(segment_size)); + R_UNLESS_LOG(decompressed, ldr::ResultInvalidNso(), "[ldr] Failed to decompress segment with lz4!\n"); + } + + R_SUCCEED(); + } + + Result CheckSegmentHash(const NsoHeader *nso_header, uintptr_t map_address, NsoHeader::Segment segment) { + if ((nso_header->flags & (NsoHeader::Flag_CheckHashText << segment)) == 0) { + R_SUCCEED(); + } + + u8 hash[crypto::Sha256Generator::HashSize]; + crypto::GenerateSha256(hash, sizeof(hash), + reinterpret_cast(map_address + nso_header->segments[segment].dst_offset), + nso_header->segments[segment].size); + R_UNLESS_LOG(std::memcmp(hash, nso_header->segment_hashes[segment], sizeof(hash)) == 0, ldr::ResultInvalidNso(), "[ldr] Invalid segment hash!\n"); + R_SUCCEED(); + } + + Result LoadAutoLoadModule(os::NativeHandle process_handle, fs::FileHandle file, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size, size_t map_size) { + const bool is_zbic = (nso_header->flags & NsoHeader::Flag_UseZbicCompression) != 0; + + const size_t module_size = static_cast(nso_header->rw_dst_offset) + util::AlignUp(nso_header->rw_size + nso_header->bss_size, os::MemoryPageSize); + const size_t arena_size = (nso_size > module_size) ? (nso_size - module_size) : 0; + + /* Map and read data from file. */ + { + /* Map the process memory. */ + void *mapped_memory = nullptr; + R_TRY(os::MapProcessMemory(std::addressof(mapped_memory), process_handle, nso_address, map_size, GenerateSecureRandom)); + ON_SCOPE_EXIT { os::UnmapProcessMemory(mapped_memory, process_handle, nso_address, map_size); }; + + const uintptr_t map_address = reinterpret_cast(mapped_memory); + const uintptr_t map_end = map_address + map_size; + + /* Load NSO segments. */ + R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Text].file_offset, nso_header->text_compressed_size, nso_header->text_size, + (nso_header->flags & NsoHeader::Flag_CompressedText) != 0, is_zbic, map_address + nso_header->text_dst_offset, map_end)); + R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Ro].file_offset, nso_header->ro_compressed_size, nso_header->ro_size, + (nso_header->flags & NsoHeader::Flag_CompressedRo) != 0, is_zbic, map_address + nso_header->ro_dst_offset, map_end)); + R_TRY(LoadAutoLoadModuleSegment(file, nso_header->segments[NsoHeader::Segment_Rw].file_offset, nso_header->rw_compressed_size, nso_header->rw_size, + (nso_header->flags & NsoHeader::Flag_CompressedRw) != 0, is_zbic, map_address + nso_header->rw_dst_offset, map_end)); + + /* Clear unused space to zero. */ + const size_t text_end = static_cast(nso_header->text_dst_offset) + static_cast(nso_header->text_size); + const size_t ro_end = static_cast(nso_header->ro_dst_offset) + static_cast(nso_header->ro_size); + const size_t rw_end = static_cast(nso_header->rw_dst_offset) + static_cast(nso_header->rw_size); + std::memset(reinterpret_cast(map_address + text_end), 0, nso_header->ro_dst_offset - text_end); + std::memset(reinterpret_cast(map_address + ro_end), 0, nso_header->rw_dst_offset - ro_end); + std::memset(reinterpret_cast(map_address + rw_end), 0, nso_size - rw_end); + + /* Check segment hashes. */ + R_TRY(CheckSegmentHash(nso_header, map_address, NsoHeader::Segment_Text)); + R_TRY(CheckSegmentHash(nso_header, map_address, NsoHeader::Segment_Ro)); + R_TRY(CheckSegmentHash(nso_header, map_address, NsoHeader::Segment_Rw)); + + /* Apply embedded patches. */ + ApplyEmbeddedPatchesToModule(nso_header->module_id, map_address, nso_size); + + /* Apply IPS patches. */ + LocateAndApplyIpsPatchesToModule(nso_header->module_id, map_address, nso_size); + + /* Apply PCV and PTM patches */ + if (g_is_pcv) { + const size_t text_end = static_cast(nso_header->text_size); + const size_t rx_end = util::AlignUp(text_end, os::MemoryPageSize); + const size_t ro_start = static_cast(nso_header->ro_dst_offset); + const size_t cave_end = (rx_end < ro_start) ? rx_end : ro_start; + const uintptr_t cave = map_address + text_end; + const size_t cave_size = (cave_end > text_end) ? (cave_end - text_end) : 0; + + /* module_size is used rather than nso_size to exclude the extra data section. */ + hoc::pcv::Patch(map_address, module_size, cave, cave_size, nso_address, arena_size ? (map_address + module_size) : 0); + } + + if (g_is_ptm) { + hoc::ptm::Patch(map_address, nso_size); + } + } + + /* Set permissions. */ + const size_t text_size = util::AlignUp(nso_header->text_size, os::MemoryPageSize); + const size_t ro_size = util::AlignUp(nso_header->ro_size, os::MemoryPageSize); + const size_t rw_size = util::AlignUp(nso_header->rw_size + nso_header->bss_size, os::MemoryPageSize) + arena_size; + if (text_size) { + const bool prevent_code_reads = (nso_header->flags & NsoHeader::Flag_PreventCodeReads); + R_TRY(os::SetProcessMemoryPermission(process_handle, nso_address + nso_header->text_dst_offset, text_size, prevent_code_reads ? os::MemoryPermission_ExecuteOnly : os::MemoryPermission_ReadExecute)); + } + if (ro_size) { + R_TRY(os::SetProcessMemoryPermission(process_handle, nso_address + nso_header->ro_dst_offset, ro_size, os::MemoryPermission_ReadOnly)); + } + if (rw_size) { + R_TRY(os::SetProcessMemoryPermission(process_handle, nso_address + nso_header->rw_dst_offset, rw_size, os::MemoryPermission_ReadWrite)); + } + + R_SUCCEED(); + } + + Result LoadAutoLoadModules(const ProcessInfo *process_info, const AutoLoadModuleContext &ctx, const ArgumentStore::Entry *argument) { + /* Load each NSO. */ + const uintptr_t total_end = process_info->code_address + process_info->total_size; + + for (int i = 0; i < ctx.nso_count; i++) { + const NsoIndex nso_idx = static_cast(ctx.ali.nso_indices[i]); + const bool is_zbic = (ctx.headers[i].flags & NsoHeader::Flag_UseZbicCompression) != 0; + const size_t map_size = is_zbic ? (total_end - process_info->nso_address[i]) : process_info->nso_size[i]; + + AMS_LOG("[ldr] module[%d]: idx=%d, path='%s', zbic=%d\n", i, (int)nso_idx, GetNsoPath(nso_idx), is_zbic); + + fs::FileHandle file; + R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(nso_idx), fs::OpenMode_Read)); + ON_SCOPE_EXIT { fs::CloseFile(file); }; + + R_TRY(LoadAutoLoadModule(process_info->process_handle, file, ctx.headers + i, + process_info->nso_address[i], process_info->nso_size[i], map_size)); + } + + /* Load arguments, if present. */ + if (argument != nullptr) { + /* Write argument data into memory. */ + { + void *map_address = nullptr; + R_TRY(os::MapProcessMemory(std::addressof(map_address), process_info->process_handle, process_info->args_address, process_info->args_size, GenerateSecureRandom)); + ON_SCOPE_EXIT { os::UnmapProcessMemory(map_address, process_info->process_handle, process_info->args_address, process_info->args_size); }; + + ProgramArguments *args = static_cast(map_address); + std::memset(args, 0, sizeof(*args)); + args->allocated_size = process_info->args_size; + args->arguments_size = argument->argument_size; + std::memcpy(args->arguments, argument->argument, argument->argument_size); + } + + /* Set argument region permissions. */ + /* NOTE: Nintendo uses svc::SetProcessMemoryPermission directly here. */ + R_TRY(os::SetProcessMemoryPermission(process_info->process_handle, process_info->args_address, process_info->args_size, os::MemoryPermission_ReadWrite)); + } + + R_SUCCEED(); + } + + Result CreateProcessAndLoadAutoLoadModules(ProcessInfo *out, const Meta *meta, const AutoLoadModuleContext &ctx, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) { + /* Get CreateProcessParameter. */ + svc::CreateProcessParameter param; + R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, resource_limit)); + + /* Decide on an NSO layout. */ + R_TRY(DecideAddressSpaceLayout(out, std::addressof(param), ctx, argument)); + + /* Actually create process. */ + svc::Handle process_handle; + R_TRY(svc::CreateProcess(std::addressof(process_handle), std::addressof(param), static_cast(meta->aci_kac), meta->aci->kac_size / sizeof(u32))); + + /* Set the output handle, and ensure that if we fail after this point we clean it up. */ + out->process_handle = process_handle; + out->code_address = param.code_address; + ON_RESULT_FAILURE { R_DISCARD(svc::CloseHandle(process_handle)); }; + + /* Load all auto load modules. */ + R_RETURN(LoadAutoLoadModules(out, ctx, argument)); + } + + } + + /* Process Creation API. */ + Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, const ldr::ProgramAttributes &attrs) { + /* Mount code. */ + AMS_UNUSED(path); + ScopedCodeMountForCode mount(loc, override_status, attrs); + R_TRY(mount.GetResult()); + + /* Load meta, possibly from cache. */ + Meta meta; + R_TRY(LoadMetaFromCache(std::addressof(meta), loc, override_status, attrs.platform)); + + /* Validate meta. */ + R_TRY(ValidateMeta(std::addressof(meta), loc, mount.GetCodeVerificationData())); + + /* If we should, load/validate the browser core dll. */ + util::optional bdll_mount; + if ((meta.acid->flags & Acid::AcidFlag_LoadBrowserCoreDll)) { + /* NOTE: I'm unsure whether we should be getting a fresh override status (allowing for different override between main and bdll?) */ + /* or whether we should be using the main override status. Going to go with main, for sanity's sake. */ + /* Also noting that Nintendo always passes ProgramAttributes=0 here, but this "should" be different on Ounce? */ + /* Kind of unclear how to handle this without knowing what exactly is being ifdef'd. */ + const ncm::ProgramLocation bdll_loc = ncm::ProgramLocation::Make(ncm::SystemProgramId::BrowserCoreDll, ncm::StorageId::BuiltInSystem); + const cfg::OverrideStatus bdll_override_status = override_status; + const ldr::ProgramAttributes bdll_attrs = attrs; + bdll_mount.emplace(bdll_loc, bdll_override_status, bdll_attrs); + R_TRY(bdll_mount->GetResult()); + + /* Load browser dll meta, possibly from cache. */ + Meta bdll_meta; + R_TRY(LoadMetaFromCacheForBrowserCoreDll(std::addressof(bdll_meta), bdll_loc, bdll_override_status, bdll_attrs.platform)); + + /* Validate browser dll meta. */ + R_TRY(ValidateMeta(std::addressof(bdll_meta), loc, mount.GetCodeVerificationData())); + } + + /* Load, validate NSO headers. */ + AutoLoadModuleContext ctx; + R_TRY(LoadAutoLoadHeaders(ctx, meta.acid->flags)); + R_TRY(CheckAutoLoad(ctx, meta.acid->flags)); + + /* Actually create the process and load NSOs into process memory. */ + ProcessInfo info; + R_TRY(CreateProcessAndLoadAutoLoadModules(std::addressof(info), std::addressof(meta), ctx, argument, flags, resource_limit)); + + /* Register NSOs with the RoManager. */ + { + /* Nintendo doesn't validate this get, but we do. */ + os::ProcessId process_id = os::GetProcessId(info.process_handle); + + /* Register new process. */ + const auto as_type = GetProcessAddressSpace(std::addressof(meta)); + RoManager::GetInstance().RegisterProcess(pin_id, process_id, meta.aci->program_id, as_type == Npdm::ProcessAddressSpace_64Bit39 || as_type == Npdm::ProcessAddressSpace_64Bit36); + + /* Register all NSOs. */ + for (int i = 0; i < ctx.nso_count; i++) { + RoManager::GetInstance().AddNso(pin_id, ctx.headers[i].module_id, info.nso_address[i], info.nso_size[i]); + } + } + + /* If we're overriding for HBL, perform HTML document redirection. */ + if (override_status.IsHbl()) { + /* Don't validate result, failure is okay. */ + R_DISCARD(RedirectHtmlDocumentPathForHbl(loc)); + } + + /* Clear the external code for the program. */ + fssystem::DestroyExternalCode(loc.program_id); + + /* Note that we've created the program. */ + SetLaunchedBootProgram(loc.program_id); + + /* Move the process handle to output. */ + *out = info.process_handle; + + R_SUCCEED(); + } + + Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc, const char *path, const ldr::ProgramAttributes &attrs) { + Meta meta; + + /* Load Meta. */ + { + AMS_UNUSED(path); + + ScopedCodeMountForCode mount(loc, attrs); + R_TRY(mount.GetResult()); + R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus(), attrs.platform, false)); + if (out_status != nullptr) { + *out_status = mount.GetOverrideStatus(); + } + } + + return GetProgramInfoFromMeta(out, std::addressof(meta)); + } + + Result PinProgram(PinId *out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status) { + R_UNLESS(RoManager::GetInstance().Allocate(out_id, loc, override_status), ldr::ResultMaxProcess()); + R_SUCCEED(); + } + + Result UnpinProgram(PinId id) { + R_UNLESS(RoManager::GetInstance().Free(id), ldr::ResultNotPinned()); + R_SUCCEED(); + } + + Result GetProcessModuleInfo(u32 *out_count, ldr::ModuleInfo *out, size_t max_out_count, os::ProcessId process_id) { + R_UNLESS(RoManager::GetInstance().GetProcessModuleInfo(out_count, out, max_out_count, process_id), ldr::ResultNotPinned()); + R_SUCCEED(); + } + + Result GetProgramLocationAndOverrideStatusFromPinId(ncm::ProgramLocation *out, cfg::OverrideStatus *out_status, PinId pin_id) { + R_UNLESS(RoManager::GetInstance().GetProgramLocationAndStatus(out, out_status, pin_id), ldr::ResultNotPinned()); + R_SUCCEED(); + } + +} diff --git a/Source/hoc-clk/build.sh b/Source/hoc-clk/build.sh old mode 100644 new mode 100755 index dea28f0b..bd03f5e2 --- a/Source/hoc-clk/build.sh +++ b/Source/hoc-clk/build.sh @@ -4,12 +4,21 @@ set -e ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" DIST_DIR="$ROOT_DIR/dist" CORES="$(nproc --all)" +OVERLAY_DEBUG=0 -if [[ -n "$1" ]]; then - DIST_DIR="$1" -fi +for arg in "$@"; do + case "$arg" in + -d|--debug) + OVERLAY_DEBUG=1 + ;; + "") + ;; + *) + DIST_DIR="$arg" + ;; + esac +done -echo echo "*** Compiling hoc-clk ***" TITLE_ID="$(grep -oP '"title_id":\s*"0x\K(\w+)' "$ROOT_DIR/sysmodule/perms.json")" @@ -25,7 +34,7 @@ cp -vf "$ROOT_DIR/sysmodule/toolbox.json" "$DIST_DIR/atmosphere/contents/$TITLE_ echo echo "*** Compiling hoc-clk-overlay ***" pushd "$ROOT_DIR/overlay" -make -j$CORES +make -j$CORES OVERLAY_DEBUG=$OVERLAY_DEBUG popd > /dev/null mkdir -p "$DIST_DIR/switch/.overlays" @@ -34,7 +43,11 @@ echo echo "*** Copying assets ***" 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/templates/settings.ini.template" "$DIST_DIR/config/horizon-oc/settings.ini.template" +mkdir -p "$DIST_DIR/config/horizon-oc/kip" +cp -vf "$ROOT_DIR/templates/kip/current.ini.template" "$DIST_DIR/config/horizon-oc/kip/current.ini.template" +mkdir -p "$DIST_DIR/config/horizon-oc/profiles" +cp -vf "$ROOT_DIR/templates/profiles/README.ini" "$DIST_DIR/config/horizon-oc/profiles/README.ini" mkdir -p "$DIST_DIR/config/ultrahand/assets/notifications" cp -vf "$ROOT_DIR/assets/hoc.rgba" "$DIST_DIR/config/ultrahand/assets/notifications/hoc.rgba" diff --git a/Source/hoc-clk/common/include/hocclk/board.h b/Source/hoc-clk/common/include/hocclk/board.h index 944e7271..ad04100b 100644 --- a/Source/hoc-clk/common/include/hocclk/board.h +++ b/Source/hoc-clk/common/include/hocclk/board.h @@ -31,6 +31,7 @@ #include #include #include + typedef enum { HocClkSocType_Erista = 0, // T210, found in Icosa and Copper @@ -92,6 +93,7 @@ typedef enum HocClkThermalSensor_PLLX, // PLLX temperature in millicelcius HocClkThermalSensor_AO, // AOTAG HocClkThermalSensor_BQ24193, // BQ24193 temperature. Refer to BQ24193Temp for returned values + HocClkThermalSensor_DRAM, // DRAM die temperature from LPDDR4(X) MR4. Use in combination with PCB and AO to get accurate reading HocClkThermalSensor_EnumMax } HocClkThermalSensor; @@ -141,6 +143,12 @@ enum { DVFSMode_EnumMax, }; +enum { + CPUDVFSMode_Disabled = 0, + CPUDVFSMode_Modify, // LUT Modify dvfs + CPUDVFSMode_EnumMax, +}; + typedef enum { GpuSchedulingMode_DoNotOverride = 0, GpuSchedulingMode_Enabled, @@ -162,6 +170,7 @@ typedef enum { typedef enum { RamDisplayMode_VDD2 = 0, RamDisplayMode_VDDQ, + RamDisplayMode_VDD2VDDQ, RamDisplayMode_EnumMax, } RamDisplayMode; @@ -288,6 +297,8 @@ static inline const char* hocclkFormatThermalSensor(HocClkThermalSensor thermSen return pretty ? "AO" : "ao"; case HocClkThermalSensor_BQ24193: return pretty ? "BQ24193" : "bq24193"; + case HocClkThermalSensor_DRAM: + return pretty ? "DRAM" : "dram"; default: return "unknown"; } diff --git a/Source/hoc-clk/common/include/hocclk/clock_manager.h b/Source/hoc-clk/common/include/hocclk/clock_manager.h index fcc8ec2b..73978ec2 100644 --- a/Source/hoc-clk/common/include/hocclk/clock_manager.h +++ b/Source/hoc-clk/common/include/hocclk/clock_manager.h @@ -70,7 +70,6 @@ typedef struct { GpuSchedulingMode gpuSchedulingMode; bool isSysDockInstalled; bool isSaltyNXInstalled; - bool isUsingRetroSuper; u8 maxDisplayFreq; u8 dramID; bool isDram8GB; @@ -83,9 +82,11 @@ typedef struct { u16 kipVersion; bool isKipLoaded; bool rebootRequired; - + bool isFirstLoad; + + bool isWdtEnabled; // Reserved for future use - u8 reserved[0x359]; + u8 reserved[0x358]; } HocClkContext; typedef struct @@ -100,4 +101,4 @@ typedef struct #define HOCCLK_GLOBAL_PROFILE_TID 0xA111111111111111 -static_assert(sizeof(HocClkContext) == 0x500); \ No newline at end of file +static_assert(sizeof(HocClkContext) == 0x500); diff --git a/Source/hoc-clk/common/include/hocclk/config.h b/Source/hoc-clk/common/include/hocclk/config.h index cbf37c06..f72a18b6 100644 --- a/Source/hoc-clk/common/include/hocclk/config.h +++ b/Source/hoc-clk/common/include/hocclk/config.h @@ -52,8 +52,12 @@ typedef enum { HocClkConfigValue_OverwriteRefreshRate, HocClkConfigValue_MaxDisplayClockH, - HocClkConfigValue_DVFSMode, - HocClkConfigValue_DVFSOffset, + HocClkConfigValue_GPUDVFSMode, + HocClkConfigValue_GPUDVFSOffset, + + HocClkConfigValue_CPUDVFSMode, + HocClkConfigValue_CPUDVFSOffset, + HocClkConfigValue_LiveCpuUv, HocClkConfigValue_EnableExperimentalSettings, @@ -62,6 +66,9 @@ typedef enum { HocClkConfigValue_RAMVoltDisplayMode, HocClkConfigValue_CpuGovernorMinimumFreq, + HocClkConfigValue_GovernorPollRateMs, + HocClkConfigValue_GovernorDownHoldTicks, + HocClkConfigValue_GovernorStepUtil, HocClkConfigValue_DisplayVoltage, HocClkConfigValue_MemoryFrequencyMeasurementMode, @@ -72,9 +79,10 @@ typedef enum { HocClkConfigValue_MarikoMiddleFreqs, HocClkConfigValue_LiveGpuVoltage, - HocClkConfigValue_AutoRAMCPUOverclock, - HocClkConfigValue_AutoRamCpuCpuOCFreq, - HocClkConfigValue_AutoRamCpuRamOCThreshold, + HocClkConfigValue_Watchdog, + + HocClkConfigValue_FileLogging, + HocClkConfigValue_UartLogging, KipConfigValue_custRev, KipConfigValue_KipVersion, @@ -167,6 +175,7 @@ typedef enum { KipConfigValue_g_volt_1459200, KipConfigValue_g_volt_1497600, KipConfigValue_g_volt_1536000, + KipConfigValue_g_volt_1574400, KipConfigValue_g_volt_e_76800, KipConfigValue_g_volt_e_115200, @@ -228,6 +237,8 @@ typedef enum { KipConfigValue_t6_tRTW_fine_tune, KipConfigValue_t7_tWTR_fine_tune, + KipConfigValue_PcvDebugVerbosity, + KipCrc32, HocClkConfigValue_EnumMax, } HocClkConfigValue; @@ -280,11 +291,17 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case HocClkConfigValue_MaxDisplayClockH: return pretty ? "Max Display Clock (Handheld)" : "drr_max_clock"; - case HocClkConfigValue_DVFSMode: - return pretty ? "DVFS Mode" : "dvfs_mode"; + case HocClkConfigValue_GPUDVFSMode: + return pretty ? "GPU DVFS Mode" : "dvfs_mode"; - case HocClkConfigValue_DVFSOffset: - return pretty ? "DVFS Offset" : "dvfs_offset"; + case HocClkConfigValue_GPUDVFSOffset: + return pretty ? "GPU DVFS Offset" : "dvfs_offset"; + + case HocClkConfigValue_CPUDVFSMode: + return pretty ? "CPU DVFS Mode" : "cpu_dvfs_mode"; + + case HocClkConfigValue_CPUDVFSOffset: + return pretty ? "CPU DVFS Offset" : "cpu_dvfs_offset"; case HocClkConfigValue_GPUScheduling: return pretty ? "GPU Scheduling" : "gpu_scheduling"; @@ -302,6 +319,12 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr return pretty ? "RAM Voltage / Usage Display Mode" : "ram_volt_usage_display_mode"; case HocClkConfigValue_CpuGovernorMinimumFreq: return pretty ? "CPU Governor Minimum Frequency" : "cpu_gov_min_freq"; + case HocClkConfigValue_GovernorPollRateMs: + return pretty ? "Governor Poll Rate" : "gov_poll_rate_ms"; + case HocClkConfigValue_GovernorDownHoldTicks: + return pretty ? "Governor Down Hold" : "gov_down_hold_ticks"; + case HocClkConfigValue_GovernorStepUtil: + return pretty ? "Governor Step Divisor" : "gov_step_util"; case HocClkConfigValue_DisplayVoltage: return pretty ? "Display Voltage" : "display_voltage"; @@ -319,13 +342,13 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case HocClkConfigValue_LiveGpuVoltage: return pretty ? "GPU Voltage Request" : "gpu_voltage_request"; - case HocClkConfigValue_AutoRAMCPUOverclock: - return pretty ? "Auto High RAM CPU OC" : "auto_high_ram_cpu_oc"; - case HocClkConfigValue_AutoRamCpuCpuOCFreq: - return pretty ? "Auto High RAM CPU OC Freq" : "auto_ram_cpu_cpu_oc_freq"; - case HocClkConfigValue_AutoRamCpuRamOCThreshold: - return pretty ? "Auto High RAM CPU OC RAM Threshold" : "auto_ram_cpu_ram_oc_threshold"; + case HocClkConfigValue_Watchdog: + return pretty ? "Watchcat" : "watchdog"; // More dignified + case HocClkConfigValue_FileLogging: + return pretty ? "File Logging" : "file_logging"; + case HocClkConfigValue_UartLogging: + return pretty ? "UART Logging" : "uart_logging"; // KIP config values case KipConfigValue_custRev: return pretty ? "Custom Revision" : "kip_cust_rev"; @@ -387,7 +410,7 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case KipConfigValue_low_t7_tWTR: return pretty ? "Low T7 - tWTR" : "low_t7_tWTR"; case KipConfigValue_low_t8_tREFI: - return pretty ? "Low T8 - tREFI" : "low_t7_tREFI"; + return pretty ? "Low T8 - tREFI" : "low_t8_tREFI"; case KipConfigValue_read_latency_1333: return pretty ? "1333 Read Latency" : "read_latency_1333"; @@ -481,6 +504,7 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case KipConfigValue_g_volt_1459200: return pretty ? "Mariko GPU Volt 1459 MHz" : "g_volt_1459200"; case KipConfigValue_g_volt_1497600: return pretty ? "Mariko GPU Volt 1497 MHz" : "g_volt_1497600"; case KipConfigValue_g_volt_1536000: return pretty ? "Mariko GPU Volt 1536 MHz" : "g_volt_1536000"; + case KipConfigValue_g_volt_1574400: return pretty ? "Mariko GPU Volt 1574 MHz" : "g_volt_1574400"; // Erista GPU voltages (27) case KipConfigValue_g_volt_e_76800: return pretty ? "Erista GPU Volt 76 MHz" : "g_volt_e_76800"; @@ -512,7 +536,7 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr 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_tune"; case KipConfigValue_t7_tWTR_fine_tune: return pretty ? "t7 - tWTR Fine Tune" : "t7_tWTR_fine_tune"; - + case KipConfigValue_PcvDebugVerbosity: return pretty ? "Pcv Debug Verbosity" : "debug_verbosity"; case KipConfigValue_g_soc_volt_1866000: return pretty ? "Mariko SOC Volt 1866 MHz" : "g_soc_volt_1866000"; case KipConfigValue_g_soc_volt_2000000: return pretty ? "Mariko SOC Volt 2000 MHz" : "g_soc_volt_2000000"; case KipConfigValue_g_soc_volt_2133000: return pretty ? "Mariko SOC Volt 2133 MHz" : "g_soc_volt_2133000"; @@ -551,6 +575,11 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr } } +static inline bool hocclkIsKipConfigValue(HocClkConfigValue val) +{ + return val >= KipConfigValue_custRev && val <= KipCrc32; +} + static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val) { switch(val) @@ -572,6 +601,8 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val) case HocClkConfigValue_MemoryFrequencyMeasurementMode: case HocClkConfigValue_MarikoMiddleFreqs: case HocClkConfigValue_LiveGpuVoltage: + case HocClkConfigValue_FileLogging: + case HocClkConfigValue_UartLogging: return 0ULL; case HocClkConfigValue_RamDisplayUnit: return (uint64_t)RamDisplayUnit_MHz; @@ -583,17 +614,19 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val) case HocClkConfigValue_ThermalThrottle: case HocClkConfigValue_IsFirstLoad: - case HocClkConfigValue_DVFSMode: - case HocClkConfigValue_AutoRAMCPUOverclock: + case HocClkConfigValue_GPUDVFSMode: + case HocClkConfigValue_CPUDVFSMode: return 1ULL; - case HocClkConfigValue_AutoRamCpuCpuOCFreq: - return 1683000ULL; - case HocClkConfigValue_AutoRamCpuRamOCThreshold: - return 2666000ULL; case HocClkConfigValue_ThermalThrottleThreshold: return 70ULL; case HocClkConfigValue_CpuGovernorMinimumFreq: return 612000000ULL; // 612MHz + case HocClkConfigValue_GovernorPollRateMs: + return 5ULL; // 5ms + case HocClkConfigValue_GovernorDownHoldTicks: + return 10ULL; // 10 ticks (50ms at 5ms poll) + case HocClkConfigValue_GovernorStepUtil: + return 900ULL; // max freq at 90% load case HocClkConfigValue_MaxDisplayClockH: return 60ULL; case HocClkConfigValue_DisplayVoltage: @@ -630,7 +663,10 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case HocClkConfigValue_GPUSchedulingMethod: case HocClkConfigValue_MarikoMiddleFreqs: case HocClkConfigValue_LiveGpuVoltage: - case HocClkConfigValue_AutoRAMCPUOverclock: + case HocClkConfigValue_Watchdog: + case HocClkConfigValue_FileLogging: + case HocClkConfigValue_UartLogging: + case KipConfigValue_eristaCpuUnlock: return (input & 0x1) == input; case KipConfigValue_KipVersion: @@ -710,6 +746,7 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case KipConfigValue_g_volt_1459200: case KipConfigValue_g_volt_1497600: case KipConfigValue_g_volt_1536000: + case KipConfigValue_g_volt_1574400: case KipConfigValue_g_volt_e_76800: case KipConfigValue_g_volt_e_115200: case KipConfigValue_g_volt_e_153600: @@ -766,24 +803,33 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case KipConfigValue_g_soc_volt_3266000: case KipConfigValue_g_soc_volt_3333000: case KipConfigValue_eristaCpuVmin: - case KipConfigValue_eristaCpuUnlock: case KipConfigValue_t6_tRTW_fine_tune: case KipConfigValue_t7_tWTR_fine_tune: case KipCrc32: - case HocClkConfigValue_DVFSMode: - case HocClkConfigValue_DVFSOffset: + case HocClkConfigValue_GPUDVFSMode: + case HocClkConfigValue_GPUDVFSOffset: + case HocClkConfigValue_CPUDVFSMode: + case HocClkConfigValue_CPUDVFSOffset: case HocClkConfigValue_GPUScheduling: case HocClkConfigValue_RAMVoltDisplayMode: case HocClkConfigValue_CpuGovernorMinimumFreq: case HocClkConfigValue_MemoryFrequencyMeasurementMode: case HocClkConfigValue_RamDisplayUnit: case HocClkConfigValue_AulaDisplayColorPreset: - case HocClkConfigValue_AutoRamCpuCpuOCFreq: - case HocClkConfigValue_AutoRamCpuRamOCThreshold: + case KipConfigValue_PcvDebugVerbosity: return true; case HocClkConfigValue_BatteryChargeCurrent: return ((input >= 1024) && (input <= 3072)) || !input; + case HocClkConfigValue_GovernorPollRateMs: + return ((input >= 1) && (input <= 50)); + + case HocClkConfigValue_GovernorDownHoldTicks: + return (input <= 100); + + case HocClkConfigValue_GovernorStepUtil: + return ((input >= 100) && (input <= 1500)); + case HocClkConfigValue_InputCurrentLimit: return ((input >= 100) && (input <= 3000)) || !input; diff --git a/Source/hoc-clk/config.ini.template b/Source/hoc-clk/config.ini.template deleted file mode 100644 index 4305c725..00000000 --- a/Source/hoc-clk/config.ini.template +++ /dev/null @@ -1,19 +0,0 @@ -[values] -; Defines how often sys-clk log temperatures, in milliseconds (set 0 to disable) -temp_log_interval_ms=0 -; Defines how often sys-clk writes to the CSV, in milliseconds (set 0 to disable) -csv_write_interval_ms=0 - -; Example #1: BOTW -; Overclock CPU when docked -; Overclock MEM to docked clocks when handheld -;[01007EF00011E000] -;docked_cpu=1224 -;handheld_mem=1600 - -; Example #2: Picross -; Underclock to save battery -;[0100BA0003EEA000] -;handheld_cpu=816 -;handheld_gpu=153 -;handheld_mem=800 \ No newline at end of file diff --git a/Source/hoc-clk/overlay/Makefile b/Source/hoc-clk/overlay/Makefile index 1542d854..63f6f254 100644 --- a/Source/hoc-clk/overlay/Makefile +++ b/Source/hoc-clk/overlay/Makefile @@ -17,15 +17,22 @@ include $(DEVKITPRO)/libnx/switch_rules # INCLUDES is a list of directories containing header files # EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". #--------------------------------------------------------------------------------- +rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) + TARGET := horizon-oc-overlay BUILD := build OUTDIR := out RESOURCES := res -SOURCES := src src/ui/gui src/ui/elements ../common/src ../common/src/client +CSOURCES := $(call rwildcard,src/,*.c) $(call rwildcard,../common/src/,*.c) +CPPSOURCES := $(call rwildcard,src/,*.cpp) $(call rwildcard,../common/src/,*.cpp) +SSOURCES := $(call rwildcard,src/,*.s) $(call rwildcard,../common/src/,*.s) +SOURCES := $(sort $(dir $(CSOURCES) $(CPPSOURCES) $(SSOURCES))) DATA := data ../assets INCLUDES := ../common/include EXEFS_SRC := exefs_src IS_MINIMAL := 0 +OVERLAY_DEBUG ?= 0 + APP_TITLE := Horizon OC NO_ICON := 1 @@ -46,6 +53,9 @@ TARGET_VERSION := $(APP_VERSION) # options for code generation #--------------------------------------------------------------------------------- DEFINES := -DDISABLE_IPC -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_VERSION)\"" -DIS_MINIMAL=$(IS_MINIMAL) +ifeq ($(OVERLAY_DEBUG),1) + DEFINES += -DOVERLAY_DEBUG +endif ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE @@ -69,7 +79,7 @@ CXXFLAGS := $(CFLAGS) -fno-exceptions -std=gnu++23 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,__cxa_throw -Wl,-wrap,_Unwind_Resume -Wl,-wrap,__gxx_personality_v0 -LIBS := -lcurl -lz -lminizip -lmbedtls -lmbedx509 -lmbedcrypto -ljansson -lnx +LIBS := -lcurl -lz -lminizip -lnx #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/Source/hoc-clk/overlay/lang/pt.json b/Source/hoc-clk/overlay/lang/pt.json index 86b7dea1..ce85cd59 100644 --- a/Source/hoc-clk/overlay/lang/pt.json +++ b/Source/hoc-clk/overlay/lang/pt.json @@ -2,228 +2,286 @@ "Information": "Informação", "Unknown": "Desconhecido", "Installed": "Instalado", - "Not Installed": "Não instalado", + "Not Installed": "Ausente", "Default": "Padrão", - "Do Not Override": "Não substituir", - "Do not override": "Não substitua", - "Disabled": "Desativado", + "Do Not Override": "", + "Do not override": "Padrão", + "Disabled": "Desabilitado", "Enabled": "Habilitado", - "Enabled (Default)": "Habilitado (padrão)", + "Enabled (Default)": "Habilitado (Padrão)", "Enable": "Habilitar", "Fatal error": "Erro fatal", - "Could not connect to hoc-clk sysmodule.\\n\\n": "Não foi possível conectar-se ao sysmodule hoc-clk.\\n\\n", - "Please make sure everything is\\n\\n": "Verifique se tudo está\\n\\n", - "correctly installed and enabled.": "corretamente instalado e ativado.", + "Could not connect to hoc-clk sysmodule.\\n\\n": "Má conexão com o sysmodule hoc-clk.\\n\\n", + "Please make sure everything is\\n\\n": "Cheque se tudo está corretamente\\n\\n", + "correctly installed and enabled.": "instalado e habilitado", - "Edit App Profile": "Editar perfil do aplicativo", - "Edit Global Profile": "Editar perfil global", - "Temporary Overrides": "Substituições temporárias", - "Temporary Overrides ": "Substituições temporárias", + "Edit App Profile": "Editar perfil do app atual", + "Edit Global Profile": "Editar perfil geral", + "Temporary Overrides": "Editar perfil temporário", + "Temporary Overrides ": "Perfil temporário ", "  Reset": " Redefinir", "Settings": "Configurações", "About": "Sobre", "Credits": "Créditos", "Application changed\\n\\n": "Aplicativo alterado\\n\\n", - "The running application changed\\n\\n": "O aplicativo em execução foi alterado\\n\\n", - "while editing was going on.": "enquanto a edição estava acontecendo.", + "The running application changed\\n\\n": "O app em execução foi alterado\\n\\n", + "while editing was going on.": "enquanto uma edição estava ocorrendo.", - "Sleep Mode": "Modo de suspensão", - "Stock": "Padrão de fábrica", - "Dev OC": "Desenvolvedor OC", - "Boost Mode": "Modo de reforço", - "Safe Max": "Máx. Seguro", - "Unsafe Max": "Máximo inseguro", - "Absolute Max": "Máximo absoluto", - "Handheld Safe Max": "Portátil Seguro Máx.", + "Sleep Mode": "Mod de descanso", + "Stock": "Padrão", + "Dev OC": "Dev OC", + "Boost Mode": "Modo boost", + "Safe Max": "Max. seguro", + "Unsafe Max": "Max. perigoso", + "Absolute Max": "Max. absoluto", + "Handheld Safe Max": "Seguro max. no modo portátil", - "General Settings": "Configurações Gerais", - "Governor Settings": "Configurações do Governador", - "Safety Settings": "Configurações de segurança", - "Save KIP Settings": "Salvar configurações KIP", - "RAM Settings": "Configurações de RAM", - "CPU Settings": "Configurações de CPU", - "GPU Settings": "Configurações de GPU", - "Display Settings": "Configurações de exibição", - "Experimental Settings": "Configurações experimentais", + "General Settings": "Configs gerais", + "Governor Settings": "Configs de Governor", + "Safety Settings": "Configs de segurança", + "RAM Settings": "Configs de RAM", + "CPU Settings": "Configs de CPU", + "GPU Settings": "Configs de GPU", + "Display Settings": "Configs de display", + "Experimental Settings": "Configs experimentais", "Experimental": "Experimental", - " Settings marked in blue": "Configurações marcadas em azul", - "don't require a reboot to apply!": "não requerem reinicialização para aplicar!", - "You can also press  to show": "Pressione também  para mostrar", - "information about each setting.": "informações sobre cada configuração.", + " Settings marked in blue": "Configs marcadas em azul não", + "don't require a reboot to apply!": "precisam de um reboot para aplicar", + "You can also press  to show": "Pressione  para mostrar informações", + "information about each setting.": "sobre cada configuração.", - " Experimental Settings are incomplete ": "Configurações experimentais incompletas", - "and may not work correctly or at all!": "e podem não funcionar corretamente!", - "Here be dragons!": "Aqui há dragões!", + " Experimental Settings are incomplete ": " As configs experimentais estão", + "and may not work correctly or at all!": "incompletas e podem ser instáveis", + "Here be dragons!": "Você foi avisado.", - "RAM Voltage Display Mode": "Modo de exibição de tensão RAM", - "RAM Display Unit": "Unidade de exibição de RAM", - "Polling Interval": "Intervalo de sondagem", + "RAM Voltage Display Mode": "Setor de tensão da RAM exibido", + "RAM Display Unit": "Unidade de exibição da RAM", + "Polling Interval": "Intervado de registro", - "GPU Scheduling Override Method": "Método de substituição de agendamento de GPU", - "GPU Scheduling Override": "Substituição de agendamento de GPU", - "GPU Boot Volt": "Tensão de inicialização da GPU", - "GPU Boot Voltage": "Tensão de inicialização da GPU", - "Memory Frequency Measurement Mode": "Modo de medição de frequência de memória", - " Overriding the charge current": "Substituir a corrente de carga", - "can be dangerous and may cause": "pode ser perigoso e causar", - "damage to your battery or charger!": "danos à sua bateria ou carregador!", - "Charge Current Override": "Substituição de corrente de carga", + "GPU Scheduling Override Method": "Método de substituição de scheduler da GPU", + "GPU Scheduling Override": " Substituição do scheduler da GPU ", + " Overriding the charge current": " Mexer na corrente de carga", + "can be dangerous and may cause": "pode ser perigoso e pode causar", + "damage to your battery or charger!": "danos a sua bateria e carregador!", + "Charge Current Override": "Corrente de carga custom", "Display Color Preset": "Predefinição de cor", "Basic": "Básico", "Saturated": "Saturado", "Washed": "Desbotado", "Natural": "Natural", - "Vivid": "Vívido", + "Vivid": "Vívo", - "CPU Governor Minimum Frequency": "Frequência Mínima do Governador da CPU", - " Usage of unsafe display": "O uso de frequências de tela", - "refresh rates may cause stress": "taxas de atualização podem causar estresse", - "or damage to your display! ": "ou danos ao seu monitor!", - "Proceed at your own risk!": "Prossiga por sua conta e risco!", - "Max Handheld Display": "Visor portátil máximo", - "Max Handheld Display Hz": "Hz máximo em modo portátil", - "Display Clock": "Exibir relógio", - " Adjust the display voltage": "Ajuste a tensão do display", + "CPU Governor Minimum Frequency": "Freq mínima do Governor ", + " Usage of unsafe display": " O uso de freqências de atualização", + "refresh rates may cause stress": "altas podem causar danos temporários", + "or damage to your display! ": "ou permanentes ao seu display!", + "Proceed at your own risk!": "Prossiga, mas você foi avisado.", + "Max Handheld Display": "Max. do display em modo portátil ", + "Max Handheld Display Hz": "Taxa de atualização max. no modo portáril", + "Display Clock": "Clock do display", + " Adjust the display voltage": " Ajuste a tensão do display", "with caution to avoid damage": "com cuidado para evitar danos", - "to your display panel! ": "ao painel do display!", + "to your display panel! ": "permanentes!", "Display Voltage": "Tensão do display", - "Thermal Throttle Limit": "Limite de aceleração térmica", - "Official Rating": "Classificação Oficial", - "TDP Threshold": "Limite de TDP", + "Thermal Throttle Limit": "Limite térmico", "Power": "Potência", "HP Mode": "Modo HP", - "DVB Shift": "Deslocamento DVB", - "SoC Max Volt": "Tensão máxima do SoC", - "Step Mode": "Modo passo", - "RAM VDD2 Voltage": "Tensão RAM VDD2", - "RAM VDDQ Voltage": "Tensão RAM VDDQ", + "DVB Shift": "DVB Shift", + "SoC Max Volt": "vSOC Máximo", + "Step Mode": "Modo de Step", + "RAM VDD2 Voltage": "Tensão VDD2", + "RAM VDDQ Voltage": "Tensão VDDQ", "Voltage": "Tensão", - "RAM Frequency Editor": "Editor de frequência RAM", - "Ram Max Clock": "Frequência máxima de Ram", - "RAM Latency Editor": "Editor de latência de RAM", - "RAM Timing Reductions": "Reduções de tempo de RAM", - "Memory Timings": "Tempos de memória", + "Ram Max Clock": "Clock Max da RAM", + "RAM Latency Editor": "Editor de latências", + "RAM Timing Reductions": "Reducão de latências", + "Memory Timings": "Latências da RAM", "Advanced": "Avançado", - "t6 tRTW Fine Tune": "t6 tRTW Ajuste fino", - "tRTW Fine Tune": "Ajuste fino tRTW", - "t7 tWTR Fine Tune": "t7 tWTR Ajuste fino", - "tWTR Fine Tune": "Ajuste fino tWTR", - "Memory Latencies": "Latências de memória", + "t6 tRTW Fine Tune": "t6 tRTW - Ajuste fino", + "tRTW Fine Tune": "tRTW - Ajuste fino", + "t7 tWTR Fine Tune": "t7 tWTR - Ajuste fino", + "tWTR Fine Tune": "tWTR - Ajuste fino", "Read Latency": "Latência de leitura", - "Write Latency": "Latência de gravação", - "High speedo needed!": "Alto valor de Speedo necessário!", - "3333MHz (Needs extreme Speedo/PLL)": "3333MHz (precisa de Speedo/PLL extremo)", - "3366MHz (Needs extreme Speedo/PLL)": "3366 MHz (precisa de Speedo/PLL extremo)", - "3400MHz (Needs extreme Speedo/PLL)": "3400 MHz (precisa de Speedo/PLL extremo)", - "3433MHz (Needs ridiculous Speedo/PLL)": "3433MHz (precisa de Speedo/PLL ridículo)", - "3466MHz (Needs ridiculous Speedo/PLL)": "3466 MHz (precisa de Speedo/PLL ridículo)", - "3500MHz (Needs ridiculous Speedo/PLL)": "3500 MHz (precisa de Speedo/PLL ridículo)", + "Write Latency": "Latência de escrita", "JEDEC.": "JEDEC.", - "CPU Boost Clock": "Relógio de aumento da CPU", + "CPU Boost Clock": "Clock boost", "CPU UV": "UV da CPU", - "CPU Unlock": "Desbloqueio da CPU", - "CPU VMIN": "CPU VMIN", + "CPU Unlock": "Destrave da CPU", + "CPU VMIN": "CPU vMin", "CPU Max Voltage": "Tensão máxima da CPU", - "CPU Max Clock": "Relógio máximo da CPU", - "Extreme UV Table": "Mesa UV Extrema", - "CPU UV Table": "Tabela UV da CPU", - "CPU Low UV": "UV baixo da CPU", - "CPU High UV": "CPU alta UV", - "CPU Low VMIN": "CPU baixa VMIN", - "CPU High VMIN": "VMIN alto da CPU", + "CPU Max Clock": "Clock máximo da CPU", + "Extreme UV Table": "Tabela Extreme UV", + "CPU UV Table": "Table de UV", + "CPU Low UV": "Low UV da CPU", + "CPU High UV": "High UV da CPU", + "CPU Low VMIN": "Low vMin da CPU", + "CPU High VMIN": "High vMin da CPU", - "No Undervolt": "Sem subtensão", + "No Undervolt": "Sem Undervolt", "SLT Table": "Tabela SLT", "HiOPT Table": "Tabela HiOPT", - "GPU Undervolt Table": "Tabela de subtensão da GPU", + "GPU Undervolt Table": "Tabela de undervolt da GPU", "GPU Minimum Voltage": "Tensão mínima da GPU", - "Calculate GPU Vmin": "Calcular Vmin da GPU", - "GPU VMIN": "GPU VMIN", + "Calculate GPU Vmin": "Tensão mínima calculada", + "GPU VMIN": "GPU vMin", "GPU Maximum Voltage": "Tensão máxima da GPU", - "GPU Voltage Offset": "Compensação de tensão da GPU", - "GPU DVFS Mode": "Modo GPU DVFS", - "GPU DVFS Offset": "Deslocamento DVFS da GPU", + "GPU Voltage Offset": "Offset de tensão", + "GPU DVFS Mode": "Modo de DVFS da GPU", + "GPU DVFS Offset": "Offset de DVFS da GPU", "GPU Voltage Table": "Tabela de tensão da GPU", - "GPU Custom Table (mV)": "Tabela personalizada de GPU (mV)", - "Official Service": "Serviço Oficial", - "96.6% limit": "Limite de 96,6%", - "99.7% limit": "Limite de 99,7%", - " Setting GPU Clocks past": "Definir clocks de GPU além de", - "1228MHz without a proper undervolt": "1228MHz sem undervolt adequado", + "GPU Custom Table (mV)": "Tabela custom da GPU (mV)", + "Official Service": "Padrão Oficial", + "96.6% limit": "Limite de 96.6%", + "99.7% limit": "Limite de 99.7%", + " Setting GPU Clocks past": " Definir os clocks acima de", "can cause degradation or damage": "pode causar degradação ou danos", - "to your console!": "ao seu console!", - "1075MHz without UV, 1152MHz on SLT": "1075 MHz sem UV, 1152 MHz em SLT", - "or 1228MHz on HiOPT can cause ": "ou 1228 MHz em HiOPT pode causar", - "permanent damage to your Switch!": "danos permanentes ao seu Switch!", - "921MHz without UV and 960MHz on": "921 MHz sem UV e 960 MHz ativado", - "SLT or HiOPT can cause ": "SLT ou HiOPT podem causar", + "to your console!": "permanentes ao seu console!", "Default (Mariko)": "Padrão (Mariko)", "Default (Erista)": "Padrão (Erista)", - "Rating": "Avaliação", - "Safe Max (Mariko)": "Máximo Seguro (Mariko)", - "Safe Max (Erista)": "Seguro Max (Erista)", + "Rating": "Padrão NVidia", + "Safe Max (Mariko)": "Max. seguro (Mariko)", + "Safe Max (Erista)": "Max. seguro (Mariko)", "Voltages": "Tensões", - "RAM Voltage:": "Tensão RAM:", - "Display Voltage:": "Tensão do display:", + "RAM Voltage:": "Tensão de RAM", + "Display Voltage:": "Tensão de display", "Temperatures": "Temperaturas", - "PLLX Temp:": "PLLX Temp:", - "AOTAG Temp:": "AOTAG Temp:", - "BQ24193 Temp:": "BQ24193 Temp:", + "PLLX Temp:": "Temp PLLX", + "AOTAG Temp:": "Temp AOTAG", + "BQ24193 Temp:": "Temp BQ24193", "Normal": "Normal", "Warm": "Morno", "Hot": "Quente", - "Overheat": "Superaquecimento", - "Not Patched": "Não corrigido", + "Overheat": "Superaquecido", + "Not Patched": "Sem patch", "Invalid": "Inválido", - "RAM Bandwidth": "Largura de banda RAM", - "RAM BW (Peak):": "BW RAM (Pico):", - "RAM BW (All):": "BW RAM (Total):", - "RAM BW (CPU):": "BW RAM (CPU):", - "RAM BW (GPU):": "BW RAM (GPU):", - "Hardware Info": "Info de hardware", + "RAM Bandwidth": "Largura de banda da RAM", + "RAM BW (Peak):": "RAM BW (Pico):", + "RAM BW (All):": "RAM BW (Geral):", + "RAM BW (CPU):": "RAM BW (CPU):", + "RAM BW (GPU):": "RAM BW (GPU):", + "Hardware Info": "Informação de hardware", "Console Type:": "Tipo de console:", "Speedo:": "Speedo:", "DRAM Module: ": "Módulo DRAM: ", - "Software Info": "Info de software", - "KIP version:": "Versão KIP:", - "sys-dock status:": "status do dock do sistema:", + "Software Info": "Informação de software", + "KIP version:": "Versão do KIP:", + "sys-dock status:": "Status do sys-dock:", "SaltyNX status:": "Status do SaltyNX:", - "RR Display status:": "Status de exibição do RR:", "Wafer Position:": "Posição do wafer:", "IDDQ:": "IDDQ:", - "Module: ": "Módulo:", + "Module: ": "Módulo: ", "Board": "Placa", - "Display": "Exibição", + "Display": "Display", + + "hoc-clk is not running.\\n\\n": "hoc-clk não está funcionando.\\n\\n", + "Please make sure it is correctly\\n\\n": " Verifique se tudo está corretamente\\n\\n", + "installed and enabled.": "instalado e habilitado.", + "Could not connect to hoc-clk.\\n\\n": "Não foi possível conectar com hoc-clk.\\n\\n", + "Overlay not compatible with\\n\\n": "Versão do overlay não é compatível com\\n\\n", + "the running hoc-clk version.\\n\\n": "a versão instalada do hoc-clk.", + "installed and up to date.": "Instalado e atualizado.", + "Install Update": "Instalar atualização", + " (Live)": " (Live)", + "Debug Settings": "Configs de debug", + "VDD2/VDDQ": "VDD2/VDDQ", + "MHz and MT/s": "MHz e MT/s", + "Live GPU Volt Request": "Pedido de tensão de GPU ao vivo", + "NV Service": "Serviço NV", + " Overriding the input current": " Mexer no limite de corrente", + "limit increases power draw from": "de entrada aumenta o consumo total", + "your charger. And board stress ": "do seu carregador e estresse na placa ", + "use 1500mA max.": "Use 1500 mA no máximo", + "Default (Lite)": "Padrão (Lite)", + "Input Current Limit Override": "Subistituição do limite de corrente", + "PCV Log Verbosity": "Verbosity do log de PCV", + "Governor Poll Rate": "Intervalo do Governor", + "Governor Down Hold": "Intervalo baixo do Governor", + "Governor Step Divisor": "Divisor de etapa do Governor", + "SOC Voltage Table": "Tabela de tensão de SOC", + "Timing Presets": "Presets de latência", + "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", + "RAM-Timing tBreak": "tBreak de latências", + "Low t1 tRCD": "Low t1 tRCD", + "Low t2 tRP": "Low t2 tRP", + "Low t3 tRAS": "Low t3 tRAS", + "Low t4 tRRD": "Low t4 tRRD", + "Low t5 tRFC": "Low t5 tRFC", + "Low t6 tRTW": "Low t6 tRTW", + "Low t7 tWTR": "Low t7 tWTR", + "Low t8 tREFI": "Low t8 tREFI", + "Timing Presets: ": "Presets de latência: ", + " Timing presets are only a baseline and": " Os presets de latência são somente", + "may need adjustment for your particular": "uma base e podem precisar de ajustes", + "DRAM Module": "para o seu módulo de RAM em particular", + "Apply Common Preset": "Aplicar o preset comum", + "Apply Super Tight (ST) Preset": "Aplicar o preset Super Tight (ST)", + "Timing presets are not available": "Os presets de latência não estão", + "for your RAM module.": "disponíveis para o seu módulo de RAM", + "Latency Max": "Latência máxima", + "Latency Graph": "Gráfico de latência", + "LUT Modify": "Modificador LUT", + "CPU DVFS Mode": "Modo DVFS da CPU", + "CPU DVFS Offset": "Offset DVFS da CPU", + "HOS Default": "Padrão HOS", + "HOC Default": "Padrão HOC", + "HiOPT - 15mV": "HiOPT - 15mV", + "High UV Table": "Tabela High UV", + "PCV Hijack": "Hijack de PCV", + "SOC Custom Voltages": "Tensão custom do SOC", + "No Override": "Padrão", + "Failed to create thread": "Falha ao criar um thread", + "Download cancelled": "Download cancelado", + "Download failed -- check network": "Falha no donwload -- Cheque a conexão", + "Extraction cancelled": "Extração cancelada", + "Extraction failed -- archive may be corrupt": "Falha na extração -- Arquivo pode estar corrompido", + "Update complete! Restart required.": "Atualização completa! Reinicie o dispositivo.", + "Changelog fetch cancelled": "Procura de changelog cancelada", + "Could not fetch changelog -- check network": "Não foi possível procurar o changelog -- Cheque a conexão", + "Could not parse changelog": "Não foi possível ler o changelog", + "No changelog available for this release.": "Sem changelog disponível para esta versão", + "Updates cannot be performed on a 4MB overlay heap": "Update não pode ser feita em overlays com 4 MB dedicados", + "Fetching changelog...": "Procurando changelog...", + "App ID": "ID de APP", + "USB Charger": "Carregador USB", + "DRAM Temp:": "Temp da DRAM", + "KIP status:": "Status do KIP", + "Watchcat:": "Watchcat", + "General Info": "Informação geral", + " (Cust Rev ": " (Cust Rev ", + "Not Loaded": "Ausente", "Developers": "Desenvolvedores", - "Contributors": "Colaboradores", - "Testers": "Testadores", - "Translators": "Tradutores", + "Contributors": "Contribuidores", + "Testers": "Cobaias", "Special Thanks": "Agradecimentos especiais", - "X: %u Y: %u": "X: %u Y: %u", - "%u.%u%u mV": "%u.%u%u mV", - "Compiling with minimal features": "Compilando com recursos mínimos", - "THE BEER-WARE LICENSE": "A LICENÇA DE CERVEJA", - "Horizon OC\nKip opening failed": "Horizon OC\nFalha ao abrir o KIP", - "Horizon OC\nKip read failed": "Horizon OC\nFalha ao ler o KIP", - "Horizon OC\nOutdated kip detected!\nPlease update Horizon OC": "Horizon OC\nKIP desatualizado detectado!\nAtualize o Horizon OC", - "Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC": "Horizon OC\nSysmodule desatualizado detectado!\nAtualize o Horizon OC", - "Horizon OC\nKip write failed": "Horizon OC\nFalha ao gravar o KIP", - "Horizon OC\nKip config set failed": "Horizon OC\nFalha ao configurar o KIP", - "Kip is not loaded!": "O KIP não está carregado!", - "Horizon OC\nKIP has been updated\nPlease reboot your console": "Horizon OC\nO KIP foi atualizado\nReinicie o console", + "Compiling with minimal features": "Compilado com features mínimas", + "Horizon OC\nKip opening failed": "Horizon OC\nFalha na abertua de KIP", + "Horizon OC\nKip read failed": "Horizon OC\nFalha na leitura", + "Horizon OC\nOutdated kip detected!\nPlease update Horizon OC": "Horizon OC\nKIP desatulizado detectado!\nAtualize o Horizon OC!", + "Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC": "Horizon OC\nSysmodule desatualizado detectado!\nAtualize o Horizon OC!", + "Horizon OC\nKip write failed": "Horizon OC\nFalha na escrita do KIP", + "Horizon OC\nKip config set failed": "Horizon OC\nFalha ao aplicar configurações", + "Kip is not loaded!": "KIP não carregado!", + "Horizon OC\nKIP has been updated\nPlease reboot your console": "Horizon OC\nKIP foi atualizado\nReinicie o dispositivo", "Horizon OC has been installed": "Horizon OC foi instalado", - "Horizon OC\nConfig Buffer Mismatch": "Horizon OC\nIncompatibilidade do buffer de configuração", - "Horizon OC\nDeactivated frequency.\nReboot to apply.": "Horizon OC\nFrequência desativada.\nReinicie para aplicar.", - "Horizon OC\nSecmon read failed!\n This may be a hardware issue!": "Horizon OC\nFalha na leitura do Secmon!\n Isso pode ser um problema de hardware!", - "Horizon OC\nFailed to write I2C\nwhile setting vddq": "Horizon OC\nFalha ao gravar I2C\nao definir VDDQ", - "Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC": "Horizon OC\nVersão do KIP incompatível\nReinstale o Horizon OC" + "Horizon OC\nConfig Buffer Mismatch": "Horizon OC\nBuffer mismatch da config", + "Horizon OC\nDeactivated frequency.\nReboot to apply.": "Horizon OC\nFrequencia desativada.\n Reinicie para aplicar.", + "Horizon OC\nSecmon read failed!\n This may be a hardware issue!": "Horizon OC\nFalha na leitura do Secmon!\nIsso pode ser um problema de hardware!", + "Horizon OC\nFailed to write I2C\nwhile setting vddq": "Horizon OC\nFalha ao escrever no bus I2C\nenquanto configurava o vddq", + "Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC": "Horizon OC\nVersão errada do KIP!\nRe-instale o Horizon OC" } diff --git a/Source/hoc-clk/overlay/lang/ru.json b/Source/hoc-clk/overlay/lang/ru.json index d3b36cb2..19365e69 100644 --- a/Source/hoc-clk/overlay/lang/ru.json +++ b/Source/hoc-clk/overlay/lang/ru.json @@ -7,6 +7,7 @@ "Do Not Override": "Не менять", "No Override": "Не менять", "Do not override": "Не менять", + "Auto": "Авто", "Disabled": "Отключено", "Enabled": "Включено", "Enabled (Default)": "Включено (По умолчанию)", @@ -50,36 +51,37 @@ "Experimental Settings": "Экспериментальные", "Experimental": "Экспериментальный", - " Settings marked in blue": "Настройки помеченные синим", - "don't require a reboot to apply!": "не требуют перезагрузки для применения!", + " Settings marked in blue": " Настройки синего цвета", + "don't require a reboot to apply!": "применяются без перезагрузки!", "You can also press  to show": "Нажмите  для просмотра", - "information about each setting.": "информацию о каждом параметре.", + "information about each setting.": "информации по каждому параметру.", - " Experimental Settings are incomplete ": "Экспериментальные настройки не закончены", - "and may not work correctly or at all!": "и могут не работать правильно или вообще!", - "Here be dragons!": "Здесь будут драконы!", + " Experimental Settings are incomplete ": " Экспериментальные настройки", + "and may not work correctly or at all!": "могут работать плохо или никак.", + "Here be dragons!": "Используйте на свой страх и риск!", - "RAM Voltage Display Mode": "Показ вольтажа RAM", - "RAM Display Unit": "Показ единицы измерения RAM", + "RAM Voltage Display Mode": "Вольтаж RAM (Показываемый)", + "RAM Display Unit": "Единица измерения RAM (Показываемая)", "Polling Interval": "Интервал опроса", "Enable Experimental Settings": "Экспериментальные настройки", "Mariko Middle Clocks": "Средние частоты Mariko", "Live CPU Undervolt": "Андервольт CPU в реальном времени", + "Live GPU Volt Request": "Изменение вольтажей GPU в реальном времени", "GPU Scheduling Override Method": "Метод перезаписи планировщика GPU", "GPU Scheduling Override": "Перезапись планировщика", "GPU Boot Volt": "Вольтаж GPU при загрузке", "GPU Boot Voltage": "Вольтаж GPU при загрузке", "Memory Frequency Measurement Mode": "Режим измерения частоты RAM", - " Overriding the charge current": "Изменение зарядного тока", + " Overriding the charge current": " Изменение зарядного тока", "can be dangerous and may cause": "может быть опасным и может", "damage to your battery or charger!": "повредить аккумулятор или зарядку!", - " Overriding the input current": "Изменение входного тока", - "limit increases power draw from": "повышает потребление от зарядки", - "your charger. And board stress ": "и вызывает напряжение на плате.", + "Charge Current Override": "Перезапись зарядного тока", + " Overriding the input current": " Изменение входного тока", + "limit increases power draw from": "повышает расход от зарядки", + "your charger. And board stress ": "и создаёт нагрузку на плате.", "use 1500mA max.": "Используйте максимум 1500 мА.", "Input Current Limit Override": "Перезапись лимита входного тока", - "Charge Current Override": "Перезапись зарядного тока", "Display Color Preset": "Пресет цвета дисплея", "Basic": "Базовый", "Saturated": "Насыщенный", @@ -88,14 +90,15 @@ "Vivid": "Яркий", "CPU Governor Minimum Frequency": "Минимальная частота говернора CPU", - " Usage of unsafe display": "Использование не безопасной", - "refresh rates may cause stress": "частоты обновления экрана", - "or damage to your display! ": "может повредить ваш экран!", - "Proceed at your own risk!": "Действуйте на свой страх и риск!", + " Usage of unsafe display": " Использование небезопасной", + "refresh rates may cause stress": "частоты обновления экрана может", + "or damage to your display! ": "нагружать или повредить ваш экран!", + "Proceed at your own risk!": "Используйте на свой страх и риск!", "Display Refresh Rate Changing": "Изменение герцовки экрана", + "Max Handheld Display": "Макс. в портативе", "Max Handheld Display Hz": "Макс. в портативе", "Display Clock": "Частота экрана", - " Adjust the display voltage": "Настраивайте вольтаж экрана", + " Adjust the display voltage": " Настраивайте вольтаж экрана", "with caution to avoid damage": "с осторожностью во избежание", "to your display panel! ": "повреждений экрана!", "Display Voltage": "Вольтаж экрана", @@ -120,6 +123,7 @@ "RAM Latency Editor": "Редактор задержек", "RAM Timing Reductions": "Настройка таймингов", "SOC Voltage Table": "Таблица вольтажей SoC", + "SOC Custom Voltages": "Пользовательские вольтажи SoC", "Memory Timings": "Тайминги RAM", "Advanced": "Расширенные", "t6 tRTW Fine Tune": "Точная настройка t6 tRTW", @@ -129,6 +133,15 @@ "Memory Latencies": "Задержки памяти", "Read Latency": "Задержка чтения", "Write Latency": "Задержка записи", + "Latency Graph": "График задержек", + "Latency Max": "Макс. задержка", + "1333 Latency Max": "1333 макс. задержка", + "1600 Latency Max": "1600 макс. задержка", + "1866 Latency Max": "1866 макс. задержка", + "2133 Latency Max": "2133 макс. задержка", + "Read": "Чтение", + "Write": "Запись", + "Same": "Одинаково", "High speedo needed!": "Для высоких speedo", "3333MHz (Needs extreme Speedo/PLL)": "3333 MHz (нужны невероятные speedo/PLL)", "3366MHz (Needs extreme Speedo/PLL)": "3366 MHz (нужны невероятные speedo/PLL)", @@ -139,16 +152,13 @@ "JEDEC.": "JEDEC.", "CPU Boost Clock": "Частота буста", - "Auto CPU RAM OC": "Буст CPU → Разг. RAM", - "Auto CPU RAM OC CPU clock": "Буст CPU: частота CPU", - "Auto CPU RAM OC Threshold": "Буст CPU: порог RAM", "Overwrite Boost Mode": "Перезаписать буст", "CPU UV": "Андервольт CPU", "CPU Unlock": "Разблокировка CPU", "CPU VMIN": "Мин. вольтаж", "CPU Max Voltage": "Макс. вольтаж", "CPU Max Clock": "Макс. частота", - "Extreme UV Table": "Экстримальная", + "Extreme UV Table": "Экстремальная", "CPU UV Table": "Таблица андервольта", "CPU Low UV": "Андервольт нижних частот", "CPU High UV": "Андервольт верхних частот", @@ -173,7 +183,7 @@ "Official Service": "Официальная служба", "96.6% limit": "≤96,6%", "99.7% limit": "≤99,7%", - " Setting GPU Clocks past": "Установка частот GPU выше", + " Setting GPU Clocks past": " Установка частот GPU выше", "1228MHz without a proper undervolt": "1228 МГц без хорошего андервольта", "can cause degradation or damage": "может вызвать деградацию железа", "to your console!": "или повредить вашу консоль!", @@ -213,14 +223,22 @@ "DRAM Module: ": "Модуль DRAM: ", "Software Info": "Информация о программе", "KIP version:": "Версия KIP:", + "KIP status:": "Статус KIP:", "sys-dock status:": "Статус sys-dock:", "SaltyNX status:": "Статус SaltyNX:", "RR Display status:": "Статус RR Display:", "Wafer Position:": "Расположение на «Wafer»:", + "General Info": "Общая информация", "IDDQ:": "IDDQ:", - "Module: ": "Module:", + "Module: ": "Module: ", "Board": "Board", + "Loaded": "Подгружен", + "MEM": "RAM", + "Memory": "RAM", "Display": "Дисплей", + "Governor": "Говернор", + "Releases": "Релизы", + "Status": "Статус", "Developers": "Разработчики", "Contributors": "Внесли вклад", @@ -232,7 +250,7 @@ "%u.%u%u mV": "%u.%u%u мВ", "Compiling with minimal features": "Собрано с урезанием функций", "THE BEER-WARE LICENSE": "BEER-WARE LICENSE", - "Auto": "Авто", + "Horizon OC\nKip opening failed": "Horizon OC\nНе удалось открыть KIP", "Horizon OC\nKip read failed": "Horizon OC\nНе удалось прочитать KIP", "Horizon OC\nOutdated kip detected!\nPlease update Horizon OC": "Horizon OC\nОбнаружен устаревший KIP!\nОбновите Horizon OC", @@ -244,7 +262,7 @@ "Horizon OC has been installed": "Horizon OC установлен", "Horizon OC\nConfig Buffer Mismatch": "Horizon OC\nНесоответствие буфера конфигурации", "Horizon OC\nDeactivated frequency.\nReboot to apply.": "Horizon OC\nЧастота отключена.\nПерезагрузите для применения.", - "Horizon OC\nSecmon read failed!\n This may be a hardware issue!": "Horizon OC\nОшибка чтения Secmon!\n Возможно, проблема с оборудованием!", + "Horizon OC\nSecmon read failed!\n This may be a hardware issue!": "Horizon OC\nОшибка чтения Secmon!\n Возможно, аппаратная проблема!", "Horizon OC\nFailed to write I2C\nwhile setting vddq": "Horizon OC\nОшибка записи I2C\nпри установке VDDQ", - "Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC": "Horizon OC\nНесовпадение версии KIP\nПереустановите Horizon OC" + "Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC": "Horizon OC\nНесоответствие версии KIP\nПереустановите Horizon OC" } diff --git a/Source/hoc-clk/overlay/lang/template.json b/Source/hoc-clk/overlay/lang/template.json index 3d4e5610..ad312a46 100644 --- a/Source/hoc-clk/overlay/lang/template.json +++ b/Source/hoc-clk/overlay/lang/template.json @@ -40,7 +40,6 @@ "General Settings": "", "Governor Settings": "", "Safety Settings": "", - "Save KIP Settings": "", "RAM Settings": "", "CPU Settings": "", "GPU Settings": "", @@ -63,9 +62,6 @@ "GPU Scheduling Override Method": "", "GPU Scheduling Override": "", - "GPU Boot Volt": "", - "GPU Boot Voltage": "", - "Memory Frequency Measurement Mode": "", " Overriding the charge current": "", "can be dangerous and may cause": "", "damage to your battery or charger!": "", @@ -91,8 +87,6 @@ "Display Voltage": "", "Thermal Throttle Limit": "", - "Official Rating": "", - "TDP Threshold": "", "Power": "", "HP Mode": "", @@ -102,7 +96,6 @@ "RAM VDD2 Voltage": "", "RAM VDDQ Voltage": "", "Voltage": "", - "RAM Frequency Editor": "", "Ram Max Clock": "", "RAM Latency Editor": "", "RAM Timing Reductions": "", @@ -112,16 +105,8 @@ "tRTW Fine Tune": "", "t7 tWTR Fine Tune": "", "tWTR Fine Tune": "", - "Memory Latencies": "", "Read Latency": "", "Write Latency": "", - "High speedo needed!": "", - "3333MHz (Needs extreme Speedo/PLL)": "", - "3366MHz (Needs extreme Speedo/PLL)": "", - "3400MHz (Needs extreme Speedo/PLL)": "", - "3433MHz (Needs ridiculous Speedo/PLL)": "", - "3466MHz (Needs ridiculous Speedo/PLL)": "", - "3500MHz (Needs ridiculous Speedo/PLL)": "", "JEDEC.": "", "CPU Boost Clock": "", @@ -154,14 +139,8 @@ "96.6% limit": "", "99.7% limit": "", " Setting GPU Clocks past": "", - "1228MHz without a proper undervolt": "", "can cause degradation or damage": "", "to your console!": "", - "1075MHz without UV, 1152MHz on SLT": "", - "or 1228MHz on HiOPT can cause ": "", - "permanent damage to your Switch!": "", - "921MHz without UV and 960MHz on": "", - "SLT or HiOPT can cause ": "", "Default (Mariko)": "", "Default (Erista)": "", @@ -195,21 +174,101 @@ "KIP version:": "", "sys-dock status:": "", "SaltyNX status:": "", - "RR Display status:": "", "Wafer Position:": "", "IDDQ:": "", "Module: ": "", "Board": "", "Display": "", + "hoc-clk is not running.\\n\\n": "", + "Please make sure it is correctly\\n\\n": "", + "installed and enabled.": "", + "Could not connect to hoc-clk.\\n\\n": "", + "Overlay not compatible with\\n\\n": "", + "the running hoc-clk version.\\n\\n": "", + "installed and up to date.": "", + "Install Update": "", + " (Live)": "", + "Debug Settings": "", + "VDD2/VDDQ": "", + "MHz and MT/s": "", + "Live GPU Volt Request": "", + "NV Service": "", + " Overriding the input current": "", + "limit increases power draw from": "", + "your charger. And board stress ": "", + "use 1500mA max.": "", + "Default (Lite)": "", + "Input Current Limit Override": "", + "PCV Log Verbosity": "", + "Governor Poll Rate": "", + "Governor Down Hold": "", + "Governor Step Divisor": "", + "SOC Voltage Table": "", + "Timing Presets": "", + "t1 tRCD": "", + "t2 tRP": "", + "t3 tRAS": "", + "t4 tRRD": "", + "t5 tRFC": "", + "t6 tRTW": "", + "t7 tWTR": "", + "t8 tREFI": "", + "RAM-Timing tBreak": "", + "Low t1 tRCD": "", + "Low t2 tRP": "", + "Low t3 tRAS": "", + "Low t4 tRRD": "", + "Low t5 tRFC": "", + "Low t6 tRTW": "", + "Low t7 tWTR": "", + "Low t8 tREFI": "", + "Timing Presets: ": "", + " Timing presets are only a baseline and": "", + "may need adjustment for your particular": "", + "DRAM Module": "", + "Apply Common Preset": "", + "Apply Super Tight (ST) Preset": "", + "Timing presets are not available": "", + "for your RAM module.": "", + "Latency Max": "", + "Latency Graph": "", + "LUT Modify": "", + "CPU DVFS Mode": "", + "CPU DVFS Offset": "", + "HOS Default": "", + "HOC Default": "", + "HiOPT - 15mV": "", + "High UV Table": "", + "PCV Hijack": "", + "SOC Custom Voltages": "", + "No Override": "", + "Failed to create thread": "", + "Download cancelled": "", + "Download failed -- check network": "", + "Extraction cancelled": "", + "Extraction failed -- archive may be corrupt": "", + "Update complete! Restart required.": "", + "Changelog fetch cancelled": "", + "Could not fetch changelog -- check network": "", + "Could not parse changelog": "", + "No changelog available for this release.": "", + "Updates cannot be performed on a 4MB overlay heap": "", + "Fetching changelog...": "", + "App ID": "", + "USB Charger": "", + "DRAM Temp:": "", + "KIP status:": "", + "Watchcat:": "", + "General Info": "", + " (Cust Rev ": "", + "Not Loaded": "", + "Developers": "", "Contributors": "", "Testers": "", - "Translators": "", "Special Thanks": "", - "X: %u Y: %u": "", - "%u.%u%u mV": "", "Compiling with minimal features": "", "Horizon OC\nKip opening failed": "", "Horizon OC\nKip read failed": "", diff --git a/Source/hoc-clk/overlay/lang/zh-cn.json b/Source/hoc-clk/overlay/lang/zh-cn.json index 225aaeff..bce28e3f 100644 --- a/Source/hoc-clk/overlay/lang/zh-cn.json +++ b/Source/hoc-clk/overlay/lang/zh-cn.json @@ -35,6 +35,8 @@ "Unsafe Max": "危险最大值", "Absolute Max": "绝对最大值", "Handheld Safe Max": "掌机安全最大值", + "HOS Default": "原厂默认", + "HOC Default": "HOC默认", "General Settings": "通用设置", "Governor Settings": "调频器设置", @@ -147,9 +149,6 @@ "RAM-Timing tBreak": "内存时序切换阈值", "CPU Boost Clock": "CPU加速频率", - "Auto CPU RAM OC": "高内存频率自动提频CPU", - "Auto CPU RAM OC CPU clock": "自动提频CPU频率", - "Auto CPU RAM OC Threshold": "自动提频触发阈值", "Overwrite Boost Mode": "接管系统CPU调度", "CPU UV": "CPU降压", "CPU Unlock": "CPU解锁", @@ -181,7 +180,7 @@ "96.6% limit": "使用率最高96.6%", "99.7% limit": "使用率最高99.7%", " Setting GPU Clocks past": "警告:未进行合理降压的前提下,", - "1305MHz without a proper undervolt": "将GPU频率拉到1228MHz以上(1305MHz),", + "1305MHz without a proper undervolt": "将GPU频率拉到1305MHz以上", "can cause degradation or damage": "会加速硬件老化损耗,", "to your console!": "甚至对主机造成永久性硬件损坏!", "1075MHz without UV, 1152MHz on SLT": "无降压1075MHz,SLT下1152MHz", diff --git a/Source/hoc-clk/overlay/lang/zh-tw.json b/Source/hoc-clk/overlay/lang/zh-tw.json index 7b71ad2a..d791e049 100644 --- a/Source/hoc-clk/overlay/lang/zh-tw.json +++ b/Source/hoc-clk/overlay/lang/zh-tw.json @@ -147,9 +147,6 @@ "RAM-Timing tBreak": "記憶體時序切換閾值", "CPU Boost Clock": "CPU加速頻率", - "Auto CPU RAM OC": "高記憶體頻率自動提頻CPU", - "Auto CPU RAM OC CPU clock": "自動提頻CPU頻率", - "Auto CPU RAM OC Threshold": "自動提頻觸發閾值", "Overwrite Boost Mode": "接管系統CPU調度", "CPU UV": "CPU降壓", "CPU Unlock": "CPU解鎖", diff --git a/Source/hoc-clk/overlay/src/main.cpp b/Source/hoc-clk/overlay/src/main.cpp index 1024dac5..9bf14977 100644 --- a/Source/hoc-clk/overlay/src/main.cpp +++ b/Source/hoc-clk/overlay/src/main.cpp @@ -96,15 +96,17 @@ class AppOverlay : public tsl::Overlay { ""); } - HocClkContext context = {}; - if (R_SUCCEEDED(hocclkIpcGetCurrentContext(&context)) && context.rebootRequired) { - return initially("Horizon OC has been updated.\n\n" - "\n" - "Please reboot your console\n\n" - "to finish applying the update.", - ""); - } - + // #ifndef OVERLAY_DEBUG + // HocClkContext context = {}; + // if (R_SUCCEEDED(hocclkIpcGetCurrentContext(&context)) && context.rebootRequired) { + // return initially("Horizon OC has been updated.\n\n" + // "\n" + // "Please reboot your console\n\n" + // "to finish applying the update.", + // ""); + // } + // #endif + return initially(); } }; diff --git a/Source/hoc-clk/overlay/src/ui/format.h b/Source/hoc-clk/overlay/src/ui/format.h index f8900b06..216bbee6 100644 --- a/Source/hoc-clk/overlay/src/ui/format.h +++ b/Source/hoc-clk/overlay/src/ui/format.h @@ -72,6 +72,49 @@ static inline std::string formatListFreqHzMem(uint32_t hz, RamDisplayUnit unit) return formatListFreqMem(hz / 1000000, unit); } +static inline std::string formatRamModule(uint8_t dramID) { + switch (dramID) { + case 0: return "HB-MGCH 4GB"; + case 4: return "HM-MGCH 6GB"; + case 7: return "HM-MGXX 8GB"; + + case 1: return "NLE 4GB"; + case 2: return "WT:C 4GB"; + + case 3: + case 5 ... 6: return "NEE 4GB"; + + case 8: + case 12: return "AM-MGCJ 4GB"; + case 9: + case 13: return "AM-MGCJ 8GB"; + + case 10: + case 14: return "NME 4GB"; + + case 11: + case 15: return "WT:E 4GB"; + + 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 4GB"; + + case 29 ... 31: return "x267 4GB"; + + case 32 ... 34: return "WT:B 4GB"; + + default: return "Unknown"; + } +} + static inline std::string formatMemClockKhzLabel(uint32_t khz, RamDisplayUnit unit) { uint32_t mhz = khz / 1000; uint32_t mts = khz / 500; diff --git a/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp index 523a8d40..a728757a 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/about_gui.cpp @@ -31,7 +31,6 @@ tsl::elm::ListItem* IddqItem = NULL; tsl::elm::ListItem* DramModule = NULL; tsl::elm::ListItem* sysdockStatusItem = NULL; tsl::elm::ListItem* saltyNXStatusItem = NULL; -tsl::elm::ListItem* RETROStatusItem = NULL; tsl::elm::ListItem* waferCordsItem = NULL; tsl::elm::ListItem* ramVoltItem = NULL; tsl::elm::ListItem* eristaPLLXItem = NULL; @@ -42,8 +41,10 @@ tsl::elm::ListItem* ramBWItemGpu = NULL; tsl::elm::ListItem* ramBWItemMax = NULL; tsl::elm::ListItem* bqtempitem = NULL; tsl::elm::ListItem* aotagTempItem = NULL; +tsl::elm::ListItem* dramTempItem = NULL; tsl::elm::ListItem* cTypeItem = NULL; tsl::elm::ListItem* creditsItem = NULL; +tsl::elm::ListItem* wdtItem = NULL; #define R_ARROW "\u2192" @@ -96,6 +97,10 @@ void AboutGui::listUI() new tsl::elm::ListItem("BQ24193 Temp:"); this->listElement->addItem(bqtempitem); + dramTempItem = + new tsl::elm::ListItem("DRAM Temp:"); + this->listElement->addItem(dramTempItem); + this->listElement->addItem( new tsl::elm::CategoryHeader("RAM Bandwidth") ); @@ -141,12 +146,6 @@ void AboutGui::listUI() new tsl::elm::ListItem("Wafer Position:"); this->listElement->addItem(waferCordsItem); - if(IsHoag()) { - RETROStatusItem = - new tsl::elm::ListItem("RR Display status:"); - this->listElement->addItem(RETROStatusItem); - } - this->listElement->addItem( new tsl::elm::CategoryHeader("Software Info") ); @@ -154,12 +153,16 @@ void AboutGui::listUI() // custRevItem = new tsl::elm::ListItem("CUST revision:"); // this->listElement->addItem(custRevItem); + kipVersionItem = new tsl::elm::ListItem("KIP version:"); this->listElement->addItem(kipVersionItem); kipLoadedItem = new tsl::elm::ListItem("KIP status:"); this->listElement->addItem(kipLoadedItem); + wdtItem = new tsl::elm::ListItem("Watchcat:"); + this->listElement->addItem(wdtItem); + if(!IsHoag()) { sysdockStatusItem = new tsl::elm::ListItem("sys-dock status:"); @@ -191,49 +194,6 @@ void AboutGui::listUI() lastItemName = ""; } -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 4GB"; - case 2: return "WT:C 4GB"; - - case 3: - case 5 ... 6: return "NEE 4GB"; - - case 8: - case 12: return "AM-MGCJ 4GB"; - case 9: - case 13: return "AM-MGCJ 8GB"; - - case 10: - case 14: return "NME 4GB"; - - case 11: - case 15: return "WT:E 4GB"; - - 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 4GB"; - - case 29 ... 31: return "x267 4GB"; - - case 32 ... 34: return "WT:B 4GB"; - - default: return "Unknown"; - } -} - void AboutGui::update() { BaseMenuGui::update(); @@ -255,7 +215,7 @@ void AboutGui::refresh() sprintf(strings[1], "%u/%u/%u", this->context->iddq[HocClkSpeedo_CPU], this->context->iddq[HocClkSpeedo_GPU], this->context->iddq[HocClkSpeedo_SOC]); SpeedoItem->setValue(strings[0]); IddqItem->setValue(strings[1]); - DramModule->setValue(formatRamModule()); + DramModule->setValue(formatRamModule(this->context->dramID)); // custRevItem->setValue(std::to_string(this->context->custRev)); @@ -267,9 +227,6 @@ void AboutGui::refresh() saltyNXStatusItem->setValue(this->context->isSaltyNXInstalled ? "Installed" : "Not Installed"); - if(IsHoag()) - RETROStatusItem->setValue(this->context->isUsingRetroSuper ? "Installed" : "Not Installed"); - sprintf(strings[2], "X: %d Y: %d", this->context->waferX, this->context->waferY); waferCordsItem->setValue(strings[2]); @@ -324,7 +281,12 @@ void AboutGui::refresh() bqtempitem->setValue(strings[10]); + millis = context->temps[HocClkThermalSensor_DRAM]; + sprintf(strings[12], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); + dramTempItem->setValue(strings[12]); + cTypeItem->setValue(hocClkFormatConsoleType(this->context->consoleType, true)); + wdtItem->setValue(context->isWdtEnabled ? "Enabled" : "Disabled"); } class CreditsSubMenu : public AboutGui { diff --git a/Source/hoc-clk/overlay/src/ui/gui/about_gui.h b/Source/hoc-clk/overlay/src/ui/gui/about_gui.h index 49d71d67..27d7f455 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/about_gui.h +++ b/Source/hoc-clk/overlay/src/ui/gui/about_gui.h @@ -36,7 +36,4 @@ public: void listUI() override; void update() override; void refresh() override; - -private: - std::string formatRamModule(); }; \ No newline at end of file diff --git a/Source/hoc-clk/overlay/src/ui/gui/app_profile_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/app_profile_gui.cpp index 7364711e..9781b3ee 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/app_profile_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/app_profile_gui.cpp @@ -309,7 +309,7 @@ public: static constexpr struct { const char* label; int shift; } kAll[] = { {"CPU", 0}, {"GPU", 8}, {"VRR", 16} }; - int count = configList.values[HocClkConfigValue_OverwriteRefreshRate] || this->context->isUsingRetroSuper || this->context->profile == HocClkProfile_Docked ? 3 : 2; + int count = configList.values[HocClkConfigValue_OverwriteRefreshRate] && profile != HocClkProfile_Docked ? 3 : 2; for (int i = 0; i < count; i++) { u8 cur = (this->profileList->mhzMap[this->profile][HocClkModule_Governor] >> kAll[i].shift) & 0xFF; @@ -367,7 +367,7 @@ void AppProfileGui::addProfileUI(HocClkProfile profile) if(configList.values[HocClkConfigValue_OverwriteRefreshRate]) { if(profile != HocClkProfile_Docked) { - this->addModuleListItemValue(profile, HocClkModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HocClkConfigValue_MaxDisplayClockH], this->context->isUsingRetroSuper ? 5 : 1, " Hz", 1, 0, lcdThresholds); + this->addModuleListItemValue(profile, HocClkModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HocClkConfigValue_MaxDisplayClockH], 1, " Hz", 1, 0, lcdThresholds); } else { if(IsAula() && this->context->isSysDockInstalled) { std::vector dockedFreqs = { @@ -450,14 +450,8 @@ void AppProfileGui::listUI() this->addProfileUI(HocClkProfile_HandheldChargingUSB); } -std::string jumpItemString = "Edit App Profile"; - void AppProfileGui::changeTo(std::uint64_t applicationId) { - if (applicationId == HOCCLK_GLOBAL_PROFILE_TID) { - jumpItemString = "Edit Global Profile"; - } - HocClkTitleProfileList* profileList = new HocClkTitleProfileList; Result rc = hocclkIpcGetProfiles(applicationId, profileList); if(R_FAILED(rc)) @@ -487,5 +481,5 @@ void AppProfileGui::update() } std::string AppProfileGui::getJumpToItemName() { - return jumpItemString; -} \ No newline at end of file + return this->applicationId == HOCCLK_GLOBAL_PROFILE_TID ? "Edit Global Profile" : "Edit App Profile"; +} diff --git a/Source/hoc-clk/overlay/src/ui/gui/base_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/base_gui.cpp index 894253e8..1d69efdc 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/base_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/base_gui.cpp @@ -71,6 +71,7 @@ std::string getVersionString() { static constexpr tsl::Color dynamicLogoRGB1 = tsl::Color(7, 15, 15, 15); static constexpr tsl::Color dynamicLogoRGB2 = tsl::Color(2, 8, 11, 15); static constexpr tsl::Color STATIC_TEAL = tsl::Color(7, 15, 15, 15); + const std::string name = " Horizon OC"; static s32 drawDynamicUltraText(tsl::gfx::Renderer *renderer, s32 startX, s32 y, u32 fontSize, const tsl::Color &staticColor, @@ -131,8 +132,11 @@ void BaseGui::preDraw(tsl::gfx::Renderer *renderer) { renderer->drawBitmap(LOGO_X, LOGO_Y_REAL - LOGO_LABEL_FONT_SIZE, LOGO_IMG_W, LOGO_IMG_H, hoc_rgba); drawDynamicUltraText(renderer, LOGO_TEXT_X, TEXT_Y, LOGO_LABEL_FONT_SIZE, STATIC_TEAL, false); - + #ifdef OVERLAY_DEBUG + static const std::string versionStr = "Version " + getVersionString() + " \"Athena (debug)\""; + #else static const std::string versionStr = "Version " + getVersionString() + " \"Athena\""; + #endif static constexpr tsl::Color versionColor(9, 9, 9, 15); static constexpr s32 vx = LOGO_TEXT_X + 15; static constexpr s32 vy = TEXT_Y + 18; diff --git a/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.cpp index aaee65e8..daca578f 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/base_menu_gui.cpp @@ -61,7 +61,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer *renderer) { // All constants pre-calculated and cached const char *labels[] = { "App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", - "Skin", "Now", "Avg", "BAT", "PMIC", "Fan", IsAula() || this->context->isUsingRetroSuper ? "OLED" : "LCD", + "Skin", "Now", "Avg", "BAT", "PMIC", "Fan", IsAula() ? "OLED" : "LCD", "FPS", "RES" }; static constexpr u32 dataPositions[6] = { 63 - 3 + 3, 200 - 1, 344 - 1 - 3, 200 - 1, 342 - 1, 321 - 1 }; @@ -284,6 +284,10 @@ void BaseMenuGui::refresh() { sprintf(displayStrings[10], "%u.%u mV", context->voltages[HocClkVoltage_EMCVDDQ] / 1000U, (context->voltages[HocClkVoltage_EMCVDDQ] % 1000U) / 100U); break; + case RamDisplayMode_VDD2VDDQ: + sprintf(displayStrings[10], "%u/%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, + context->voltages[HocClkVoltage_EMCVDDQ] / 1000U); + break; default: strcpy(displayStrings[10], "N/A"); break; @@ -344,15 +348,15 @@ void BaseMenuGui::refresh() { millis = context->temps[HocClkThermalSensor_CPU]; sprintf(displayStrings[28], "%u.%u", millis / 1000U, (millis % 1000U) / 100U); - tempColors[HocClkThermalSensor_CPU] = tsl::GradientColor(millis * 0.001f); + tempColors[HocClkThermalSensor_CPU] = tsl::GradientColor(millis * 0.001f, tsl::DEFAULT_TEMP_RANGE_HIGH); millis = context->temps[HocClkThermalSensor_GPU]; sprintf(displayStrings[29], "%u.%u", millis / 1000U, (millis % 1000U) / 100U); - tempColors[HocClkThermalSensor_GPU] = tsl::GradientColor(millis * 0.001f); + tempColors[HocClkThermalSensor_GPU] = tsl::GradientColor(millis * 0.001f, tsl::DEFAULT_TEMP_RANGE_HIGH); millis = context->temps[HocClkThermalSensor_MEM]; sprintf(displayStrings[30], "%u.%u", millis / 1000U, (millis % 1000U) / 100U); - tempColors[HocClkThermalSensor_MEM] = tsl::GradientColor(millis * 0.001f); + tempColors[HocClkThermalSensor_MEM] = tsl::GradientColor(millis * 0.001f, tsl::DEFAULT_TEMP_RANGE_HIGH); } tsl::elm::Element *BaseMenuGui::baseUI() { diff --git a/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp b/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp index 5fa73752..f799175e 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp @@ -45,6 +45,7 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Options:", "- VDD2 - Display VDD2 voltage", "- VDDQ - Display VDDQ voltage", + "- VDD2/VDDQ - Display both voltages, but without decimal place", "Default: VDD2" }; @@ -75,15 +76,6 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Default: INI" }; - case HocClkConfigValue_MemoryFrequencyMeasurementMode: - return { - "How the RAM real frequency is measured", - "Options:", - "- PLL: Measure from PLLMB and PLLM (more accurate)", - "- Actmon: Measure from Actmon (less accurate)", - "Default: PLL" - }; - case HocClkConfigValue_BatteryChargeCurrent: return { "Overrides the charge current to the battery. Use with caution!", @@ -115,6 +107,26 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Default: 612MHz" }; + case HocClkConfigValue_GovernorPollRateMs: + return { + "How often the CPU/GPU governor runs its loop.", + "Default: 5ms" + }; + + case HocClkConfigValue_GovernorDownHoldTicks: + return { + "How many governor ticks to hold the current frequency", + "before ramping down. 0 disables holding", + "Default: 10 ticks" + }; + + case HocClkConfigValue_GovernorStepUtil: + return { + "Load divisor mapping utilization to frequency.", + "Lower ramps up faster, above 1000 caps the top end", + "Default: 900" + }; + case HocClkConfigValue_OverwriteRefreshRate: return { "Controls the availability of display refresh rate features.", @@ -188,15 +200,21 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, }; case KipConfigValue_emcDvbShift: - return { - "Each level adds/removes 25mV from the SOC Voltage table", - "Consoles are bracketed by SoC Speedo. The brackets are as follows:", - " - Speedo 1487-1598: Bracket 0", - " - Speedo 1598-1709: Bracket 1", - " - Speedo 1709-1820: Bracket 2", - "Default: 0" - }; - + if(isMariko) { + return { + "Each level adds/removes 25mV from the SOC Voltage table", + "Consoles are bracketed by SoC Speedo. The brackets are as follows:", + " - Speedo 1487-1598: Bracket 0", + " - Speedo 1598-1709: Bracket 1", + " - Speedo 1709-1820: Bracket 2", + "Default: 0" + }; + } else { + return { + "Each level adds 25mV from the SOC Voltage table", + "Default: 0" + }; + } case KipConfigValue_marikoSocVmax: return { "The maximum available SOC Voltage that the DVB-adjusted table can use", @@ -439,24 +457,6 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "The clock used for the CPU in \"boost mode\"", "Default: 1785 MHz" }; - case HocClkConfigValue_AutoRAMCPUOverclock: - return { - "When enabled, automatically raises the CPU clock to the configured OC frequency when RAM clock meets or exceeds the threshold to meet the increased voltage requirement.", - "Default: ON" - }; - - case HocClkConfigValue_AutoRamCpuCpuOCFreq: - return { - "The CPU clock (in MHz) applied when Auto High RAM CPU OC is enabled and the RAM threshold is met.", - "Default: 1683 MHz" - }; - - case HocClkConfigValue_AutoRamCpuRamOCThreshold: - return { - "The RAM clock threshold (in MHz) at or above which the Auto High RAM CPU OC will activate.", - "Default: 2133MHz" - }; - case HocClkConfigValue_OverwriteBoostMode: return { "If enabled, profiles can override the boost mode setting", @@ -488,7 +488,7 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Default: 800 mV" }; - case HocClkConfigValue_DVFSMode: + case HocClkConfigValue_GPUDVFSMode: return { "The mode used for GPU DVFS", "Adjusts GPU vmin when RAM clock is changed due to a higher requirement", @@ -498,12 +498,28 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Default: PCV Hijack" }; - case HocClkConfigValue_DVFSOffset: + case HocClkConfigValue_GPUDVFSOffset: return { "The offset added/subtracted to the GPU vmin when the RAM clock is changed due to a higher requirement in PCV Hijack mode", "Default: 0 mV (Disabled)" }; + case HocClkConfigValue_CPUDVFSMode: + return { + "The mode used for CPU DVFS", + "Adjusts CPU vmin when RAM clock is changed due to a higher requirement", + "Options:", + "- Disabled: No CPU vmin adjustment", + "- LUT Modify: Modifies the CLDVFS LUT", + "Default: LUT Modify" + }; + + case HocClkConfigValue_CPUDVFSOffset: + return { + "The offset added/subtracted to the CPU vmin when the RAM clock is changed due to a higher requirement in LUT Modify mode", + "Default: 0 mV (Disabled)" + }; + case KipConfigValue_eristaGpuUV: return { "GPU undervolt level", @@ -544,6 +560,18 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Voltage applies globally across all frequencies.", "\"Reset\" restores default or RAM-stable minimum." }; + case HocClkConfigValue_FileLogging: + return { + "Write sysmodule logs to log.txt in the config folder.", + "Takes effect after a reboot.", + "Default: Off" + }; + case HocClkConfigValue_UartLogging: + return { + "Output sysmodule logs over UART.", + "Takes effect after a reboot.", + "Default: Off" + }; default: return {}; } diff --git a/Source/hoc-clk/overlay/src/ui/gui/global_override_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/global_override_gui.cpp index 25a8cd0f..6bf7ae20 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/global_override_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/global_override_gui.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -320,7 +320,7 @@ public: static constexpr struct { const char* label; int shift; } kAll[] = { {"CPU", 0}, {"GPU", 8}, {"VRR", 16} }; - int count = configList.values[HocClkConfigValue_OverwriteRefreshRate] || this->context->isUsingRetroSuper ? 3 : 2; + int count = configList.values[HocClkConfigValue_OverwriteRefreshRate] && this->context->profile != HocClkProfile_Docked ? 3 : 2; for (int i = 0; i < count; i++) { u8 cur = (this->packed >> kAll[i].shift) & 0xFF; @@ -375,7 +375,7 @@ void GlobalOverrideGui::listUI() #if IS_MINIMAL == 0 ValueThresholds lcdThresholds(60, 65); if(configList.values[HocClkConfigValue_OverwriteRefreshRate]) - this->addModuleListItemValue(HocClkModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HocClkConfigValue_MaxDisplayClockH], this->context->isUsingRetroSuper ? 5 : 1, " Hz", 1, 0, lcdThresholds); + this->addModuleListItemValue(HocClkModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HocClkConfigValue_MaxDisplayClockH], 1, " Hz", 1, 0, lcdThresholds); #endif this->addGovernorSection(); diff --git a/Source/hoc-clk/overlay/src/ui/gui/info_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/info_gui.cpp index 3a339d5b..32d1e3ce 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/info_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/info_gui.cpp @@ -64,23 +64,26 @@ static std::vector wrapText(const std::string &text, s32 maxWidth) return lines; } -void InfoGui::listUI() { - this->listElement->addItem(new tsl::elm::CategoryHeader(m_title)); - +void addWrappedTextItems(tsl::elm::List *list, const std::vector ¶graphs) { const s32 maxWidth = tsl::cfg::FramebufferWidth - MARGIN_L - MARGIN_R; - for (const auto ¶ : m_strings) { + for (const auto ¶ : paragraphs) { for (const auto &lineText : wrapText(para, maxWidth)) { auto *d = new FocusableDrawer([lineText](tsl::gfx::Renderer *r, s32 x, s32 y, s32 w, s32 h) { r->drawString((lineText + "\n").c_str(), false, x + MARGIN_L, y + LINE_H - 5, TEXT_SIZE, tsl::style::color::ColorText); }); d->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, LINE_H); - this->listElement->addItem(d, LINE_H); + list->addItem(d, LINE_H); } // paragraph gap auto *gap = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *, s32, s32, s32, s32) {}); gap->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, PARA_GAP); - this->listElement->addItem(gap, PARA_GAP); + list->addItem(gap, PARA_GAP); } } + +void InfoGui::listUI() { + this->listElement->addItem(new tsl::elm::CategoryHeader(m_title)); + addWrappedTextItems(this->listElement, m_strings); +} diff --git a/Source/hoc-clk/overlay/src/ui/gui/info_gui.h b/Source/hoc-clk/overlay/src/ui/gui/info_gui.h index 0721060d..dfb5339d 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/info_gui.h +++ b/Source/hoc-clk/overlay/src/ui/gui/info_gui.h @@ -21,6 +21,10 @@ #include "base_menu_gui.h" +// Word-wraps and appends `paragraphs` to `list` as CustomDrawer text items, +// using the same layout/rendering rules InfoGui uses for its body text. +void addWrappedTextItems(tsl::elm::List *list, const std::vector ¶graphs); + class InfoGui : public BaseMenuGui { public: InfoGui(std::string title, std::vector strings); diff --git a/Source/hoc-clk/overlay/src/ui/gui/labels.cpp b/Source/hoc-clk/overlay/src/ui/gui/labels.cpp index 55f59189..cd83e4a9 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/labels.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/labels.cpp @@ -21,12 +21,12 @@ std::map cpu_freq_label_m = { { 612000000, "Sleep Mode" }, { 1020000000, "Stock" }, { 1224000000, "Dev OC" }, { 1785000000, "Boost Mode" }, - { 1963000000, "Safe Max" }, { 2397000000, "Unsafe Max" }, { 2703000000, "Absolute Max" }, + { 1963000000, "Safe Max" }, { 2397000000, "Unsafe Max" }, { 2805000000, "Absolute Max" }, }; std::map cpu_freq_label_m_uv = { { 612000000, "Sleep Mode" }, { 1020000000, "Stock" }, { 1224000000, "Dev OC" }, { 1785000000, "Boost Mode" }, - { 2397000000, "Safe Max" }, { 2499000000, "Unsafe Max" }, { 2703000000, "Absolute Max" }, + { 2397000000, "Safe Max" }, { 2499000000, "Unsafe Max" }, { 2805000000, "Absolute Max" }, }; std::map cpu_freq_label_e = { @@ -59,19 +59,19 @@ std::map gpu_freq_label_m = { std::map gpu_freq_label_m_slt = { { 76800000, "Boost Mode" }, { 307200000, "Handheld" }, { 345600000, "Handheld" }, { 384000000, "Handheld" }, { 422400000, "Handheld" }, { 460800000, "Handheld" }, { 614400000, "Handheld Safe Max" }, { 768000000, "Docked" }, - { 1075200000, "Safe Max" }, { 1305600000, "Unsafe Max" }, { 1536000000, "Absolute Max" }, + { 1075200000, "Safe Max" }, { 1305600000, "Unsafe Max" }, { 1574400000, "Absolute Max" }, }; std::map gpu_freq_label_m_hiopt = { { 76800000, "Boost Mode" }, { 307200000, "Handheld" }, { 345600000, "Handheld" }, { 384000000, "Handheld" }, { 422400000, "Handheld" }, { 460800000, "Handheld" }, { 614400000, "Handheld Safe Max" }, { 768000000, "Docked" }, - { 1152000000, "Safe Max" }, { 1305600000, "Unsafe Max" }, { 1536000000, "Absolute Max" }, + { 1152000000, "Safe Max" }, { 1305600000, "Unsafe Max" }, { 1574400000, "Absolute Max" }, }; std::map gpu_freq_label_m_highuv = { { 76800000, "Boost Mode" }, { 307200000, "Handheld" }, { 384000000, "Handheld" }, { 460800000, "Handheld" }, { 614400000, "Handheld Safe Max" }, { 768000000, "Docked" }, - { 1228800000, "Safe Max" }, { 1305600000, "Unsafe Max" }, { 1536000000, "Absolute Max" }, + { 1228800000, "Safe Max" }, { 1305600000, "Unsafe Max" }, { 1574400000, "Absolute Max" }, }; std::map *marikoUV[5]{ diff --git a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp index 616f8e7e..c8b4afab 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp @@ -60,13 +60,16 @@ class DisplaySubMenuGui; class SafetySubMenuGui; class RamSubmenuGui; class RamTimingsSubmenuGui; +class RamTimingPresetsSubmenuGui; class RamLatenciesSubmenuGui; class SocCustomTableSubmenuGui; class CpuSubmenuGui; class GpuSubmenuGui; class GpuCustomTableSubmenuGui; class ExperimentalSettingsSubMenuGui; - +#ifdef OVERLAY_DEBUG +class DebugSettingsSubMenuGui; +#endif MiscGui::MiscGui() { this->configList = new HocClkConfigValueList{}; } @@ -735,7 +738,18 @@ void MiscGui::listUI() { experimentalSubMenu->setValue(R_ARROW); this->listElement->addItem(experimentalSubMenu); } - + #ifdef OVERLAY_DEBUG + tsl::elm::ListItem *debugSubMenu = new tsl::elm::ListItem("Debug Settings"); + debugSubMenu->setClickListener([](u64 keys) { + if (keys & HidNpadButton_A) { + tsl::swapTo(); + return true; + } + return false; + }); + debugSubMenu->setValue(R_ARROW); + this->listElement->addItem(debugSubMenu); + #endif if (!lastItemName.empty()) { this->listElement->jumpToItem(lastItemName); } @@ -771,6 +785,7 @@ class GeneralSettingsSubMenuGui : public MiscGui { std::vector ramVoltDispModes = { NamedValue("VDD2", RamDisplayMode_VDD2), NamedValue("VDDQ", RamDisplayMode_VDDQ), + NamedValue("VDD2/VDDQ", RamDisplayMode_VDD2VDDQ), }; if (IsMariko()) { @@ -791,6 +806,13 @@ class GeneralSettingsSubMenuGui : public MiscGui { addConfigButton(HocClkConfigValue_PollingIntervalMs, "Polling Interval", ValueRange(50, 1000, 50, "ms", 1), "Polling Interval", &thresholdsDisabled, {}, {}, false); + tsl::elm::CustomDrawer *loggingSpacer = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *, s32, s32, s32, s32) {}); + loggingSpacer->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 12); + this->listElement->addItem(loggingSpacer); + this->listElement->addItem(new CompactCategoryHeader("Logging")); + addConfigToggle(HocClkConfigValue_FileLogging, nullptr); + addConfigToggle(HocClkConfigValue_UartLogging, nullptr); + tsl::elm::CustomDrawer *exSetWarning = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { renderer->drawString("\uE150 Experimental Settings are incomplete ", false, x + 20, y + 30, 18, tsl::style::color::ColorText); renderer->drawString("and may not work correctly or at all!", false, x + 20, y + 50, 18, tsl::style::color::ColorText); @@ -826,13 +848,24 @@ class ExperimentalSettingsSubMenuGui : public MiscGui { FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); return; } - this->listElement->addItem(new CompactCategoryHeader("Experimental Settings")); + auto addHeaderSpacer = [this]() { + tsl::elm::CustomDrawer *spacer = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *, s32, s32, s32, s32) {}); + spacer->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 12); + this->listElement->addItem(spacer); + }; + ValueThresholds thresholdsDisabled(0, 0); if (IsMariko()) { - addConfigToggle(HocClkConfigValue_MarikoMiddleFreqs, nullptr, true); + this->listElement->addItem(new CompactCategoryHeader("CPU Settings")); addConfigToggle(HocClkConfigValue_LiveCpuUv, nullptr); } + if (IsMariko()) + addHeaderSpacer(); + this->listElement->addItem(new CompactCategoryHeader("GPU Settings")); + if (IsMariko()) + addConfigToggle(HocClkConfigValue_MarikoMiddleFreqs, nullptr, true); + addConfigToggle(HocClkConfigValue_LiveGpuVoltage, "Live GPU Volt Request", false); std::vector gpuSchedMethodValues = { @@ -842,13 +875,6 @@ class ExperimentalSettingsSubMenuGui : public MiscGui { addConfigButton(HocClkConfigValue_GPUSchedulingMethod, "GPU Scheduling Override Method", ValueRange(0, 0, 1, "", 0), "GPU Scheduling Override Method", &thresholdsDisabled, {}, gpuSchedMethodValues, false); - std::vector ramRFMeasurementMethods = { - NamedValue("PLL", MemoryFrequencyMeasurementMode_PLL), - NamedValue("Actmon", MemoryFrequencyMeasurementMode_Actmon), - }; - addConfigButton(HocClkConfigValue_MemoryFrequencyMeasurementMode, "Memory Frequency Measurement Mode", ValueRange(0, 0, 1, "", 0), - "Memory Frequency Measurement Mode", &thresholdsDisabled, {}, ramRFMeasurementMethods, false); - tsl::elm::CustomDrawer *chargeWarningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { renderer->drawString("\uE150 Overriding the charge current", false, x + 20, y + 30, 18, tsl::style::color::ColorText); renderer->drawString("can be dangerous and may cause", false, x + 20, y + 50, 18, tsl::style::color::ColorText); @@ -896,7 +922,7 @@ class ExperimentalSettingsSubMenuGui : public MiscGui { NamedValue("100mA", 100), NamedValue("150mA", 150), NamedValue("500mA", 500), - NamedValue("900mA", 900, "Hoag Default"), + NamedValue("900mA", 900, "Default (Lite)"), NamedValue("1200mA", 1200, "Default"), NamedValue("1500mA", 1500), NamedValue("2000mA", 2000), @@ -928,6 +954,44 @@ class ExperimentalSettingsSubMenuGui : public MiscGui { } }; +#ifdef OVERLAY_DEBUG +class DebugSettingsSubMenuGui : public MiscGui { + public: + DebugSettingsSubMenuGui() { + } + + bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState leftJoyStick, + HidAnalogStickState rightJoyStick) override { + if (keysDown & KEY_B) { + triggerExitFeedback(); + lastItemName = "Debug Settings"; + tsl::swapTo(); + return true; + } + return false; + } + + protected: + void listUI() override { + Result rc = hocclkIpcGetConfigValues(this->configList); + if (R_FAILED(rc)) [[unlikely]] { + FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); + return; + } + this->listElement->addItem(new CompactCategoryHeader("Debug Settings")); + ValueThresholds thresholdsDisabled(0, 0); + std::vector VerbosityList = { + NamedValue("Disabled", 0xff), NamedValue("0", 0), NamedValue("1", 1), + NamedValue("2", 2), NamedValue("3", 3), + }; + + addConfigButton(KipConfigValue_PcvDebugVerbosity, "PCV Log Verbosity", ValueRange(0, 0, 1, "", 0), + "Verbosity", &thresholdsDisabled, {}, VerbosityList, false, true); + } +}; + +#endif + class GovernorSettingsSubMenuGui : public MiscGui { public: GovernorSettingsSubMenuGui() { @@ -961,6 +1025,13 @@ class GovernorSettingsSubMenuGui : public MiscGui { addConfigButton(HocClkConfigValue_CpuGovernorMinimumFreq, "CPU Governor Minimum Frequency", ValueRange(0, 0, 1, "", 0), "CPU Governor Minimum Frequency", &thresholdsDisabled, {}, GovernorMinHz, false); + + addConfigButton(HocClkConfigValue_GovernorPollRateMs, "Governor Poll Rate", ValueRange(1, 50, 1, " ms", 1), + "Governor Poll Rate", &thresholdsDisabled, {}, {}, false); + addConfigButton(HocClkConfigValue_GovernorDownHoldTicks, "Governor Down Hold", ValueRange(0, 100, 1, " ticks", 1), + "Governor Down Hold", &thresholdsDisabled, {}, {}, false); + addConfigButton(HocClkConfigValue_GovernorStepUtil, "Governor Step Divisor", ValueRange(100, 1500, 25, "", 1), + "Governor Step Divisor", &thresholdsDisabled, {}, {}, false); } }; @@ -995,20 +1066,18 @@ class DisplaySubMenuGui : public MiscGui { this->listElement->addItem(new CompactCategoryHeader("Display Settings")); addConfigToggle(HocClkConfigValue_OverwriteRefreshRate, nullptr); - if (!this->context->isUsingRetroSuper) { - tsl::elm::CustomDrawer *warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString("\uE150 Usage of unsafe display", false, x + 20, y + 30, 18, tsl::style::color::ColorText); - renderer->drawString("refresh rates may cause stress", false, x + 20, y + 50, 18, tsl::style::color::ColorText); - renderer->drawString("or damage to your display! ", false, x + 20, y + 70, 18, tsl::style::color::ColorText); - renderer->drawString("Proceed at your own risk!", false, x + 20, y + 90, 18, tsl::style::color::ColorText); - }); + tsl::elm::CustomDrawer *warningText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("\uE150 Usage of unsafe display", false, x + 20, y + 30, 18, tsl::style::color::ColorText); + renderer->drawString("refresh rates may cause stress", false, x + 20, y + 50, 18, tsl::style::color::ColorText); + renderer->drawString("or damage to your display! ", false, x + 20, y + 70, 18, tsl::style::color::ColorText); + renderer->drawString("Proceed at your own risk!", false, x + 20, y + 90, 18, tsl::style::color::ColorText); + }); - warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 110); - this->listElement->addItem(warningText); - ValueThresholds displayThresholds(60, 65); - addConfigButton(HocClkConfigValue_MaxDisplayClockH, "Max Handheld Display Hz", ValueRange(60, IsAula() ? 65 : 75, 1, " Hz", 1), - "Display Clock", &displayThresholds, {}, {}, false); - } + warningText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 110); + this->listElement->addItem(warningText); + ValueThresholds displayThresholds(60, 65); + addConfigButton(HocClkConfigValue_MaxDisplayClockH, "Max Handheld Display Hz", ValueRange(60, IsAula() ? 65 : 75, 1, " Hz", 1), + "Display Clock", &displayThresholds, {}, {}, false); if (!IsAula()) { tsl::elm::CustomDrawer *warningTextDV = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { renderer->drawString("\uE150 Adjust the display voltage", false, x + 20, y + 30, 18, tsl::style::color::ColorText); @@ -1050,6 +1119,7 @@ class SafetySubMenuGui : public MiscGui { this->listElement->addItem(new CompactCategoryHeader("Safety Settings")); addConfigToggle(HocClkConfigValue_UncappedClocks, nullptr); addConfigToggle(HocClkConfigValue_ThermalThrottle, nullptr); + addConfigToggle(HocClkConfigValue_Watchdog, nullptr); #if IS_MINIMAL == 0 ValueThresholds throttleThresholds(70, 80); @@ -1090,10 +1160,15 @@ class RamSubmenuGui : public MiscGui { std::vector noNamedValues = {}; this->listElement->addItem(new CompactCategoryHeader("RAM Settings")); - - addMappedConfigTrackbar(KipConfigValue_emcDvbShift, "DVB Shift", - { 0xFFFFFFFCu, 0xFFFFFFFDu, 0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u }, - { "-4", "-3", "-2", "-1", " 0", "1", "2", "3", "4", "5", "6", "7", "8" }); + if(IsMariko()) { + addMappedConfigTrackbar(KipConfigValue_emcDvbShift, "DVB Shift", + { 0xFFFFFFFCu, 0xFFFFFFFDu, 0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u }, + { "-4", "-3", "-2", "-1", "0", "1", "2", "3", "4", "5", "6", "7", "8" }); + } else { + addMappedConfigTrackbar(KipConfigValue_emcDvbShift, "DVB Shift", + { 0u, 1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u }, + { "0", "1", "2", "3", "4", "5", "6", "7", "8" }); + } if (IsMariko()) { u32 socSpeedo = this->context->speedos[HocClkSpeedo_SOC]; @@ -1132,7 +1207,7 @@ class RamSubmenuGui : public MiscGui { }; ValueThresholds vdd2Thresholds(IsMariko() ? 1212500 : 1237500, IsMariko() ? 1250000 : 1275000); - addConfigButton(KipConfigValue_commonEmcMemVolt, "RAM VDD2 Voltage", ValueRange(912500, 1350000, 12500, "mV", 1000, 1), "Voltage", + addConfigButton(KipConfigValue_commonEmcMemVolt, "RAM VDD2 Voltage", ValueRange(912500, IsMariko() ? 1275000 : 1350000, 12500, "mV", 1000, 1), "Voltage", &vdd2Thresholds, emc_voltage_label, noNamedValues, false, true); if (IsMariko()) { @@ -1196,6 +1271,11 @@ class RamSubmenuGui : public MiscGui { NamedValue("2361 MHz", 2361600), NamedValue("2380 MHz", 2380800), NamedValue("2400 MHz", 2400000, "JEDEC."), + NamedValue("2419 MHz", 2419200), + NamedValue("2438 MHz", 2438400), + NamedValue("2457 MHz", 2457600), + NamedValue("2476 MHz", 2476800), + NamedValue("2496 MHz", 2496000), }; } else { emcMaxClock = { @@ -1254,7 +1334,10 @@ class RamSubmenuGui : public MiscGui { NamedValue("3300 MHz", 3300000, "±1760 speedo"), NamedValue("3333 MHz", 3333000, "±1780 speedo"), NamedValue("3366 MHz", 3366000, "±1800 speedo"), - NamedValue("3400 MHz", 3400000, "±1820 speedo") + NamedValue("3400 MHz", 3400000, "±1820 speedo"), + NamedValue("3433 MHz", 3433000, "±???? speedo"), + NamedValue("3466 MHz", 3466000, "±???? speedo"), + NamedValue("3500 MHz", 3500000, "±???? speedo"), }; } @@ -1272,17 +1355,6 @@ class RamSubmenuGui : public MiscGui { emcMaxClock, false, true); } - tsl::elm::ListItem *latenciesSubmenu = new tsl::elm::ListItem("RAM Latency Editor"); - latenciesSubmenu->setClickListener([](u64 keys) { - if (keys & HidNpadButton_A) { - tsl::swapTo(); - return true; - } - return false; - }); - latenciesSubmenu->setValue(R_ARROW); - this->listElement->addItem(latenciesSubmenu); - tsl::elm::ListItem *timingsSubmenu = new tsl::elm::ListItem("RAM Timing Reductions"); timingsSubmenu->setClickListener([](u64 keys) { if (keys & HidNpadButton_A) { @@ -1294,6 +1366,17 @@ class RamSubmenuGui : public MiscGui { timingsSubmenu->setValue(R_ARROW); this->listElement->addItem(timingsSubmenu); + tsl::elm::ListItem *latenciesSubmenu = new tsl::elm::ListItem("RAM Latency Editor"); + latenciesSubmenu->setClickListener([](u64 keys) { + if (keys & HidNpadButton_A) { + tsl::swapTo(); + return true; + } + return false; + }); + latenciesSubmenu->setValue(R_ARROW); + this->listElement->addItem(latenciesSubmenu); + if (IsMariko()) { tsl::elm::ListItem *socVoltageTable = new tsl::elm::ListItem("SOC Voltage Table"); socVoltageTable->setClickListener([](u64 keys) { @@ -1314,6 +1397,67 @@ class RamSubmenuGui : public MiscGui { } }; +struct RamTimingPresetSet { + uint32_t t[8]; +}; + +struct RamTimingPresetRow { + std::initializer_list dramIds; + RamTimingPresetSet common; + RamTimingPresetSet st; +}; + +static const RamTimingPresetRow kMarikoRamTimingPresets[] = { + { { 32, 33, 34 }, { { 4, 4, 5, 4, 2, 6, 5, 6 } }, { { 6, 6, 7, 5, 2, 6, 5, 6 } } }, // WT:B + { { 3, 5, 6, 29, 30, 31 }, { { 3, 3, 2, 1, 5, 5, 4, 6 } }, { { 4, 4, 4, 2, 7, 6, 5, 6 } } }, // NEE / x267 + { { 17, 19, 24 }, { { 4, 4, 5, 4, 5, 5, 6, 6 } }, { { 4, 4, 8, 5, 5, 6, 7, 6 } } }, // AA-MGCL 4GB + { { 11, 15 }, { { 2, 2, 2, 1, 4, 4, 4, 6 } }, { { 3, 5, 3, 2, 5, 4, 5, 6 } } }, // WT:E + { { 8, 12 }, { { 3, 2, 4, 1, 4, 4, 4, 6 } }, { { 4, 3, 8, 1, 5, 4, 4, 6 } } }, // AM-MGCJ 4GB + { { 25, 26, 27 }, { { 4, 4, 2, 4, 4, 6, 3, 6 } }, { { 5, 5, 4, 4, 5, 6, 5, 6 } } }, // WT:F + { { 20, 21, 22 }, { { 4, 4, 4, 3, 4, 5, 6, 6 } }, { { 4, 4, 8, 4, 5, 6, 8, 6 } } }, // AB-MGCL + { { 10, 14 }, { { 2, 2, 3, 0, 1, 2, 2, 6 } }, { { 5, 3, 4, 1, 8, 3, 3, 6 } } }, // NME +}; + +static const RamTimingPresetSet kEristaCommonTiming = { { 4, 4, 4, 0, 1, 5, 4, 6 } }; +static const RamTimingPresetSet kEristaSTTiming = { { 4, 5, 9, 1, 2, 6, 4, 6 } }; + +// 8GB DRAM modules are commonly used for ram upgrade +// and are not representative of the actual ram in the console +// Theoretically you could do it via MRR Vendor registers +// but thats for the future +static bool isEightGigRamID(u8 dramID) { + switch (dramID) { + case 7: + case 9: + case 13: + case 18: + case 23: + case 28: + return true; + default: + return false; + } +} + +static const RamTimingPresetRow *findMarikoRamTimingPreset(u8 dramID) { + for (const auto &row : kMarikoRamTimingPresets) { + for (auto id : row.dramIds) { + if (id == dramID) + return &row; + } + } + return nullptr; +} + +static void applyRamTimingPreset(HocClkConfigValueList *configList, const RamTimingPresetSet &set) { + static constexpr HocClkConfigValue keys[8] = { + KipConfigValue_t1_tRCD, KipConfigValue_t2_tRP, KipConfigValue_t3_tRAS, KipConfigValue_t4_tRRD, + KipConfigValue_t5_tRFC, KipConfigValue_t6_tRTW, KipConfigValue_t7_tWTR, KipConfigValue_t8_tREFI, + }; + for (int i = 0; i < 8; i++) + configList->values[keys[i]] = set.t[i]; +} + class RamTimingsSubmenuGui : public MiscGui { public: RamTimingsSubmenuGui() { @@ -1339,10 +1483,21 @@ class RamTimingsSubmenuGui : public MiscGui { } this->listElement->addItem(new CompactCategoryHeader("Memory Timings")); + tsl::elm::ListItem *timingPresetsSubMenu = new tsl::elm::ListItem("Timing Presets"); + timingPresetsSubMenu->setClickListener([](u64 keys) { + if (keys & HidNpadButton_A) { + tsl::swapTo(); + return true; + } + return false; + }); + timingPresetsSubMenu->setValue(R_ARROW); + this->listElement->addItem(timingPresetsSubMenu); + addConfigTrackbar(KipConfigValue_t1_tRCD, "t1 tRCD", ValueRange(0, 7, 1)); addConfigTrackbar(KipConfigValue_t2_tRP, "t2 tRP", ValueRange(0, 7, 1)); addConfigTrackbar(KipConfigValue_t3_tRAS, "t3 tRAS", ValueRange(0, 9, 1)); - addConfigTrackbar(KipConfigValue_t4_tRRD, "t4 tRRD", ValueRange(0, 6, 1)); + addConfigTrackbar(KipConfigValue_t4_tRRD, "t4 tRRD", ValueRange(0, IsErista() ? 7u : 6u , 1)); addConfigTrackbar(KipConfigValue_t5_tRFC, "t5 tRFC", ValueRange(0, IsErista() ? 5u : 10u, 1)); addConfigTrackbar(KipConfigValue_t6_tRTW, "t6 tRTW", ValueRange(0, 9, 1)); addConfigTrackbar(KipConfigValue_t7_tWTR, "t7 tWTR", ValueRange(0, 9, 1)); @@ -1406,6 +1561,9 @@ class RamTimingsSubmenuGui : public MiscGui { NamedValue("3333 MHz", 3333000, "±1780 speedo"), NamedValue("3366 MHz", 3366000, "±1800 speedo"), NamedValue("3400 MHz", 3400000, "±1820 speedo"), + NamedValue("3433 MHz", 3433000, "±???? speedo"), + NamedValue("3466 MHz", 3466000, "±???? speedo"), + NamedValue("3500 MHz", 3500000, "±???? speedo"), }; RamDisplayUnit unit = (RamDisplayUnit)this->configList->values[HocClkConfigValue_RamDisplayUnit]; @@ -1554,6 +1712,114 @@ class RamTimingsSubmenuGui : public MiscGui { { "-2", "-1", " 0", "+1", "+2" }); addMappedConfigTrackbar(KipConfigValue_t7_tWTR_fine_tune, "t7 tWTR Fine Tune", { 0xFFFFFFFDu, 0xFFFFFFFEu, 0xFFFFFFFFu, 0u, 1u, 2u, 3u }, { "-3", "-2", "-1", " 0", "+1", "+2", "+3" }); + + if (!lastItemName.empty()) { + this->listElement->jumpToItem(lastItemName); + } + lastItemName = ""; + } +}; + +class RamTimingPresetsSubmenuGui : public MiscGui { + public: + RamTimingPresetsSubmenuGui() { + } + + bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState leftJoyStick, + HidAnalogStickState rightJoyStick) override { + if (keysDown & KEY_B) { + triggerExitFeedback(); + lastItemName = "Timing Presets"; + tsl::swapTo(); + return true; + } + return false; + } + + protected: + void listUI() override { + Result rc = hocclkIpcGetConfigValues(this->configList); + if (R_FAILED(rc)) [[unlikely]] { + FatalGui::openWithResultCode("hocclkIpcGetConfigValues", rc); + return; + } + + if (!this->context) { + this->context = new HocClkContext; + } + Result crc = hocclkIpcGetCurrentContext(this->context); + if (R_FAILED(crc)) [[unlikely]] { + FatalGui::openWithResultCode("hocclkIpcGetCurrentContext", crc); + return; + } + u8 dramID = this->context->dramID; + this->listElement->addItem(new CompactCategoryHeader("Timing Presets: " + formatRamModule(dramID))); + + tsl::elm::CustomDrawer *presetWarning = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("\uE150 Timing presets are only a baseline and", false, x + 20, y + 30, 18, tsl::style::color::ColorText); + renderer->drawString("may need adjustment for your particular", false, x + 20, y + 50, 18, tsl::style::color::ColorText); + renderer->drawString("DRAM Module", false, x + 20, y + 70, 18, tsl::style::color::ColorText); + }); + presetWarning->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 90); + this->listElement->addItem(presetWarning); + + const RamTimingPresetSet *presetCommon = nullptr; + const RamTimingPresetSet *presetST = nullptr; + if (!isEightGigRamID(dramID)) { + if (IsMariko()) { + const RamTimingPresetRow *row = findMarikoRamTimingPreset(dramID); + if (row) { + presetCommon = &row->common; + presetST = &row->st; + } + } else { + presetCommon = &kEristaCommonTiming; + presetST = &kEristaSTTiming; + } + } + + if (presetCommon && presetST) { + tsl::elm::ListItem *commonPresetBtn = new tsl::elm::ListItem("Apply Common Preset"); + commonPresetBtn->setClickListener([this, presetCommon](u64 keys) { + if (!(keys & HidNpadButton_A)) + return false; + applyRamTimingPreset(this->configList, *presetCommon); + Result rc = hocclkIpcSetConfigValues(this->configList); + if (R_FAILED(rc)) { + FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc); + return false; + } + shouldSaveKip = true; + lastItemName = "Timing Presets"; + tsl::swapTo(); + return true; + }); + this->listElement->addItem(commonPresetBtn); + + tsl::elm::ListItem *stPresetBtn = new tsl::elm::ListItem("Apply Super Tight (ST) Preset"); + stPresetBtn->setClickListener([this, presetST](u64 keys) { + if (!(keys & HidNpadButton_A)) + return false; + applyRamTimingPreset(this->configList, *presetST); + Result rc = hocclkIpcSetConfigValues(this->configList); + if (R_FAILED(rc)) { + FatalGui::openWithResultCode("hocclkIpcSetConfigValues", rc); + return false; + } + shouldSaveKip = true; + lastItemName = "Timing Presets"; + tsl::swapTo(); + return true; + }); + this->listElement->addItem(stPresetBtn); + } else { + tsl::elm::CustomDrawer *noPresetText = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("Timing presets are not available", false, x + 20, y + 30, 18, tsl::style::color::ColorText); + renderer->drawString("for your RAM module.", false, x + 20, y + 50, 18, tsl::style::color::ColorText); + }); + noPresetText->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 70); + this->listElement->addItem(noPresetText); + } } }; @@ -1644,7 +1910,8 @@ class RamLatenciesSubmenuGui : public MiscGui { kFreqOptions = { 1633000, 1666000, 1700000, 1733000, 1800000, 1833000, 1862400, 1881600, 1900800, 1920000, 1939200, 1958400, 1977600, 1996800, 2016000, 2035200, 2054400, 2073600, 2092800, 2112000, 2131200, 2150400, 2169600, 2188800, - 2208000, 2227200, 2246400, 2265600, 2284800, 2304000, 2323200, 2342400, 2361600, 2380800, 2400000, + 2208000, 2227200, 2246400, 2265600, 2284800, 2304000, 2323200, 2342400, 2361600, 2380800, 2400000, 2419200, + 2438400, 2457600, 2476800, 2496000, }; } @@ -2059,8 +2326,10 @@ class RamLatenciesSubmenuGui : public MiscGui { this->listElement->addItem(graph); } + const int readTierCount = IsMariko() ? 4 : 3; + this->listElement->addItem(new CompactCategoryHeader("Read Latency")); - for (int i = 0; i < 4; i++) + for (int i = 0; i < readTierCount; i++) addLatencyRow(kTierLabels[i], i, kLatencyRKeys); this->listElement->addItem(new CompactCategoryHeader("Write Latency")); @@ -2102,7 +2371,7 @@ class CpuSubmenuGui : public MiscGui { this->listElement->addItem(new CompactCategoryHeader("CPU Settings")); if (IsMariko()) { addConfigTrackbar(KipConfigValue_marikoCpuUVLow, "CPU Low UV", ValueRange(0, 8, 1)); - addConfigTrackbar(KipConfigValue_marikoCpuUVHigh, "CPU High UV", ValueRange(0, 12, 1)); + addConfigTrackbar(KipConfigValue_marikoCpuUVHigh, "CPU High UV", ValueRange(0, 13, 1)); std::vector marikoTableConf = { // NamedValue("Auto", 0), NamedValue("Default", 1), NamedValue("1581MHz Tbreak", 2), NamedValue("1683MHz Tbreak", 3), @@ -2119,92 +2388,43 @@ class CpuSubmenuGui : public MiscGui { {}, false, true); ValueThresholds mCpuVoltThresholds(1160, 1180); - addConfigButton(KipConfigValue_marikoCpuMaxVolt, "CPU Max Voltage", ValueRange(1000, 1200, 5, "mV", 1), "CPU Max Voltage", + addConfigButton(KipConfigValue_marikoCpuMaxVolt, "CPU Max Voltage", ValueRange(1000, 1235, 5, "mV", 1), "CPU Max Voltage", &mCpuVoltThresholds, {}, {}, false, true); std::vector maxClkOptions = { NamedValue("1963 MHz", 1963500, "Rating"), NamedValue("2091 MHz", 2091000), NamedValue("2193 MHz", 2193000), NamedValue("2295 MHz", 2295000), - NamedValue("2397 MHz", 2397000, "Safe Max"), NamedValue("2499 MHz", 2499000, "Unsafe Max"), NamedValue("2601 MHz", 2601000), NamedValue("2703 MHz", 2703000, "Absolute Max"), + NamedValue("2397 MHz", 2397000, "Safe Max"), NamedValue("2499 MHz", 2499000, "Unsafe Max"), NamedValue("2601 MHz", 2601000), NamedValue("2703 MHz", 2703000), + NamedValue("2805 MHz", 2805000, "Absolute Max"), }; addConfigButton(KipConfigValue_marikoCpuMaxClock, "CPU Max Clock", ValueRange(0, 0, 1, "", 1), "CPU Max Clock", this->configList->values[KipConfigValue_marikoCpuUVHigh] ? &mCpuClockThresholdsUV : &mCpuClockThresholds, {}, maxClkOptions, false, true); - std::vector clkOptionsRamOc = { - NamedValue("1122 MHz", 1122000), NamedValue("1224 MHz", 1224000), NamedValue("1326 MHz", 1326000), NamedValue("1428 MHz", 1428000), - NamedValue("1581 MHz", 1581000), NamedValue("1683 MHz", 1683000, "Default"), NamedValue("1785 MHz", 1785000), NamedValue("1887 MHz", 1887000), - NamedValue("1963 MHz", 1963500), NamedValue("2091 MHz", 2091000), NamedValue("2193 MHz", 2193000), NamedValue("2295 MHz", 2295000), - NamedValue("2397 MHz", 2397000), NamedValue("2499 MHz", 2499000), NamedValue("2601 MHz", 2601000), NamedValue("2703 MHz", 2703000), - }; - addConfigButton(KipConfigValue_marikoCpuBoostClock, "CPU Boost Clock", ValueRange(0, 0, 1, "", 1), "CPU Boost Clock", this->configList->values[KipConfigValue_marikoCpuUVHigh] ? &mCpuClockThresholdsUV : &mCpuClockThresholds, {}, maxClkOptions, false, true); - std::vector emcMaxClock = { - NamedValue("1600 MHz", 1600000), - NamedValue("1633 MHz", 1633000), - NamedValue("1666 MHz", 1666000), - NamedValue("1700 MHz", 1700000), - NamedValue("1733 MHz", 1733000), - NamedValue("1766 MHz", 1766000), - NamedValue("1800 MHz", 1800000), - NamedValue("1833 MHz", 1833000), - NamedValue("1866 MHz", 1866000, "JEDEC."), - NamedValue("1900 MHz", 1900000), - NamedValue("1933 MHz", 1933000), - NamedValue("1966 MHz", 1966000), - NamedValue("1996 MHz", 1996800, "JEDEC."), - NamedValue("2000 MHz", 2000000), - NamedValue("2033 MHz", 2033000), - NamedValue("2066 MHz", 2066000), - NamedValue("2100 MHz", 2100000), - NamedValue("2133 MHz", 2133000, "JEDEC."), - NamedValue("2166 MHz", 2166000), - NamedValue("2200 MHz", 2200000), - NamedValue("2233 MHz", 2233000), - NamedValue("2266 MHz", 2266000), - NamedValue("2300 MHz", 2300000), - NamedValue("2333 MHz", 2333000), - NamedValue("2366 MHz", 2366000), - NamedValue("2400 MHz", 2400000, "JEDEC."), - NamedValue("2433 MHz", 2433000), - NamedValue("2466 MHz", 2466000), - NamedValue("2500 MHz", 2500000), - NamedValue("2533 MHz", 2533000), - NamedValue("2566 MHz", 2566000), - NamedValue("2600 MHz", 2600000), - NamedValue("2633 MHz", 2633000), - NamedValue("2666 MHz", 2666000, "JEDEC."), - NamedValue("2700 MHz", 2700000), - NamedValue("2733 MHz", 2733000), - NamedValue("2766 MHz", 2766000), - NamedValue("2800 MHz", 2800000), - NamedValue("2833 MHz", 2833000), - NamedValue("2866 MHz", 2866000), - NamedValue("2900 MHz", 2900000), - NamedValue("2933 MHz", 2933000, "JEDEC."), - NamedValue("2966 MHz", 2966000), - NamedValue("3000 MHz", 3000000), - NamedValue("3033 MHz", 3033000), - NamedValue("3066 MHz", 3066000), - NamedValue("3100 MHz", 3100000), - NamedValue("3133 MHz", 3133000), - NamedValue("3166 MHz", 3166000), - NamedValue("3200 MHz", 3200000, "JEDEC."), - NamedValue("3233 MHz", 3233000, "±1720 speedo"), - NamedValue("3266 MHz", 3266000, "±1740 speedo"), - NamedValue("3300 MHz", 3300000, "±1760 speedo"), - NamedValue("3333 MHz", 3333000, "±1780 speedo"), - NamedValue("3366 MHz", 3366000, "±1800 speedo"), - NamedValue("3400 MHz", 3400000, "±1820 speedo"), + std::vector cpuDvfsOffset = { + NamedValue("-80 mV", 0xFFFFFFB0), NamedValue("-75 mV", 0xFFFFFFB5), NamedValue("-70 mV", 0xFFFFFFBA), NamedValue("-65 mV", 0xFFFFFFBF), + NamedValue("-60 mV", 0xFFFFFFC4), NamedValue("-55 mV", 0xFFFFFFC9), NamedValue("-50 mV", 0xFFFFFFCE), NamedValue("-45 mV", 0xFFFFFFD3), + NamedValue("-40 mV", 0xFFFFFFD8), NamedValue("-35 mV", 0xFFFFFFDD), NamedValue("-30 mV", 0xFFFFFFE2), NamedValue("-25 mV", 0xFFFFFFE7), + NamedValue("-20 mV", 0xFFFFFFEC), NamedValue("-15 mV", 0xFFFFFFF1), NamedValue("-10 mV", 0xFFFFFFF6), NamedValue(" -5 mV", 0xFFFFFFFB), + NamedValue("Disabled", 0), NamedValue(" +5 mV", 5), NamedValue("+10 mV", 10), NamedValue("+15 mV", 15), + NamedValue("+20 mV", 20), }; - addConfigToggle(HocClkConfigValue_AutoRAMCPUOverclock, "Auto CPU RAM OC"); - addConfigButton(HocClkConfigValue_AutoRamCpuCpuOCFreq, "Auto CPU RAM OC CPU clock", ValueRange(0, 0, 1, "", 1), "CPU Clock", - &thresholdsDisabled, {}, clkOptionsRamOc, false, false); - addConfigButton(HocClkConfigValue_AutoRamCpuRamOCThreshold, "Auto CPU RAM OC Threshold", ValueRange(0, 0, 1, "", 1), "RAM Clock", - &thresholdsDisabled, {}, emcMaxClock, false, false); + + std::vector cpuDvfsValues = { + NamedValue("Disabled", CPUDVFSMode_Disabled), + NamedValue("LUT Modify", CPUDVFSMode_Modify), + }; + + addConfigButton(HocClkConfigValue_CPUDVFSMode, "CPU DVFS Mode", ValueRange(0, 0, 1, "", 0), "CPU DVFS Mode", &thresholdsDisabled, {}, cpuDvfsValues, + false); + + addConfigButton(HocClkConfigValue_CPUDVFSOffset, "CPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "CPU DVFS Offset", &thresholdsDisabled, {}, + cpuDvfsOffset, false); + } else { addConfigTrackbar(KipConfigValue_eristaCpuUV, "CPU UV", ValueRange(0, 5, 1)); @@ -2319,8 +2539,10 @@ class GpuSubmenuGui : public MiscGui { addConfigButton(KipConfigValue_marikoGpuVmin, "GPU VMIN", ValueRange(0, 0, 0, "0", 1), "GPU VMIN", &thresholdsDisabled, {}, mGpuVoltsVmin, false, true); ValueThresholds MgpuVmaxThresholds(805, 850); - addConfigButton(KipConfigValue_marikoGpuVmax, "GPU Maximum Voltage", ValueRange(800, 960, 5, "mV", 1), "GPU Maximum Voltage", - &MgpuVmaxThresholds, {}, {}, false, true); + if(IsMariko()) { + addConfigButton(KipConfigValue_marikoGpuVmax, "GPU Maximum Voltage", ValueRange(800, 995, 5, "mV", 1), "GPU Maximum Voltage", + &MgpuVmaxThresholds, {}, {}, false, true); + } } std::vector gpuOffset = { @@ -2374,10 +2596,10 @@ class GpuSubmenuGui : public MiscGui { // NamedValue("Official Service", DVFSMode_OfficialService), }; - addConfigButton(HocClkConfigValue_DVFSMode, "GPU DVFS Mode", ValueRange(0, 0, 1, "", 0), "GPU DVFS Mode", &thresholdsDisabled, {}, dvfsValues, + addConfigButton(HocClkConfigValue_GPUDVFSMode, "GPU DVFS Mode", ValueRange(0, 0, 1, "", 0), "GPU DVFS Mode", &thresholdsDisabled, {}, dvfsValues, false); - addConfigButton(HocClkConfigValue_DVFSOffset, "GPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "GPU DVFS Offset", &thresholdsDisabled, {}, + addConfigButton(HocClkConfigValue_GPUDVFSOffset, "GPU DVFS Offset", ValueRange(0, 12, 1, "", 0), "GPU DVFS Offset", &thresholdsDisabled, {}, dvfsOffset, false); tsl::elm::ListItem *customTableSubmenu = new tsl::elm::ListItem("GPU Voltage Table"); @@ -2425,7 +2647,7 @@ class GpuCustomTableSubmenuGui : public MiscGui { this->listElement->addItem(new CompactCategoryHeader("GPU Custom Table (mV)")); - ValueThresholds MgpuVmaxThresholds(800, 850); + ValueThresholds MgpuVmaxThresholds(825, 900); ValueThresholds EgpuVmaxThresholds(950, 975); std::vector mGpuVolts = { @@ -2448,7 +2670,9 @@ class GpuCustomTableSubmenuGui : public MiscGui { NamedValue("870mV", 870), NamedValue("875mV", 875), NamedValue("880mV", 880), NamedValue("885mV", 885), NamedValue("890mV", 890), NamedValue("895mV", 895), NamedValue("900mV", 900), NamedValue("905mV", 905), NamedValue("910mV", 910), NamedValue("915mV", 915), NamedValue("920mV", 920), NamedValue("925mV", 925), NamedValue("930mV", 930), NamedValue("935mV", 935), NamedValue("940mV", 940), - NamedValue("945mV", 945), NamedValue("950mV", 950), NamedValue("955mV", 955), NamedValue("960mV", 960), + NamedValue("945mV", 945), NamedValue("950mV", 950), NamedValue("955mV", 955), NamedValue("960mV", 960), NamedValue("965mV", 965), + NamedValue("970mV", 970), NamedValue("975mV", 975), NamedValue("980mV", 980), NamedValue("985mV", 985), NamedValue("990mV", 990), + NamedValue("995mV", 995), }; std::vector eGpuVolts = { @@ -2488,7 +2712,8 @@ class GpuCustomTableSubmenuGui : public MiscGui { NamedValue("875mV", 875), NamedValue("880mV", 880), NamedValue("885mV", 885), NamedValue("890mV", 890), NamedValue("895mV", 895), NamedValue("900mV", 900), NamedValue("905mV", 905), NamedValue("910mV", 910), NamedValue("915mV", 915), NamedValue("920mV", 920), NamedValue("925mV", 925), NamedValue("930mV", 930), NamedValue("935mV", 935), NamedValue("940mV", 940), NamedValue("945mV", 945), - NamedValue("950mV", 950), NamedValue("955mV", 955), NamedValue("960mV", 960), + NamedValue("950mV", 950), NamedValue("955mV", 955), NamedValue("960mV", 960), NamedValue("965mV", 965), NamedValue("970mV", 970), + NamedValue("975mV", 975), NamedValue("980mV", 980), NamedValue("985mV", 985), NamedValue("990mV", 990), NamedValue("995mV", 995), }; std::vector eGpuVolts_noAuto = { @@ -2570,6 +2795,9 @@ class GpuCustomTableSubmenuGui : public MiscGui { &MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true); addGpuFreqVoltageButton(KipConfigValue_g_volt_1536000, "1536.0MHz", 1'536'000'000, ValueRange(0, 0, 0, "0", 1), "Voltage", &MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true); + addGpuFreqVoltageButton(KipConfigValue_g_volt_1574400, "1574.4MHz", 1'574'400'000, ValueRange(0, 0, 0, "0", 1), "Voltage", + &MgpuVmaxThresholds, {}, mGpuVolts_noAuto, false, true); + } } } else { diff --git a/Source/hoc-clk/overlay/src/ui/gui/update_confirm_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/update_confirm_gui.cpp new file mode 100644 index 00000000..8341bd99 --- /dev/null +++ b/Source/hoc-clk/overlay/src/ui/gui/update_confirm_gui.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 . + */ + +#include "update_confirm_gui.h" +#include "info_gui.h" +#include "update_gui.h" + +#include + +UpdateConfirmGui::UpdateConfirmGui(UpdateGui *parent, int packageIndex, std::string packageName, + std::string tag, std::vector changelog) + : m_parent(parent), m_packageIndex(packageIndex), m_packageName(std::move(packageName)), + m_tag(std::move(tag)), m_changelog(std::move(changelog)) { +} + +void UpdateConfirmGui::listUI() { + std::string header = m_packageName; + if (!m_tag.empty()) + header += " " + m_tag; + this->listElement->addItem(new tsl::elm::CategoryHeader(header)); + + addWrappedTextItems(this->listElement, m_changelog); + + this->listElement->addItem(new tsl::elm::CategoryHeader("Confirm")); + + auto *installItem = new tsl::elm::ListItem("Install Update"); + installItem->setValue(""); + installItem->setClickListener([this](u64 keys) -> bool { + if ((keys & HidNpadButton_A) == HidNpadButton_A) { + m_parent->startJob(m_packageIndex, false); + tsl::goBack(); + return true; + } + return false; + }); + this->listElement->addItem(installItem); +} + +bool UpdateConfirmGui::handleInput(u64, u64, const HidTouchState &, + HidAnalogStickState, HidAnalogStickState) { + return false; +} diff --git a/Source/hoc-clk/overlay/src/ui/gui/update_confirm_gui.h b/Source/hoc-clk/overlay/src/ui/gui/update_confirm_gui.h new file mode 100644 index 00000000..3439f0fc --- /dev/null +++ b/Source/hoc-clk/overlay/src/ui/gui/update_confirm_gui.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 . + */ + +#pragma once +#include +#include + +#include "base_menu_gui.h" + +class UpdateGui; + +class UpdateConfirmGui : public BaseMenuGui { +public: + UpdateConfirmGui(UpdateGui *parent, int packageIndex, std::string packageName, + std::string tag, std::vector changelog); + ~UpdateConfirmGui() = default; + + void listUI() override; + bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, + HidAnalogStickState leftJoy, HidAnalogStickState rightJoy) override; + +private: + UpdateGui *m_parent; + int m_packageIndex; + std::string m_packageName; + std::string m_tag; + std::vector m_changelog; +}; diff --git a/Source/hoc-clk/overlay/src/ui/gui/update_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/update_gui.cpp index 7160c946..c56c8d5c 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/update_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/update_gui.cpp @@ -17,12 +17,14 @@ #include "update_gui.h" #include "ult_ext.h" #include "base_menu_gui.h" +#include "update_confirm_gui.h" #include "../format.h" #include "../style.h" #include #include #include +#include #include @@ -131,6 +133,29 @@ void UpdateGui::startJob(int packageIndex, bool extractOnly) { } } +void UpdateGui::startChangelogFetch(int packageIndex) { + if (isBusy()) return; + + m_activePackage = packageIndex; + m_resultMessage.clear(); + m_changelogTag.clear(); + m_changelogLines.clear(); + + ult::abortDownload.store(false, std::memory_order_release); + + m_stage.store(UpdateStage::FetchingChangelog, std::memory_order_release); + + if (R_SUCCEEDED(threadCreate(&m_thread, fetchChangelogEntry, this, + nullptr, 0x8000, 0x20, -2))) { + m_threadActive = true; + threadStart(&m_thread); + } else { + m_resultMessage = "Failed to create thread"; + m_stage.store(UpdateStage::Failed, std::memory_order_release); + m_threadActive = false; + } +} + void UpdateGui::requestCancel() { ult::abortDownload.store(true, std::memory_order_release); ult::abortUnzip.store(true, std::memory_order_release); @@ -186,6 +211,55 @@ void UpdateGui::jobBody() { m_stage.store(UpdateStage::Done, std::memory_order_release); } +/* static */ void UpdateGui::fetchChangelogEntry(void *arg) { + static_cast(arg)->fetchChangelogBody(); +} + +void UpdateGui::fetchChangelogBody() { + ult::createDirectory("sdmc:/config/horizon-oc/"); + + bool ok = ult::downloadFile(kReleaseApiUrl, kReleaseInfoPath, false, false); + if (!ok || ult::abortDownload.load(std::memory_order_acquire)) { + m_resultMessage = ult::abortDownload.load(std::memory_order_acquire) + ? "Changelog fetch cancelled" + : "Could not fetch changelog -- check network"; + m_stage.store( + ult::abortDownload.load() ? UpdateStage::Cancelled : UpdateStage::Failed, + std::memory_order_release); + return; + } + + std::unique_ptr root(ult::readJsonFromFile(kReleaseInfoPath)); + std::remove(kReleaseInfoPath); + + if (!root) { + m_resultMessage = "Could not parse changelog"; + m_stage.store(UpdateStage::Failed, std::memory_order_release); + return; + } + + m_changelogTag = ult::getStringFromJson(root.get(), "tag_name"); + const std::string body = ult::getStringFromJson(root.get(), "body"); + + m_changelogLines.clear(); + size_t pos = 0; + while (pos <= body.size()) { + size_t nl = body.find('\n', pos); + std::string line = (nl == std::string::npos) ? body.substr(pos) : body.substr(pos, nl - pos); + if (!line.empty() && line.back() == '\r') + line.pop_back(); + if (!line.empty()) + m_changelogLines.push_back(line); + if (nl == std::string::npos) + break; + pos = nl + 1; + } + if (m_changelogLines.empty()) + m_changelogLines.push_back("No changelog available for this release."); + + m_stage.store(UpdateStage::ChangelogReady, std::memory_order_release); +} + void UpdateGui::listUI() { BaseMenuGui::refresh(); @@ -201,7 +275,12 @@ void UpdateGui::listUI() { item->setClickListener([this, idx](u64 keys) -> bool { if (isBusy()) return false; if (keys & HidNpadButton_A) { - startJob(idx, false); + if (ult::limitedMemory) { + m_status->setState(4, 100, kPackages[idx].displayName, + "Updates cannot be performed on a 4MB overlay heap"); + return true; + } + startChangelogFetch(idx); return true; } return false; @@ -242,6 +321,24 @@ void UpdateGui::pollJob() { return; } + if (stage == UpdateStage::FetchingChangelog) { + m_status->setState(6, 0, pkgName, "Fetching changelog..."); + if (m_items[m_activePackage]) + m_items[m_activePackage]->setValue("..."); + return; + } + + if (stage == UpdateStage::ChangelogReady) { + reapThread(); + m_stage.store(UpdateStage::Idle, std::memory_order_release); + m_status->setState(0, 0, "", ""); + if (m_items[m_activePackage]) + m_items[m_activePackage]->setValue(""); + + m_pendingChangelogConfirm = true; + return; + } + int panelStage = (stage == UpdateStage::Done) ? 3 : (stage == UpdateStage::Failed) ? 4 : 5; @@ -263,6 +360,13 @@ bool UpdateGui::handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState leftJoy, HidAnalogStickState rightJoy) { + if (m_pendingChangelogConfirm) { + m_pendingChangelogConfirm = false; + tsl::changeTo(this, m_activePackage, kPackages[m_activePackage].displayName, + m_changelogTag, m_changelogLines); + return true; + } + if ((keysDown & HidNpadButton_R) && isBusy()) { requestCancel(); return true; diff --git a/Source/hoc-clk/overlay/src/ui/gui/update_gui.h b/Source/hoc-clk/overlay/src/ui/gui/update_gui.h index f81e821b..17b5dd04 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/update_gui.h +++ b/Source/hoc-clk/overlay/src/ui/gui/update_gui.h @@ -19,6 +19,7 @@ #include #include +#include #include "base_menu_gui.h" @@ -35,6 +36,8 @@ public: bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState leftJoy, HidAnalogStickState rightJoy) override; + void startJob(int packageIndex, bool extractOnly); + private: enum class UpdateStage { Idle, @@ -43,6 +46,8 @@ private: Done, Failed, Cancelled, + FetchingChangelog, + ChangelogReady, }; struct PackageInfo { @@ -56,11 +61,14 @@ private: {"Horizon OC + Extensions", "https://github.com/Horizon-OC/Horizon-OC/releases/latest/download/dist_ext.zip", "sdmc:/config/horizon-oc/dist_ext.zip"}, }; + static constexpr const char *kReleaseApiUrl = "https://api.github.com/repos/Horizon-OC/Horizon-OC/releases/latest"; + static constexpr const char *kReleaseInfoPath = "sdmc:/config/horizon-oc/release_info.json"; + bool isBusy() const { return m_stage.load(std::memory_order_acquire) != UpdateStage::Idle; } - void startJob(int packageIndex, bool extractOnly); + void startChangelogFetch(int packageIndex); void requestCancel(); void reapThread(); void pollJob(); @@ -68,6 +76,9 @@ private: static void jobEntry(void *arg); void jobBody(); + static void fetchChangelogEntry(void *arg); + void fetchChangelogBody(); + std::atomic m_stage{UpdateStage::Idle}; int m_activePackage = -1; bool m_extractOnly = false; @@ -75,6 +86,11 @@ private: Thread m_thread{}; std::string m_resultMessage; + std::string m_changelogTag; + std::vector m_changelogLines; + + bool m_pendingChangelogConfirm = false; + tsl::elm::ListItem *m_items[2] = {nullptr, nullptr}; UpdateStatusPanel *m_status = nullptr; diff --git a/Source/hoc-clk/sysmodule/Makefile b/Source/hoc-clk/sysmodule/Makefile index 03b7eb07..362b95f5 100644 --- a/Source/hoc-clk/sysmodule/Makefile +++ b/Source/hoc-clk/sysmodule/Makefile @@ -17,12 +17,18 @@ include $(DEVKITPRO)/libnx/switch_rules # INCLUDES is a list of directories containing header files # EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". #--------------------------------------------------------------------------------- + +rwildcard = $(wildcard $1$2) $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)) + TARGET := hoc-clk CONFIG_DIR := horizon-oc BUILD := build OUTDIR := out RESOURCES := res -SOURCES := src src/hos src/i2c src/ipc src/board src/display src/tsensor src/mgr src/file src/soc src/mapping src/pwr src/util +CSOURCES := $(call rwildcard,src/,*.c) $(call rwildcard,../common/src/,*.c) +CPPSOURCES := $(call rwildcard,src/,*.cpp) $(call rwildcard,../common/src/,*.cpp) +SSOURCES := $(call rwildcard,src/,*.s) $(call rwildcard,../common/src/,*.s) +SOURCES := $(sort $(dir $(CSOURCES) $(CPPSOURCES) $(SSOURCES))) DATA := data INCLUDES := ../common/include src/hos src/soc src/i2c src/util src/pwr src/ipc EXEFS_SRC := exefs_src @@ -39,7 +45,7 @@ DEFINES := -DDISABLE_IPC -DKIP_VERSION=$(KIP_VERSION) -DCUST_REV=$(CUST_REV) -DT ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE -CFLAGS := -g -Wall -Os \ +CFLAGS := -g -Wall -Os -flto=auto \ -ffast-math -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-unwind-tables \ $(ARCH) $(DEFINES) @@ -48,7 +54,7 @@ CFLAGS += $(INCLUDE) -D__SWITCH__ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++23 ASFLAGS := -g $(ARCH) -LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -Wl,-wrap,__cxa_throw -Wl,-wrap,_Unwind_Resume -Wl,-wrap,__gxx_personality_v0 +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Os -flto=auto -Wl,-Map,$(notdir $*.map) -Wl,-wrap,__cxa_throw -Wl,-wrap,_Unwind_Resume -Wl,-wrap,__gxx_personality_v0 LIBS := $(foreach lib,$(LIBNAMES),-l$(lib)) -lnx diff --git a/Source/hoc-clk/sysmodule/perms.json b/Source/hoc-clk/sysmodule/perms.json index 01728ddf..10f005cb 100644 --- a/Source/hoc-clk/sysmodule/perms.json +++ b/Source/hoc-clk/sysmodule/perms.json @@ -46,6 +46,7 @@ "size": "0x00001000", "is_io": true } + }, { "type": "map", "value": { diff --git a/Source/hoc-clk/sysmodule/src/board/board.cpp b/Source/hoc-clk/sysmodule/src/board/board.cpp index bc79045d..de2a7ede 100644 --- a/Source/hoc-clk/sysmodule/src/board/board.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board.cpp @@ -32,7 +32,6 @@ #include #include #include -#include #include #include "../display/display_refresh_rate.hpp" @@ -49,6 +48,12 @@ #include "board_volt.hpp" #include #include +#include "../mapping/mem_map.hpp" +#include "../soc/dram_mrr.hpp" +#include "../i2c/max77620_wdt.hpp" +#include "../mgr/clock_manager.hpp" +#include "../file/config.hpp" +#include "../file/kip.hpp" namespace board { @@ -59,20 +64,91 @@ namespace board { HocClkConsoleType gConsoleType = HocClkConsoleType_Icosa; FuseData fuseData; u8 speedoBracket; + u8 cpuSpeedoBracket; PwmChannelSession iCon; u32 fd = 0, fd2 = 0; -#define PMC_BASE 0x7000E400 -#define APB_MISC_GP_HIDREV 0x804 -#define GP_HIDREV_MAJOR_T210 0x1 -#define GP_HIDREV_MAJOR_T210B01 0x2 -#define APB_BASE 0x70000000 -#define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) -#define FUSE_OFFSET 0x800 + #define PMC_BASE 0x7000E400 + #define APB_MISC_GP_HIDREV 0x804 + #define GP_HIDREV_MAJOR_T210 0x1 + #define GP_HIDREV_MAJOR_T210B01 0x2 + #define APB_BASE 0x70000000 + #define FUSE_RESERVED_ODMX(x) (0x1C8 + 4 * (x)) + #define FUSE_OFFSET 0x800 + + constexpr u32 pscDependencies[] = { PscPmModuleId_Olsc }; + constexpr PscPmModuleId PscModuleId = (PscPmModuleId)705; + + PscPmModule s_pscModule; + bool s_pscPrepared = false; + Thread s_pscThread; + bool s_pscExit = false; + + std::atomic_bool s_isAwake = true; + + void PscThreadFunc(void *) { + while (!s_pscExit) { + Result rc = eventWait(&s_pscModule.event, 1'000'000'000ULL); + if (R_FAILED(rc)) { + continue; // Timeout + } + + PscPmState state; + u32 flags; + rc = pscPmModuleGetRequest(&s_pscModule, &state, &flags); + if (R_SUCCEEDED(rc)) { + if (state == PscPmState_ReadyAwaken) { + i2c::wdt::ResetWdtEnableState(); + i2c::wdt::Pet(); + + if(board::GetSocType() == HocClkSocType_Mariko && + file::config::GetConfigValue(HocClkConfigValue_CPUDVFSMode) == CPUDVFSMode_Modify) { + s32 cpuDvfsOffset = file::config::GetConfigValue(HocClkConfigValue_CPUDVFSOffset); + cpuDvfsOffset = std::max(cpuDvfsOffset, -80); + u32 cpuVmin = GetMinimumCpuVmin(mgr::GetNearestOverrideHz(HocClkModule_MEM) / 1000000, GetCpuSpeedoBracket()); + + if (cpuVmin) { + cpuVmin += cpuDvfsOffset; + } + + ApplyCpuMinVolt(cpuVmin, true); + } + + file::utils::LogLine("[brd]: Ready to awaken"); + + s_isAwake = true; + } else if (state == PscPmState_ReadySleep) { + i2c::wdt::Disarm(); + + ResetToStockMem(); + ResetToStockCpu(); + ApplyCpuMinVolt(0, true); + + file::utils::LogLine("[brd]: Ready to sleep"); + + s_isAwake = false; + } else if (state == PscPmState_ReadyShutdown) { + i2c::wdt::Disarm(); + + ResetToStockMem(); + ResetToStockCpu(); + ApplyCpuMinVolt(0, true); + + file::utils::LogLine("[brd]: Ready to shutdown"); + + s_isAwake = false; + } + + pscPmModuleAcknowledge(&s_pscModule, state); + } + } + } + void FetchHardwareInfos() { ReadFuses(fuseData, fuseVirtAddr); SetGpuBracket(fuseData.gpuSpeedo, speedoBracket); + SetCpuBracket(fuseData.cpuSpeedo, cpuSpeedoBracket); u32 hidrev = *(u32 *)(apbVirtAddr + APB_MISC_GP_HIDREV); if (((hidrev >> 4) & 0xF) >= GP_HIDREV_MAJOR_T210B01) { @@ -193,14 +269,30 @@ namespace board { display::DisplayRefreshConfig cfg = { .clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr, .isLite = (GetConsoleType() == HocClkConsoleType_Hoag), - .isRetroSUPER = integrations::GetRETROSuperStatus() }; + .isRetroSUPER = false }; display::Initialize(&cfg); CacheDfllData(); + InitializeCpuLut(file::kip::IsKipLoaded()); CacheGpuVoltTable(); + + rc = pscmInitialize(); + ASSERT_RESULT_OK(rc, "pscmInitialize"); + + rc = pscmGetPmModule(&s_pscModule, PscModuleId, pscDependencies, sizeof(pscDependencies) / sizeof(u32), true); + ASSERT_RESULT_OK(rc, "pscmGetPmModule"); + + rc = threadCreate(&s_pscThread, PscThreadFunc, nullptr, NULL, 0x1000, 0x10, 3); + ASSERT_RESULT_OK(rc, "threadCreate"); + + rc = threadStart(&s_pscThread); + ASSERT_RESULT_OK(rc, "threadStart"); + + s_isAwake = true; } void Exit() { + if (HOSSVC_HAS_CLKRST) { clkrstExit(); } else { @@ -227,6 +319,16 @@ namespace board { batteryInfoExit(); pmdmntExit(); nvExit(); + + eventFire(&s_pscModule.event); + threadWaitForExit(&s_pscThread); + threadClose(&s_pscThread); + + pscPmModuleFinalize(&s_pscModule); + pscPmModuleClose(&s_pscModule); + pscmExit(); + + i2c::wdt::Disarm(); } HocClkSocType GetSocType() { @@ -238,6 +340,10 @@ namespace board { } u8 GetDramID() { + return soc::IdentifyDramId(); + } + + u8 GetFuseDramId() { return gDramID; } @@ -248,7 +354,7 @@ namespace board { svcCallSecureMonitor(&args); if (args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed - notification::writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!"); + hos::WriteNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!"); return false; } @@ -270,8 +376,12 @@ namespace board { return speedoBracket; } - bool IsUsingRetroSuperDisplay() { - return false; /* stub for now. */ + u8 GetCpuSpeedoBracket() { + return cpuSpeedoBracket; + } + + bool IsAwake() { + return s_isAwake; } } // namespace board diff --git a/Source/hoc-clk/sysmodule/src/board/board.hpp b/Source/hoc-clk/sysmodule/src/board/board.hpp index 453d5fa0..15b50a9b 100644 --- a/Source/hoc-clk/sysmodule/src/board/board.hpp +++ b/Source/hoc-clk/sysmodule/src/board/board.hpp @@ -48,16 +48,18 @@ namespace board { extern HocClkConsoleType gConsoleType; extern FuseData fuseData; extern u8 speedoBracket; + extern u8 cpuSpeedoBracket; void Initialize(); void Exit(); HocClkSocType GetSocType(); HocClkConsoleType GetConsoleType(); + u8 GetFuseDramId(); u8 GetDramID(); u8 GetGpuSpeedoBracket(); + u8 GetCpuSpeedoBracket(); bool IsDram8GB(); void SetDisplayRefreshDockedState(bool docked); FuseData *GetFuseData(); - bool IsUsingRetroSuperDisplay(); - + bool IsAwake(); } // namespace board diff --git a/Source/hoc-clk/sysmodule/src/board/board_freq.cpp b/Source/hoc-clk/sysmodule/src/board/board_freq.cpp index 8386d8ef..5e714da8 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_freq.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_freq.cpp @@ -83,10 +83,10 @@ namespace board { void HandleCpuUv() { if (board::GetSocType() == HocClkSocType_Erista) - board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); // Erista tbreak is always 1581MHz + board::SetDfllTunings(file::config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); // Erista tbreak is always 1581MHz else - board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), - board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf))); + board::SetDfllTunings(file::config::GetConfigValue(KipConfigValue_marikoCpuUVLow), file::config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), + board::CalculateTbreak(file::config::GetConfigValue(KipConfigValue_tableConf))); } void SetHz(HocClkModule module, u32 hz) { @@ -121,7 +121,6 @@ namespace board { svcSleepThread(300'000); ClkrstSetHz(session, pcvHz); } - clkrstCloseSession(&session); } else { PcvSetHz(GetPcvModule(module), pcvHz); @@ -131,12 +130,13 @@ namespace board { PcvSetHz(GetPcvModule(module), pcvHz); } } - if (config::GetConfigValue(HocClkConfigValue_LiveCpuUv) && module == HocClkModule_CPU) { + if (file::config::GetConfigValue(HocClkConfigValue_LiveCpuUv) && module == HocClkModule_CPU) { HandleCpuUv(); } if (useGm20b) { - gm20b::setClock(hz / 1000); - currentInjectedHz = hz; + if (soc::SetClock(hz / 1000)) { + currentInjectedHz = hz; + } } } @@ -154,7 +154,11 @@ namespace board { } if (module == HocClkModule_GPU && currentInjectedHz != 0) { - return currentInjectedHz; + if (GetRealHz(HocClkModule_GPU) != currentInjectedHz) { + currentInjectedHz = 0; + } else { + return currentInjectedHz; + } } if (HOSSVC_HAS_CLKRST) { @@ -183,7 +187,7 @@ namespace board { case HocClkModule_GPU: return t210ClkGpuFreq(); case HocClkModule_MEM: - return config::GetConfigValue(HocClkConfigValue_MemoryFrequencyMeasurementMode) == MemoryFrequencyMeasurementMode_PLL + return file::config::GetConfigValue(HocClkConfigValue_MemoryFrequencyMeasurementMode) == MemoryFrequencyMeasurementMode_PLL ? pllmb::getRamClockRatePLLMB() : t210ClkMemFreq(); case HocClkModule_Display: diff --git a/Source/hoc-clk/sysmodule/src/board/board_freq.hpp b/Source/hoc-clk/sysmodule/src/board/board_freq.hpp index fa774cbe..b0a91b6f 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_freq.hpp +++ b/Source/hoc-clk/sysmodule/src/board/board_freq.hpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "../file/errors.hpp" diff --git a/Source/hoc-clk/sysmodule/src/board/board_fuse.cpp b/Source/hoc-clk/sysmodule/src/board/board_fuse.cpp index 3fd3b849..68b0f102 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_fuse.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_fuse.cpp @@ -60,6 +60,36 @@ namespace board { } } + void SetCpuBracket(u16 speedo, u8 &cpuBracket) { + switch (speedo) { + // Mariko + case 1451 ... 1500: + cpuBracket = 6; + break; + case 1501 ... 1550: + cpuBracket = 5; + break; + case 1551 ... 1600: + cpuBracket = 4; + break; + case 1601 ... 1650: + cpuBracket = 3; + break; + case 1651 ... 1700: + cpuBracket = 2; + break; + case 1701 ... 1750: + cpuBracket = 1; + break; + case 1751 ... 1800: + cpuBracket = 0; + break; + default: + cpuBracket = 6; + break; + } + } + void ReadFuses(FuseData &speedo, u64 fuseVa) { constexpr u32 FuseOffset = 0x800; u8 *fusePtr = reinterpret_cast(fuseVa) + FuseOffset; diff --git a/Source/hoc-clk/sysmodule/src/board/board_fuse.hpp b/Source/hoc-clk/sysmodule/src/board/board_fuse.hpp index 5d81f835..554e2004 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_fuse.hpp +++ b/Source/hoc-clk/sysmodule/src/board/board_fuse.hpp @@ -36,5 +36,6 @@ namespace board { void ReadFuses(FuseData &speedo, u64 fuseVa); void SetGpuBracket(u16 gpuSpeedo, u8 &gpuBracket); + void SetCpuBracket(u16 cpuSpeedo, u8 &cpuBracket); } // namespace board diff --git a/Source/hoc-clk/sysmodule/src/board/board_profile.cpp b/Source/hoc-clk/sysmodule/src/board/board_profile.cpp index 6d7da57e..eadeba8a 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_profile.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_profile.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include "../hos/apm_ext.h" diff --git a/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp b/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp index 3e88eba3..2bdf42ae 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_sensor.cpp @@ -31,12 +31,12 @@ #include #include #include -#include #include #include "../file/config.hpp" #include "../hos/apm_ext.h" #include "../i2c/i2cDrv.h" +#include "../soc/dram_mrr.hpp" #include "../tsensor/aotag.hpp" #include "../tsensor/bq24193.hpp" #include "../tsensor/soctherm.hpp" @@ -47,6 +47,33 @@ namespace board { + namespace { + /* Only poll every 10 ticks to avoid stalling EMC too much */ + constexpr u32 DramMr4PollDivisor = 20; // 1 - 20 seconds depending on polling interval + u32 gDramMr4Tick = DramMr4PollDivisor; + s32 gDramMr4Millis = 30000; /* 4x refresh default */ + + s32 PollDramMr4TempMilli() { + u8 mr4 = 0; + if (!soc::ReadRamMr4(&mr4)) + return 0; /* stock exosphere */ + + /* TODO: verify this table manually*/ + /* Higher tREFI multiplier = slower refresh and vice versa */ + switch (mr4 & 0x7) + { + case 0x0: return 0; /* below operating range */ + case 0x1: return 30000; /* 4x refresh */ + case 0x2: return 50000; /* 2x refresh */ + case 0x3: return 85000; /* 1x refresh */ + case 0x4: return 95000; /* 0.5x refresh */ + case 0x5: return 100000; /* 0.25x refresh */ + case 0x6: return 105000; /* 0.25x refresh, de-rated */ + default: return 110000; /* above operating range */ + } + } + } + s32 GetTemperatureMilli(HocClkThermalSensor sensor) { s32 millis = 0; BatteryChargeInfo info; @@ -90,7 +117,11 @@ namespace board { } case HocClkThermalSensor_MEM: { if (board::GetSocType() == HocClkSocType_Mariko && tsensor::IsInitialized() && tsensor::ReadAotag() > 0) { - millis = (temps.pllx * 0.10f) + (tsensor::ReadAotag() * 0.90f); + if(board::GetConsoleType() == HocClkConsoleType_Aula) { // Aula has a misplaced thermal sensor that makes tBoard report too high + millis = (tsensor::ReadAotag() * 1.0f);// + (gDramMr4Millis * 0.60f); + } else { // On other consoles it's placed correctly so avoid relying on AOTAG + millis = (tsensor::ReadAotag() * 0.40f) + (tmp451TempPcb() * 0.60f);// + (gDramMr4Millis * 0.40f); + } } else { millis = board::GetSocType() == HocClkSocType_Mariko ? temps.pllx : temps.mem; } @@ -101,13 +132,21 @@ namespace board { break; } case HocClkThermalSensor_BQ24193: { - millis = bq24193::getBQTemp(); + millis = tsensor::GetBqTemp(); break; } case HocClkThermalSensor_AO: { millis = tsensor::ReadAotag(); break; } + case HocClkThermalSensor_DRAM: { + if (++gDramMr4Tick >= DramMr4PollDivisor) { + gDramMr4Tick = 0; + gDramMr4Millis = 0;//PollDramMr4TempMilli(); + } + millis = gDramMr4Millis; + break; + } default: { ASSERT_ENUM_VALID(HocClkThermalSensor, sensor); } diff --git a/Source/hoc-clk/sysmodule/src/board/board_volt.cpp b/Source/hoc-clk/sysmodule/src/board/board_volt.cpp index af43b344..12f2b293 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_volt.cpp +++ b/Source/hoc-clk/sysmodule/src/board/board_volt.cpp @@ -70,10 +70,11 @@ namespace board { { 0xdfff, 0xdfff, 0x21707ff, 0x27d07ff }, { 0xdfff, 0xdfff, 0x21707ff, 0x27e07ff }, { 0xdfff, 0xdfff, 0x21707ff, 0x27f07ff }, }; - MarikoCpuUvEntry marikoCpuUvHigh[12] = { + MarikoCpuUvEntry marikoCpuUvHigh[13] = { { 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 }, + { 0x0, 0xdfff, 0, 0x27ff7ff }, }; } // namespace @@ -283,14 +284,13 @@ namespace board { bool ValidateHandle(Handle handle) { if (handle == INVALID_HANDLE) { - fileUtils::LogLine("Invalid handle!"); + file::utils::LogLine("Invalid handle!"); return false; } return true; } - void CacheGpuVoltTable() { // Likely CPU regulator? UnkRegulator reg = { @@ -319,7 +319,7 @@ namespace board { if (R_FAILED(resultProcessMemory) || !address) { svcCloseHandle(handle); - fileUtils::LogLine("[dvfs] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory)); + file::utils::LogLine("[dvfs] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory)); handle = INVALID_HANDLE; return; } @@ -359,11 +359,11 @@ namespace board { // Print info AFTER we exit the handle to avoid hangs for (int i = 0; i < (int)std::size(cpuVoltTable); ++i) { - fileUtils::LogLine("[dvfs] cpu volt %d: %u mV", i, cpuVoltTable[i]); + file::utils::LogLine("[dvfs] cpu volt %d: %u mV", i, cpuVoltTable[i]); } for (int i = 0; i < (int)std::size(voltData.voltTableStock); ++i) { - fileUtils::LogLine("[dvfs] gpu volt %d: %u mV", i, voltData.voltTableStock[0][i]); + file::utils::LogLine("[dvfs] gpu volt %d: %u mV", i, voltData.voltTableStock[0][i]); } return; } @@ -412,7 +412,7 @@ namespace board { ASSERT_RESULT_OK(WriteGpuVoltTable(table), "WriteGpuVoltTable"); voltData.ramVmin = vmin; - fileUtils::LogLine("[dvfs] voltage set to %u mV", vmin); + file::utils::LogLine("[dvfs] voltage set to %u mV", vmin); } u32 GetGpuFreqIndex(u32 hz) { @@ -610,4 +610,237 @@ namespace board { return baseVolt; } } -} // namespace board \ No newline at end of file + + namespace { + constexpr size_t MaxPotentialLutSize = 64; + size_t LutSize = 33; + constexpr u32 PmicVmin = 250; + constexpr u32 PmicStep = 5; + + struct { + volatile u32 *lut = nullptr; + u32 table[MaxPotentialLutSize] = {}; + u32 lastVmin = 0; + u32 outputCfg = 0; + bool initialized = false; + } cpuVoltData; + } + + namespace { + inline void DataSyncBarrier() { + __asm__ volatile("dsb sy" ::: "memory"); + } + + void VolatileCopyDwords(volatile u32 *dst, const volatile u32 *src, size_t dwords) { + for (size_t i = 0; i < dwords; ++i) { + dst[i] = src[i]; + } + + DataSyncBarrier(); + } + + u32 GetLutCode(u32 mv) { + return mv <= PmicVmin ? 0 : (mv - PmicVmin) / PmicStep; + } + + [[maybe_unused]] u32 GetLutVolt(u32 code) { + return code * PmicStep + PmicVmin; + } + + void InitializeLutPtr() { + cpuVoltData.lut = reinterpret_cast(cldvfs + CL_DVFS_LUT_TABLE_0); + } + + void CacheCpuLut() { + VolatileCopyDwords(cpuVoltData.table, cpuVoltData.lut, LutSize); + } + + /* TODO: Dynamically get this from the PCV LUT? */ + void UnstuckFreqWar() { + u32 hz = board::GetHz(HocClkModule_CPU); + /* Voltage needs to be above the forced minimum voltage, so we set a high frequency (will be capped by pcv) for a short time. */ + /* This frequency is only applied for ~255ms. */ + constexpr u32 HighFreqVoltBump = 1963'000'000; + board::SetHz(HocClkModule_CPU, HighFreqVoltBump); + svcSleepThread(5'000'000); + board::SetHz(HocClkModule_CPU, hz); + } + + void AdjustMinLutIndex() { + constexpr u32 Shift = 8; + constexpr u32 Mask = 0x3F << Shift; + /* Index is always 0 for us. */ + constexpr u32 MinLutIndex = 0; + + volatile u32 *reg = reinterpret_cast(cldvfs + CL_DVFS_OUTPUT_CFG_0); + + *reg = (*reg & ~Mask) | ((MinLutIndex << Shift) & Mask); + + static_cast(*reg); + } + + void RestoreMinLutIndex() { + *reinterpret_cast(cldvfs + CL_DVFS_OUTPUT_CFG_0) = cpuVoltData.outputCfg; + } + + void RestoreCpuLut() { + cpuVoltData.lastVmin = 0; + VolatileCopyDwords(cpuVoltData.lut, cpuVoltData.table, LutSize); + RestoreMinLutIndex(); + UnstuckFreqWar(); + } + + u32 FloorLutTable(u32 *lut, u32 minCode) { + u32 floored = 0; + while (floored < LutSize && lut[floored] < minCode) { + lut[floored++] = minCode; + } + return floored; + } + + u32 StripRedundantLutEntries(u32 *lut, u32 redundant) { + const u32 strippedCount = LutSize - redundant; + std::memmove(lut, lut + redundant, sizeof(u32) * strippedCount); + + return strippedCount; + } + + /* Naiive interpolation. */ + u32 InterpolateLut(u32 low, u32 high) { + return low + (high - low) / 2; + } + + /* Find biggest deltas, shift to create a new slot in between it, interpolate later. */ + u32 SplitAndInterpolateDeltas(u32 *lut, u32 validCount) { + while (validCount < LutSize) { + u32 biggestDelta = 0; + u32 upperIdx = 0; + + for (u32 i = 0; i + 1 < validCount; ++i) { + const u32 delta = lut[i + 1] - lut[i]; + if (delta > biggestDelta) { + biggestDelta = delta; + upperIdx = i + 1; + } + } + + if (biggestDelta < 2) { + break; + } + + const u32 mid = InterpolateLut(lut[upperIdx - 1], lut[upperIdx]); + std::memmove(lut + upperIdx + 1, lut + upperIdx, (validCount - upperIdx) * sizeof(u32)); + lut[upperIdx] = mid; + ++validCount; + } + + return validCount; + } + + void PadLutTail(u32 *lut, u32 validCount) { + if (validCount == 0) + return; + for (u32 i = validCount; i < LutSize; ++i) { + lut[i] = lut[validCount - 1]; + } + } + } + + void InitializeCpuLut(bool kip) { + if (kip) { + LutSize = 64; /* Account for patched LUT by KIP */ + } + + InitializeLutPtr(); + + CacheCpuLut(); + + cpuVoltData.outputCfg = *reinterpret_cast(cldvfs + CL_DVFS_OUTPUT_CFG_0); + + cpuVoltData.initialized = true; + + for (u32 i = 0; i < LutSize; i++) { + file::utils::LogLine("[dvfs] CPU Real LUT %d: %dmV", i, GetLutVolt(*(u32*)(cldvfs + CL_DVFS_LUT_TABLE_0 + (i * sizeof(u32))))); + } + } + + /* TODO: Verify table on consoles */ + u32 GetMinimumCpuVmin(u32 freqMhz, u32 bracket) { + struct CpuVminEntry { + u32 freq; + u32 volt; + }; + + static const CpuVminEntry cpuVminRamTable[/* Bracket */ 7][/* Entry */ 12] = { + { {1866, 550}, {1996, 560}, {2133, 570}, {2400, 580}, {2533, 590}, {2666, 600}, {2800, 610}, {2933, 620}, {3066, 630}, {3200, 640}, {3333, 660}, {3466, 680} }, // Bracket 0 (Speedo 1751-1800) + { {1866, 555}, {1996, 565}, {2133, 575}, {2400, 585}, {2533, 595}, {2666, 605}, {2800, 615}, {2933, 625}, {3066, 635}, {3200, 645}, {3333, 665}, {3466, 685} }, // Bracket 1 (Speedo 1701-1750) + { {1866, 560}, {1996, 570}, {2133, 580}, {2400, 590}, {2533, 600}, {2666, 610}, {2800, 620}, {2933, 630}, {3066, 640}, {3200, 650}, {3333, 670}, {3466, 690} }, // Bracket 2 (Speedo 1651-1700) + { {1866, 565}, {1996, 575}, {2133, 585}, {2400, 595}, {2533, 605}, {2666, 615}, {2800, 625}, {2933, 635}, {3066, 645}, {3200, 655}, {3333, 675}, {3466, 695} }, // Bracket 3 (Speedo 1601-1650) + { {1866, 570}, {1996, 580}, {2133, 590}, {2400, 600}, {2533, 610}, {2666, 620}, {2800, 630}, {2933, 640}, {3066, 650}, {3200, 660}, {3333, 680}, {3466, 700} }, // Bracket 4 (Speedo 1551-1600) + { {1866, 575}, {1996, 585}, {2133, 595}, {2400, 605}, {2533, 615}, {2666, 625}, {2800, 635}, {2933, 645}, {3066, 655}, {3200, 665}, {3333, 685}, {3466, 705} }, // Bracket 5 (Speedo 1501-1550) + { {1866, 580}, {1996, 590}, {2133, 600}, {2400, 610}, {2533, 620}, {2666, 630}, {2800, 640}, {2933, 650}, {3066, 660}, {3200, 670}, {3333, 690}, {3466, 710} }, // Bracket 6 (Speedo 1451-1500) + }; + + if (freqMhz <= 1600) { + return 0; // DVFS doesnt work below 1600MHz, it will just use vMin + } + + if (bracket >= std::size(cpuVminRamTable)) { + bracket = 0; + } + + const auto &entries = cpuVminRamTable[bracket]; + u32 baseVolt = entries[std::size(entries) - 1].volt; + for (const auto &entry : entries) { + if (freqMhz <= entry.freq) { + baseVolt = entry.volt; + break; + } + } + + return baseVolt; + } + void ApplyCpuMinVolt(u32 vmin, bool force) { + if(!force) { + if (!cpuVoltData.initialized || (vmin == cpuVoltData.lastVmin)) { + return; + } + } + + file::utils::LogLine("[dvfs]: %setting cpu vmin to %dmV", force ? "Forcefully s" : "S", vmin); + + if (vmin == 0) { + RestoreCpuLut(); + file::utils::LogLine("[dvfs]: Restored LUT"); + return; + } + + u32 tmpLut[MaxPotentialLutSize]; + std::memcpy(tmpLut, cpuVoltData.table, sizeof(tmpLut)); + + const u32 minCode = std::min(GetLutCode(vmin), tmpLut[LutSize - 1]); + + const u32 floored = FloorLutTable(tmpLut, minCode); + if (floored == 0) { + RestoreCpuLut(); + file::utils::LogLine("[dvfs]: Floored, restored LUT"); + return; + } + + u32 redundant = floored - 1; + if (floored < LutSize && tmpLut[floored] == minCode) { + redundant = floored; + } + + u32 valid = StripRedundantLutEntries(tmpLut, redundant); + valid = SplitAndInterpolateDeltas(tmpLut, valid); + PadLutTail(tmpLut, valid); + + VolatileCopyDwords(cpuVoltData.lut, tmpLut, LutSize); + AdjustMinLutIndex(); + + UnstuckFreqWar(); + + cpuVoltData.lastVmin = vmin; + } +} diff --git a/Source/hoc-clk/sysmodule/src/board/board_volt.hpp b/Source/hoc-clk/sysmodule/src/board/board_volt.hpp index bf47470f..49fa4be8 100644 --- a/Source/hoc-clk/sysmodule/src/board/board_volt.hpp +++ b/Source/hoc-clk/sysmodule/src/board/board_volt.hpp @@ -59,5 +59,11 @@ namespace board { void PcvHijackGpuVolts(u32 vmin); void PcvHijackGpuFrequency(u32 voltage, u32 hz); u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket); + void ClDvfsSetOutputCfg(u8 safe, u8 max, u8 min); + void LogOutputCfg(const char *tag); + void SetSafeToMaxAndRelock(); + void InitializeCpuLut(bool kip); + void ApplyCpuMinVolt(u32 vmin, bool force); + u32 GetMinimumCpuVmin(u32 freqMhz, u32 bracket); } // namespace board diff --git a/Source/hoc-clk/sysmodule/src/display/aula.cpp b/Source/hoc-clk/sysmodule/src/display/aula.cpp index 7a6297da..bb8e4eca 100644 --- a/Source/hoc-clk/sysmodule/src/display/aula.cpp +++ b/Source/hoc-clk/sysmodule/src/display/aula.cpp @@ -22,11 +22,9 @@ // I *think* HOS changes this in some ways, so look into it more -namespace AulaDisplay { +namespace display { #define MMIO_REG32(base, off) *(vu32 *)((base) + (off)) #define DSI(off) MMIO_REG32(board::dsiVirtAddr, (off) << 2u) -#define DSI_WR_DATA 0xA -#define DSI_TRIGGER 0x13 void _display_dsi_send_cmd(u8 cmd, u32 param, u32 wait) { DSI(DSI_WR_DATA) = (param << 8) | cmd; @@ -43,4 +41,4 @@ namespace AulaDisplay { _display_dsi_send_cmd(MIPI_DSI_DCS_SHORT_WRITE_PARAM, MIPI_DCS_PRIV_SM_SET_COLOR_MODE | (mode << 8), 0); } -} // namespace AulaDisplay \ No newline at end of file +} // namespace display \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/display/aula.hpp b/Source/hoc-clk/sysmodule/src/display/aula.hpp index 14537fd7..e42b2626 100644 --- a/Source/hoc-clk/sysmodule/src/display/aula.hpp +++ b/Source/hoc-clk/sysmodule/src/display/aula.hpp @@ -18,6 +18,6 @@ #pragma once #include "../board/board.hpp" -namespace AulaDisplay { +namespace display { void SetDisplayColorMode(AulaColorMode mode); } \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/file/config.cpp b/Source/hoc-clk/sysmodule/src/file/config.cpp index d911cebb..92eb9053 100644 --- a/Source/hoc-clk/sysmodule/src/file/config.cpp +++ b/Source/hoc-clk/sysmodule/src/file/config.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #include #include #include -#include #include #include @@ -49,37 +49,45 @@ #include #include -namespace config { +namespace file::config { uint64_t configValues[HocClkConfigValue_EnumMax]; namespace { bool gLoaded = false; - std::string gPath; - time_t gMtime = 0; + std::string gSettingsPath; + std::string gKipPath; + std::string gProfilesDir; + std::string gLegacyPath; + time_t gSettingsMtime = 0; + time_t gKipMtime = 0; std::atomic_bool gEnabled{ false }; std::uint32_t gOverrideFreqs[HocClkModule_EnumMax]; std::map, std::uint32_t> gProfileMHzMap; std::map gProfileCountMap; + std::map gProfileMtimes; + + bool gGlobalLoaded = false; + std::uint64_t gCurrentGameTid = 0; + bool gProfilesDirty = false; + bool gMigrationHappened = false; LockableMutex gConfigMutex; LockableMutex gOverrideMutex; - time_t CheckModificationTime() { + time_t CheckFileMtime(const char *path) { time_t mtime = 0; struct stat st; - if (stat(gPath.c_str(), &st) == 0) { + if (stat(path, &st) == 0) { mtime = st.st_mtime; } return mtime; } std::uint32_t FindClockMHz(std::uint64_t tid, HocClkModule module, HocClkProfile profile) { - if (gLoaded) { - auto it = gProfileMHzMap.find(std::make_tuple(tid, profile, module)); - if (it != gProfileMHzMap.end()) { - return it->second; - } + auto it = gProfileMHzMap.find(std::make_tuple(tid, profile, module)); + if (it != gProfileMHzMap.end()) { + return it->second; } return 0; } @@ -100,33 +108,59 @@ namespace config { return std::max((std::uint32_t)0, mhz * mhzMultiplier); } - int BrowseIniFunc(const char *section, const char *key, const char *value, void *userdata) { + int BrowseSettingsIni(const char *section, const char *key, const char *value, void *userdata) { (void)userdata; - std::uint64_t input; - if (!strcmp(section, CONFIG_VAL_SECTION)) { - for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) { - if (!strcmp(key, hocclkFormatConfigValue((HocClkConfigValue)kval, false))) { - input = strtoul(value, NULL, 0); - if (!hocclkValidConfigValue((HocClkConfigValue)kval, input)) { - input = hocclkDefaultConfigValue((HocClkConfigValue)kval); - fileUtils::LogLine("[cfg] Invalid value for key '%s' in section '%s': using default %d", key, section, input); - } - configValues[kval] = input; - return 1; - } + if (strcmp(section, CONFIG_VAL_SECTION) != 0) { + return 1; + } + + for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) { + if (hocclkIsKipConfigValue((HocClkConfigValue)kval)) { + continue; } + if (!strcmp(key, hocclkFormatConfigValue((HocClkConfigValue)kval, false))) { + std::uint64_t input = strtoul(value, NULL, 0); + if (!hocclkValidConfigValue((HocClkConfigValue)kval, input)) { + input = hocclkDefaultConfigValue((HocClkConfigValue)kval); + file::utils::LogLine("[cfg] Invalid value for key '%s': using default %llu", key, input); + } + configValues[kval] = input; + return 1; + } + } - fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized config value", key, section); + file::utils::LogLine("[cfg] Skipping key '%s' in settings: Unrecognized config value", key); + return 1; + } + + int BrowseKipIni(const char *section, const char *key, const char *value, void *userdata) { + (void)userdata; + if (strcmp(section, CONFIG_VAL_SECTION) != 0) { return 1; } - std::uint64_t tid = strtoul(section, NULL, 16); - - if (!tid || strlen(section) != 16) { - fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Invalid TitleID", key, section); - return 1; + for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) { + if (!hocclkIsKipConfigValue((HocClkConfigValue)kval)) { + continue; + } + if (!strcmp(key, hocclkFormatConfigValue((HocClkConfigValue)kval, false))) { + std::uint64_t input = strtoul(value, NULL, 0); + if (!hocclkValidConfigValue((HocClkConfigValue)kval, input)) { + input = hocclkDefaultConfigValue((HocClkConfigValue)kval); + file::utils::LogLine("[cfg] Invalid value for key '%s': using default %llu", key, input); + } + configValues[kval] = input; + return 1; + } } + file::utils::LogLine("[cfg] Skipping key '%s' in kip: Unrecognized config value", key); + return 1; + } + + int BrowseProfileIni(const char *section, const char *key, const char *value, void *userdata) { + std::uint64_t tid = (std::uint64_t)(uintptr_t)userdata; + HocClkProfile parsedProfile = HocClkProfile_EnumMax; HocClkModule parsedModule = HocClkModule_EnumMax; @@ -149,13 +183,11 @@ namespace config { } if (parsedModule == HocClkModule_EnumMax || parsedProfile == HocClkProfile_EnumMax) { - fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized key", key, section); return 1; } std::uint32_t mhz = strtoul(value, NULL, 10); if (!mhz) { - fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Invalid value", key, section); return 1; } @@ -174,33 +206,327 @@ namespace config { gLoaded = false; gProfileMHzMap.clear(); gProfileCountMap.clear(); + gProfileMtimes.clear(); + gGlobalLoaded = false; + gCurrentGameTid = 0; + gProfilesDirty = false; for (unsigned int i = 0; i < HocClkConfigValue_EnumMax; i++) { configValues[i] = hocclkDefaultConfigValue((HocClkConfigValue)i); } } - void Load() { - fileUtils::LogLine("[cfg] Reading %s", gPath.c_str()); + void LoadSettings() { + file::utils::LogLine("[cfg] Reading %s", gSettingsPath.c_str()); + gSettingsMtime = CheckFileMtime(gSettingsPath.c_str()); + if (!gSettingsMtime) { + file::utils::LogLine("[cfg] Settings file not found, using defaults"); + return; + } + if (!ini_browse(&BrowseSettingsIni, nullptr, gSettingsPath.c_str())) { + file::utils::LogLine("[cfg] Error loading settings file"); + } + } - Close(); - gMtime = CheckModificationTime(); - if (!gMtime) { - fileUtils::LogLine("[cfg] Error finding file"); - } else if (!ini_browse(&BrowseIniFunc, nullptr, gPath.c_str())) { - fileUtils::LogLine("[cfg] Error loading file"); + void LoadKip() { + file::utils::LogLine("[cfg] Reading %s", gKipPath.c_str()); + gKipMtime = CheckFileMtime(gKipPath.c_str()); + if (!gKipMtime) { + file::utils::LogLine("[cfg] KIP config file not found, using defaults"); + return; + } + if (!ini_browse(&BrowseKipIni, nullptr, gKipPath.c_str())) { + file::utils::LogLine("[cfg] Error loading KIP config file"); + } + } + + // "/<16-hex-tid>.ini" + NUL + constexpr size_t PROFILE_PATH_MAX = 64; + + void ProfilePathForTid(std::uint64_t tid, char *outPath, size_t outSize) { + snprintf(outPath, outSize, "%s/%016lX.ini", gProfilesDir.c_str(), tid); + } + + bool IsProfileLoaded(std::uint64_t tid) { + if (tid == HOCCLK_GLOBAL_PROFILE_TID) { + return gGlobalLoaded; + } + return tid != 0 && tid == gCurrentGameTid; + } + + void EvictCurrentGame() { + if (gCurrentGameTid == 0) { + return; + } + const std::uint64_t tid = gCurrentGameTid; + for (unsigned int profile = 0; profile < HocClkProfile_EnumMax; profile++) { + for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) { + gProfileMHzMap.erase(std::make_tuple(tid, (HocClkProfile)profile, (HocClkModule)module)); + } + } + gProfileCountMap.erase(tid); + gProfileMtimes.erase(tid); + gCurrentGameTid = 0; + } + + void DropGlobalProfile() { + for (unsigned int profile = 0; profile < HocClkProfile_EnumMax; profile++) { + for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) { + gProfileMHzMap.erase(std::make_tuple(HOCCLK_GLOBAL_PROFILE_TID, (HocClkProfile)profile, (HocClkModule)module)); + } + } + gProfileCountMap.erase(HOCCLK_GLOBAL_PROFILE_TID); + gProfileMtimes.erase(HOCCLK_GLOBAL_PROFILE_TID); + gGlobalLoaded = false; + } + + void LoadProfileTid(std::uint64_t tid) { + if (tid == 0) { + return; } + const bool isGlobal = (tid == HOCCLK_GLOBAL_PROFILE_TID); + if (IsProfileLoaded(tid)) { + return; + } + + if (!isGlobal) { + EvictCurrentGame(); + } + + char path[PROFILE_PATH_MAX]; + ProfilePathForTid(tid, path, sizeof(path)); + + struct stat st; + if (stat(path, &st) == 0) { + file::utils::LogLine("[cfg] Loading profile %s", path); + ini_browse(&BrowseProfileIni, (void *)(uintptr_t)tid, path); + gProfileMtimes[tid] = st.st_mtime; + } else { + gProfileMtimes.erase(tid); + } + if (isGlobal) { + gGlobalLoaded = true; + } else { + gCurrentGameTid = tid; + } + } + + void Load() { + gLoaded = false; + for (unsigned int i = 0; i < HocClkConfigValue_EnumMax; i++) { + configValues[i] = hocclkDefaultConfigValue((HocClkConfigValue)i); + } + LoadSettings(); + LoadKip(); gLoaded = true; } + struct MigrationData { + std::vector> settingsKeys; + std::vector> kipKeys; + std::vector>> profileEntries; + }; + + int MigrationBrowseFunc(const char *section, const char *key, const char *value, void *userdata) { + MigrationData *data = static_cast(userdata); + + if (!strcmp(section, CONFIG_VAL_SECTION)) { + for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) { + if (!strcmp(key, hocclkFormatConfigValue((HocClkConfigValue)kval, false))) { + if (hocclkIsKipConfigValue((HocClkConfigValue)kval)) { + data->kipKeys.push_back({key, value}); + return 1; + } + data->settingsKeys.push_back({key, value}); + return 1; + } + } + file::utils::LogLine("[cfg] Skipping unrecognized key '%s'", key); + } else { + std::uint64_t tid = strtoul(section, NULL, 16); + if (tid && strlen(section) == 16) { + data->profileEntries.push_back({tid, {key, value}}); + } + } + return 1; + } + + void MigrateLegacyConfig() { + struct stat st; + if (stat(gLegacyPath.c_str(), &st) != 0) { + return; + } + + file::utils::LogLine("[cfg] Migrating legacy config.ini"); + file::utils::LogLine("[cfg] Legacy path: %s", gLegacyPath.c_str()); + file::utils::LogLine("[cfg] Settings path: %s", gSettingsPath.c_str()); + file::utils::LogLine("[cfg] Profiles dir: %s", gProfilesDir.c_str()); + + MigrationData data; + file::utils::LogLine("[cfg] Parsing legacy config.ini..."); + ini_browse(&MigrationBrowseFunc, &data, gLegacyPath.c_str()); + file::utils::LogLine("[cfg] Found %zu settings keys, %zu KIP keys, %zu profile entries", + data.settingsKeys.size(), data.kipKeys.size(), data.profileEntries.size()); + + if (!data.settingsKeys.empty()) { + file::utils::LogLine("[cfg] Creating kip directory: %s", FILE_KIP_DIR); + mkdir(FILE_KIP_DIR, 0777); + file::utils::LogLine("[cfg] Writing %zu settings to %s", data.settingsKeys.size(), gSettingsPath.c_str()); + + std::vector sKeys; + std::vector sVals; + sKeys.reserve(data.settingsKeys.size()); + sVals.reserve(data.settingsKeys.size()); + for (const auto &entry : data.settingsKeys) { + file::utils::LogLine("[cfg] %s = %s", entry.first.c_str(), entry.second.c_str()); + sKeys.push_back(entry.first); + sVals.push_back(entry.second); + } + + std::vector keyPtrs; + std::vector valPtrs; + keyPtrs.reserve(sKeys.size() + 1); + valPtrs.reserve(sVals.size() + 1); + for (size_t i = 0; i < sKeys.size(); i++) { + keyPtrs.push_back(sKeys[i].c_str()); + valPtrs.push_back(sVals[i].c_str()); + } + keyPtrs.push_back(NULL); + valPtrs.push_back(NULL); + + if (!ini_putsection(CONFIG_VAL_SECTION, keyPtrs.data(), valPtrs.data(), gSettingsPath.c_str())) { + file::utils::LogLine("[cfg] FAILED to write settings section"); + } else { + file::utils::LogLine("[cfg] Settings migration done"); + } + } else { + file::utils::LogLine("[cfg] No settings keys to migrate"); + } + + if (!data.kipKeys.empty()) { + file::utils::LogLine("[cfg] Writing %zu KIP keys to %s", data.kipKeys.size(), gKipPath.c_str()); + + std::vector kKeys; + std::vector kVals; + kKeys.reserve(data.kipKeys.size()); + kVals.reserve(data.kipKeys.size()); + for (const auto &entry : data.kipKeys) { + file::utils::LogLine("[cfg] %s = %s", entry.first.c_str(), entry.second.c_str()); + kKeys.push_back(entry.first); + kVals.push_back(entry.second); + } + + std::vector kKeyPtrs; + std::vector kValPtrs; + kKeyPtrs.reserve(kKeys.size() + 1); + kValPtrs.reserve(kVals.size() + 1); + for (size_t i = 0; i < kKeys.size(); i++) { + kKeyPtrs.push_back(kKeys[i].c_str()); + kValPtrs.push_back(kVals[i].c_str()); + } + kKeyPtrs.push_back(NULL); + kValPtrs.push_back(NULL); + + if (!ini_putsection(CONFIG_VAL_SECTION, kKeyPtrs.data(), kValPtrs.data(), gKipPath.c_str())) { + file::utils::LogLine("[cfg] FAILED to write KIP section"); + } else { + file::utils::LogLine("[cfg] KIP migration done"); + } + + for (const auto &entry : data.kipKeys) { + for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) { + if (!hocclkIsKipConfigValue((HocClkConfigValue)kval)) { + continue; + } + if (!strcmp(entry.first.c_str(), hocclkFormatConfigValue((HocClkConfigValue)kval, false))) { + std::uint64_t input = strtoul(entry.second.c_str(), NULL, 0); + if (hocclkValidConfigValue((HocClkConfigValue)kval, input)) { + configValues[kval] = input; + } + break; + } + } + } + } else { + file::utils::LogLine("[cfg] No KIP keys to migrate"); + } + + file::utils::LogLine("[cfg] Creating profiles directory: %s", FILE_PROFILES_DIR); + mkdir(FILE_PROFILES_DIR, 0777); + + std::map>> profileBuckets; + for (const auto &entry : data.profileEntries) { + profileBuckets[entry.first].push_back(entry.second); + } + + file::utils::LogLine("[cfg] Writing %zu profiles (%zu TIDs)", data.profileEntries.size(), profileBuckets.size()); + for (const auto &bucket : profileBuckets) { + char filename[32]; + snprintf(filename, sizeof(filename), "%016lX.ini", bucket.first); + std::string profilePath = gProfilesDir + "/" + filename; + + file::utils::LogLine("[cfg] TID=%016lX %zu keys -> %s", bucket.first, bucket.second.size(), profilePath.c_str()); + + std::vector pKeys; + std::vector pVals; + pKeys.reserve(bucket.second.size()); + pVals.reserve(bucket.second.size()); + for (const auto &kv : bucket.second) { + file::utils::LogLine("[cfg] %s = %s", kv.first.c_str(), kv.second.c_str()); + pKeys.push_back(kv.first); + pVals.push_back(kv.second); + } + + std::vector keyPtrs; + std::vector valPtrs; + keyPtrs.reserve(pKeys.size() + 1); + valPtrs.reserve(pVals.size() + 1); + for (size_t i = 0; i < pKeys.size(); i++) { + keyPtrs.push_back(pKeys[i].c_str()); + valPtrs.push_back(pVals[i].c_str()); + } + keyPtrs.push_back(NULL); + valPtrs.push_back(NULL); + + if (!ini_putsection(CONFIG_VAL_SECTION, keyPtrs.data(), valPtrs.data(), profilePath.c_str())) { + file::utils::LogLine("[cfg] FAILED to write profile for TID %016lX", bucket.first); + } + } + file::utils::LogLine("[cfg] Profiles migration done"); + + file::utils::LogLine("[cfg] Renaming legacy config to config.ini.migrated"); + if (rename(gLegacyPath.c_str(), (gLegacyPath + ".migrated").c_str()) != 0) { + file::utils::LogLine("[cfg] WARNING: Failed to rename legacy config file"); + } + gMigrationHappened = true; + file::utils::LogLine("[cfg] Migration complete"); + } + } // namespace + bool IsProfileDirty() { + return gProfilesDirty; + } + + void SetProfileDirty(bool dirty) { + gProfilesDirty = dirty; + } + void Initialize() { - gPath = FILE_CONFIG_DIR "/config.ini"; + gSettingsPath = FILE_SETTINGS_PATH; + gKipPath = FILE_KIP_CONFIG_PATH; + gProfilesDir = FILE_PROFILES_DIR; + gLegacyPath = FILE_LEGACY_CONFIG_PATH; gLoaded = false; + gMigrationHappened = false; gProfileMHzMap.clear(); gProfileCountMap.clear(); - gMtime = 0; + gProfileMtimes.clear(); + gGlobalLoaded = false; + gCurrentGameTid = 0; + gProfilesDirty = false; + gSettingsMtime = 0; + gKipMtime = 0; gEnabled = false; for (unsigned int i = 0; i < HocClkModule_EnumMax; i++) { gOverrideFreqs[i] = 0; @@ -208,6 +534,15 @@ namespace config { for (unsigned int i = 0; i < HocClkConfigValue_EnumMax; i++) { configValues[i] = hocclkDefaultConfigValue((HocClkConfigValue)i); } + + mkdir(FILE_CONFIG_DIR, 0777); + mkdir(FILE_KIP_DIR, 0777); + mkdir(FILE_PROFILES_DIR, 0777); + + MigrateLegacyConfig(); + + gLoaded = true; + LoadProfileTid(HOCCLK_GLOBAL_PROFILE_TID); } void Exit() { @@ -217,11 +552,40 @@ namespace config { bool Refresh() { std::scoped_lock lock{ gConfigMutex }; - if (!gLoaded || gMtime != CheckModificationTime()) { + time_t settingsMtime = CheckFileMtime(gSettingsPath.c_str()); + time_t kipMtime = CheckFileMtime(gKipPath.c_str()); + if (!gLoaded || gSettingsMtime != settingsMtime || gKipMtime != kipMtime) { Load(); return true; } - return false; + if (IsProfileDirty()) { + SetProfileDirty(false); + return true; + } + + bool profilesChanged = false; + char profilePath[PROFILE_PATH_MAX]; + if (gGlobalLoaded) { + ProfilePathForTid(HOCCLK_GLOBAL_PROFILE_TID, profilePath, sizeof(profilePath)); + auto it = gProfileMtimes.find(HOCCLK_GLOBAL_PROFILE_TID); + time_t known = (it != gProfileMtimes.end()) ? it->second : 0; + if (CheckFileMtime(profilePath) != known) { + file::utils::LogLine("[cfg] Global profile changed on disk, dropping cache"); + DropGlobalProfile(); + profilesChanged = true; + } + } + if (gCurrentGameTid != 0) { + ProfilePathForTid(gCurrentGameTid, profilePath, sizeof(profilePath)); + auto it = gProfileMtimes.find(gCurrentGameTid); + time_t known = (it != gProfileMtimes.end()) ? it->second : 0; + if (CheckFileMtime(profilePath) != known) { + file::utils::LogLine("[cfg] Profile %016lX changed on disk, dropping cache", gCurrentGameTid); + EvictCurrentGame(); + profilesChanged = true; + } + } + return profilesChanged; } bool HasProfilesLoaded() { @@ -231,6 +595,9 @@ namespace config { std::uint32_t GetAutoClockHz(std::uint64_t tid, HocClkModule module, HocClkProfile profile, bool returnRaw) { std::scoped_lock lock{ gConfigMutex }; + if (gLoaded && !IsProfileLoaded(tid)) { + LoadProfileTid(tid); + } switch (profile) { case HocClkProfile_Handheld: return FindClockHzFromProfiles(tid, module, { HocClkProfile_Handheld }, returnRaw ? 1 : 1000000); @@ -253,6 +620,7 @@ namespace config { void GetProfiles(std::uint64_t tid, HocClkTitleProfileList *out_profiles) { std::scoped_lock lock{ gConfigMutex }; + LoadProfileTid(tid); for (unsigned int profile = 0; profile < HocClkProfile_EnumMax; profile++) { for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) { out_profiles->mhzMap[profile][module] = FindClockMHz(tid, (HocClkModule)module, (HocClkProfile)profile); @@ -262,10 +630,13 @@ namespace config { bool SetProfiles(std::uint64_t tid, HocClkTitleProfileList *profiles, bool immediate) { std::scoped_lock lock{ gConfigMutex }; - uint8_t numProfiles = 0; - char section[17] = { 0 }; - snprintf(section, sizeof(section), "%016lX", tid); + mkdir(FILE_PROFILES_DIR, 0777); + + char profilePath[PROFILE_PATH_MAX]; + ProfilePathForTid(tid, profilePath, sizeof(profilePath)); + + uint8_t numProfiles = 0; std::vector keys; std::vector values; @@ -302,10 +673,18 @@ namespace config { keyPointers.push_back(NULL); valuePointers.push_back(NULL); - if (!ini_putsection(section, keyPointers.data(), valuePointers.data(), gPath.c_str())) { + if (keys.empty()) { + struct stat st; + if (stat(profilePath, &st) == 0 && remove(profilePath) != 0) { + file::utils::LogLine("[cfg] Failed to remove empty profile %s", profilePath); + return false; + } + } else if (!ini_putsection(CONFIG_VAL_SECTION, keyPointers.data(), valuePointers.data(), profilePath)) { return false; } + gProfileMtimes[tid] = CheckFileMtime(profilePath); + if (immediate) { mhz = &profiles->mhz[0]; gProfileCountMap[tid] = numProfiles; @@ -319,12 +698,26 @@ namespace config { mhz++; } } + if (tid == HOCCLK_GLOBAL_PROFILE_TID) { + gGlobalLoaded = true; + } else { + if (tid != gCurrentGameTid) { + EvictCurrentGame(); + } + gCurrentGameTid = tid; + } + + SetProfileDirty(true); } return true; } std::uint8_t GetProfileCount(std::uint64_t tid) { + std::scoped_lock lock{ gConfigMutex }; + if (tid != 0 && gLoaded && !IsProfileLoaded(tid)) { + LoadProfileTid(tid); + } auto it = gProfileCountMap.find(tid); if (it == gProfileCountMap.end()) { return 0; @@ -340,6 +733,10 @@ namespace config { return gEnabled; } + bool MigrationHappened() { + return gMigrationHappened; + } + void SetOverrideHz(HocClkModule module, std::uint32_t hz) { ASSERT_ENUM_VALID(HocClkModule, module); std::scoped_lock lock{ gOverrideMutex }; @@ -373,49 +770,79 @@ namespace config { bool SetConfigValues(HocClkConfigValueList *configValues, bool immediate) { std::scoped_lock lock{ gConfigMutex }; - std::vector iniKeys; - std::vector iniValues; - iniKeys.reserve(HocClkConfigValue_EnumMax + 1); - iniValues.reserve(HocClkConfigValue_EnumMax); + std::vector settingsKeys; + std::vector settingsValues; + std::vector kipKeys; + std::vector kipValues; for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) { if (!hocclkValidConfigValue((HocClkConfigValue)kval, configValues->values[kval]) || configValues->values[kval] == hocclkDefaultConfigValue((HocClkConfigValue)kval)) { continue; } - iniValues.push_back(std::to_string(configValues->values[kval])); - iniKeys.push_back(hocclkFormatConfigValue((HocClkConfigValue)kval, false)); + std::string key = hocclkFormatConfigValue((HocClkConfigValue)kval, false); + std::string value = std::to_string(configValues->values[kval]); + + if (hocclkIsKipConfigValue((HocClkConfigValue)kval)) { + kipKeys.push_back(key); + kipValues.push_back(value); + } else { + settingsKeys.push_back(key); + settingsValues.push_back(value); + } } - iniKeys.push_back(NULL); + bool success = true; - std::vector valuePointers; - valuePointers.reserve(iniValues.size() + 1); - for (const auto &val : iniValues) { - valuePointers.push_back(val.c_str()); + if (!settingsKeys.empty()) { + std::vector sKeyPtrs; + std::vector sValPtrs; + sKeyPtrs.reserve(settingsKeys.size() + 1); + sValPtrs.reserve(settingsValues.size() + 1); + for (size_t i = 0; i < settingsKeys.size(); i++) { + sKeyPtrs.push_back(settingsKeys[i].c_str()); + sValPtrs.push_back(settingsValues[i].c_str()); + } + sKeyPtrs.push_back(NULL); + sValPtrs.push_back(NULL); + if (!ini_putsection(CONFIG_VAL_SECTION, sKeyPtrs.data(), sValPtrs.data(), gSettingsPath.c_str())) { + success = false; + } } - valuePointers.push_back(NULL); - if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) { - return false; + if (!kipKeys.empty()) { + std::vector kKeyPtrs; + std::vector kValPtrs; + kKeyPtrs.reserve(kipKeys.size() + 1); + kValPtrs.reserve(kipValues.size() + 1); + for (size_t i = 0; i < kipKeys.size(); i++) { + kKeyPtrs.push_back(kipKeys[i].c_str()); + kValPtrs.push_back(kipValues[i].c_str()); + } + kKeyPtrs.push_back(NULL); + kValPtrs.push_back(NULL); + if (!ini_putsection(CONFIG_VAL_SECTION, kKeyPtrs.data(), kValPtrs.data(), gKipPath.c_str())) { + success = false; + } } if (immediate) { for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) { if (hocclkValidConfigValue((HocClkConfigValue)kval, configValues->values[kval])) { - config::configValues[kval] = configValues->values[kval]; + file::config::configValues[kval] = configValues->values[kval]; } else { - config::configValues[kval] = hocclkDefaultConfigValue((HocClkConfigValue)kval); + file::config::configValues[kval] = hocclkDefaultConfigValue((HocClkConfigValue)kval); } } + SetProfileDirty(true); } - return true; + return success; } bool ResetConfigValue(HocClkConfigValue kval) { if (!HOCCLK_ENUM_VALID(HocClkConfigValue, kval)) { - fileUtils::LogLine("[cfg] Invalid HocClkConfigValue: %u", kval); + file::utils::LogLine("[cfg] Invalid HocClkConfigValue: %u", kval); return false; } @@ -439,13 +866,16 @@ namespace config { } valuePointers.push_back(NULL); - if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) { - fileUtils::LogLine("[cfg] Failed to reset config value %u in INI", kval); + const char *targetPath = hocclkIsKipConfigValue(kval) ? gKipPath.c_str() : gSettingsPath.c_str(); + + if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), targetPath)) { + file::utils::LogLine("[cfg] Failed to reset config value %u in INI", kval); return false; } configValues[kval] = defaultValue; - fileUtils::LogLine("[cfg] Reset config value %u to default: %llu", kval, defaultValue); + file::utils::LogLine("[cfg] Reset config value %u to default: %llu", kval, defaultValue); + SetProfileDirty(true); return true; } @@ -474,12 +904,15 @@ namespace config { valuePointers.push_back(iniValues[0].c_str()); valuePointers.push_back(NULL); - if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) { + const char *targetPath = hocclkIsKipConfigValue(kval) ? gKipPath.c_str() : gSettingsPath.c_str(); + + if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), targetPath)) { return false; } if (immediate) { configValues[kval] = value; + SetProfileDirty(true); } return true; @@ -487,6 +920,7 @@ namespace config { void DeleteKey(const char *section, const char *key) { std::scoped_lock lock{ gConfigMutex }; - ini_puts(section, key, NULL, gPath.c_str()); + ini_puts(section, key, NULL, gSettingsPath.c_str()); + ini_puts(section, key, NULL, gKipPath.c_str()); } -} // namespace config +} // namespace file::config diff --git a/Source/hoc-clk/sysmodule/src/file/config.hpp b/Source/hoc-clk/sysmodule/src/file/config.hpp index 969fa24b..b23ed167 100644 --- a/Source/hoc-clk/sysmodule/src/file/config.hpp +++ b/Source/hoc-clk/sysmodule/src/file/config.hpp @@ -26,12 +26,14 @@ #pragma once +#include +#include #include #include #define CONFIG_VAL_SECTION "values" -namespace config { +namespace file::config { void Initialize(); void Exit(); @@ -39,6 +41,9 @@ namespace config { bool Refresh(); bool HasProfilesLoaded(); + bool IsProfileDirty(); + void SetProfileDirty(bool dirty); + std::uint8_t GetProfileCount(std::uint64_t tid); void GetProfiles(std::uint64_t tid, HocClkTitleProfileList *out_profiles); bool SetProfiles(std::uint64_t tid, HocClkTitleProfileList *profiles, bool immediate); @@ -46,6 +51,7 @@ namespace config { void SetEnabled(bool enabled); bool Enabled(); + bool MigrationHappened(); void SetOverrideHz(HocClkModule module, std::uint32_t hz); std::uint32_t GetOverrideHz(HocClkModule module); @@ -59,4 +65,4 @@ namespace config { extern uint64_t configValues[HocClkConfigValue_EnumMax]; -} // namespace config +} // namespace file::config diff --git a/Source/hoc-clk/sysmodule/src/file/errors.cpp b/Source/hoc-clk/sysmodule/src/file/errors.cpp index 14625cdd..b01171a9 100644 --- a/Source/hoc-clk/sysmodule/src/file/errors.cpp +++ b/Source/hoc-clk/sysmodule/src/file/errors.cpp @@ -30,13 +30,13 @@ #include "errors.hpp" #include "file_utils.hpp" -namespace errors { +namespace file::utils { void ThrowException(const char *format, ...) { va_list args; va_start(args, format); - fileUtils::LogLine(format, args); + LogLine(format, args); va_end(args); diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); // throw std::runtime_error(msg); } -} // namespace errors +} // namespace file::utils diff --git a/Source/hoc-clk/sysmodule/src/file/errors.hpp b/Source/hoc-clk/sysmodule/src/file/errors.hpp index ff9d5c7b..6814c4a4 100644 --- a/Source/hoc-clk/sysmodule/src/file/errors.hpp +++ b/Source/hoc-clk/sysmodule/src/file/errors.hpp @@ -29,7 +29,7 @@ #include #include -#define ERROR_THROW(format, ...) errors::ThrowException(format "\n in %s:%u", ##__VA_ARGS__, __FILE__, __LINE__) +#define ERROR_THROW(format, ...) file::utils::ThrowException(format "\n in %s:%u", ##__VA_ARGS__, __FILE__, __LINE__) #define ERROR_RESULT_THROW(rc, format, ...) ERROR_THROW(format "\n RC: [0x%x] %04d-%04d", ##__VA_ARGS__, rc, R_MODULE(rc), R_DESCRIPTION(rc)) #define ASSERT_RESULT_OK(rc, format, ...) \ if (R_FAILED(rc)) { \ @@ -40,7 +40,7 @@ ERROR_THROW("No such %s: %u", #n, v); \ } -namespace errors { +namespace file::utils { void ThrowException(const char *format, ...); diff --git a/Source/hoc-clk/sysmodule/src/file/file_utils.cpp b/Source/hoc-clk/sysmodule/src/file/file_utils.cpp index 1de9ae5c..5aa9cce7 100644 --- a/Source/hoc-clk/sysmodule/src/file/file_utils.cpp +++ b/Source/hoc-clk/sysmodule/src/file/file_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -26,17 +26,20 @@ #include #include -#include #include #include "../hos/apm_ext.h" #include "file_utils.hpp" +#include "config.hpp" #include #include +#include +#include +#include extern "C" void __libnx_init_time(void); -namespace fileUtils { +namespace file::utils { namespace { @@ -45,23 +48,25 @@ namespace fileUtils { LockableMutex g_csv_mutex; std::atomic_bool g_has_initialized = false; bool g_log_enabled = false; - std::uint64_t g_last_flag_check = 0; + bool g_uart_enabled = false; + bool g_flags_resolved = false; - void RefreshFlags(bool force) { - std::uint64_t now = armTicksToNs(armGetSystemTick()); - if (!force && (now - g_last_flag_check) < FILE_FLAG_CHECK_INTERVAL_NS) { - return; + constexpr size_t MaxPendingLines = 64; + std::vector> g_pending_lines; + + void EmitLine(u64 secs, const char *buff, int len) { + if (g_uart_enabled) { + svcOutputDebugString(buff, len); } - FILE *file = fopen(FILE_LOG_FLAG_PATH, "r"); - if (file) { - g_log_enabled = true; - fclose(file); - } else { - g_log_enabled = false; - } + if (g_log_enabled) { + FILE *file = fopen(FILE_LOG_FILE_PATH, "a"); - g_last_flag_check = now; + if (file) { + fprintf(file, "[%luls] %s", secs, buff); + fclose(file); + } + } } void InitializeThreadFunc(void *args) { @@ -70,6 +75,24 @@ namespace fileUtils { } // namespace + void InitializeLogging() { + const bool logEnabled = config::GetConfigValue(HocClkConfigValue_FileLogging); + const bool uartEnabled = config::GetConfigValue(HocClkConfigValue_UartLogging); + + std::scoped_lock lock{ g_log_mutex }; + g_log_enabled = logEnabled; + g_uart_enabled = uartEnabled; + g_flags_resolved = true; + + if (g_log_enabled || g_uart_enabled) { + for (const auto &[secs, line] : g_pending_lines) { + EmitLine(secs, line.c_str(), (int)line.size()); + } + } + g_pending_lines.clear(); + g_pending_lines.shrink_to_fit(); + } + bool IsInitialized() { return g_has_initialized; } @@ -78,13 +101,25 @@ namespace fileUtils { return g_log_enabled; } + bool IsUartEnabled() { + return g_uart_enabled; + } + void LogLine(const char *format, ...) { std::scoped_lock lock{ g_log_mutex }; + if (!g_has_initialized) { + return; + } + + if (g_flags_resolved && !g_log_enabled && !g_uart_enabled) { + return; + } + va_list args; va_start(args, format); - char buff[0xfff]; + char buff[0x200]; int len = vsnprintf(buff, sizeof(buff), format, args); va_end(args); @@ -98,24 +133,18 @@ namespace fileUtils { buff[len++] = '\n'; buff[len] = '\0'; - // Debug UART log - svcOutputDebugString(buff, len); + timespec now = {}; + clock_gettime(CLOCK_REALTIME, &now); + const u64 secs = now.tv_sec - bootTimeS; - if (g_has_initialized) { - RefreshFlags(false); - - if (g_log_enabled) { - FILE *file = fopen(FILE_LOG_FILE_PATH, "a"); - - if (file) { - timespec now = {}; - clock_gettime(CLOCK_REALTIME, &now); - - fprintf(file, "[%luls] %s", now.tv_sec - bootTimeS, buff); - fclose(file); - } + if (!g_flags_resolved) { + if (g_pending_lines.size() < MaxPendingLines) { + g_pending_lines.emplace_back(secs, std::string(buff, len)); } + return; } + + EmitLine(secs, buff, len); } void WriteContextToCsv(const HocClkContext *context) { @@ -206,7 +235,6 @@ namespace fileUtils { } if (R_SUCCEEDED(rc)) { - RefreshFlags(true); g_has_initialized = true; LogLine("=== hoc-clk " TARGET_VERSION " ==="); LogLine("by m4xw, natinusala, p-sam, Souldbminer, Lightos_ and Dominatorul"); @@ -222,9 +250,10 @@ namespace fileUtils { g_has_initialized = false; g_log_enabled = false; + g_uart_enabled = false; fsdevUnmountAll(); fsExit(); } -} // namespace fileUtils +} // namespace file::utils diff --git a/Source/hoc-clk/sysmodule/src/file/file_utils.hpp b/Source/hoc-clk/sysmodule/src/file/file_utils.hpp index 80460f46..340a6676 100644 --- a/Source/hoc-clk/sysmodule/src/file/file_utils.hpp +++ b/Source/hoc-clk/sysmodule/src/file/file_utils.hpp @@ -35,19 +35,24 @@ #include #define FILE_CONFIG_DIR "/config/" CONFIG_DIR -#define FILE_FLAG_CHECK_INTERVAL_NS (10000ULL * 1000000000ULL) #define FILE_CONTEXT_CSV_PATH FILE_CONFIG_DIR "/context.csv" -#define FILE_LOG_FLAG_PATH FILE_CONFIG_DIR "/log.flag" #define FILE_LOG_FILE_PATH FILE_CONFIG_DIR "/log.txt" +#define FILE_SETTINGS_PATH FILE_CONFIG_DIR "/settings.ini" +#define FILE_KIP_DIR FILE_CONFIG_DIR "/kip" +#define FILE_KIP_CONFIG_PATH FILE_KIP_DIR "/current.ini" +#define FILE_PROFILES_DIR FILE_CONFIG_DIR "/profiles" +#define FILE_LEGACY_CONFIG_PATH FILE_CONFIG_DIR "/config.ini" -namespace fileUtils { +namespace file::utils { void Exit(); Result Initialize(); bool IsInitialized(); bool IsLogEnabled(); + bool IsUartEnabled(); void InitializeAsync(); + void InitializeLogging(); void LogLine(const char *format, ...); void WriteContextToCsv(const HocClkContext *context); -} // namespace fileUtils +} // namespace file::utils diff --git a/Source/hoc-clk/sysmodule/src/file/kip.cpp b/Source/hoc-clk/sysmodule/src/file/kip.cpp index 4f5f675a..6ee37cb7 100644 --- a/Source/hoc-clk/sysmodule/src/file/kip.cpp +++ b/Source/hoc-clk/sysmodule/src/file/kip.cpp @@ -22,22 +22,22 @@ #include "../mapping/mem_map.hpp" #include "kip.hpp" -namespace kip { +namespace file::kip { bool kipAvailable = false; void SetKipData() { // TODO: figure out if this REALLY causes issues (i doubt it) // if(board::GetSocType() == HocClkSocType_Mariko) { - // if(R_FAILED(I2c_BuckConverter_SetMvOut(&I2c_Mariko_DRAM_VDDQ, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt) / 1000))) { - // fileUtils::LogLine("[clock_manager] Failed set i2c vddq"); - // notification::writeNotification("Horizon OC\nFailed to write I2C\nwhile setting vddq"); + // if(R_FAILED(I2c_BuckConverter_SetMvOut(&I2c_Mariko_DRAM_VDDQ, file::config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt) / 1000))) { + // file::utils::LogLine("[clock_manager] Failed set i2c vddq"); + // hos::WriteNotification("Horizon OC\nFailed to write I2C\nwhile setting vddq"); // } // } CustomizeTable table; FILE *fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r+b"); if (fp == NULL) { - notification::writeNotification("Horizon OC\nKip opening failed"); + hos::WriteNotification("Horizon OC\nKip opening failed"); kipAvailable = false; return; } @@ -45,8 +45,8 @@ namespace kip { if (!cust_read_table_f(fp, &table)) { fclose(fp); - fileUtils::LogLine("[kip] Failed to read KIP file"); - notification::writeNotification("Horizon OC\nKip read failed"); + file::utils::LogLine("[kip] Failed to read KIP file"); + hos::WriteNotification("Horizon OC\nKip read failed"); return; } @@ -54,139 +54,147 @@ namespace kip { u32 kipVersion = cust_get_kip_version(&table); if (custRev < CUST_REV || kipVersion < KIP_VERSION) { fclose(fp); - notification::writeNotification("Horizon OC\nOutdated kip detected!\nPlease update Horizon OC"); - fileUtils::LogLine("Cust revision: %u", custRev); - fileUtils::LogLine("Kip version: %u", kipVersion); + hos::WriteNotification("Horizon OC\nOutdated kip detected!\nPlease update Horizon OC"); + file::utils::LogLine("Cust revision: %u", custRev); + file::utils::LogLine("Kip version: %u", kipVersion); return; } else if (custRev > CUST_REV || kipVersion > KIP_VERSION) { fclose(fp); - notification::writeNotification("Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC"); - fileUtils::LogLine("Cust revision: %u", custRev); - fileUtils::LogLine("Kip version: %u", kipVersion); + hos::WriteNotification("Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC"); + file::utils::LogLine("Cust revision: %u", custRev); + file::utils::LogLine("Kip version: %u", kipVersion); return; } - // CUST_WRITE_FIELD_BATCH(&table, mtcConf, config::GetConfigValue(KipConfigValue_mtcConf)); - CUST_WRITE_FIELD_BATCH(&table, hpMode, config::GetConfigValue(KipConfigValue_hpMode)); + // CUST_WRITE_FIELD_BATCH(&table, mtcConf, file::config::GetConfigValue(KipConfigValue_mtcConf)); + CUST_WRITE_FIELD_BATCH(&table, hpMode, file::config::GetConfigValue(KipConfigValue_hpMode)); - CUST_WRITE_FIELD_BATCH(&table, commonEmcMemVolt, config::GetConfigValue(KipConfigValue_commonEmcMemVolt)); - CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock)); - CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, config::GetConfigValue(KipConfigValue_marikoEmcMaxClock)); - CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt)); - CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, config::GetConfigValue(KipConfigValue_emcDvbShift)); - CUST_WRITE_FIELD_BATCH(&table, marikoSocVmax, config::GetConfigValue(KipConfigValue_marikoSocVmax)); + CUST_WRITE_FIELD_BATCH(&table, commonEmcMemVolt, file::config::GetConfigValue(KipConfigValue_commonEmcMemVolt)); + CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock, file::config::GetConfigValue(KipConfigValue_eristaEmcMaxClock)); + CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, file::config::GetConfigValue(KipConfigValue_marikoEmcMaxClock)); + CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, file::config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt)); + CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, file::config::GetConfigValue(KipConfigValue_emcDvbShift)); + CUST_WRITE_FIELD_BATCH(&table, marikoSocVmax, file::config::GetConfigValue(KipConfigValue_marikoSocVmax)); - CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, config::GetConfigValue(KipConfigValue_t1_tRCD)); - CUST_WRITE_FIELD_BATCH(&table, t2_tRP, config::GetConfigValue(KipConfigValue_t2_tRP)); - CUST_WRITE_FIELD_BATCH(&table, t3_tRAS, config::GetConfigValue(KipConfigValue_t3_tRAS)); - CUST_WRITE_FIELD_BATCH(&table, t4_tRRD, config::GetConfigValue(KipConfigValue_t4_tRRD)); - CUST_WRITE_FIELD_BATCH(&table, t5_tRFC, config::GetConfigValue(KipConfigValue_t5_tRFC)); - CUST_WRITE_FIELD_BATCH(&table, t6_tRTW, config::GetConfigValue(KipConfigValue_t6_tRTW)); - CUST_WRITE_FIELD_BATCH(&table, t7_tWTR, config::GetConfigValue(KipConfigValue_t7_tWTR)); - CUST_WRITE_FIELD_BATCH(&table, t8_tREFI, config::GetConfigValue(KipConfigValue_t8_tREFI)); - CUST_WRITE_FIELD_BATCH(&table, stepMode, config::GetConfigValue(KipConfigValue_stepMode)); + CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, file::config::GetConfigValue(KipConfigValue_t1_tRCD)); + CUST_WRITE_FIELD_BATCH(&table, t2_tRP, file::config::GetConfigValue(KipConfigValue_t2_tRP)); + CUST_WRITE_FIELD_BATCH(&table, t3_tRAS, file::config::GetConfigValue(KipConfigValue_t3_tRAS)); + CUST_WRITE_FIELD_BATCH(&table, t4_tRRD, file::config::GetConfigValue(KipConfigValue_t4_tRRD)); + CUST_WRITE_FIELD_BATCH(&table, t5_tRFC, file::config::GetConfigValue(KipConfigValue_t5_tRFC)); + CUST_WRITE_FIELD_BATCH(&table, t6_tRTW, file::config::GetConfigValue(KipConfigValue_t6_tRTW)); + CUST_WRITE_FIELD_BATCH(&table, t7_tWTR, file::config::GetConfigValue(KipConfigValue_t7_tWTR)); + CUST_WRITE_FIELD_BATCH(&table, t8_tREFI, file::config::GetConfigValue(KipConfigValue_t8_tREFI)); + CUST_WRITE_FIELD_BATCH(&table, stepMode, file::config::GetConfigValue(KipConfigValue_stepMode)); - CUST_WRITE_FIELD_BATCH(&table, timingEmcTbreak, config::GetConfigValue(KipConfigValue_timingEmcTbreak)); - CUST_WRITE_FIELD_BATCH(&table, low_t1_tRCD, config::GetConfigValue(KipConfigValue_low_t1_tRCD)); - CUST_WRITE_FIELD_BATCH(&table, low_t2_tRP, config::GetConfigValue(KipConfigValue_low_t2_tRP)); - CUST_WRITE_FIELD_BATCH(&table, low_t3_tRAS, config::GetConfigValue(KipConfigValue_low_t3_tRAS)); - CUST_WRITE_FIELD_BATCH(&table, low_t4_tRRD, config::GetConfigValue(KipConfigValue_low_t4_tRRD)); - CUST_WRITE_FIELD_BATCH(&table, low_t5_tRFC, config::GetConfigValue(KipConfigValue_low_t5_tRFC)); - CUST_WRITE_FIELD_BATCH(&table, low_t6_tRTW, config::GetConfigValue(KipConfigValue_low_t6_tRTW)); - CUST_WRITE_FIELD_BATCH(&table, low_t7_tWTR, config::GetConfigValue(KipConfigValue_low_t7_tWTR)); - CUST_WRITE_FIELD_BATCH(&table, low_t8_tREFI, config::GetConfigValue(KipConfigValue_low_t8_tREFI)); + CUST_WRITE_FIELD_BATCH(&table, timingEmcTbreak, file::config::GetConfigValue(KipConfigValue_timingEmcTbreak)); + CUST_WRITE_FIELD_BATCH(&table, low_t1_tRCD, file::config::GetConfigValue(KipConfigValue_low_t1_tRCD)); + CUST_WRITE_FIELD_BATCH(&table, low_t2_tRP, file::config::GetConfigValue(KipConfigValue_low_t2_tRP)); + CUST_WRITE_FIELD_BATCH(&table, low_t3_tRAS, file::config::GetConfigValue(KipConfigValue_low_t3_tRAS)); + CUST_WRITE_FIELD_BATCH(&table, low_t4_tRRD, file::config::GetConfigValue(KipConfigValue_low_t4_tRRD)); + CUST_WRITE_FIELD_BATCH(&table, low_t5_tRFC, file::config::GetConfigValue(KipConfigValue_low_t5_tRFC)); + CUST_WRITE_FIELD_BATCH(&table, low_t6_tRTW, file::config::GetConfigValue(KipConfigValue_low_t6_tRTW)); + CUST_WRITE_FIELD_BATCH(&table, low_t7_tWTR, file::config::GetConfigValue(KipConfigValue_low_t7_tWTR)); + CUST_WRITE_FIELD_BATCH(&table, low_t8_tREFI, file::config::GetConfigValue(KipConfigValue_low_t8_tREFI)); - CUST_WRITE_FIELD_BATCH(&table, readLatency1333, config::GetConfigValue(KipConfigValue_read_latency_1333)); - CUST_WRITE_FIELD_BATCH(&table, readLatency1600, config::GetConfigValue(KipConfigValue_read_latency_1600)); - CUST_WRITE_FIELD_BATCH(&table, readLatency1866, config::GetConfigValue(KipConfigValue_read_latency_1866)); - CUST_WRITE_FIELD_BATCH(&table, readLatency2133, config::GetConfigValue(KipConfigValue_read_latency_2133)); + CUST_WRITE_FIELD_BATCH(&table, readLatency1333, file::config::GetConfigValue(KipConfigValue_read_latency_1333)); + CUST_WRITE_FIELD_BATCH(&table, readLatency1600, file::config::GetConfigValue(KipConfigValue_read_latency_1600)); + CUST_WRITE_FIELD_BATCH(&table, readLatency1866, file::config::GetConfigValue(KipConfigValue_read_latency_1866)); + CUST_WRITE_FIELD_BATCH(&table, readLatency2133, file::config::GetConfigValue(KipConfigValue_read_latency_2133)); - CUST_WRITE_FIELD_BATCH(&table, writeLatency1333, config::GetConfigValue(KipConfigValue_write_latency_1333)); - CUST_WRITE_FIELD_BATCH(&table, writeLatency1600, config::GetConfigValue(KipConfigValue_write_latency_1600)); - CUST_WRITE_FIELD_BATCH(&table, writeLatency1866, config::GetConfigValue(KipConfigValue_write_latency_1866)); - CUST_WRITE_FIELD_BATCH(&table, writeLatency2133, config::GetConfigValue(KipConfigValue_write_latency_2133)); + CUST_WRITE_FIELD_BATCH(&table, writeLatency1333, file::config::GetConfigValue(KipConfigValue_write_latency_1333)); + CUST_WRITE_FIELD_BATCH(&table, writeLatency1600, file::config::GetConfigValue(KipConfigValue_write_latency_1600)); + CUST_WRITE_FIELD_BATCH(&table, writeLatency1866, file::config::GetConfigValue(KipConfigValue_write_latency_1866)); + CUST_WRITE_FIELD_BATCH(&table, writeLatency2133, file::config::GetConfigValue(KipConfigValue_write_latency_2133)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuUV, config::GetConfigValue(KipConfigValue_eristaCpuUV)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuVmin, config::GetConfigValue(KipConfigValue_eristaCpuVmin)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuMaxVolt, config::GetConfigValue(KipConfigValue_eristaCpuMaxVolt)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuUnlock, config::GetConfigValue(KipConfigValue_eristaCpuUnlock)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuUV, file::config::GetConfigValue(KipConfigValue_eristaCpuUV)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuVmin, file::config::GetConfigValue(KipConfigValue_eristaCpuVmin)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuMaxVolt, file::config::GetConfigValue(KipConfigValue_eristaCpuMaxVolt)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuUnlock, file::config::GetConfigValue(KipConfigValue_eristaCpuUnlock)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuUVLow, config::GetConfigValue(KipConfigValue_marikoCpuUVLow)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuUVHigh, config::GetConfigValue(KipConfigValue_marikoCpuUVHigh)); - CUST_WRITE_FIELD_BATCH(&table, tableConf, config::GetConfigValue(KipConfigValue_tableConf)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuLowVmin, config::GetConfigValue(KipConfigValue_marikoCpuLowVmin)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuHighVmin, config::GetConfigValue(KipConfigValue_marikoCpuHighVmin)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuMaxVolt, config::GetConfigValue(KipConfigValue_marikoCpuMaxVolt)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuMaxClock, config::GetConfigValue(KipConfigValue_marikoCpuMaxClock)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuUVLow, file::config::GetConfigValue(KipConfigValue_marikoCpuUVLow)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuUVHigh, file::config::GetConfigValue(KipConfigValue_marikoCpuUVHigh)); + CUST_WRITE_FIELD_BATCH(&table, tableConf, file::config::GetConfigValue(KipConfigValue_tableConf)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuLowVmin, file::config::GetConfigValue(KipConfigValue_marikoCpuLowVmin)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuHighVmin, file::config::GetConfigValue(KipConfigValue_marikoCpuHighVmin)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuMaxVolt, file::config::GetConfigValue(KipConfigValue_marikoCpuMaxVolt)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuMaxClock, file::config::GetConfigValue(KipConfigValue_marikoCpuMaxClock)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuBoostClock, config::GetConfigValue(KipConfigValue_eristaCpuBoostClock)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuBoostClock, config::GetConfigValue(KipConfigValue_marikoCpuBoostClock)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuBoostClock, file::config::GetConfigValue(KipConfigValue_eristaCpuBoostClock)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuBoostClock, file::config::GetConfigValue(KipConfigValue_marikoCpuBoostClock)); - CUST_WRITE_FIELD_BATCH(&table, eristaGpuUV, config::GetConfigValue(KipConfigValue_eristaGpuUV)); - CUST_WRITE_FIELD_BATCH(&table, eristaGpuVmin, config::GetConfigValue(KipConfigValue_eristaGpuVmin)); + CUST_WRITE_FIELD_BATCH(&table, eristaGpuUV, file::config::GetConfigValue(KipConfigValue_eristaGpuUV)); + CUST_WRITE_FIELD_BATCH(&table, eristaGpuVmin, file::config::GetConfigValue(KipConfigValue_eristaGpuVmin)); - CUST_WRITE_FIELD_BATCH(&table, marikoGpuUV, config::GetConfigValue(KipConfigValue_marikoGpuUV)); - CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmin, config::GetConfigValue(KipConfigValue_marikoGpuVmin)); - CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmax, config::GetConfigValue(KipConfigValue_marikoGpuVmax)); + CUST_WRITE_FIELD_BATCH(&table, marikoGpuUV, file::config::GetConfigValue(KipConfigValue_marikoGpuUV)); + CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmin, file::config::GetConfigValue(KipConfigValue_marikoGpuVmin)); + CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmax, file::config::GetConfigValue(KipConfigValue_marikoGpuVmax)); - CUST_WRITE_FIELD_BATCH(&table, commonGpuVoltOffset, config::GetConfigValue(KipConfigValue_commonGpuVoltOffset)); + CUST_WRITE_FIELD_BATCH(&table, commonGpuVoltOffset, file::config::GetConfigValue(KipConfigValue_commonGpuVoltOffset)); - for (int i = 0; i < 24; i++) { - table.marikoGpuVoltArray[i] = config::GetConfigValue((HocClkConfigValue)(KipConfigValue_g_volt_76800 + i)); + for (int i = 0; i < 25; i++) { + table.marikoGpuVoltArray[i] = file::config::GetConfigValue((HocClkConfigValue)(KipConfigValue_g_volt_76800 + i)); } for (int i = 0; i < 27; i++) { - table.eristaGpuVoltArray[i] = config::GetConfigValue((HocClkConfigValue)(KipConfigValue_g_volt_e_76800 + i)); + table.eristaGpuVoltArray[i] = file::config::GetConfigValue((HocClkConfigValue)(KipConfigValue_g_volt_e_76800 + i)); } for (size_t i = 0; i < 28; ++i) { - table.marikoSocVoltArray[i] = config::GetConfigValue((HocClkConfigValue) (KipConfigValue_g_soc_volt_1866000 + i)); + table.marikoSocVoltArray[i] = file::config::GetConfigValue((HocClkConfigValue) (KipConfigValue_g_soc_volt_1866000 + i)); } - CUST_WRITE_FIELD_BATCH(&table, t6_tRTW_fine_tune, config::GetConfigValue(KipConfigValue_t6_tRTW_fine_tune)); - CUST_WRITE_FIELD_BATCH(&table, t7_tWTR_fine_tune, config::GetConfigValue(KipConfigValue_t7_tWTR_fine_tune)); + CUST_WRITE_FIELD_BATCH(&table, t6_tRTW_fine_tune, file::config::GetConfigValue(KipConfigValue_t6_tRTW_fine_tune)); + CUST_WRITE_FIELD_BATCH(&table, t7_tWTR_fine_tune, file::config::GetConfigValue(KipConfigValue_t7_tWTR_fine_tune)); + CUST_WRITE_FIELD_BATCH(&table, pcvLogVerbosity, file::config::GetConfigValue(KipConfigValue_PcvDebugVerbosity)); if (!cust_write_table_f(fp, &table)) { fclose(fp); - fileUtils::LogLine("[kip] Failed to write KIP file"); - notification::writeNotification("Horizon OC\nKip write failed"); + file::utils::LogLine("[kip] Failed to write KIP file"); + hos::WriteNotification("Horizon OC\nKip write failed"); return; } fclose(fp); HocClkConfigValueList configValues; - config::GetConfigValues(&configValues); + file::config::GetConfigValues(&configValues); - configValues.values[KipCrc32] = (u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum + configValues.values[KipCrc32] = (u64)util::ChecksumFile("sdmc:/atmosphere/kips/hoc.kip"); // write checksum - if (config::SetConfigValues(&configValues, true)) { - fileUtils::LogLine("[kip] KIP data set. CRC32: %ld (Cust Rev %ld)", configValues.values[KipCrc32], + if (file::config::SetConfigValues(&configValues, true)) { + file::utils::LogLine("[kip] KIP data set. CRC32: %ld (Cust Rev %ld)", configValues.values[KipCrc32], configValues.values[KipConfigValue_custRev]); for (u64 i = KipConfigValue_hpMode; i < HocClkConfigValue_EnumMax; i++) { - fileUtils::LogLine("%s: %ld", hocclkFormatConfigValue((HocClkConfigValue)i, false), configValues.values[i]); + file::utils::LogLine("%s: %ld", hocclkFormatConfigValue((HocClkConfigValue)i, false), configValues.values[i]); } } else { - fileUtils::LogLine("[kip] Warning: Failed to set config values from KIP"); - notification::writeNotification("Horizon OC\nKip config set failed"); + file::utils::LogLine("[kip] Warning: Failed to set config values from KIP"); + hos::WriteNotification("Horizon OC\nKip config set failed"); } } bool IsKipLoaded() { - constexpr u32 ExpectedMagic = 0x686F634D; - constexpr uintptr_t LoadMagicAddress = 0x4003DC00; - u32 iramValue = {}; + static bool ran = false; + static bool loaded = false; + if(!ran) { + constexpr u32 ExpectedMagic = 0x686F634D; + constexpr uintptr_t LoadMagicAddress = 0x4003DC00; + u32 iramValue = {}; - SmcCopyFromIram(&iramValue, LoadMagicAddress, sizeof(iramValue)); + SmcCopyFromIram(&iramValue, LoadMagicAddress, sizeof(iramValue)); - if (iramValue == ExpectedMagic) { - iramValue = 0; - SmcCopyToIram(LoadMagicAddress, &iramValue, sizeof(iramValue)); - return true; + if (iramValue == ExpectedMagic) { + iramValue = 0; + SmcCopyToIram(LoadMagicAddress, &iramValue, sizeof(iramValue)); + loaded = true; + } else { + hos::WriteNotification("Kip is not loaded!"); + file::utils::LogLine("Kip was not loaded!"); + loaded = false; + } + ran = true; } - notification::writeNotification("Kip is not loaded!"); - fileUtils::LogLine("Kip was not loaded!"); - return false; + return loaded; } // I know this is very hacky, but the config system in the sysmodule doesn't really support writing @@ -195,62 +203,74 @@ namespace kip { FILE *fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "rb"); if (fp == NULL) { - notification::writeNotification("Horizon OC\nKip opening failed"); + hos::WriteNotification("Horizon OC\nKip opening failed"); kipAvailable = false; return; } kipAvailable = true; HocClkConfigValueList configValues; - config::GetConfigValues(&configValues); + file::config::GetConfigValues(&configValues); CustomizeTable table; if (!cust_read_table_f(fp, &table)) { fclose(fp); - fileUtils::LogLine("[kip] Failed to read KIP file for GetKipData"); - notification::writeNotification("Horizon OC\nKip read failed"); + file::utils::LogLine("[kip] Failed to read KIP file for GetKipData"); + hos::WriteNotification("Horizon OC\nKip read failed"); return; } fclose(fp); // if(cust_get_cust_rev(&table) != CUST_REV) { - // notification::writeNotification("Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC"); + // hos::WriteNotification("Horizon OC\nKip version mismatch\nPlease reinstall Horizon OC"); // return; // } - if ((u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip") != config::GetConfigValue(KipCrc32) && - !config::GetConfigValue(HocClkConfigValue_IsFirstLoad)) { - MigrateKipData(cust_get_cust_rev(&table), cust_get_kip_version(&table)); - SetKipData(); - clockManager::gContext.rebootRequired = true; - notification::writeNotification("Horizon OC\nKIP has been updated\nPlease reboot your console to use Horizon OC"); - return; - } - if (config::GetConfigValue(HocClkConfigValue_IsFirstLoad) == true) { - configValues.values[HocClkConfigValue_IsFirstLoad] = (u64) false; - notification::writeNotification("Horizon OC has been installed"); + /* Hack: Get the actually applied and in use emc max clock for 64 lut freq hack. */ + /* I hate this. */ + /* Don't fetch frequency if it's already set or we would overwrite it. */ + /* This technically only applies to Mariko *for now*. */ + if (mgr::patchedEmcMaxClock == 0) { + if (board::GetSocType() == HocClkSocType_Mariko) { + mgr::patchedEmcMaxClock = cust_get_mariko_emc_max(&table); + } else { + mgr::patchedEmcMaxClock = cust_get_erista_emc_max(&table); + } } - configValues.values[KipCrc32] = (u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum + if ((u64)util::ChecksumFile("sdmc:/atmosphere/kips/hoc.kip") != file::config::GetConfigValue(KipCrc32) && + !file::config::GetConfigValue(HocClkConfigValue_IsFirstLoad)) { + MigrateKipData(cust_get_cust_rev(&table), cust_get_kip_version(&table)); + SetKipData(); + mgr::gContext.rebootRequired = true; + hos::WriteNotification("Horizon OC\nKIP has been updated\nPlease reboot your console to use Horizon OC"); + return; + } + if (file::config::GetConfigValue(HocClkConfigValue_IsFirstLoad) == true) { + configValues.values[HocClkConfigValue_IsFirstLoad] = (u64) false; + hos::WriteNotification("Horizon OC has been installed"); + } + + configValues.values[KipCrc32] = (u64)util::ChecksumFile("sdmc:/atmosphere/kips/hoc.kip"); // write checksum // configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table); - clockManager::gContext.custRev = cust_get_cust_rev(&table); + mgr::gContext.custRev = cust_get_cust_rev(&table); u32 custRev = cust_get_cust_rev(&table); u32 kipVersion = cust_get_kip_version(&table); if (custRev < CUST_REV || kipVersion < KIP_VERSION) { - notification::writeNotification("Horizon OC\nOutdated kip detected!\nPlease update Horizon OC"); - fileUtils::LogLine("Cust revision: %u", custRev); - fileUtils::LogLine("Kip version: %u", kipVersion); + hos::WriteNotification("Horizon OC\nOutdated kip detected!\nPlease update Horizon OC"); + file::utils::LogLine("Cust revision: %u", custRev); + file::utils::LogLine("Kip version: %u", kipVersion); return; } else if (custRev > CUST_REV || kipVersion > KIP_VERSION) { - notification::writeNotification("Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC"); - fileUtils::LogLine("Cust revision: %u", custRev); - fileUtils::LogLine("Kip version: %u", kipVersion); + hos::WriteNotification("Horizon OC\nOutdated sysmodule detected!\nPlease update Horizon OC"); + file::utils::LogLine("Cust revision: %u", custRev); + file::utils::LogLine("Kip version: %u", kipVersion); return; } - clockManager::gContext.isKipLoaded = IsKipLoaded(); - clockManager::gContext.kipVersion = kipVersion; + mgr::gContext.isKipLoaded = IsKipLoaded(); + mgr::gContext.kipVersion = kipVersion; configValues.values[KipConfigValue_custRev] = cust_get_cust_rev(&table); configValues.values[KipConfigValue_KipVersion] = cust_get_kip_version(&table); // Run this after the check so we can do migration process configValues.values[KipConfigValue_hpMode] = cust_get_hp_mode(&table); @@ -314,7 +334,7 @@ namespace kip { configValues.values[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table); configValues.values[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table); - for (int i = 0; i < 24; i++) { + for (int i = 0; i < 25; i++) { configValues.values[KipConfigValue_g_volt_76800 + i] = cust_get_mariko_gpu_volt(&table, i); } @@ -322,33 +342,35 @@ namespace kip { configValues.values[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_volt(&table, i); } - for (size_t i = 0; i < 26; ++i) { + for (size_t i = 0; i < 28; ++i) { configValues.values[KipConfigValue_g_soc_volt_1866000 + i] = cust_get_mariko_soc_volt(&table, i); } configValues.values[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table); configValues.values[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table); + configValues.values[KipConfigValue_PcvDebugVerbosity] = cust_get_log_verbosity(&table); + if (sizeof(HocClkConfigValueList) <= sizeof(configValues)) { - if (config::SetConfigValues(&configValues, true)) { - fileUtils::LogLine("[kip] KIP loaded. CRC32: %ld (Cust Rev %ld)", configValues.values[KipCrc32], + if (file::config::SetConfigValues(&configValues, true)) { + file::utils::LogLine("[kip] KIP loaded. CRC32: %ld (Cust Rev %ld)", configValues.values[KipCrc32], configValues.values[KipConfigValue_custRev]); for (u64 i = KipConfigValue_hpMode; i < HocClkConfigValue_EnumMax; i++) { - fileUtils::LogLine("%s: %ld", hocclkFormatConfigValue((HocClkConfigValue)i, false), configValues.values[i]); + file::utils::LogLine("%s: %ld", hocclkFormatConfigValue((HocClkConfigValue)i, false), configValues.values[i]); } } else { - fileUtils::LogLine("[kip] Warning: Failed to set config values from KIP"); - notification::writeNotification("Horizon OC\nKip config set failed"); + file::utils::LogLine("[kip] Warning: Failed to set config values from KIP"); + hos::WriteNotification("Horizon OC\nKip config set failed"); } } else { - fileUtils::LogLine("[kip] Error: Config value list buffer size mismatch"); - notification::writeNotification("Horizon OC\nConfig Buffer Mismatch"); + file::utils::LogLine("[kip] Error: Config value list buffer size mismatch"); + hos::WriteNotification("Horizon OC\nConfig Buffer Mismatch"); } } void MigrateKipData(u32 custRev, u32 version) { HocClkConfigValueList configValues; - config::GetConfigValues(&configValues); + file::config::GetConfigValues(&configValues); u32 previousVersion = configValues.values[KipConfigValue_KipVersion]; if (previousVersion < 240 && version >= 240) { // <2.4.0 -> 2.4.0 migration @@ -362,11 +384,15 @@ namespace kip { } // delete handheld TDP config entries - config::DeleteKey(CONFIG_VAL_SECTION, "handheld_tdp"); - config::DeleteKey(CONFIG_VAL_SECTION, "tdp_limit"); - config::DeleteKey(CONFIG_VAL_SECTION, "tdp_limit_l"); + file::config::DeleteKey(CONFIG_VAL_SECTION, "handheld_tdp"); + file::config::DeleteKey(CONFIG_VAL_SECTION, "tdp_limit"); + file::config::DeleteKey(CONFIG_VAL_SECTION, "tdp_limit_l"); } - config::SetConfigValues(&configValues, true); + if(previousVersion < 300 && version >= 300) { + configValues.values[KipConfigValue_g_volt_1574400] = 2000; + } + file::config::SetConfigValues(&configValues, true); + } -} // namespace kip +} // namespace file::kip diff --git a/Source/hoc-clk/sysmodule/src/file/kip.hpp b/Source/hoc-clk/sysmodule/src/file/kip.hpp index 408047ee..7c229ff9 100644 --- a/Source/hoc-clk/sysmodule/src/file/kip.hpp +++ b/Source/hoc-clk/sysmodule/src/file/kip.hpp @@ -28,7 +28,7 @@ #include "file_utils.hpp" -namespace kip { +namespace file::kip { extern bool kipAvailable; typedef struct { @@ -94,13 +94,15 @@ namespace kip { u32 commonGpuVoltOffset; u32 eristaGpuVoltArray[27]; - u32 marikoGpuVoltArray[24]; + u32 marikoGpuVoltArray[25]; s32 marikoSocVoltArray[28]; u32 t6_tRTW_fine_tune; u32 t7_tWTR_fine_tune; + + u32 pcvLogVerbosity; - u32 reserved[60]; + u32 reserved[57]; } CustomizeTable; #define CUST_MAGIC "CUST" @@ -393,7 +395,7 @@ namespace kip { } static inline bool cust_set_mariko_gpu_volt(const char *p, int idx, u32 v) { - if (idx < 0 || idx >= 24) + if (idx < 0 || idx >= 25) return false; CustomizeTable t; if (!cust_read_table(p, &t)) @@ -505,6 +507,10 @@ namespace kip { return CUST_GET_FIELD(t, t7_tWTR_fine_tune); } + static inline u32 cust_get_log_verbosity(const CustomizeTable *t) { + return CUST_GET_FIELD(t, pcvLogVerbosity); + } + static inline u32 cust_get_read_latency_1333(const CustomizeTable *t) { return CUST_GET_FIELD(t, readLatency1333); } @@ -601,7 +607,7 @@ namespace kip { } static inline u32 cust_get_mariko_gpu_volt(const CustomizeTable *t, int idx) { - if (!t || idx < 0 || idx >= 24) + if (!t || idx < 0 || idx >= 25) return 0; return t->marikoGpuVoltArray[idx]; } @@ -679,6 +685,7 @@ namespace kip { DECL_MARIKO_GPU_VOLT_HELPER(1459200, 21) DECL_MARIKO_GPU_VOLT_HELPER(1497600, 22) DECL_MARIKO_GPU_VOLT_HELPER(1536000, 23) + DECL_MARIKO_GPU_VOLT_HELPER(1574400, 24) DECL_MARIKO_SOC_VOLT_HELPER(1866000, 0) DECL_MARIKO_SOC_VOLT_HELPER(2000000, 1) @@ -784,6 +791,7 @@ namespace kip { DECL_MARIKO_GPU_VOLT_GET(1459200, 21) DECL_MARIKO_GPU_VOLT_GET(1497600, 22) DECL_MARIKO_GPU_VOLT_GET(1536000, 23) + DECL_MARIKO_GPU_VOLT_GET(1574400, 24) DECL_MARIKO_SOC_VOLT_GET(1866000, 0) DECL_MARIKO_SOC_VOLT_GET(2000000, 1) @@ -817,4 +825,5 @@ namespace kip { void MigrateKipData(u32 custRev, u32 version); void SetKipData(); void GetKipData(); -} // namespace kip \ No newline at end of file + bool IsKipLoaded(); +} // namespace file::kip \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/hos/integrations.cpp b/Source/hoc-clk/sysmodule/src/hos/integrations.cpp index 88dade23..2398d44b 100644 --- a/Source/hoc-clk/sysmodule/src/hos/integrations.cpp +++ b/Source/hoc-clk/sysmodule/src/hos/integrations.cpp @@ -21,7 +21,7 @@ #include "process_management.hpp" #include -namespace integrations { +namespace hos { namespace { @@ -88,11 +88,6 @@ namespace integrations { return stat("sdmc:/atmosphere/contents/0000000000534C56/flags/boot2.flag", &st) == 0; } - bool GetRETROSuperStatus() { - struct stat st = { 0 }; - return stat("sdmc:/config/horizon-oc/retro.flag", &st) == 0; // TODO: unhardcode this - } - void LoadSaltyNX() { if (!CheckSaltyNXPort()) return; @@ -103,7 +98,7 @@ namespace integrations { if (!gSharedMemoryUsed) return 254; - u64 tid = processManagement::GetCurrentApplicationId(); + u64 tid = GetCurrentApplicationId(); if (tid == 0) return 254; @@ -124,7 +119,7 @@ namespace integrations { if (!gSharedMemoryUsed) return 0; - u64 tid = processManagement::GetCurrentApplicationId(); + u64 tid = GetCurrentApplicationId(); if (tid == 0) return 0; @@ -156,4 +151,4 @@ namespace integrations { return 0; } -} // namespace integrations +} // namespace hos diff --git a/Source/hoc-clk/sysmodule/src/hos/integrations.hpp b/Source/hoc-clk/sysmodule/src/hos/integrations.hpp index fe5a8c0f..8d9fee3a 100644 --- a/Source/hoc-clk/sysmodule/src/hos/integrations.hpp +++ b/Source/hoc-clk/sysmodule/src/hos/integrations.hpp @@ -20,7 +20,7 @@ #include #include -namespace integrations { +namespace hos { struct NxFpsSharedBlock { uint32_t MAGIC; @@ -61,9 +61,9 @@ namespace integrations { bool GetSysDockState(); bool GetSaltyNXState(); - bool GetRETROSuperStatus(); + void LoadSaltyNX(); u8 GetSaltyNXFPS(); u16 GetSaltyNXResolutionHeight(); -} // namespace integrations +} // namespace hos diff --git a/Source/hoc-clk/sysmodule/src/hos/lang.cpp b/Source/hoc-clk/sysmodule/src/hos/lang.cpp index 6d959c01..3c2b07ac 100644 --- a/Source/hoc-clk/sysmodule/src/hos/lang.cpp +++ b/Source/hoc-clk/sysmodule/src/hos/lang.cpp @@ -24,7 +24,7 @@ #include "../file/file_utils.hpp" -namespace lang { +namespace hos { namespace { constexpr const char *UltrahandConfigPath = "sdmc:/config/ultrahand/config.ini"; @@ -138,4 +138,4 @@ namespace lang { return text; } -} // namespace lang +} // namespace hos diff --git a/Source/hoc-clk/sysmodule/src/hos/lang.hpp b/Source/hoc-clk/sysmodule/src/hos/lang.hpp index 7b03635b..59a12b17 100644 --- a/Source/hoc-clk/sysmodule/src/hos/lang.hpp +++ b/Source/hoc-clk/sysmodule/src/hos/lang.hpp @@ -19,11 +19,11 @@ #include -namespace lang { +namespace hos { // Translates text using Ultrahand's language setting and // /config/horizon-oc/lang/.json (same format as the overlay). // Returns the original text when no translation is available. std::string Translate(const std::string &text); -} // namespace lang +} // namespace hos diff --git a/Source/hoc-clk/sysmodule/src/hos/notification.cpp b/Source/hoc-clk/sysmodule/src/hos/notification.cpp index 333b0604..c5a2f9fa 100644 --- a/Source/hoc-clk/sysmodule/src/hos/notification.cpp +++ b/Source/hoc-clk/sysmodule/src/hos/notification.cpp @@ -18,8 +18,8 @@ #include "lang.hpp" #include "notification.h" -namespace notification { - void writeNotification(const std::string &message) { +namespace hos { + void WriteNotification(const std::string &message) { static const char *flagPath = "sdmc:/config/ultrahand/flags/NOTIFICATIONS.flag"; FILE *flagFile = fopen(flagPath, "r"); @@ -28,7 +28,7 @@ namespace notification { } fclose(flagFile); - const std::string translated = lang::Translate(message); + const std::string translated = Translate(message); std::string filename = "hoc-" + std::to_string(std::time(nullptr)) + ".notify"; std::string fullPath = "sdmc:/config/ultrahand/notifications/" + filename; @@ -42,4 +42,4 @@ namespace notification { fclose(file); } } -} // namespace notification +} // namespace hos diff --git a/Source/hoc-clk/sysmodule/src/hos/notification.h b/Source/hoc-clk/sysmodule/src/hos/notification.h index 105d1512..ead5028a 100644 --- a/Source/hoc-clk/sysmodule/src/hos/notification.h +++ b/Source/hoc-clk/sysmodule/src/hos/notification.h @@ -20,6 +20,6 @@ #include #include #include -namespace notification { - void writeNotification(const std::string &message); +namespace hos { + void WriteNotification(const std::string &message); } diff --git a/Source/hoc-clk/sysmodule/src/hos/process_management.cpp b/Source/hoc-clk/sysmodule/src/hos/process_management.cpp index 1c2869fd..7c9e4654 100644 --- a/Source/hoc-clk/sysmodule/src/hos/process_management.cpp +++ b/Source/hoc-clk/sysmodule/src/hos/process_management.cpp @@ -31,7 +31,7 @@ #include "process_management.hpp" -namespace processManagement { +namespace hos { namespace { constexpr u64 Qlaunch = 0x0100000000001000ULL; @@ -39,7 +39,7 @@ namespace processManagement { Service pdmqryClone; } // namespace - void Initialize() { + void InitializeProcessManagement() { Result rc = 0; rc = pmdmntInitialize(); @@ -67,7 +67,7 @@ namespace processManagement { } // Ty to Masa for this function! - Result isApplicationOutOfFocus(bool *outOfFocus) { + Result IsApplicationOutOfFocus(bool *outOfFocus) { static s32 last_total_entries = 0; static bool isOutOfFocus = false; s32 total_entries = 0; @@ -158,10 +158,10 @@ namespace processManagement { return tid; } - void Exit() { + void ExitProcessManagement() { pmdmntExit(); pminfoExit(); pdmqryExit(); } -} // namespace processManagement +} // namespace hos diff --git a/Source/hoc-clk/sysmodule/src/hos/process_management.hpp b/Source/hoc-clk/sysmodule/src/hos/process_management.hpp index 6714e067..47cdafc4 100644 --- a/Source/hoc-clk/sysmodule/src/hos/process_management.hpp +++ b/Source/hoc-clk/sysmodule/src/hos/process_management.hpp @@ -27,12 +27,12 @@ #pragma once #include -namespace processManagement { +namespace hos { - void Initialize(); + void InitializeProcessManagement(); void WaitForQLaunch(); u64 GetCurrentApplicationId(); - Result isApplicationOutOfFocus(bool *outOfFocus); - void Exit(); + Result IsApplicationOutOfFocus(bool *outOfFocus); + void ExitProcessManagement(); -} // namespace processManagement +} // namespace hos diff --git a/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp new file mode 100644 index 00000000..22937f8b --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.cpp @@ -0,0 +1,139 @@ +/* + * + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 . + * + */ + +#include "max77620_wdt.hpp" +#include "../file/config.hpp" +#include +#include + +/* PMIC Registers */ +#define MAX77620_REG_CNFGGLBL2 ((u8)0x01) +#define MAX77620_REG_CNFGGLBL3 ((u8)0x02) +#define MAX77620_REG_ONOFFCNFG2 ((u8)0x42) + +/* CNFGGLBL2 bits */ +#define MAX77620_WDTOFFC ((u8)(1u << 4)) /* WDT clear in OFF mode */ +#define MAX77620_WDTSLPC ((u8)(1u << 3)) /* WDT clear in sleep mode */ +#define MAX77620_WDTEN ((u8)(1u << 2)) /* WDT enabled */ + +/* Watchdog timeout period (CNFGGLBL2[1:0]) */ +#define MAX77620_TWD_MASK ((u8)0x03) +#define MAX77620_TWD_2s ((u8)0x00) +#define MAX77620_TWD_16s ((u8)0x01) +#define MAX77620_TWD_64s ((u8)0x02) +#define MAX77620_TWD_128s ((u8)0x03) + +/* CNFGGLBL3 watchdog-clear field (WDTC[1:0]). Writing 0x1 disables WDT. */ +#define MAX77620_WDTC_MASK ((u8)0x03) +#define MAX77620_WDTC_KICK ((u8)0x01) + +/* ONOFFCNFG2 bits */ +#define MAX77620_ONOFFCNFG2_WD_RST_WK ((u8)(1u << 6)) + +/* Is this a watchdog or a watchcat, that is the question */ + +namespace i2c::wdt { + + static bool isWdtEnabled = false; + + static Result update_bits(u8 reg, u8 mask, u8 val) { + u8 cur; + Result rc; + + rc = I2cRead_OutU8(I2cDevice_Max77620Pmic, reg, &cur); + if (R_FAILED(rc)) + return rc; + + cur = (u8)((cur & (u8)~mask) | (val & mask)); + return I2cSet_U8(I2cDevice_Max77620Pmic, reg, cur); + } + + void Arm(max77620_wdt_time_t timeout) { + if (isWdtEnabled) { + return; + } + + Result rc; + u8 twd; + + if ((int)timeout < (int)MAX77620_WDT_2S || (int)timeout > (int)MAX77620_WDT_128S) + return; + + twd = (u8)timeout; + + /* WDT expiry results in a restart */ + rc = update_bits(MAX77620_REG_ONOFFCNFG2, + MAX77620_ONOFFCNFG2_WD_RST_WK, + MAX77620_ONOFFCNFG2_WD_RST_WK); + ASSERT_RESULT_OK(rc, "update_bits"); + + /* Clear WDT in OFF and sleep modes. */ + rc = update_bits(MAX77620_REG_CNFGGLBL2, + (u8)(MAX77620_WDTOFFC | MAX77620_WDTSLPC), + (u8)(MAX77620_WDTOFFC | MAX77620_WDTSLPC)); + ASSERT_RESULT_OK(rc, "update_bits"); + + /* Do what the kernel dows */ + rc = update_bits(MAX77620_REG_CNFGGLBL3, + MAX77620_WDTC_MASK, MAX77620_WDTC_KICK); + ASSERT_RESULT_OK(rc, "update_bits"); + + /* Program the period. */ + rc = update_bits(MAX77620_REG_CNFGGLBL2, MAX77620_TWD_MASK, twd); + ASSERT_RESULT_OK(rc, "update_bits"); + + /* Enable. */ + rc = update_bits(MAX77620_REG_CNFGGLBL2, MAX77620_WDTEN, MAX77620_WDTEN); + ASSERT_RESULT_OK(rc, "update_bits"); + + isWdtEnabled = true; + } + + void Disarm() { + if (!isWdtEnabled) { + return; + } + + Result rc = update_bits(MAX77620_REG_CNFGGLBL2, MAX77620_WDTEN, (u8)0x00); + ASSERT_RESULT_OK(rc, "update_bits"); + + isWdtEnabled = false; + } + + void ResetWdtEnableState() { + + isWdtEnabled = false; + } + + bool IsWdtEnabled() { + return isWdtEnabled; + } + + void Pet() { + const bool watchdogEnabled = file::config::GetConfigValue(HocClkConfigValue_Watchdog); + + if (watchdogEnabled) { + Arm(i2c::wdt::MAX77620_WDT_2S); + Result rc = update_bits(MAX77620_REG_CNFGGLBL3, MAX77620_WDTC_MASK, MAX77620_WDTC_KICK); + ASSERT_RESULT_OK(rc, "update_bits"); + } else { + Disarm(); + } + } + +} // namespace i2c::wdt diff --git a/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.hpp b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.hpp new file mode 100644 index 00000000..005ef6e0 --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/i2c/max77620_wdt.hpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * 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 . + * + */ + +#pragma once + +#include +#include +#include "i2cDrv.h" +#include "../file/errors.hpp" + +namespace i2c::wdt { + + typedef enum { + MAX77620_WDT_2S = 0, /* ~2 seconds */ + MAX77620_WDT_16S = 1, /* ~16 seconds */ + MAX77620_WDT_64S = 2, /* ~64 seconds */ + MAX77620_WDT_128S = 3, /* ~128 seconds */ + } max77620_wdt_time_t; + + void Arm(max77620_wdt_time_t timeout); + void Disarm(); + + void Pet(); + + void ResetWdtEnableState(); + bool IsWdtEnabled(); +} // namespace i2c::wdt diff --git a/Source/hoc-clk/sysmodule/src/ipc/ipc_service.cpp b/Source/hoc-clk/sysmodule/src/ipc/ipc_service.cpp index f6230f69..81247151 100644 --- a/Source/hoc-clk/sysmodule/src/ipc/ipc_service.cpp +++ b/Source/hoc-clk/sysmodule/src/ipc/ipc_service.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include "../file/config.hpp" @@ -62,44 +61,44 @@ namespace ipcService { } Result GetCurrentContext(HocClkContext *out_ctx) { - *out_ctx = clockManager::GetCurrentContext(); + *out_ctx = mgr::GetCurrentContext(); return 0; } Result ExitHandler() { - clockManager::SetRunning(false); + mgr::SetRunning(false); return 0; } Result GetProfileCount(std::uint64_t *tid, std::uint8_t *out_count) { - if (!config::HasProfilesLoaded()) { + if (!file::config::HasProfilesLoaded()) { return HOCCLK_ERROR(ConfigNotLoaded); } - *out_count = config::GetProfileCount(*tid); + *out_count = file::config::GetProfileCount(*tid); return 0; } Result GetProfiles(std::uint64_t *tid, HocClkTitleProfileList *out_profiles) { - if (!config::HasProfilesLoaded()) { + if (!file::config::HasProfilesLoaded()) { return HOCCLK_ERROR(ConfigNotLoaded); } - config::GetProfiles(*tid, out_profiles); + file::config::GetProfiles(*tid, out_profiles); return 0; } Result SetProfiles(HocClkIpc_SetProfiles_Args *args) { - if (!config::HasProfilesLoaded()) { + if (!file::config::HasProfilesLoaded()) { return HOCCLK_ERROR(ConfigNotLoaded); } HocClkTitleProfileList profiles = args->profiles; - if (!config::SetProfiles(args->tid, &profiles, true)) { + if (!file::config::SetProfiles(args->tid, &profiles, true)) { return HOCCLK_ERROR(ConfigSaveFailed); } return 0; } Result SetEnabled(std::uint8_t *enabled) { - config::SetEnabled(*enabled); + file::config::SetEnabled(*enabled); return 0; } @@ -107,24 +106,24 @@ namespace ipcService { if (!HOCCLK_ENUM_VALID(HocClkModule, args->module)) { return HOCCLK_ERROR(Generic); } - config::SetOverrideHz(args->module, args->hz); + file::config::SetOverrideHz(args->module, args->hz); return 0; } Result GetConfigValuesHandler(HocClkConfigValueList *out_configValues) { - if (!config::HasProfilesLoaded()) { + if (!file::config::HasProfilesLoaded()) { return HOCCLK_ERROR(ConfigNotLoaded); } - config::GetConfigValues(out_configValues); + file::config::GetConfigValues(out_configValues); return 0; } Result SetConfigValuesHandler(HocClkConfigValueList *configValues) { - if (!config::HasProfilesLoaded()) { + if (!file::config::HasProfilesLoaded()) { return HOCCLK_ERROR(ConfigNotLoaded); } HocClkConfigValueList copy = *configValues; - if (!config::SetConfigValues(©, true)) { + if (!file::config::SetConfigValues(©, true)) { return HOCCLK_ERROR(ConfigSaveFailed); } return 0; @@ -137,12 +136,12 @@ namespace ipcService { if (args->maxCount != size / sizeof(*out_list)) { return HOCCLK_ERROR(Generic); } - clockManager::GetFreqList(args->module, out_list, args->maxCount, out_count); + mgr::GetFreqList(args->module, out_list, args->maxCount, out_count); return 0; } Result RequestGpuVoltage(HocClkIpc_RequestGpuVoltage_Args *args) { - clockManager::ApplyGpuFreqVoltRequest(args->voltage, args->hz); + mgr::ApplyGpuFreqVoltRequest(args->voltage, args->hz); return 0; } @@ -236,7 +235,7 @@ namespace ipcService { case HocClkIpcCmd_SetKipData: if (r->data.size >= 0) { - kip::SetKipData(); + file::kip::SetKipData(); return 0; } break; @@ -261,7 +260,7 @@ namespace ipcService { return; } if (rc != KERNELRESULT(ConnectionClosed)) { - fileUtils::LogLine("[ipc] ipcServerProcess: [0x%x] %04d-%04d", rc, R_MODULE(rc), R_DESCRIPTION(rc)); + file::utils::LogLine("[ipc] ipcServerProcess: [0x%x] %04d-%04d", rc, R_MODULE(rc), R_DESCRIPTION(rc)); } } } diff --git a/Source/hoc-clk/sysmodule/src/main.cpp b/Source/hoc-clk/sysmodule/src/main.cpp index f7c5b0c1..5ddac8dd 100644 --- a/Source/hoc-clk/sysmodule/src/main.cpp +++ b/Source/hoc-clk/sysmodule/src/main.cpp @@ -120,44 +120,45 @@ void __appExit(void) { } int main(int argc, char **argv) { - Result rc = fileUtils::Initialize(); + Result rc = file::utils::Initialize(); if (R_FAILED(rc)) { fatalThrow(rc); return 1; } - config::Initialize(); - config::Refresh(); // Get config from file + file::config::Initialize(); + file::config::Refresh(); + file::utils::InitializeLogging(); board::Initialize(); - processManagement::Initialize(); + hos::InitializeProcessManagement(); - processManagement::WaitForQLaunch(); + hos::WaitForQLaunch(); - clockManager::Initialize(); + mgr::Initialize(); ipcService::Initialize(); - clockManager::SetRunning(true); - config::SetEnabled(true); + mgr::SetRunning(true); + file::config::SetEnabled(true); ipcService::SetRunning(true); // TemperaturePoint *table; // ReadConfigFile(&table); // InitFanController(table); // StartFanControllerThread(); - while (clockManager::Running()) { - clockManager::Tick(); - clockManager::WaitForNextTick(); + while (mgr::Running()) { + mgr::Tick(); + mgr::WaitForNextTick(); } ipcService::SetRunning(false); ipcService::Exit(); - clockManager::Exit(); - processManagement::Exit(); + mgr::Exit(); + hos::ExitProcessManagement(); board::Exit(); - config::Exit(); - fileUtils::LogLine("Exiting hoc-clk"); + file::config::Exit(); + file::utils::LogLine("Exiting hoc-clk"); svcSleepThread(1000000ULL); - fileUtils::Exit(); + file::utils::Exit(); return 0; } diff --git a/Source/hoc-clk/sysmodule/src/mapping/mem_map.cpp b/Source/hoc-clk/sysmodule/src/mapping/mem_map.cpp index 860df53d..0f807665 100644 --- a/Source/hoc-clk/sysmodule/src/mapping/mem_map.cpp +++ b/Source/hoc-clk/sysmodule/src/mapping/mem_map.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -31,7 +31,7 @@ Result QueryMemoryMapping(u64 *virtaddr, u64 physaddr, u64 size) { Result MapAddress(u64 &va, const u64 &physAddr, const char *name) { Result mapResult = QueryMemoryMapping(&va, physAddr, 0x1000); if (R_FAILED(mapResult)) { - fileUtils::LogLine("Failed to map %s! %u", name, R_DESCRIPTION(mapResult)); + file::utils::LogLine("Failed to map %s! %u", name, R_DESCRIPTION(mapResult)); } return mapResult; @@ -65,4 +65,4 @@ Result SmcCopyToIram(uintptr_t dest, const void *src, u32 size) { rc = (26u | ((u32)args.X[0] << 9u)); } return rc; -} \ No newline at end of file +} diff --git a/Source/hoc-clk/sysmodule/src/mapping/mem_map.hpp b/Source/hoc-clk/sysmodule/src/mapping/mem_map.hpp index d2f76373..6cb6e1be 100644 --- a/Source/hoc-clk/sysmodule/src/mapping/mem_map.hpp +++ b/Source/hoc-clk/sysmodule/src/mapping/mem_map.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, diff --git a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp index a4e75ca5..c5811bb5 100644 --- a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp +++ b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.cpp @@ -44,15 +44,20 @@ #include "../util/lockable_mutex.h" #include "clock_manager.hpp" #include "governor.hpp" +#include "../i2c/max77620_wdt.hpp" + #define HOSPPC_HAS_BOOST (hosversionAtLeast(7, 0, 0)) -namespace clockManager { +namespace mgr { bool gRunning = false; LockableMutex gContextMutex; HocClkContext gContext = {}; FreqTable gFreqTable[HocClkModule_EnumMax]; + /* Hack: Fixes emc 64 lut freq list hack edge case. */ + /* The clock in the config may differ from the actual max clock, so it's read out from the kip before migration or any other potential overwrite. */ + u32 patchedEmcMaxClock = {}; std::uint64_t gLastTempLogNs = 0; std::uint64_t gLastFreqLogNs = 0; std::uint64_t gLastPowerLogNs = 0; @@ -70,7 +75,7 @@ namespace clockManager { } std::uint32_t GetMaxAllowedHz(HocClkModule module, HocClkProfile profile) { - if (config::GetConfigValue(HocClkConfigValue_UncappedClocks)) { + if (file::config::GetConfigValue(HocClkConfigValue_UncappedClocks)) { return ~0; // Integer limit, uncapped clocks ON } else { if (module == HocClkModule_GPU) { @@ -80,7 +85,7 @@ namespace clockManager { return 460800000; case HocClkSocType_Mariko: if (board::GetConsoleType() == HocClkConsoleType_Hoag) { - switch (config::GetConfigValue(KipConfigValue_marikoGpuUV)) { + switch (file::config::GetConfigValue(KipConfigValue_marikoGpuUV)) { case 0 ... 2: return 614400000; case 3 ... 4: @@ -89,7 +94,7 @@ namespace clockManager { return 614400000; } } else { - switch (config::GetConfigValue(KipConfigValue_marikoGpuUV)) { + switch (file::config::GetConfigValue(KipConfigValue_marikoGpuUV)) { case 0: return 614400000; case 1: @@ -112,7 +117,7 @@ namespace clockManager { case HocClkSocType_Erista: return 768000000; case HocClkSocType_Mariko: - switch (config::GetConfigValue(KipConfigValue_marikoGpuUV)) { + switch (file::config::GetConfigValue(KipConfigValue_marikoGpuUV)) { case 0: return 844800000; case 1: @@ -161,19 +166,19 @@ namespace clockManager { void ResetToStockClocks() { board::ResetToStockCpu(); - if (config::GetConfigValue(HocClkConfigValue_LiveCpuUv)) { + if (file::config::GetConfigValue(HocClkConfigValue_LiveCpuUv)) { if (board::GetSocType() == HocClkSocType_Erista) - board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); + board::SetDfllTunings(file::config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); else - board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), - board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf))); + board::SetDfllTunings(file::config::GetConfigValue(KipConfigValue_marikoCpuUVLow), file::config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), + board::CalculateTbreak(file::config::GetConfigValue(KipConfigValue_tableConf))); } board::ResetToStockGpu(); } bool ConfigIntervalTimeout(HocClkConfigValue intervalMsConfigValue, std::uint64_t ns, std::uint64_t *lastLogNs) { - std::uint64_t logInterval = config::GetConfigValue(intervalMsConfigValue) * 1000000ULL; + std::uint64_t logInterval = file::config::GetConfigValue(intervalMsConfigValue) * 1000000ULL; bool shouldLog = logInterval && ((ns - *lastLogNs) > logInterval); if (shouldLog) { @@ -189,14 +194,14 @@ namespace clockManager { std::uint32_t freqs[HOCCLK_FREQ_LIST_MAX]; std::uint32_t count; - fileUtils::LogLine("[mgr] %s freq list refresh", board::GetModuleName(module, true)); + file::utils::LogLine("[mgr] %s freq list refresh", board::GetModuleName(module, true)); board::GetFreqList(module, &freqs[0], HOCCLK_FREQ_LIST_MAX, &count); std::uint32_t *hz = &gFreqTable[module].list[0]; gFreqTable[module].count = 0; if (module == HocClkModule_GPU && board::GetSocType() == HocClkSocType_Mariko && - config::GetConfigValue(HocClkConfigValue_MarikoMiddleFreqs)) { + file::config::GetConfigValue(HocClkConfigValue_MarikoMiddleFreqs)) { constexpr u32 kStep = 38400000; constexpr u32 kPcvStep = 76800000; u32 kMax = ~0; @@ -278,7 +283,7 @@ namespace clockManager { bool skip = false; for (auto &entry : eristaGpuVoltMap) { if (entry.hz == freqs[i]) { - if (config::GetConfigValue(entry.kval) == 2000) { + if (file::config::GetConfigValue(entry.kval) == 2000) { skip = true; } break; @@ -289,7 +294,7 @@ namespace clockManager { } *hz = freqs[i]; - fileUtils::LogLine("[mgr] %02u - %u - %u.%u MHz", gFreqTable[module].count, *hz, *hz / 1000000, *hz / 100000 - *hz / 1000000 * 10); + file::utils::LogLine("[mgr] %02u - %u - %u.%u MHz", gFreqTable[module].count, *hz, *hz / 1000000, *hz / 100000 - *hz / 1000000 * 10); gFreqTable[module].count++; hz++; @@ -297,10 +302,10 @@ namespace clockManager { /* Since it is a pain to patch the vtables in ipc we can just hack the freqs in. You can still set them. */ constexpr u64 EmcClkOSLimitHz = 1600000ULL * 1000; // 1600 MHz - const u64 maxHz = static_cast(config::GetConfigValue(KipConfigValue_marikoEmcMaxClock)) * 1000; + const u64 maxHz = patchedEmcMaxClock * 1000; if (module == HocClkModule_MEM && board::GetSocType() == HocClkSocType_Mariko && - kip::kipAvailable && maxHz >= EmcClkOSLimitHz && - config::GetConfigValue(KipConfigValue_stepMode) == 4 /* 33 MHz */) { + file::kip::kipAvailable && maxHz >= EmcClkOSLimitHz && + file::config::GetConfigValue(KipConfigValue_stepMode) == 4 /* 33 MHz */) { /* Drop the clkrst entries above the OS limit */ u32 kept = 0; @@ -336,12 +341,12 @@ namespace clockManager { } } - fileUtils::LogLine("[mgr] count = %u", gFreqTable[module].count); + file::utils::LogLine("[mgr] count = %u", gFreqTable[module].count); } bool HandleSafetyFeatures(bool isBoost) { - if (((tmp451TempSoc() / 1000) > (int)config::GetConfigValue(HocClkConfigValue_ThermalThrottleThreshold)) && - config::GetConfigValue(HocClkConfigValue_ThermalThrottle)) { + if (((tmp451TempSoc() / 1000) > (int)file::config::GetConfigValue(HocClkConfigValue_ThermalThrottleThreshold)) && + file::config::GetConfigValue(HocClkConfigValue_ThermalThrottle)) { ResetToStockClocks(); return true; } @@ -355,19 +360,19 @@ namespace clockManager { if (++tick > 10) { tick = 0; - if (config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)) { - I2c_Bq24193_SetFastChargeCurrentLimit(config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)); + if (file::config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)) { + I2c_Bq24193_SetFastChargeCurrentLimit(file::config::GetConfigValue(HocClkConfigValue_BatteryChargeCurrent)); } - if (config::GetConfigValue(HocClkConfigValue_InputCurrentLimit)) { - I2c_Bq24193_SetInputCurrentLimit(config::GetConfigValue(HocClkConfigValue_InputCurrentLimit)); + if (file::config::GetConfigValue(HocClkConfigValue_InputCurrentLimit)) { + I2c_Bq24193_SetInputCurrentLimit(file::config::GetConfigValue(HocClkConfigValue_InputCurrentLimit)); } - I2c_BuckConverter_SetMvOut(&I2c_Display, config::GetConfigValue(HocClkConfigValue_DisplayVoltage)); + I2c_BuckConverter_SetMvOut(&I2c_Display, file::config::GetConfigValue(HocClkConfigValue_DisplayVoltage)); if (board::GetConsoleType() == HocClkConsoleType_Aula) - AulaDisplay::SetDisplayColorMode((AulaColorMode)config::GetConfigValue(HocClkConfigValue_AulaDisplayColorPreset)); - if (config::GetConfigValue(HocClkConfigValue_LiveCpuUv)) { + display::SetDisplayColorMode((AulaColorMode)file::config::GetConfigValue(HocClkConfigValue_AulaDisplayColorPreset)); + if (file::config::GetConfigValue(HocClkConfigValue_LiveCpuUv)) { board::HandleCpuUv(); } } @@ -388,9 +393,9 @@ namespace clockManager { u32 GetNearestOverrideHz(HocClkModule module) { u32 targetHz = gContext.overrideFreqs[module]; if (!targetHz) { - targetHz = config::GetAutoClockHz(gContext.applicationId, module, gContext.profile, false); + targetHz = file::config::GetAutoClockHz(gContext.applicationId, module, gContext.profile, false); if (!targetHz) { - targetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, module, gContext.profile, false); + targetHz = file::config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, module, gContext.profile, false); } } @@ -405,7 +410,7 @@ namespace clockManager { /* Apply nothing with disabled voltage. */ constexpr u32 DisabledVoltage = 2000; if (voltage == DisabledVoltage) { - notification::writeNotification("Horizon OC\nDeactivated frequency.\nReboot to apply."); + hos::WriteNotification("Horizon OC\nDeactivated frequency.\nReboot to apply."); return; } @@ -421,32 +426,54 @@ namespace clockManager { board::SetHz(HocClkModule_GPU, currentFreq); } - void ApplyGpuDvfs(u32 targetHz) { - s32 dvfsOffset = config::GetConfigValue(HocClkConfigValue_DVFSOffset); - dvfsOffset = std::max(dvfsOffset, -80); - u32 vmin = board::GetMinimumGpuVmin(targetHz / 1000000, board::GetGpuSpeedoBracket()); + bool IsGpuDvfsEnabled() { + return file::config::GetConfigValue(HocClkConfigValue_GPUDVFSMode) == DVFSMode_Hijack; + } - if (vmin) { - vmin += dvfsOffset; + bool IsCpuDvfsEnabled() { + return board::GetSocType() == HocClkSocType_Mariko && file::config::GetConfigValue(HocClkConfigValue_CPUDVFSMode) == CPUDVFSMode_Modify; + } + + void ApplyRamOcDvfs(u32 targetHz) { + if (IsGpuDvfsEnabled()) { + s32 gpuDvfsOffset = file::config::GetConfigValue(HocClkConfigValue_GPUDVFSOffset); + gpuDvfsOffset = std::max(gpuDvfsOffset, -80); + u32 gpuVmin = board::GetMinimumGpuVmin(targetHz / 1000000, board::GetGpuSpeedoBracket()); + + if (gpuVmin) { + gpuVmin += gpuDvfsOffset; + } + + /* Prevent console from combusting if for some reason bad shit happens :P */ + gpuVmin = ClampGpuVoltage(gpuVmin); + + /* Hijack gpu volt table. */ + board::PcvHijackGpuVolts(gpuVmin); + + /* Update gpu frequency to actually use the voltage. */ + if (targetHz) { + board::SetHz(HocClkModule_GPU, GetCurrentNearestFrequency(HocClkModule_GPU)); + } else { + /* If the target frequency is zero, we reset the frequency to ensure it gets updated even without any frequency override. */ + board::ResetToStockGpu(); + } } - /* Prevent console from combusting if for some reason bad shit happens :P */ - vmin = ClampGpuVoltage(vmin); + if (IsCpuDvfsEnabled()) { + s32 cpuDvfsOffset = file::config::GetConfigValue(HocClkConfigValue_CPUDVFSOffset); + cpuDvfsOffset = std::max(cpuDvfsOffset, -80); + u32 cpuVmin = board::GetMinimumCpuVmin(targetHz / 1000000, board::GetCpuSpeedoBracket()); - /* Hijack gpu volt table. */ - board::PcvHijackGpuVolts(vmin); + if (cpuVmin) { + cpuVmin += cpuDvfsOffset; + } - /* Update gpu frequency to actually use the voltage. */ - if (targetHz) { - board::SetHz(HocClkModule_GPU, GetCurrentNearestFrequency(HocClkModule_GPU)); - } else { - /* If the target frequency is zero, we reset the frequency to ensure it gets updated even without any frequency override. */ - board::ResetToStockGpu(); + board::ApplyCpuMinVolt(cpuVmin, false); } } void DVFSReset() { - if (config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { + if (IsGpuDvfsEnabled()) { board::PcvHijackGpuVolts(0); // Reset to vMin u32 targetHz = GetNearestOverrideHz(HocClkModule_GPU); @@ -455,20 +482,24 @@ namespace clockManager { if (targetHz) board::SetHz(HocClkModule_GPU, targetHz); } + + if (IsCpuDvfsEnabled()) { + board::ApplyCpuMinVolt(0, false); + } } void HandleFreqReset(HocClkModule module, bool isBoost, bool didHijackPcv) { switch (module) { case HocClkModule_CPU: - if (!(isBoost || (config::GetConfigValue(HocClkConfigValue_OverwriteBoostMode) && isBoost))) + if (!(isBoost || (file::config::GetConfigValue(HocClkConfigValue_OverwriteBoostMode) && isBoost))) board::ResetToStockCpu(); - if (config::GetConfigValue(HocClkConfigValue_LiveCpuUv)) { + if (file::config::GetConfigValue(HocClkConfigValue_LiveCpuUv)) { if (board::GetSocType() == HocClkSocType_Erista) - board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); + board::SetDfllTunings(file::config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); else - board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), - config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), - board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf))); + board::SetDfllTunings(file::config::GetConfigValue(KipConfigValue_marikoCpuUVLow), + file::config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), + board::CalculateTbreak(file::config::GetConfigValue(KipConfigValue_tableConf))); } break; case HocClkModule_GPU: @@ -482,7 +513,7 @@ namespace clockManager { } break; case HocClkModule_Display: - if (config::GetConfigValue(HocClkConfigValue_OverwriteRefreshRate)) { + if (file::config::GetConfigValue(HocClkConfigValue_OverwriteRefreshRate)) { board::ResetToStockDisplay(); } break; @@ -500,12 +531,12 @@ namespace clockManager { u32 nearestFreq = GetCurrentNearestFrequency(HocClkModule_MEM); - if (targetRamHz != nearestFreq) { - if (config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { - ApplyGpuDvfs(targetRamHz); - } - + if (targetRamHz > nearestFreq) { + ApplyRamOcDvfs(targetRamHz); board::SetHz(HocClkModule_MEM, targetRamHz); + } else if (targetRamHz < nearestFreq) { + board::SetHz(HocClkModule_MEM, targetRamHz); + ApplyRamOcDvfs(targetRamHz); } } @@ -516,7 +547,7 @@ namespace clockManager { static bool prepareBoostExit = false; bool didHijackPcv = false; - bool skipCpuDueToBoost = isBoost && !config::GetConfigValue(HocClkConfigValue_OverwriteBoostMode); + bool skipCpuDueToBoost = isBoost && !file::config::GetConfigValue(HocClkConfigValue_OverwriteBoostMode); if (skipCpuDueToBoost) { board::SetHz(HocClkModule_CPU, board::GetHz(HocClkModule_CPU)); prepareBoostExit = true; @@ -529,8 +560,6 @@ namespace clockManager { prepareBoostExit = false; } - u32 ramTargetHz = GetNearestOverrideHz(HocClkModule_MEM); - bool returnRaw = false; // Return a value scaled to MHz instead of raw value for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) { u32 oldHz = board::GetHz((HocClkModule)module); // Get Old hz (used primarily for DVFS Logic) @@ -541,22 +570,22 @@ namespace clockManager { returnRaw = false; targetHz = gContext.overrideFreqs[module]; if (!targetHz) { - targetHz = config::GetAutoClockHz(gContext.applicationId, (HocClkModule)module, gContext.profile, returnRaw); + targetHz = file::config::GetAutoClockHz(gContext.applicationId, (HocClkModule)module, gContext.profile, returnRaw); if (!targetHz) - targetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, (HocClkModule)module, gContext.profile, returnRaw); + targetHz = file::config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, (HocClkModule)module, gContext.profile, returnRaw); } if (module == HocClkModule_Governor) { - governor::HandleGovernor(targetHz); + mgr::HandleGovernor(targetHz); } - bool noCPU = governor::isCpuGovernorEnabled; - bool noGPU = governor::isGpuGovernorEnabled; - bool noDisp = governor::isVRREnabled; + bool noCPU = mgr::isCpuGovernorEnabled; + bool noGPU = mgr::isGpuGovernorEnabled; + bool noDisp = mgr::isVRREnabled; if (noDisp && module == HocClkModule_Display) continue; - if (module == HocClkModule_Display && config::GetConfigValue(HocClkConfigValue_OverwriteRefreshRate) && !noDisp) { + if (module == HocClkModule_Display && file::config::GetConfigValue(HocClkConfigValue_OverwriteRefreshRate) && !noDisp) { if (targetHz) { board::SetHz(HocClkModule_Display, targetHz); gContext.freqs[HocClkModule_Display] = targetHz; @@ -579,30 +608,20 @@ namespace clockManager { if (noGPU && module == HocClkModule_GPU) continue; - u32 autoCpuOcHz = 0; - if (module == HocClkModule_CPU && config::GetConfigValue(HocClkConfigValue_AutoRAMCPUOverclock) && !isBoost && - !governor::isCpuGovernorEnabled && (board::GetSocType() == HocClkSocType_Mariko)) { - u32 threshold = (u32)config::GetConfigValue(HocClkConfigValue_AutoRamCpuRamOCThreshold) * 1000; - if (ramTargetHz >= threshold) - autoCpuOcHz = (u32)config::GetConfigValue(HocClkConfigValue_AutoRamCpuCpuOCFreq) * 1000; - } - - if (targetHz || autoCpuOcHz) { + if (targetHz) { maxHz = GetMaxAllowedHz((HocClkModule)module, gContext.profile); - nearestHz = targetHz ? GetNearestHz((HocClkModule)module, targetHz, maxHz) : 0; - - if (autoCpuOcHz > nearestHz) - nearestHz = GetNearestHz(HocClkModule_CPU, autoCpuOcHz, maxHz); + nearestHz = GetNearestHz((HocClkModule)module, targetHz, maxHz); if (nearestHz != gContext.freqs[module]) { - fileUtils::LogLine("[mgr] %s clock set : %u.%u MHz (target = %u.%u MHz)", board::GetModuleName((HocClkModule)module, true), + file::utils::LogLine("[mgr] %s clock set : %u.%u MHz (target = %u.%u MHz)", board::GetModuleName((HocClkModule)module, true), nearestHz / 1000000, nearestHz / 100000 - nearestHz / 1000000 * 10, targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10); // The logic MUST be done in this order otherwise you WILL get crashes - if (module == HocClkModule_MEM && targetHz > oldHz && config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { - ApplyGpuDvfs(targetHz); + if (module == HocClkModule_MEM && targetHz > oldHz) { + ApplyRamOcDvfs(targetHz); } + board::SetHz((HocClkModule)module, nearestHz); gContext.freqs[module] = nearestHz; @@ -610,12 +629,13 @@ namespace clockManager { gContext.stable.freqs[module] = nearestHz; } - if (module == HocClkModule_MEM && targetHz < oldHz && config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { - ApplyGpuDvfs(targetHz); + if (module == HocClkModule_MEM && targetHz < oldHz) { + ApplyRamOcDvfs(targetHz); } - if (module == HocClkModule_MEM && config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) + if (module == HocClkModule_MEM && file::config::GetConfigValue(HocClkConfigValue_GPUDVFSMode) == DVFSMode_Hijack) didHijackPcv = false; + } } else { HandleFreqReset((HocClkModule)module, isBoost, didHijackPcv); @@ -630,16 +650,16 @@ namespace clockManager { Result rc = apmExtGetCurrentPerformanceConfiguration(&mode); ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration"); - std::uint64_t applicationId = processManagement::GetCurrentApplicationId(); + std::uint64_t applicationId = hos::GetCurrentApplicationId(); if (applicationId != gContext.applicationId) { - fileUtils::LogLine("[mgr] TitleID change: %016lX", applicationId); + file::utils::LogLine("[mgr] TitleID change: %016lX", applicationId); gContext.applicationId = applicationId; hasChanged = true; } HocClkProfile profile = board::GetProfile(); if (profile != gContext.profile) { - fileUtils::LogLine("[mgr] Profile change: %s", board::GetProfileName(profile, true)); + file::utils::LogLine("[mgr] Profile change: %s", board::GetProfileName(profile, true)); gContext.profile = profile; hasChanged = true; } @@ -647,10 +667,14 @@ namespace clockManager { // restore clocks to stock values on app or profile change if (hasChanged) { board::ResetToStock(); - if (config::GetConfigValue(HocClkConfigValue_DVFSMode) == DVFSMode_Hijack) { + if (IsGpuDvfsEnabled()) { board::PcvHijackGpuVolts(0); board::ResetToStockGpu(); } + + if (IsCpuDvfsEnabled()) { + board::ApplyCpuMinVolt(0, false); + } WaitForNextTick(); } @@ -658,7 +682,7 @@ namespace clockManager { for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) { hz = board::GetHz((HocClkModule)module); if (hz != 0 && hz != gContext.freqs[module]) { - fileUtils::LogLine("[mgr] %s clock change: %u.%u MHz", board::GetModuleName((HocClkModule)module, true), hz / 1000000, + file::utils::LogLine("[mgr] %s clock change: %u.%u MHz", board::GetModuleName((HocClkModule)module, true), hz / 1000000, hz / 100000 - hz / 1000000 * 10); gContext.freqs[module] = hz; @@ -668,10 +692,10 @@ namespace clockManager { hasChanged = true; } - hz = config::GetOverrideHz((HocClkModule)module); + hz = file::config::GetOverrideHz((HocClkModule)module); if (hz != gContext.overrideFreqs[module]) { if (hz) { - fileUtils::LogLine("[mgr] %s override change: %u.%u MHz", board::GetModuleName((HocClkModule)module, true), hz / 1000000, + file::utils::LogLine("[mgr] %s override change: %u.%u MHz", board::GetModuleName((HocClkModule)module, true), hz / 1000000, hz / 100000 - hz / 1000000 * 10); } gContext.overrideFreqs[module] = hz; @@ -691,7 +715,7 @@ namespace clockManager { for (unsigned int sensor = 0; sensor < HocClkThermalSensor_EnumMax; sensor++) { millis = board::GetTemperatureMilli((HocClkThermalSensor)sensor); if (shouldLogTemp) { - fileUtils::LogLine("[mgr] %s temp: %u.%u °C", board::GetThermalSensorName((HocClkThermalSensor)sensor, true), millis / 1000, + file::utils::LogLine("[mgr] %s temp: %u.%u °C", board::GetThermalSensorName((HocClkThermalSensor)sensor, true), millis / 1000, (millis - millis / 1000 * 1000) / 100); } gContext.temps[sensor] = millis; @@ -707,7 +731,7 @@ namespace clockManager { for (unsigned int sensor = 0; sensor < HocClkPowerSensor_EnumMax; sensor++) { mw = board::GetPowerMw((HocClkPowerSensor)sensor); if (shouldLogPower) { - fileUtils::LogLine("[mgr] Power %s: %d mW", board::GetPowerSensorName((HocClkPowerSensor)sensor, false), mw); + file::utils::LogLine("[mgr] Power %s: %d mW", board::GetPowerSensorName((HocClkPowerSensor)sensor, false), mw); } gContext.power[sensor] = mw; @@ -722,7 +746,7 @@ namespace clockManager { for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) { realHz = board::GetRealHz((HocClkModule)module); if (shouldLogFreq) { - fileUtils::LogLine("[mgr] %s real freq: %u.%u MHz", board::GetModuleName((HocClkModule)module, true), realHz / 1000000, + file::utils::LogLine("[mgr] %s real freq: %u.%u MHz", board::GetModuleName((HocClkModule)module, true), realHz / 1000000, realHz / 100000 - realHz / 1000000 * 10); } gContext.realFreqs[module] = realHz; @@ -750,30 +774,32 @@ namespace clockManager { } if (ConfigIntervalTimeout(HocClkConfigValue_CsvWriteIntervalMs, ns, &gLastCsvWriteNs)) { - fileUtils::WriteContextToCsv(&gContext); + file::utils::WriteContextToCsv(&gContext); } // this->context->maxDisplayFreq = board::GetHighestDockedDisplayRate(); u32 targetHz = gContext.overrideFreqs[HocClkModule_Display]; if (!targetHz) { - targetHz = config::GetAutoClockHz(gContext.applicationId, HocClkModule_Display, gContext.profile, true); + targetHz = file::config::GetAutoClockHz(gContext.applicationId, HocClkModule_Display, gContext.profile, true); if (!targetHz) - targetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Display, gContext.profile, true); + targetHz = file::config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Display, gContext.profile, true); } if (board::GetConsoleType() != HocClkConsoleType_Hoag) board::SetDisplayRefreshDockedState(gContext.profile == HocClkProfile_Docked); if (gContext.isSaltyNXInstalled) - gContext.fps = integrations::GetSaltyNXFPS(); + gContext.fps = hos::GetSaltyNXFPS(); else gContext.fps = 254; // N/A if (gContext.isSaltyNXInstalled) - gContext.resolutionHeight = integrations::GetSaltyNXResolutionHeight(); + gContext.resolutionHeight = hos::GetSaltyNXResolutionHeight(); else gContext.resolutionHeight = 0; // N/A + gContext.isWdtEnabled = i2c::wdt::IsWdtEnabled(); + return hasChanged; } @@ -784,7 +810,7 @@ namespace clockManager { /* Load the KIP customize table before building the freq tables: the MEM freq-list synthesis in RefreshFreqTableRow reads marikoEmcMaxClock / stepMode from it. */ - kip::GetKipData(); + file::kip::GetKipData(); for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) { gContext.freqs[module] = 0; @@ -818,23 +844,23 @@ namespace clockManager { gContext.dramID = board::GetDramID(); gContext.isDram8GB = board::IsDram8GB(); gContext.consoleType = board::GetConsoleType(); + gContext.isFirstLoad = file::config::GetConfigValue(HocClkConfigValue_IsFirstLoad); - board::SetGpuSchedulingMode((GpuSchedulingMode)config::GetConfigValue(HocClkConfigValue_GPUScheduling), - (GpuSchedulingOverrideMethod)config::GetConfigValue(HocClkConfigValue_GPUSchedulingMethod)); - gContext.gpuSchedulingMode = (GpuSchedulingMode)config::GetConfigValue(HocClkConfigValue_GPUScheduling); + board::SetGpuSchedulingMode((GpuSchedulingMode)file::config::GetConfigValue(HocClkConfigValue_GPUScheduling), + (GpuSchedulingOverrideMethod)file::config::GetConfigValue(HocClkConfigValue_GPUSchedulingMethod)); + gContext.gpuSchedulingMode = (GpuSchedulingMode)file::config::GetConfigValue(HocClkConfigValue_GPUScheduling); - gContext.isSysDockInstalled = integrations::GetSysDockState(); - gContext.isSaltyNXInstalled = integrations::GetSaltyNXState(); + gContext.isSysDockInstalled = hos::GetSysDockState(); + gContext.isSaltyNXInstalled = hos::GetSaltyNXState(); if (gContext.isSaltyNXInstalled) { - integrations::LoadSaltyNX(); + hos::LoadSaltyNX(); } - gContext.isUsingRetroSuper = integrations::GetRETROSuperStatus(); - governor::startThreads(); + mgr::StartThreads(); } void Exit() { - governor::exitThreads(); + mgr::ExitThreads(); } HocClkContext GetCurrentContext() { @@ -869,16 +895,14 @@ namespace clockManager { HandleMiscFeatures(); // GPU clock should always be the same unless PCV has overwriten our change, so reset it - if ((RefreshContext() || config::Refresh() || (board::GetRealHz(HocClkModule_GPU) != gContext.freqs[HocClkModule_GPU])) && + if ((RefreshContext() || file::config::Refresh() || (board::GetRealHz(HocClkModule_GPU) != gContext.freqs[HocClkModule_GPU])) && !shouldSkipClockSet) { SetClocks(isBoost); } } void WaitForNextTick() { - if (board::GetHz(HocClkModule_MEM) > 665000000) - svcSleepThread(config::GetConfigValue(HocClkConfigValue_PollingIntervalMs) * 1000000ULL); - else - svcSleepThread(5000 * 1000000ULL); // 5 seconds in sleep mode + i2c::wdt::Pet(); + svcSleepThread(file::config::GetConfigValue(HocClkConfigValue_PollingIntervalMs) * 1000000ULL); } -} // namespace clockManager +} // namespace mgr diff --git a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.hpp b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.hpp index 6caee007..3532a30e 100644 --- a/Source/hoc-clk/sysmodule/src/mgr/clock_manager.hpp +++ b/Source/hoc-clk/sysmodule/src/mgr/clock_manager.hpp @@ -31,7 +31,7 @@ #include "../util/lockable_mutex.h" -namespace clockManager { +namespace mgr { struct FreqTable { std::uint32_t count; @@ -45,6 +45,7 @@ namespace clockManager { extern LockableMutex gContextMutex; extern HocClkContext gContext; extern FreqTable gFreqTable[HocClkModule_EnumMax]; + extern u32 patchedEmcMaxClock; extern std::uint64_t gLastTempLogNs; extern std::uint64_t gLastFreqLogNs; extern std::uint64_t gLastPowerLogNs; @@ -65,6 +66,8 @@ namespace clockManager { void ApplyGpuFreqVoltRequest(u32 voltage, u32 hz); + u32 GetNearestOverrideHz(HocClkModule module); + void Tick(); void WaitForNextTick(); -} // namespace clockManager +} // namespace mgr diff --git a/Source/hoc-clk/sysmodule/src/mgr/governor.cpp b/Source/hoc-clk/sysmodule/src/mgr/governor.cpp index 3bd87f44..f72fe387 100644 --- a/Source/hoc-clk/sysmodule/src/mgr/governor.cpp +++ b/Source/hoc-clk/sysmodule/src/mgr/governor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -19,11 +19,29 @@ #include "governor.hpp" #include -namespace governor { +namespace mgr { -#define POLL_NS 5'000'000 // 5 ms – governor poll rate -#define DOWN_HOLD_TICKS 10 // 50 ms – how long to in POLL_NS to hold while ramping down -#define STEP_UTIL 900 // multiplier for step calculations +#define DOWN_HOLD_TICKS_DEFAULT 10 // 50 ms at 5ms poll – how long to hold while ramping down +#define STEP_UTIL_DEFAULT 900 // multiplier for step calculations (max freq at 90% load) + + u64 GovernorPollNs() { + u64 ms = file::config::GetConfigValue(HocClkConfigValue_GovernorPollRateMs); + if (ms < 1 || ms > 50) + ms = 5; + return ms * 1'000'000ULL; + } + + u32 GovernorDownHoldTicks() { + u64 ticks = file::config::GetConfigValue(HocClkConfigValue_GovernorDownHoldTicks); + return (ticks <= 100) ? (u32)ticks : DOWN_HOLD_TICKS_DEFAULT; + } + + u32 GovernorStepUtil() { + u64 step = file::config::GetConfigValue(HocClkConfigValue_GovernorStepUtil); + if (step < 100 || step > 1500) + step = STEP_UTIL_DEFAULT; + return (u32)step; + } bool isGpuGovernorEnabled = false; bool isCpuGovernorEnabled = false; @@ -37,11 +55,11 @@ namespace governor { Thread governorTHREAD; void HandleGovernor(uint32_t targetHz) { - u32 tempTargetHz = clockManager::gContext.overrideFreqs[HocClkModule_Governor]; + u32 tempTargetHz = mgr::gContext.overrideFreqs[HocClkModule_Governor]; if (!tempTargetHz) { - tempTargetHz = config::GetAutoClockHz(clockManager::gContext.applicationId, HocClkModule_Governor, clockManager::gContext.profile, true); + tempTargetHz = file::config::GetAutoClockHz(mgr::gContext.applicationId, HocClkModule_Governor, mgr::gContext.profile, true); if (!tempTargetHz) - tempTargetHz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Governor, clockManager::gContext.profile, true); + tempTargetHz = file::config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Governor, mgr::gContext.profile, true); } auto resolve = [](u8 app, u8 temp) -> u8 { @@ -73,7 +91,7 @@ namespace governor { if (newCpuGovernorState != lastCpuGovernorState || newGpuGovernorState != lastGpuGovernorState || newVrrGovernorState != lastVrrGovernorState) { - fileUtils::LogLine("[mgr] Governor state changed: CPU %s, GPU %s, VRR %s", newCpuGovernorState ? "enabled" : "disabled", + file::utils::LogLine("[mgr] Governor state changed: CPU %s, GPU %s, VRR %s", newCpuGovernorState ? "enabled" : "disabled", newGpuGovernorState ? "enabled" : "disabled", newVrrGovernorState ? "enabled" : "disabled"); lastCpuGovernorState = newCpuGovernorState; lastGpuGovernorState = newGpuGovernorState; @@ -82,11 +100,11 @@ namespace governor { } u32 SchedutilTargetHz(u32 util, u32 tableMaxHz) { - u64 hz = (u64)tableMaxHz * util / STEP_UTIL; + u64 hz = (u64)tableMaxHz * util / GovernorStepUtil(); return (u32)(std::min(hz, static_cast(tableMaxHz))); } - u32 TableIndexForHz(const clockManager::FreqTable &table, u32 targetHz) { + u32 TableIndexForHz(const mgr::FreqTable &table, u32 targetHz) { for (u32 i = 0; i < table.count; i++) if (table.list[i] >= targetHz) return i; @@ -94,11 +112,11 @@ namespace governor { } u32 ResolveTargetHz(HocClkModule module) { - u32 hz = clockManager::gContext.overrideFreqs[module]; + u32 hz = mgr::gContext.overrideFreqs[module]; if (!hz) - hz = config::GetAutoClockHz(clockManager::gContext.applicationId, module, clockManager::gContext.profile, false); + hz = file::config::GetAutoClockHz(mgr::gContext.applicationId, module, mgr::gContext.profile, false); if (!hz) - hz = config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, module, clockManager::gContext.profile, false); + hz = file::config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, module, mgr::gContext.profile, false); return hz; } @@ -115,13 +133,14 @@ namespace governor { u8 vrrFocusTick = 0; for (;;) { + const u64 pollNs = GovernorPollNs(); - if (!clockManager::gRunning) { + if (!mgr::gRunning) { cpuDownHoldRemaining = 0; cpuLastHz = 0; gpuDownHoldRemaining = 0; gpuLastHz = 0; - svcSleepThread(POLL_NS); + svcSleepThread(pollNs); continue; } @@ -136,14 +155,14 @@ namespace governor { } else { isCpuGovernorInBoostMode = false; - auto &table = clockManager::gFreqTable[HocClkModule_CPU]; - std::scoped_lock lock{ clockManager::gContextMutex }; + auto &table = mgr::gFreqTable[HocClkModule_CPU]; + std::scoped_lock lock{ mgr::gContextMutex }; u32 cpuLoad = board::GetPartLoad(HocClkPartLoad_CPUMax); u32 tableMaxHz = table.list[table.count - 1]; u32 desiredHz = SchedutilTargetHz(cpuLoad, tableMaxHz); u32 targetHz = ResolveTargetHz(HocClkModule_CPU); - u32 maxHz = clockManager::GetMaxAllowedHz(HocClkModule_CPU, clockManager::gContext.profile); + u32 maxHz = mgr::GetMaxAllowedHz(HocClkModule_CPU, mgr::gContext.profile); if (targetHz && desiredHz > targetHz) desiredHz = targetHz; @@ -156,32 +175,23 @@ namespace governor { if (!goingDown) cpuDownHoldRemaining = 0; else if (cpuDownHoldRemaining == 0) - cpuDownHoldRemaining = DOWN_HOLD_TICKS; + cpuDownHoldRemaining = GovernorDownHoldTicks(); if (cpuDownHoldRemaining > 0) cpuDownHoldRemaining--; if (++cpuTick > 50) { - minHz = config::GetConfigValue(HocClkConfigValue_CpuGovernorMinimumFreq); - if (config::GetConfigValue(HocClkConfigValue_AutoRAMCPUOverclock)) { - u32 ramHz = clockManager::gContext.freqs[HocClkModule_MEM]; - u32 threshold = (u32)config::GetConfigValue(HocClkConfigValue_AutoRamCpuRamOCThreshold) * 1000; - if (ramHz >= threshold) { - u32 overrideHz = (u32)config::GetConfigValue(HocClkConfigValue_AutoRamCpuCpuOCFreq) * 1000; - if (overrideHz > minHz) - minHz = overrideHz; - } - } + minHz = file::config::GetConfigValue(HocClkConfigValue_CpuGovernorMinimumFreq); cpuTick = 0; } if (newHz < minHz) newHz = minHz; - if ((!goingDown || (cpuDownHoldRemaining == 0)) && clockManager::IsAssignableHz(HocClkModule_CPU, newHz)) { + if ((!goingDown || (cpuDownHoldRemaining == 0)) && mgr::IsAssignableHz(HocClkModule_CPU, newHz)) { board::SetHz(HocClkModule_CPU, newHz); - clockManager::gContext.freqs[HocClkModule_CPU] = newHz; - clockManager::gContext.stable.freqs[HocClkModule_CPU] = newHz; + mgr::gContext.freqs[HocClkModule_CPU] = newHz; + mgr::gContext.stable.freqs[HocClkModule_CPU] = newHz; cpuLastHz = newHz; } } @@ -192,14 +202,14 @@ namespace governor { } if (isGpuGovernorEnabled) { - auto &table = clockManager::gFreqTable[HocClkModule_GPU]; - std::scoped_lock lock{ clockManager::gContextMutex }; + auto &table = mgr::gFreqTable[HocClkModule_GPU]; + std::scoped_lock lock{ mgr::gContextMutex }; u32 gpuLoad = board::GetPartLoad(HocClkPartLoad_GPU); u32 tableMaxHz = table.list[table.count - 1]; u32 desiredHz = SchedutilTargetHz(gpuLoad, tableMaxHz); u32 targetHz = ResolveTargetHz(HocClkModule_GPU); - u32 maxHz = clockManager::GetMaxAllowedHz(HocClkModule_GPU, clockManager::gContext.profile); + u32 maxHz = mgr::GetMaxAllowedHz(HocClkModule_GPU, mgr::gContext.profile); if (targetHz && desiredHz > targetHz) desiredHz = targetHz; @@ -212,15 +222,15 @@ namespace governor { if (!goingDown) gpuDownHoldRemaining = 0; else if (gpuDownHoldRemaining == 0) - gpuDownHoldRemaining = DOWN_HOLD_TICKS; + gpuDownHoldRemaining = GovernorDownHoldTicks(); if (gpuDownHoldRemaining > 0) gpuDownHoldRemaining--; - if ((!goingDown || (gpuDownHoldRemaining == 0)) && clockManager::IsAssignableHz(HocClkModule_GPU, newHz)) { + if ((!goingDown || (gpuDownHoldRemaining == 0)) && mgr::IsAssignableHz(HocClkModule_GPU, newHz)) { board::SetHz(HocClkModule_GPU, newHz); - clockManager::gContext.freqs[HocClkModule_GPU] = newHz; - clockManager::gContext.stable.freqs[HocClkModule_GPU] = newHz; + mgr::gContext.freqs[HocClkModule_GPU] = newHz; + mgr::gContext.stable.freqs[HocClkModule_GPU] = newHz; gpuLastHz = newHz; } } else { @@ -228,13 +238,13 @@ namespace governor { gpuLastHz = 0; } - if (isVRREnabled && clockManager::gContext.profile != HocClkProfile_Docked && clockManager::gContext.isSaltyNXInstalled) { + if (isVRREnabled && mgr::gContext.profile != HocClkProfile_Docked && mgr::gContext.isSaltyNXInstalled) { bool skipVrr = false; if (++vrrFocusTick > 100) { vrrFocusTick = 0; bool isApplicationOutOfFocus = false; - Result rc = processManagement::isApplicationOutOfFocus(&isApplicationOutOfFocus); + Result rc = hos::IsApplicationOutOfFocus(&isApplicationOutOfFocus); if (R_FAILED(rc) || isApplicationOutOfFocus) { board::ResetToStockDisplay(); skipVrr = true; @@ -242,18 +252,18 @@ namespace governor { } if (!skipVrr) { - u8 fps = integrations::GetSaltyNXFPS(); + u8 fps = hos::GetSaltyNXFPS(); if (fps != 254) { - std::scoped_lock lock{ clockManager::gContextMutex }; + std::scoped_lock lock{ mgr::gContextMutex }; - u32 targetHz = clockManager::gContext.overrideFreqs[HocClkModule_Display]; + u32 targetHz = mgr::gContext.overrideFreqs[HocClkModule_Display]; if (!targetHz) { - targetHz = config::GetAutoClockHz(clockManager::gContext.applicationId, HocClkModule_Display, - clockManager::gContext.profile, false); + targetHz = file::config::GetAutoClockHz(mgr::gContext.applicationId, HocClkModule_Display, + mgr::gContext.profile, false); if (!targetHz) targetHz = - config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Display, clockManager::gContext.profile, false); + file::config::GetAutoClockHz(HOCCLK_GLOBAL_PROFILE_TID, HocClkModule_Display, mgr::gContext.profile, false); } u8 maxDisplay = targetHz ? (u8)targetHz : 60; @@ -262,19 +272,19 @@ namespace governor { if (maxDisplay != minDisplay) { if (fps >= minDisplay && fps <= maxDisplay) { board::SetHz(HocClkModule_Display, fps); - clockManager::gContext.freqs[HocClkModule_Display] = fps; - clockManager::gContext.realFreqs[HocClkModule_Display] = fps; - clockManager::gContext.stable.freqs[HocClkModule_Display] = fps; - clockManager::gContext.stable.realFreqs[HocClkModule_Display] = fps; + mgr::gContext.freqs[HocClkModule_Display] = fps; + mgr::gContext.realFreqs[HocClkModule_Display] = fps; + mgr::gContext.stable.freqs[HocClkModule_Display] = fps; + mgr::gContext.stable.realFreqs[HocClkModule_Display] = fps; } else { for (u32 i = 0; i < 10; i++) { u32 compareHz = fps * i; if (compareHz >= minDisplay && compareHz <= maxDisplay) { board::SetHz(HocClkModule_Display, compareHz); - clockManager::gContext.freqs[HocClkModule_Display] = compareHz; - clockManager::gContext.realFreqs[HocClkModule_Display] = compareHz; - clockManager::gContext.stable.freqs[HocClkModule_Display] = compareHz; - clockManager::gContext.stable.realFreqs[HocClkModule_Display] = compareHz; + mgr::gContext.freqs[HocClkModule_Display] = compareHz; + mgr::gContext.realFreqs[HocClkModule_Display] = compareHz; + mgr::gContext.stable.freqs[HocClkModule_Display] = compareHz; + mgr::gContext.stable.realFreqs[HocClkModule_Display] = compareHz; break; } } @@ -290,16 +300,16 @@ namespace governor { } } - svcSleepThread(POLL_NS); + svcSleepThread(pollNs); } } - void startThreads() { + void StartThreads() { threadCreate(&governorTHREAD, GovernorThread, nullptr, NULL, 0x2000, 0x3F, -2); threadStart(&governorTHREAD); } - void exitThreads() { + void ExitThreads() { threadClose(&governorTHREAD); } -} // namespace governor +} // namespace mgr diff --git a/Source/hoc-clk/sysmodule/src/mgr/governor.hpp b/Source/hoc-clk/sysmodule/src/mgr/governor.hpp index 0622eee1..a5989a0c 100644 --- a/Source/hoc-clk/sysmodule/src/mgr/governor.hpp +++ b/Source/hoc-clk/sysmodule/src/mgr/governor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) Souldbminer 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 * under the terms and conditions of the GNU General Public License, @@ -28,7 +28,7 @@ #include "clock_manager.hpp" -namespace governor { +namespace mgr { extern bool isCpuGovernorInBoostMode; extern bool isVRREnabled; extern bool isGpuGovernorEnabled; @@ -36,7 +36,7 @@ namespace governor { extern bool lastGpuGovernorState; extern bool lastCpuGovernorState; extern bool lastVrrGovernorState; - void startThreads(); - void exitThreads(); + void StartThreads(); + void ExitThreads(); void HandleGovernor(uint32_t targetHz); -} // namespace governor \ No newline at end of file +} // namespace mgr \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp new file mode 100644 index 00000000..85265253 --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.cpp @@ -0,0 +1,393 @@ +/* + * Copyright (c) CtCaer + * + * Copyright (c) Souldbminer + * + * 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 . + * + */ + +#include "dram_mrr.hpp" +#include "../board/board.hpp" + +#include +#include +#include + +namespace soc { + constexpr u64 EmcPhysBase = 0x7001B000; + constexpr u64 Emc0PhysBase = 0x7001E000; + constexpr u64 Emc1PhysBase = 0x7001F000; + + constexpr u32 EmcRegMrr = 0xEC; + constexpr u32 EmcRegAdrCfg = 0x10; + constexpr u32 EmcRegFbioCfg7 = 0x584; + constexpr u32 EmcRegEmcStatus = 0x2B4; + constexpr u32 EmcStatusMrrDivld = (1u << 20); + constexpr int EmcStatusUpdateTimeout = 100000; + + static bool SmcRead(u64 phys_addr, u32 *out) { + SecmonArgs args = {}; + args.X[0] = 0xF0000002; + args.X[1] = phys_addr; + args.X[2] = 0; + args.X[3] = 0; + svcCallSecureMonitor(&args); + if (args.X[1] == phys_addr) { + return false; + } + *out = static_cast(args.X[1]); + return true; + } + + static bool SmcWrite(u64 phys_addr, u32 value) { + SecmonArgs args = {}; + args.X[0] = 0xF0000002; + args.X[1] = phys_addr; + args.X[2] = 0xFFFFFFFF; + args.X[3] = value; + svcCallSecureMonitor(&args); + return args.X[1] != phys_addr; + } + + static bool EmcRead(u32 offset, u32 *out) { return SmcRead(EmcPhysBase + offset, out); } + static bool EmcWrite(u32 offset, u32 value) { return SmcWrite(EmcPhysBase + offset, value); } + static bool Emc0Read(u32 offset, u32 *out) { return SmcRead(Emc0PhysBase + offset, out); } + static bool Emc1Read(u32 offset, u32 *out) { return SmcRead(Emc1PhysBase + offset, out); } + + /* 0 = ignore */ + + const DramRevisionMap rev[DRAM_COUNT] = { + /* Erista */ + { .soc = HocClkSocType_Erista, .mfg = MFG_Samsung, .major = 0, .minor = 0, .density = 0, .densityCount = 0 }, /* HB-MGCH */ + { .soc = HocClkSocType_Erista, .mfg = MFG_SKHynix, .major = 0, .minor = 0, .density = 0, .densityCount = 0 }, /* NLE */ + { .soc = HocClkSocType_Erista, .mfg = MFG_Micron, .major = 0, .minor = 0, .density = 0, .densityCount = 0 }, /* WT:C */ + + /* Mariko */ + /* Samsung */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_Samsung, .major = 6, .minor = 0x10, .density = 1, .densityCount = 2 }, /* AM-MGCJ (6.10, 4GB) */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_Samsung, .major = 7, .minor = 0, .density = 1, .densityCount = 2 }, /* AA-MGCL (7.00, 4GB) */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_Samsung, .major = 8, .minor = 0, .density = 1, .densityCount = 2 }, /* AB-MGCL (8.00, 4GB) */ + + /* Micron */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_Micron, .major = 4, .minor = 0x10, .density = 1, .densityCount = 2 }, /* WT:E (4.10, 4GB) */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_Micron, .major = 5, .minor = 0, .density = 1, .densityCount = 2 }, /* WT:F (5.00, 4GB) */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_Micron, .major = 7, .minor = 0, .density = 1, .densityCount = 2 }, /* WT:B (7.00, 4GB) */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_Micron, .major = 7, .minor = 0, .density = 1, .densityCount = 4 }, /* WT:B (7.00, 8GB) */ + + /* SK Hynix */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_SKHynix, .major = 4, .minor = 0, .density = 1, .densityCount = 2 }, /* NME (4.00, 4GB) */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_SKHynix, .major = 6, .minor = 0, .density = 1, .densityCount = 2 }, /* NEE (6.00, 4GB) */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_SKHynix, .major = 6, .minor = 0, .density = 1, .densityCount = 4 }, /* NEE (6.00, 8GB) */ + { .soc = HocClkSocType_Mariko, .mfg = MFG_SKHynix, .major = 8, .minor = 0, .density = 1, .densityCount = 2 }, /* x267 (8.00, 4GB) */ + }; + + /* Ported from hekate */ + + bool IsMrrAvailable() { + u32 val = 0; + return EmcRead(EmcRegAdrCfg, &val); + } + + static int _sdram_wait_emc_status(u32 reg_offset, u32 bit_mask, bool updated_state, s32 emc_channel) + { + for (s32 i = 0; i < EmcStatusUpdateTimeout; i++) + { + u32 val = 0; + bool ok; + if (emc_channel) + { + if (emc_channel != 1) + return 1; + + ok = Emc1Read(reg_offset, &val); + } + else + { + ok = EmcRead(reg_offset, &val); + } + + if (ok && (((val & bit_mask) != 0) == updated_state)) + return 0; + + usleep(1); + } + + return 1; + } + + static bool _sdram_req_mrr_data(u32 data, bool dual_channel) + { + if (!EmcWrite(EmcRegMrr, data)) + return false; + if (_sdram_wait_emc_status(EmcRegEmcStatus, EmcStatusMrrDivld, true, EMC_CHAN0) != 0) + return false; + if (dual_channel && _sdram_wait_emc_status(EmcRegEmcStatus, EmcStatusMrrDivld, true, EMC_CHAN1) != 0) + return false; + return true; + } + + struct EmcTopology { + u32 ranks; + u32 channels; + }; + + static bool QueryTopology(EmcTopology *topo) { + u32 tmp = 0; + if (!EmcRead(EmcRegAdrCfg, &tmp)) + return false; + topo->ranks = (tmp & 1) + 1; + if (!EmcRead(EmcRegFbioCfg7, &tmp)) + return false; + u32 ch = (tmp >> 1) & 3; + topo->channels = (ch & 1) + ((ch & 2) >> 1); + return topo->channels != 0; + } + + static void ClearMrrLeftovers() { + u32 tmp = 0; + for (u32 i = 0; i < 16; i++) + { + (void)EmcRead(EmcRegMrr, &tmp); + usleep(1); + } + } + + static void StoreMrrBytes(u32 mrr, u8 *lo, u8 *hi) { + *lo = mrr & 0xFF; + *hi = (mrr >> 8) & 0xFF; + } + + static bool ReadMrxRank(emc_mr_t mrx, bool dual_rank, bool dual_channel, emc_mr_data_t *out) { + memset(out, 0xFF, sizeof(*out)); + u32 mrr = 0; + + // Get Device 0 (Rank 0) info from both dram chips (channels). + if (!_sdram_req_mrr_data((2u << 30) | (static_cast(mrx) << 16), dual_channel)) + return false; + + // Ram module 0 info. + if (!Emc0Read(EmcRegMrr, &mrr)) + return false; + StoreMrrBytes(mrr, &out->chip0.rank0_ch0, &out->chip0.rank0_ch1); + + // Ram module 1 info. + if (dual_channel) + { + if (!Emc1Read(EmcRegMrr, &mrr)) + return false; + StoreMrrBytes(mrr, &out->chip1.rank0_ch0, &out->chip1.rank0_ch1); + } + + // If Rank 1 exists, get info. + if (dual_rank) + { + // Get Device 1 (Rank 1) info from both dram chips (channels). + if (!_sdram_req_mrr_data((1u << 30) | (static_cast(mrx) << 16), dual_channel)) + return false; + + // Ram module 0 info. + if (!Emc0Read(EmcRegMrr, &mrr)) + return false; + StoreMrrBytes(mrr, &out->chip0.rank1_ch0, &out->chip0.rank1_ch1); + + // Ram module 1 info. + if (dual_channel) + { + if (!Emc1Read(EmcRegMrr, &mrr)) + return false; + StoreMrrBytes(mrr, &out->chip1.rank1_ch0, &out->chip1.rank1_ch1); + } + } + + return true; + } + + static bool ReadMrxSet(emc_mr_data_t *vendor, emc_mr_data_t *rev0, emc_mr_data_t *rev1, + emc_mr_data_t *density, EmcTopology *topo) { + EmcTopology t = {}; + if (!QueryTopology(&t)) + return false; + const bool dual_rank = t.ranks > 1; + const bool dual_channel = t.channels > 1; + + ClearMrrLeftovers(); + + if (!ReadMrxRank(MR5_MAN_ID, dual_rank, dual_channel, vendor)) + return false; + if (!ReadMrxRank(MR6_REV_ID1, dual_rank, dual_channel, rev0)) + return false; + if (!ReadMrxRank(MR7_REV_ID2, dual_rank, dual_channel, rev1)) + return false; + if (!ReadMrxRank(MR8_DENSITY, dual_rank, dual_channel, density)) + return false; + + *topo = t; + return true; + } + + emc_mr_data_t sdram_read_mrx(emc_mr_t mrx) + { + emc_mr_data_t data; + memset(&data, 0xFF, sizeof(emc_mr_data_t)); + + EmcTopology topo = {}; + if (!QueryTopology(&topo)) + return data; + + ClearMrrLeftovers(); + + (void)ReadMrxRank(mrx, topo.ranks > 1, topo.channels > 1, &data); + return data; + } + + bool ReadRamMr4(u8 *mr4) { + EmcTopology topo = {}; + if (!QueryTopology(&topo)) + return false; + + ClearMrrLeftovers(); + + emc_mr_data_t data = {}; + if (!ReadMrxRank(MR4_TEMP, topo.ranks > 1, topo.channels > 1, &data)) + return false; + + *mr4 = data.chip0.rank0_ch0; + return true; + } + + /* MR8 density field (bits 5:2) to MB */ + static bool DecodeDensityMb(u8 mr8, u32 *mb) { + switch ((mr8 & 0x3C) >> 2) + { + case 2: *mb = 512; break; + case 3: *mb = 768; break; + case 4: *mb = 1024; break; + case 5: *mb = 1536; break; + case 6: *mb = 2048; break; + default: return false; + } + return true; + } + + static bool MatchModule(HocClkSocType soc, DramMfg mfg, u8 major, u8 minor, + u32 densityMb, u32 densityCount, RealDramModule *mod) { + for (int i = 0; i < DRAM_COUNT; i++) + { + const DramRevisionMap &e = rev[i]; + if (e.soc != soc || e.mfg != mfg) + continue; + if (soc != HocClkSocType_Erista) + { + if (e.major != major || e.minor != minor) + continue; + if (e.density * 1024u != densityMb) + continue; + if (e.densityCount != densityCount) + continue; + } + *mod = static_cast(i); + return true; + } + return false; + } + + static u8 FuseIdForModule(RealDramModule mod, HocClkConsoleType console, u8 fuseFallback) { + switch (mod) + { + case DRAM_HBMGCH: + case DRAM_NLE: + case DRAM_WTC: + return fuseFallback; + case DRAM_AMMGCJ: + if (console == HocClkConsoleType_Hoag) return 12; + if (console == HocClkConsoleType_Iowa) return 8; + return fuseFallback; + case DRAM_AAMGCL: + if (console == HocClkConsoleType_Iowa) return 17; + if (console == HocClkConsoleType_Hoag) return 19; + if (console == HocClkConsoleType_Aula) return 24; + return fuseFallback; + case DRAM_ABMGCL: + if (console == HocClkConsoleType_Iowa) return 20; + if (console == HocClkConsoleType_Hoag) return 21; + if (console == HocClkConsoleType_Aula) return 22; + return fuseFallback; + case DRAM_WTE: + if (console == HocClkConsoleType_Iowa) return 11; + if (console == HocClkConsoleType_Hoag) return 15; + return fuseFallback; + case DRAM_WTF: + if (console == HocClkConsoleType_Iowa) return 25; + if (console == HocClkConsoleType_Hoag) return 26; + if (console == HocClkConsoleType_Aula) return 27; + return fuseFallback; + case DRAM_WTB: + if (console == HocClkConsoleType_Iowa) return 32; + if (console == HocClkConsoleType_Hoag) return 33; + if (console == HocClkConsoleType_Aula) return 34; + return fuseFallback; + case DRAM_WTB_8GB: + case DRAM_NEE_8GB: + /* Used in atmosphere and commonly burnt for 8gb upgrade */ + return 28; + case DRAM_NME: + if (console == HocClkConsoleType_Iowa) return 10; + if (console == HocClkConsoleType_Hoag) return 14; + return fuseFallback; + case DRAM_NEE: + if (console == HocClkConsoleType_Iowa) return 6; + if (console == HocClkConsoleType_Hoag) return 3; + if (console == HocClkConsoleType_Aula) return 5; + return fuseFallback; + case DRAM_X267: + if (console == HocClkConsoleType_Iowa) return 29; + if (console == HocClkConsoleType_Hoag) return 30; + if (console == HocClkConsoleType_Aula) return 31; + return fuseFallback; + default: + return fuseFallback; + } + } + + u8 IdentifyDramId() { + const u8 fuseId = board::GetFuseDramId(); + const HocClkSocType soc = board::GetSocType(); + + // if (soc == HocClkSocType_Erista) + return fuseId; + + // if (!IsMrrAvailable()) + // return fuseId; + + emc_mr_data_t vendor = {}, rev0 = {}, rev1 = {}, density = {}; + EmcTopology topo = {}; + if (!ReadMrxSet(&vendor, &rev0, &rev1, &density, &topo)) + return fuseId; + + DramMfg mfg = static_cast(vendor.chip0.rank0_ch0); + + u32 densityMb = 0; + if (!DecodeDensityMb(density.chip0.rank0_ch0, &densityMb)) + return fuseId; + + RealDramModule mod = DRAM_COUNT; + if (!MatchModule(soc, mfg, rev0.chip0.rank0_ch0, rev1.chip0.rank0_ch0, + densityMb, topo.ranks * topo.channels, &mod)) + return fuseId; + + return FuseIdForModule(mod, board::GetConsoleType(), fuseId); + } + + +} \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp new file mode 100644 index 00000000..a148477e --- /dev/null +++ b/Source/hoc-clk/sysmodule/src/soc/dram_mrr.hpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) CtCaer + * + * Copyright (c) Souldbminer + * + * 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 . + * + */ +#include + +namespace soc { + typedef enum RealDramModule { + /* Erista */ + DRAM_HBMGCH = 0, + DRAM_NLE, + DRAM_WTC, + + /* Mariko */ + + /* Samsung */ + DRAM_AMMGCJ, + DRAM_AAMGCL, + DRAM_ABMGCL, + + /* Micron */ + DRAM_WTE, + DRAM_WTF, + DRAM_WTB, + DRAM_WTB_8GB, + + /* SK Hynix */ + DRAM_NME, + DRAM_NEE, + DRAM_NEE_8GB, + DRAM_X267, + DRAM_COUNT, + } RealDramModule; + + typedef enum _emc_mr_t + { + MR0_FEAT = 0, + MR4_TEMP = 4, + MR5_MAN_ID = 5, + MR6_REV_ID1 = 6, + MR7_REV_ID2 = 7, + MR8_DENSITY = 8, + } emc_mr_t; + + enum + { + EMC_CHAN0 = 0, + EMC_CHAN1 = 1 + }; + + typedef struct _emc_mr_chip_data_t + { + // Device 0. + u8 rank0_ch0; + u8 rank0_ch1; + + // Device 1. + u8 rank1_ch0; + u8 rank1_ch1; + } emc_mr_chip_data_t; + + typedef struct _emc_mr_data_t + { + emc_mr_chip_data_t chip0; + emc_mr_chip_data_t chip1; + } emc_mr_data_t; + + typedef enum DramMfg { + MFG_Samsung = 1, + MFG_SKHynix = 6, + MFG_Micron = 255, + } DramMfg; + + typedef struct DramRevisionMap { + HocClkSocType soc; + DramMfg mfg; + u8 major; + u8 minor; + u8 density; // GB per die + u8 densityCount; // number of dies (2 = 4GB, 4 = 8GB) + } DramRevisionMap; + + extern const DramRevisionMap rev[DRAM_COUNT]; + + emc_mr_data_t sdram_read_mrx(emc_mr_t mrx); + bool IsMrrAvailable(); + + bool ReadRamMr4(u8 *mr4); + + u8 IdentifyDramId(); +} \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/soc/gm20b.cpp b/Source/hoc-clk/sysmodule/src/soc/gm20b.cpp index e2a4e158..e394ae13 100644 --- a/Source/hoc-clk/sysmodule/src/soc/gm20b.cpp +++ b/Source/hoc-clk/sysmodule/src/soc/gm20b.cpp @@ -21,18 +21,18 @@ #include "gm20b.hpp" -namespace gm20b { +namespace soc { u64 gpu_base = 0; #define GPU_PA 0x57000000 #define GPU_SIZE 0x1000000 #define GPU_TRIM_SYS_GPCPLL_CFG 0x00 #define GPU_TRIM_SYS_GPCPLL_COEFF 0x04 -#define GPU_TRIM_SYS_GPCPLL_CFG2 0x08 -#define GPU_TRIM_SYS_GPCPLL_CFG3 0x0C +#define GPU_TRIM_SYS_GPCPLL_CFG2 0x0C +#define GPU_TRIM_SYS_GPCPLL_CFG3 0x18 #define GPU_TRIM_SYS_GPCPLL_DVFS0 0x10 #define GPU_TRIM_SYS_GPCPLL_DVFS1 0x14 #define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN 0x1C -#define GPU_TRIM_SYS_SEL_VCO 0x2C +#define GPU_TRIM_SYS_SEL_VCO 0x100 #define GPU_TRIM_SYS_GPC2CLK_OUT 0x250 #define GPC_BCAST(x) (*(volatile u32 *)(gpu_base + 0x132800ul + (x))) @@ -47,7 +47,7 @@ namespace gm20b { #define GPCPLL_CFG_LOCK BIT(17) #define GPCPLL_CFG2_SDM_DIN_MASK 0x000000FFu -#define GPCPLL_CFG2_SDM_DIN_NEW_MASK 0x007FFF00u +#define GPCPLL_CFG2_SDM_DIN_NEW_MASK 0x0000FF00u #define GPCPLL_CFG2_STEPA_SHIFT 24 #define GPCPLL_CFG2_STEPA_MASK 0xFF000000u @@ -57,7 +57,7 @@ namespace gm20b { #define GPCPLL_DVFS0_DFS_COEFF_MASK 0x0000007Fu #define NDIV_SLOWDOWN_SLOWDOWN_USING_PLL BIT(22) -#define NDIV_SLOWDOWN_EN_DYNRAMP BIT(23) +#define NDIV_SLOWDOWN_EN_DYNRAMP BIT(31) #define DYNRAMP_DONE_SYNCED BIT(24) @@ -123,7 +123,7 @@ namespace gm20b { return success; } - bool setClock(u32 khz) { + bool SetClock(u32 khz) { if (!gpu_base) QueryMemoryMapping(&gpu_base, GPU_PA, GPU_SIZE); @@ -146,4 +146,4 @@ namespace gm20b { return _gpu_pllg_slide(new_divn); } -} // namespace gm20b \ No newline at end of file +} // namespace soc \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/soc/gm20b.hpp b/Source/hoc-clk/sysmodule/src/soc/gm20b.hpp index ec7726cc..9ebfb4be 100644 --- a/Source/hoc-clk/sysmodule/src/soc/gm20b.hpp +++ b/Source/hoc-clk/sysmodule/src/soc/gm20b.hpp @@ -19,6 +19,6 @@ #pragma once #include <../board/board.hpp> -namespace gm20b { - bool setClock(u32 khz); +namespace soc { + bool SetClock(u32 khz); } \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/soc/registers.h b/Source/hoc-clk/sysmodule/src/soc/registers.h index f6f11b06..576075eb 100644 --- a/Source/hoc-clk/sysmodule/src/soc/registers.h +++ b/Source/hoc-clk/sysmodule/src/soc/registers.h @@ -528,6 +528,8 @@ #define CLK_SOURCE_EMC 0x19c +#define CL_DVFS_LUT_TABLE_0 0x200 + #define PLLC_BASE 0x080 #define PLLM_BASE 0x090 #define PLLP_BASE 0x0a0 @@ -545,4 +547,3458 @@ #define PLLA1_BASE 0x6a4 #define PLLDP_BASE 0x590 -#define OSC_HZ 38400000ULL \ No newline at end of file +#define OSC_HZ 38400000ULL + +#define GPU_BUS_BAR0_WINDOW 0x00001700 +#define GPU_BUS_BAR0_WINDOW_BASE_SHIFT 0x00000000 +#define GPU_BUS_BAR0_WINDOW_BASE_FIELDMASK 0x00ffffff +#define GPU_BUS_BAR0_WINDOW_TARGET_VID_MEM_F 0x00000000 +#define GPU_BUS_BAR0_WINDOW_TARGET_SYS_MEM_COHERENT_F 0x02000000 +#define GPU_BUS_BAR0_WINDOW_TARGET_SYS_MEM_NONCOHERENT_F 0x03000000 +#define GPU_BUS_BAR0_WINDOW_TARGET_BAR0_WINDOW_BASE_SHIFT_V 0x00000010 +#define GPU_BUS_BAR1_BLOCK 0x00001704 +#define GPU_BUS_BAR1_BLOCK_PTR_SHIFT 0x00000000 +#define GPU_BUS_BAR1_BLOCK_PTR_FIELDMASK 0x0fffffff +#define GPU_BUS_BAR1_BLOCK_TARGET_VID_MEM_F 0x00000000 +#define GPU_BUS_BAR1_BLOCK_TARGET_SYS_MEM_COH_F 0x20000000 +#define GPU_BUS_BAR1_BLOCK_TARGET_SYS_MEM_NCOH_F 0x30000000 +#define GPU_BUS_BAR1_BLOCK_MODE_VIRTUAL_F 0x80000000 +#define GPU_BUS_BAR2_BLOCK 0x00001714 +#define GPU_BUS_BAR2_BLOCK_PTR_SHIFT 0x00000000 +#define GPU_BUS_BAR2_BLOCK_PTR_FIELDMASK 0x0fffffff +#define GPU_BUS_BAR2_BLOCK_TARGET_VID_MEM_F 0x00000000 +#define GPU_BUS_BAR2_BLOCK_TARGET_SYS_MEM_COH_F 0x20000000 +#define GPU_BUS_BAR2_BLOCK_TARGET_SYS_MEM_NCOH_F 0x30000000 +#define GPU_BUS_BAR2_BLOCK_MODE_VIRTUAL_F 0x80000000 +#define GPU_BUS_BAR1_BLOCK_PTR_SHIFT_V 0x0000000c +#define GPU_BUS_BAR2_BLOCK_PTR_SHIFT_V 0x0000000c +#define GPU_BUS_BIND_STATUS 0x00001710 +#define GPU_BUS_BIND_STATUS_BAR1_PENDING_SHIFT 0x00000000 +#define GPU_BUS_BIND_STATUS_BAR1_PENDING_FIELDMASK 0x00000001 +#define GPU_BUS_BIND_STATUS_BAR1_PENDING_EMPTY_F 0x00000000 +#define GPU_BUS_BIND_STATUS_BAR1_PENDING_BUSY_F 0x00000001 +#define GPU_BUS_BIND_STATUS_BAR1_OUTSTANDING_SHIFT 0x00000001 +#define GPU_BUS_BIND_STATUS_BAR1_OUTSTANDING_FIELDMASK 0x00000001 +#define GPU_BUS_BIND_STATUS_BAR1_OUTSTANDING_FALSE_F 0x00000000 +#define GPU_BUS_BIND_STATUS_BAR1_OUTSTANDING_TRUE_F 0x00000002 +#define GPU_BUS_BIND_STATUS_BAR2_PENDING_SHIFT 0x00000002 +#define GPU_BUS_BIND_STATUS_BAR2_PENDING_FIELDMASK 0x00000001 +#define GPU_BUS_BIND_STATUS_BAR2_PENDING_EMPTY_F 0x00000000 +#define GPU_BUS_BIND_STATUS_BAR2_PENDING_BUSY_F 0x00000004 +#define GPU_BUS_BIND_STATUS_BAR2_OUTSTANDING_SHIFT 0x00000003 +#define GPU_BUS_BIND_STATUS_BAR2_OUTSTANDING_FIELDMASK 0x00000001 +#define GPU_BUS_BIND_STATUS_BAR2_OUTSTANDING_FALSE_F 0x00000000 +#define GPU_BUS_BIND_STATUS_BAR2_OUTSTANDING_TRUE_F 0x00000008 +#define GPU_BUS_INTR_0 0x00001100 +#define GPU_BUS_INTR_0_PRI_SQUASH_MASK 0x00000002 +#define GPU_BUS_INTR_0_PRI_SQUASH_SHIFT 0x00000001 +#define GPU_BUS_INTR_0_PRI_SQUASH_FIELDMASK 0x00000001 +#define GPU_BUS_INTR_0_PRI_FECSERR_MASK 0x00000004 +#define GPU_BUS_INTR_0_PRI_FECSERR_SHIFT 0x00000002 +#define GPU_BUS_INTR_0_PRI_FECSERR_FIELDMASK 0x00000001 +#define GPU_BUS_INTR_0_PRI_TIMEOUT_MASK 0x00000008 +#define GPU_BUS_INTR_0_PRI_TIMEOUT_SHIFT 0x00000003 +#define GPU_BUS_INTR_0_PRI_TIMEOUT_FIELDMASK 0x00000001 +#define GPU_BUS_INTR_EN_0 0x00001140 +#define GPU_BUS_INTR_EN_0_PRI_SQUASH_MASK 0x00000002 +#define GPU_BUS_INTR_EN_0_PRI_SQUASH_SHIFT 0x00000001 +#define GPU_BUS_INTR_EN_0_PRI_SQUASH_FIELDMASK 0x00000001 +#define GPU_BUS_INTR_EN_0_PRI_FECSERR_MASK 0x00000004 +#define GPU_BUS_INTR_EN_0_PRI_FECSERR_SHIFT 0x00000002 +#define GPU_BUS_INTR_EN_0_PRI_FECSERR_FIELDMASK 0x00000001 +#define GPU_BUS_INTR_EN_0_PRI_TIMEOUT_MASK 0x00000008 +#define GPU_BUS_INTR_EN_0_PRI_TIMEOUT_SHIFT 0x00000003 +#define GPU_BUS_INTR_EN_0_PRI_TIMEOUT_FIELDMASK 0x00000001 + +#define GPU_CCSR_CHANNEL_INST__BASE 0x00800000 +#define GPU_CCSR_CHANNEL_INST__STRIDE 0x00000008 +#define GPU_CCSR_CHANNEL_INST(i) (0x00800000 + (i) * 0x00000008) +#define GPU_CCSR_CHANNEL_INST__SIZE_1_V 0x00000200 +#define GPU_CCSR_CHANNEL_INST_PTR_SHIFT 0x00000000 +#define GPU_CCSR_CHANNEL_INST_PTR_FIELDMASK 0x0fffffff +#define GPU_CCSR_CHANNEL_INST_TARGET_VID_MEM_F 0x00000000 +#define GPU_CCSR_CHANNEL_INST_TARGET_SYS_MEM_COH_F 0x20000000 +#define GPU_CCSR_CHANNEL_INST_TARGET_SYS_MEM_NCOH_F 0x30000000 +#define GPU_CCSR_CHANNEL_INST_BIND_FALSE_F 0x00000000 +#define GPU_CCSR_CHANNEL_INST_BIND_TRUE_F 0x80000000 +#define GPU_CCSR_CHANNEL__BASE 0x00800004 +#define GPU_CCSR_CHANNEL__STRIDE 0x00000008 +#define GPU_CCSR_CHANNEL(i) (0x00800004 + (i) * 0x00000008) +#define GPU_CCSR_CHANNEL__SIZE_1_V 0x00000200 +#define GPU_CCSR_CHANNEL_ENABLE_SHIFT 0x00000000 +#define GPU_CCSR_CHANNEL_ENABLE_FIELDMASK 0x00000001 +#define GPU_CCSR_CHANNEL_ENABLE_SET_SHIFT 0x0000000a +#define GPU_CCSR_CHANNEL_ENABLE_SET_FIELDMASK 0x00000001 +#define GPU_CCSR_CHANNEL_ENABLE_SET_TRUE_F 0x00000400 +#define GPU_CCSR_CHANNEL_ENABLE_CLR_TRUE_F 0x00000800 +#define GPU_CCSR_CHANNEL_STATUS_SHIFT 0x00000018 +#define GPU_CCSR_CHANNEL_STATUS_FIELDMASK 0x0000000f +#define GPU_CCSR_CHANNEL_BUSY_SHIFT 0x0000001c +#define GPU_CCSR_CHANNEL_BUSY_FIELDMASK 0x00000001 + +#define GPU_CE2_INTR_STATUS 0x00106908 +#define GPU_CE2_INTR_STATUS_BLOCKPIPE_PENDING_F 0x00000001 +#define GPU_CE2_INTR_STATUS_BLOCKPIPE_RESET_F 0x00000001 +#define GPU_CE2_INTR_STATUS_NONBLOCKPIPE_PENDING_F 0x00000002 +#define GPU_CE2_INTR_STATUS_NONBLOCKPIPE_RESET_F 0x00000002 +#define GPU_CE2_INTR_STATUS_LAUNCHERR_PENDING_F 0x00000004 +#define GPU_CE2_INTR_STATUS_LAUNCHERR_RESET_F 0x00000004 + +#define GPU_CTXSW_PROG_FECS_HEADER_V 0x00000100 +#define GPU_CTXSW_PROG_MAIN_IMAGE_NUM_GPCS_O 0x00000008 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CTL_O 0x0000000c +#define GPU_CTXSW_PROG_MAIN_IMAGE_CTL_CDE_ENABLED_F 0x00000400 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CTL_CDE_DISABLED_F 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PATCH_COUNT_O 0x00000010 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_ID_O 0x000000f0 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PATCH_ADR_LO_O 0x00000014 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PATCH_ADR_HI_O 0x00000018 +#define GPU_CTXSW_PROG_MAIN_IMAGE_ZCULL_O 0x0000001c +#define GPU_CTXSW_PROG_MAIN_IMAGE_ZCULL_MODE_NO_CTXSW_V 0x00000001 +#define GPU_CTXSW_PROG_MAIN_IMAGE_ZCULL_MODE_SEPARATE_BUFFER_V 0x00000002 +#define GPU_CTXSW_PROG_MAIN_IMAGE_ZCULL_PTR_O 0x00000020 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_O 0x00000028 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_MODE_MASK 0x00000007 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_MODE_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_MODE_FIELDMASK 0x00000007 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_MODE_NO_CTXSW_F 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_SMPC_MODE_MASK 0x00000038 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_SMPC_MODE_SHIFT 0x00000003 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_SMPC_MODE_FIELDMASK 0x00000007 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_SMPC_MODE_CTXSW_F 0x00000008 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_SMPC_MODE_NO_CTXSW_F 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_PC_SAMPLING_SHIFT 0x00000006 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_PC_SAMPLING_FIELDMASK 0x00000001 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_PC_SAMPLING_MASK 0x00000040 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PM_PTR_O 0x0000002c +#define GPU_CTXSW_PROG_MAIN_IMAGE_NUM_SAVE_OPS_O 0x000000f4 +#define GPU_CTXSW_PROG_MAIN_IMAGE_NUM_RESTORE_OPS_O 0x000000f8 +#define GPU_CTXSW_PROG_MAIN_IMAGE_MAGIC_VALUE_O 0x000000fc +#define GPU_CTXSW_PROG_MAIN_IMAGE_MAGIC_VALUE_V_VALUE_V 0x600dc0de +#define GPU_CTXSW_PROG_LOCAL_PRIV_REGISTER_CTL_O 0x0000000c +#define GPU_CTXSW_PROG_LOCAL_PRIV_REGISTER_CTL_OFFSET_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_LOCAL_PRIV_REGISTER_CTL_OFFSET_FIELDMASK 0x0000ffff +#define GPU_CTXSW_PROG_LOCAL_IMAGE_PPC_INFO_O 0x000000f4 +#define GPU_CTXSW_PROG_LOCAL_IMAGE_PPC_INFO_NUM_PPCS_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_LOCAL_IMAGE_PPC_INFO_NUM_PPCS_FIELDMASK 0x0000ffff +#define GPU_CTXSW_PROG_LOCAL_IMAGE_PPC_INFO_PPC_MASK_SHIFT 0x00000010 +#define GPU_CTXSW_PROG_LOCAL_IMAGE_PPC_INFO_PPC_MASK_FIELDMASK 0x0000ffff +#define GPU_CTXSW_PROG_LOCAL_IMAGE_NUM_TPCS_O 0x000000f8 +#define GPU_CTXSW_PROG_LOCAL_MAGIC_VALUE_O 0x000000fc +#define GPU_CTXSW_PROG_LOCAL_MAGIC_VALUE_V_VALUE_V 0xad0becab +#define GPU_CTXSW_PROG_MAIN_EXTENDED_BUFFER_CTL_O 0x000000ec +#define GPU_CTXSW_PROG_MAIN_EXTENDED_BUFFER_CTL_OFFSET_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_MAIN_EXTENDED_BUFFER_CTL_OFFSET_FIELDMASK 0x0000ffff +#define GPU_CTXSW_PROG_MAIN_EXTENDED_BUFFER_CTL_SIZE_SHIFT 0x00000010 +#define GPU_CTXSW_PROG_MAIN_EXTENDED_BUFFER_CTL_SIZE_FIELDMASK 0x000000ff +#define GPU_CTXSW_PROG_EXTENDED_BUFFER_SEGMENTS_SIZE_IN_BYTES_V 0x00000100 +#define GPU_CTXSW_PROG_EXTENDED_MARKER_SIZE_IN_BYTES_V 0x00000004 +#define GPU_CTXSW_PROG_EXTENDED_SM_DSM_PERF_COUNTER_REGISTER_STRIDE_V 0x00000000 +#define GPU_CTXSW_PROG_EXTENDED_SM_DSM_PERF_COUNTER_CONTROL_REGISTER_STRIDE_V 0x00000002 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_CONFIG_O 0x000000a0 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_CONFIG_MODE_SIZE 0x00000002 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_CONFIG_MODE_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_CONFIG_MODE_FIELDMASK 0x00000003 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_CONFIG_MODE_MASK 0x00000003 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_CONFIG_MODE_ALLOW_ALL_F 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_CONFIG_MODE_USE_MAP_F 0x00000002 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_ADDR_LO_O 0x000000a4 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PRIV_ACCESS_MAP_ADDR_HI_O 0x000000a8 +#define GPU_CTXSW_PROG_MAIN_IMAGE_MISC_OPTIONS_O 0x0000003c +#define GPU_CTXSW_PROG_MAIN_IMAGE_MISC_OPTIONS_VERIF_FEATURES_MASK 0x00000008 +#define GPU_CTXSW_PROG_MAIN_IMAGE_MISC_OPTIONS_VERIF_FEATURES_SHIFT 0x00000003 +#define GPU_CTXSW_PROG_MAIN_IMAGE_MISC_OPTIONS_VERIF_FEATURES_FIELDMASK 0x00000001 +#define GPU_CTXSW_PROG_MAIN_IMAGE_MISC_OPTIONS_VERIF_FEATURES_DISABLED_F 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_CONTROL_O 0x000000ac +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_CONTROL_NUM_RECORDS_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_CONTROL_NUM_RECORDS_FIELDMASK 0x0000ffff +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_O 0x000000b0 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_V_MASK 0x0fffffff +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_V_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_V_FIELDMASK 0x0fffffff +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_TARGET_MASK 0x30000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_TARGET_SHIFT 0x0000001c +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_TARGET_FIELDMASK 0x00000003 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_TARGET_VID_MEM_F 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_TARGET_SYS_MEM_COHERENT_F 0x20000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_HI_TARGET_SYS_MEM_NONCOHERENT_F 0x30000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_O 0x000000b4 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_V_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_CONTEXT_TIMESTAMP_BUFFER_PTR_V_FIELDMASK 0xffffffff +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_RECORD_SIZE_IN_BYTES_V 0x00000080 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_RECORD_SIZE_IN_WORDS_V 0x00000020 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_MAGIC_VALUE_LO_O 0x00000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_MAGIC_VALUE_LO_V_VALUE_V 0x00000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_MAGIC_VALUE_HI_O 0x00000004 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_MAGIC_VALUE_HI_V_VALUE_V 0x600dbeef +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_CONTEXT_ID_O 0x00000008 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_CONTEXT_PTR_O 0x0000000c +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_NEW_CONTEXT_ID_O 0x00000010 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_NEW_CONTEXT_PTR_O 0x00000014 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_LO_O 0x00000018 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_O 0x0000001c +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_V_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_V_FIELDMASK 0x00ffffff +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_SHIFT 0x00000018 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FIELDMASK 0x000000ff +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_MASK 0xff000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_CTXSW_REQ_BY_HOST_V 0x00000001 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_CTXSW_REQ_BY_HOST_F 0x01000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_V 0x00000002 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_F 0x02000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_WFI_V 0x0000000a +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_WFI_F 0x0a000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_GFXP_V 0x0000000b +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_GFXP_F 0x0b000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_CTAP_V 0x0000000c +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_CTAP_F 0x0c000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_CILP_V 0x0000000d +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_FE_ACK_CILP_F 0x0d000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_SAVE_END_V 0x00000003 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_SAVE_END_F 0x03000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_RESTORE_START_V 0x00000004 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_RESTORE_START_F 0x04000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_CONTEXT_START_V 0x00000005 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_CONTEXT_START_F 0x05000000 +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_INVALID_TIMESTAMP_V 0x000000ff +#define GPU_CTXSW_PROG_RECORD_TIMESTAMP_TIMESTAMP_HI_TAG_INVALID_TIMESTAMP_F 0xff000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PREEMPTION_OPTIONS_O 0x00000060 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PREEMPTION_OPTIONS_CONTROL_SHIFT 0x00000000 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PREEMPTION_OPTIONS_CONTROL_FIELDMASK 0x00000003 +#define GPU_CTXSW_PROG_MAIN_IMAGE_PREEMPTION_OPTIONS_CONTROL_CTA_ENABLED_F 0x00000001 + +#define GPU_FB_FBHUB_NUM_ACTIVE_LTCS 0x00100800 +#define GPU_FB_MMU_CTRL 0x00100c80 +#define GPU_FB_MMU_CTRL_VM_PG_SIZE_SHIFT 0x00000000 +#define GPU_FB_MMU_CTRL_VM_PG_SIZE_FIELDMASK 0x00000001 +#define GPU_FB_MMU_CTRL_VM_PG_SIZE_128KB_F 0x00000000 +#define GPU_FB_MMU_CTRL_VM_PG_SIZE_64KB_F 0x00000001 +#define GPU_FB_MMU_CTRL_PRI_FIFO_EMPTY_SHIFT 0x0000000f +#define GPU_FB_MMU_CTRL_PRI_FIFO_EMPTY_FIELDMASK 0x00000001 +#define GPU_FB_MMU_CTRL_PRI_FIFO_EMPTY_FALSE_F 0x00000000 +#define GPU_FB_MMU_CTRL_PRI_FIFO_SPACE_SHIFT 0x00000010 +#define GPU_FB_MMU_CTRL_PRI_FIFO_SPACE_FIELDMASK 0x000000ff +#define GPU_FB_MMU_CTRL_USE_PDB_BIG_PAGE_SIZE_SHIFT 0x0000000b +#define GPU_FB_MMU_CTRL_USE_PDB_BIG_PAGE_SIZE_FIELDMASK 0x00000001 +#define GPU_FB_MMU_CTRL_USE_PDB_BIG_PAGE_SIZE_TRUE_F 0x00000800 +#define GPU_FB_MMU_CTRL_USE_PDB_BIG_PAGE_SIZE_FALSE_F 0x00000000 +#define GPU_FB_MMU_CTRL_USE_FULL_COMP_TAG_LINE_SHIFT 0x0000000c +#define GPU_FB_MMU_CTRL_USE_FULL_COMP_TAG_LINE_FIELDMASK 0x00000001 +#define GPU_FB_MMU_CTRL_USE_FULL_COMP_TAG_LINE_TRUE_F 0x00001000 +#define GPU_FB_PRIV_MMU_PHY_SECURE 0x00100ce4 +#define GPU_FB_MMU_INVALIDATE_PDB 0x00100cb8 +#define GPU_FB_MMU_INVALIDATE_PDB_APERTURE_VID_MEM_F 0x00000000 +#define GPU_FB_MMU_INVALIDATE_PDB_APERTURE_SYS_MEM_F 0x00000002 +#define GPU_FB_MMU_INVALIDATE_PDB_ADDR_SHIFT 0x00000004 +#define GPU_FB_MMU_INVALIDATE_PDB_ADDR_FIELDMASK 0x0fffffff +#define GPU_FB_MMU_INVALIDATE 0x00100cbc +#define GPU_FB_MMU_INVALIDATE_ALL_VA_TRUE_F 0x00000001 +#define GPU_FB_MMU_INVALIDATE_ALL_PDB_TRUE_F 0x00000002 +#define GPU_FB_MMU_INVALIDATE_TRIGGER_SIZE 0x00000001 +#define GPU_FB_MMU_INVALIDATE_TRIGGER_SHIFT 0x0000001f +#define GPU_FB_MMU_INVALIDATE_TRIGGER_FIELDMASK 0x00000001 +#define GPU_FB_MMU_INVALIDATE_TRIGGER_MASK 0x80000000 +#define GPU_FB_MMU_INVALIDATE_TRIGGER_TRUE_F 0x80000000 +#define GPU_FB_MMU_DEBUG_WR 0x00100cc8 +#define GPU_FB_MMU_DEBUG_WR_APERTURE_SIZE 0x00000002 +#define GPU_FB_MMU_DEBUG_WR_APERTURE_SHIFT 0x00000000 +#define GPU_FB_MMU_DEBUG_WR_APERTURE_FIELDMASK 0x00000003 +#define GPU_FB_MMU_DEBUG_WR_APERTURE_MASK 0x00000003 +#define GPU_FB_MMU_DEBUG_WR_APERTURE_VID_MEM_F 0x00000000 +#define GPU_FB_MMU_DEBUG_WR_APERTURE_SYS_MEM_COH_F 0x00000002 +#define GPU_FB_MMU_DEBUG_WR_APERTURE_SYS_MEM_NCOH_F 0x00000003 +#define GPU_FB_MMU_DEBUG_WR_VOL_FALSE_F 0x00000000 +#define GPU_FB_MMU_DEBUG_WR_VOL_TRUE_V 0x00000001 +#define GPU_FB_MMU_DEBUG_WR_VOL_TRUE_F 0x00000004 +#define GPU_FB_MMU_DEBUG_WR_ADDR_SHIFT 0x00000004 +#define GPU_FB_MMU_DEBUG_WR_ADDR_FIELDMASK 0x0fffffff +#define GPU_FB_MMU_DEBUG_WR_ADDR_ALIGNMENT_V 0x0000000c +#define GPU_FB_MMU_DEBUG_RD 0x00100ccc +#define GPU_FB_MMU_DEBUG_RD_APERTURE_VID_MEM_F 0x00000000 +#define GPU_FB_MMU_DEBUG_RD_APERTURE_SYS_MEM_COH_F 0x00000002 +#define GPU_FB_MMU_DEBUG_RD_APERTURE_SYS_MEM_NCOH_F 0x00000003 +#define GPU_FB_MMU_DEBUG_RD_VOL_FALSE_F 0x00000000 +#define GPU_FB_MMU_DEBUG_RD_ADDR_SHIFT 0x00000004 +#define GPU_FB_MMU_DEBUG_RD_ADDR_FIELDMASK 0x0fffffff +#define GPU_FB_MMU_DEBUG_RD_ADDR_ALIGNMENT_V 0x0000000c +#define GPU_FB_MMU_DEBUG_CTRL 0x00100cc4 +#define GPU_FB_MMU_DEBUG_CTRL_DEBUG_SHIFT 0x00000010 +#define GPU_FB_MMU_DEBUG_CTRL_DEBUG_FIELDMASK 0x00000001 +#define GPU_FB_MMU_DEBUG_CTRL_DEBUG_MASK 0x00010000 +#define GPU_FB_MMU_DEBUG_CTRL_DEBUG_ENABLED_V 0x00000001 +#define GPU_FB_MMU_DEBUG_CTRL_DEBUG_ENABLED_F 0x00010000 +#define GPU_FB_MMU_DEBUG_CTRL_DEBUG_DISABLED_V 0x00000000 +#define GPU_FB_MMU_DEBUG_CTRL_DEBUG_DISABLED_F 0x00000000 +#define GPU_FB_MMU_VPR_INFO 0x00100cd0 +#define GPU_FB_MMU_VPR_INFO_INDEX_SHIFT 0x00000000 +#define GPU_FB_MMU_VPR_INFO_INDEX_FIELDMASK 0x00000003 +#define GPU_FB_MMU_VPR_INFO_INDEX_ADDR_LO_V 0x00000000 +#define GPU_FB_MMU_VPR_INFO_INDEX_ADDR_HI_V 0x00000001 +#define GPU_FB_MMU_VPR_INFO_INDEX_CYA_LO_V 0x00000002 +#define GPU_FB_MMU_VPR_INFO_INDEX_CYA_HI_V 0x00000003 +#define GPU_FB_MMU_VPR_INFO_FETCH_SHIFT 0x00000002 +#define GPU_FB_MMU_VPR_INFO_FETCH_FIELDMASK 0x00000001 +#define GPU_FB_MMU_VPR_INFO_FETCH_FALSE_V 0x00000000 +#define GPU_FB_MMU_VPR_INFO_FETCH_TRUE_V 0x00000001 +#define GPU_FB_MMU_WPR_INFO 0x00100cd4 +#define GPU_FB_MMU_WPR_INFO_INDEX_SHIFT 0x00000000 +#define GPU_FB_MMU_WPR_INFO_INDEX_FIELDMASK 0x0000000f +#define GPU_FB_MMU_WPR_INFO_INDEX_ALLOW_READ_V 0x00000000 +#define GPU_FB_MMU_WPR_INFO_INDEX_ALLOW_WRITE_V 0x00000001 +#define GPU_FB_MMU_WPR_INFO_INDEX_WPR1_ADDR_LO_V 0x00000002 +#define GPU_FB_MMU_WPR_INFO_INDEX_WPR1_ADDR_HI_V 0x00000003 +#define GPU_FB_MMU_WPR_INFO_INDEX_WPR2_ADDR_LO_V 0x00000004 +#define GPU_FB_MMU_WPR_INFO_INDEX_WPR2_ADDR_HI_V 0x00000005 + +#define GPU_FIFO_BAR1_BASE 0x00002254 +#define GPU_FIFO_BAR1_BASE_PTR_SHIFT 0x00000000 +#define GPU_FIFO_BAR1_BASE_PTR_FIELDMASK 0x0fffffff +#define GPU_FIFO_BAR1_BASE_PTR_ALIGN_SHIFT_V 0x0000000c +#define GPU_FIFO_BAR1_BASE_VALID_FALSE_F 0x00000000 +#define GPU_FIFO_BAR1_BASE_VALID_TRUE_F 0x10000000 +#define GPU_FIFO_RUNLIST_BASE 0x00002270 +#define GPU_FIFO_RUNLIST_BASE_PTR_SHIFT 0x00000000 +#define GPU_FIFO_RUNLIST_BASE_PTR_FIELDMASK 0x0fffffff +#define GPU_FIFO_RUNLIST_BASE_TARGET_VID_MEM_F 0x00000000 +#define GPU_FIFO_RUNLIST_BASE_TARGET_SYS_MEM_COH_F 0x20000000 +#define GPU_FIFO_RUNLIST_BASE_TARGET_SYS_MEM_NCOH_F 0x30000000 +#define GPU_FIFO_RUNLIST 0x00002274 +#define GPU_FIFO_RUNLIST_ENGINE_SHIFT 0x00000014 +#define GPU_FIFO_RUNLIST_ENGINE_FIELDMASK 0x0000000f +#define GPU_FIFO_ENG_RUNLIST_BASE__BASE 0x00002280 +#define GPU_FIFO_ENG_RUNLIST_BASE__STRIDE 0x00000008 +#define GPU_FIFO_ENG_RUNLIST_BASE(i) (0x00002280 + (i) * 0x00000008) +#define GPU_FIFO_ENG_RUNLIST_BASE__SIZE_1_V 0x00000001 +#define GPU_FIFO_ENG_RUNLIST__BASE 0x00002284 +#define GPU_FIFO_ENG_RUNLIST__STRIDE 0x00000008 +#define GPU_FIFO_ENG_RUNLIST(i) (0x00002284 + (i) * 0x00000008) +#define GPU_FIFO_ENG_RUNLIST__SIZE_1_V 0x00000001 +#define GPU_FIFO_ENG_RUNLIST_LENGTH_SHIFT 0x00000000 +#define GPU_FIFO_ENG_RUNLIST_LENGTH_FIELDMASK 0x0000ffff +#define GPU_FIFO_ENG_RUNLIST_LENGTH_MAX_V 0x0000ffff +#define GPU_FIFO_ENG_RUNLIST_PENDING_TRUE_F 0x00100000 +#define GPU_FIFO_PB_TIMESLICE__BASE 0x00002350 +#define GPU_FIFO_PB_TIMESLICE__STRIDE 0x00000004 +#define GPU_FIFO_PB_TIMESLICE(i) (0x00002350 + (i) * 0x00000004) +#define GPU_FIFO_PB_TIMESLICE_TIMEOUT_16_F 0x00000010 +#define GPU_FIFO_PB_TIMESLICE_TIMESCALE_0_F 0x00000000 +#define GPU_FIFO_PB_TIMESLICE_ENABLE_TRUE_F 0x10000000 +#define GPU_FIFO_PBDMA_MAP__BASE 0x00002390 +#define GPU_FIFO_PBDMA_MAP__STRIDE 0x00000004 +#define GPU_FIFO_PBDMA_MAP(i) (0x00002390 + (i) * 0x00000004) +#define GPU_FIFO_INTR_0 0x00002100 +#define GPU_FIFO_INTR_0_BIND_ERROR_PENDING_F 0x00000001 +#define GPU_FIFO_INTR_0_BIND_ERROR_RESET_F 0x00000001 +#define GPU_FIFO_INTR_0_SCHED_ERROR_PENDING_F 0x00000100 +#define GPU_FIFO_INTR_0_SCHED_ERROR_RESET_F 0x00000100 +#define GPU_FIFO_INTR_0_CHSW_ERROR_PENDING_F 0x00010000 +#define GPU_FIFO_INTR_0_CHSW_ERROR_RESET_F 0x00010000 +#define GPU_FIFO_INTR_0_FB_FLUSH_TIMEOUT_PENDING_F 0x00800000 +#define GPU_FIFO_INTR_0_FB_FLUSH_TIMEOUT_RESET_F 0x00800000 +#define GPU_FIFO_INTR_0_LB_ERROR_PENDING_F 0x01000000 +#define GPU_FIFO_INTR_0_LB_ERROR_RESET_F 0x01000000 +#define GPU_FIFO_INTR_0_DROPPED_MMU_FAULT_PENDING_F 0x08000000 +#define GPU_FIFO_INTR_0_DROPPED_MMU_FAULT_RESET_F 0x08000000 +#define GPU_FIFO_INTR_0_MMU_FAULT_PENDING_F 0x10000000 +#define GPU_FIFO_INTR_0_PBDMA_INTR_PENDING_F 0x20000000 +#define GPU_FIFO_INTR_0_RUNLIST_EVENT_PENDING_F 0x40000000 +#define GPU_FIFO_INTR_0_CHANNEL_INTR_PENDING_F 0x80000000 +#define GPU_FIFO_INTR_EN_0 0x00002140 +#define GPU_FIFO_INTR_EN_0_SCHED_ERROR_SHIFT 0x00000008 +#define GPU_FIFO_INTR_EN_0_SCHED_ERROR_FIELDMASK 0x00000001 +#define GPU_FIFO_INTR_EN_0_SCHED_ERROR_MASK 0x00000100 +#define GPU_FIFO_INTR_EN_0_MMU_FAULT_SHIFT 0x0000001c +#define GPU_FIFO_INTR_EN_0_MMU_FAULT_FIELDMASK 0x00000001 +#define GPU_FIFO_INTR_EN_0_MMU_FAULT_MASK 0x10000000 +#define GPU_FIFO_INTR_EN_1 0x00002528 +#define GPU_FIFO_INTR_BIND_ERROR 0x0000252c +#define GPU_FIFO_INTR_SCHED_ERROR 0x0000254c +#define GPU_FIFO_INTR_SCHED_ERROR_CODE_SHIFT 0x00000000 +#define GPU_FIFO_INTR_SCHED_ERROR_CODE_FIELDMASK 0x000000ff +#define GPU_FIFO_INTR_SCHED_ERROR_CODE_CTXSW_TIMEOUT_V 0x0000000a +#define GPU_FIFO_INTR_CHSW_ERROR 0x0000256c +#define GPU_FIFO_INTR_MMU_FAULT_ID 0x0000259c +#define GPU_FIFO_INTR_MMU_FAULT_ENG_ID_GRAPHICS_V 0x00000000 +#define GPU_FIFO_INTR_MMU_FAULT_ENG_ID_GRAPHICS_F 0x00000000 +#define GPU_FIFO_INTR_MMU_FAULT_INST__BASE 0x00002800 +#define GPU_FIFO_INTR_MMU_FAULT_INST__STRIDE 0x00000010 +#define GPU_FIFO_INTR_MMU_FAULT_INST(i) (0x00002800 + (i) * 0x00000010) +#define GPU_FIFO_INTR_MMU_FAULT_INST_PTR_SHIFT 0x00000000 +#define GPU_FIFO_INTR_MMU_FAULT_INST_PTR_FIELDMASK 0x0fffffff +#define GPU_FIFO_INTR_MMU_FAULT_INST_PTR_ALIGN_SHIFT_V 0x0000000c +#define GPU_FIFO_INTR_MMU_FAULT_LO__BASE 0x00002804 +#define GPU_FIFO_INTR_MMU_FAULT_LO__STRIDE 0x00000010 +#define GPU_FIFO_INTR_MMU_FAULT_LO(i) (0x00002804 + (i) * 0x00000010) +#define GPU_FIFO_INTR_MMU_FAULT_HI__BASE 0x00002808 +#define GPU_FIFO_INTR_MMU_FAULT_HI__STRIDE 0x00000010 +#define GPU_FIFO_INTR_MMU_FAULT_HI(i) (0x00002808 + (i) * 0x00000010) +#define GPU_FIFO_INTR_MMU_FAULT_INFO__BASE 0x0000280c +#define GPU_FIFO_INTR_MMU_FAULT_INFO__STRIDE 0x00000010 +#define GPU_FIFO_INTR_MMU_FAULT_INFO(i) (0x0000280c + (i) * 0x00000010) +#define GPU_FIFO_INTR_MMU_FAULT_INFO_TYPE_SHIFT 0x00000000 +#define GPU_FIFO_INTR_MMU_FAULT_INFO_TYPE_FIELDMASK 0x0000000f +#define GPU_FIFO_INTR_MMU_FAULT_INFO_ENGINE_SUBID_SHIFT 0x00000006 +#define GPU_FIFO_INTR_MMU_FAULT_INFO_ENGINE_SUBID_FIELDMASK 0x00000001 +#define GPU_FIFO_INTR_MMU_FAULT_INFO_ENGINE_SUBID_GPC_V 0x00000000 +#define GPU_FIFO_INTR_MMU_FAULT_INFO_ENGINE_SUBID_HUB_V 0x00000001 +#define GPU_FIFO_INTR_MMU_FAULT_INFO_CLIENT_SHIFT 0x00000008 +#define GPU_FIFO_INTR_MMU_FAULT_INFO_CLIENT_FIELDMASK 0x0000003f +#define GPU_FIFO_INTR_PBDMA_ID 0x000025a0 +#define GPU_FIFO_INTR_PBDMA_ID_STATUS_FIELDMASK 0x00000001 +#define GPU_FIFO_INTR_PBDMA_ID_STATUS__SHIFT_BASE 0x00000000 +#define GPU_FIFO_INTR_PBDMA_ID_STATUS__SHIFT_STRIDE 0x00000001 +#define GPU_FIFO_INTR_PBDMA_ID_STATUS__SHIFT_I(i) (0 + (i) * 1) +#define GPU_FIFO_INTR_PBDMA_ID_STATUS__SIZE_1_V 0x00000001 +#define GPU_FIFO_INTR_RUNLIST 0x00002a00 +#define GPU_FIFO_FB_TIMEOUT 0x00002a04 +#define GPU_FIFO_FB_TIMEOUT_PERIOD_MASK 0x3fffffff +#define GPU_FIFO_FB_TIMEOUT_PERIOD_SHIFT 0x00000000 +#define GPU_FIFO_FB_TIMEOUT_PERIOD_FIELDMASK 0x3fffffff +#define GPU_FIFO_FB_TIMEOUT_PERIOD_MAX_F 0x3fffffff +#define GPU_FIFO_ERROR_SCHED_DISABLE 0x0000262c +#define GPU_FIFO_SCHED_DISABLE 0x00002630 +#define GPU_FIFO_SCHED_DISABLE_RUNLIST_FIELDMASK 0x00000001 +#define GPU_FIFO_SCHED_DISABLE_RUNLIST__SHIFT_BASE 0x00000000 +#define GPU_FIFO_SCHED_DISABLE_RUNLIST__SHIFT_STRIDE 0x00000001 +#define GPU_FIFO_SCHED_DISABLE_RUNLIST__SHIFT_I(i) (0 + (i) * 1) +#define GPU_FIFO_SCHED_DISABLE_TRUE_V 0x00000001 +#define GPU_FIFO_PREEMPT 0x00002634 +#define GPU_FIFO_PREEMPT_PENDING_TRUE_F 0x00100000 +#define GPU_FIFO_PREEMPT_TYPE_CHANNEL_F 0x00000000 +#define GPU_FIFO_PREEMPT_TYPE_TSG_F 0x01000000 +#define GPU_FIFO_PREEMPT_CHID_SHIFT 0x00000000 +#define GPU_FIFO_PREEMPT_CHID_FIELDMASK 0x00000fff +#define GPU_FIFO_PREEMPT_ID_SHIFT 0x00000000 +#define GPU_FIFO_PREEMPT_ID_FIELDMASK 0x00000fff +#define GPU_FIFO_TRIGGER_MMU_FAULT__BASE 0x00002a30 +#define GPU_FIFO_TRIGGER_MMU_FAULT__STRIDE 0x00000004 +#define GPU_FIFO_TRIGGER_MMU_FAULT(i) (0x00002a30 + (i) * 0x00000004) +#define GPU_FIFO_TRIGGER_MMU_FAULT_ID_SHIFT 0x00000000 +#define GPU_FIFO_TRIGGER_MMU_FAULT_ID_FIELDMASK 0x0000001f +#define GPU_FIFO_TRIGGER_MMU_FAULT_ENABLE_SHIFT 0x00000008 +#define GPU_FIFO_TRIGGER_MMU_FAULT_ENABLE_FIELDMASK 0x00000001 +#define GPU_FIFO_ENGINE_STATUS__BASE 0x00002640 +#define GPU_FIFO_ENGINE_STATUS__STRIDE 0x00000008 +#define GPU_FIFO_ENGINE_STATUS(i) (0x00002640 + (i) * 0x00000008) +#define GPU_FIFO_ENGINE_STATUS__SIZE_1_V 0x00000002 +#define GPU_FIFO_ENGINE_STATUS_ID_SHIFT 0x00000000 +#define GPU_FIFO_ENGINE_STATUS_ID_FIELDMASK 0x00000fff +#define GPU_FIFO_ENGINE_STATUS_ID_TYPE_SHIFT 0x0000000c +#define GPU_FIFO_ENGINE_STATUS_ID_TYPE_FIELDMASK 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_ID_TYPE_CHID_V 0x00000000 +#define GPU_FIFO_ENGINE_STATUS_ID_TYPE_TSGID_V 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_CTX_STATUS_SHIFT 0x0000000d +#define GPU_FIFO_ENGINE_STATUS_CTX_STATUS_FIELDMASK 0x00000007 +#define GPU_FIFO_ENGINE_STATUS_CTX_STATUS_INVALID_V 0x00000000 +#define GPU_FIFO_ENGINE_STATUS_CTX_STATUS_VALID_V 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_CTX_STATUS_CTXSW_LOAD_V 0x00000005 +#define GPU_FIFO_ENGINE_STATUS_CTX_STATUS_CTXSW_SAVE_V 0x00000006 +#define GPU_FIFO_ENGINE_STATUS_CTX_STATUS_CTXSW_SWITCH_V 0x00000007 +#define GPU_FIFO_ENGINE_STATUS_NEXT_ID_SHIFT 0x00000010 +#define GPU_FIFO_ENGINE_STATUS_NEXT_ID_FIELDMASK 0x00000fff +#define GPU_FIFO_ENGINE_STATUS_NEXT_ID_TYPE_SHIFT 0x0000001c +#define GPU_FIFO_ENGINE_STATUS_NEXT_ID_TYPE_FIELDMASK 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_NEXT_ID_TYPE_CHID_V 0x00000000 +#define GPU_FIFO_ENGINE_STATUS_FAULTED_SHIFT 0x0000001e +#define GPU_FIFO_ENGINE_STATUS_FAULTED_FIELDMASK 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_FAULTED_TRUE_V 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_ENGINE_SHIFT 0x0000001f +#define GPU_FIFO_ENGINE_STATUS_ENGINE_FIELDMASK 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_ENGINE_IDLE_V 0x00000000 +#define GPU_FIFO_ENGINE_STATUS_ENGINE_BUSY_V 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_CTXSW_SHIFT 0x0000000f +#define GPU_FIFO_ENGINE_STATUS_CTXSW_FIELDMASK 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_CTXSW_IN_PROGRESS_V 0x00000001 +#define GPU_FIFO_ENGINE_STATUS_CTXSW_IN_PROGRESS_F 0x00008000 +#define GPU_FIFO_PBDMA_STATUS__BASE 0x00003080 +#define GPU_FIFO_PBDMA_STATUS__STRIDE 0x00000004 +#define GPU_FIFO_PBDMA_STATUS(i) (0x00003080 + (i) * 0x00000004) +#define GPU_FIFO_PBDMA_STATUS__SIZE_1_V 0x00000001 +#define GPU_FIFO_PBDMA_STATUS_ID_SHIFT 0x00000000 +#define GPU_FIFO_PBDMA_STATUS_ID_FIELDMASK 0x00000fff +#define GPU_FIFO_PBDMA_STATUS_ID_TYPE_SHIFT 0x0000000c +#define GPU_FIFO_PBDMA_STATUS_ID_TYPE_FIELDMASK 0x00000001 +#define GPU_FIFO_PBDMA_STATUS_ID_TYPE_CHID_V 0x00000000 +#define GPU_FIFO_PBDMA_STATUS_ID_TYPE_TSGID_V 0x00000001 +#define GPU_FIFO_PBDMA_STATUS_CHAN_STATUS_SHIFT 0x0000000d +#define GPU_FIFO_PBDMA_STATUS_CHAN_STATUS_FIELDMASK 0x00000007 +#define GPU_FIFO_PBDMA_STATUS_CHAN_STATUS_VALID_V 0x00000001 +#define GPU_FIFO_PBDMA_STATUS_CHAN_STATUS_CHSW_LOAD_V 0x00000005 +#define GPU_FIFO_PBDMA_STATUS_CHAN_STATUS_CHSW_SAVE_V 0x00000006 +#define GPU_FIFO_PBDMA_STATUS_CHAN_STATUS_CHSW_SWITCH_V 0x00000007 +#define GPU_FIFO_PBDMA_STATUS_NEXT_ID_SHIFT 0x00000010 +#define GPU_FIFO_PBDMA_STATUS_NEXT_ID_FIELDMASK 0x00000fff +#define GPU_FIFO_PBDMA_STATUS_NEXT_ID_TYPE_SHIFT 0x0000001c +#define GPU_FIFO_PBDMA_STATUS_NEXT_ID_TYPE_FIELDMASK 0x00000001 +#define GPU_FIFO_PBDMA_STATUS_NEXT_ID_TYPE_CHID_V 0x00000000 +#define GPU_FIFO_PBDMA_STATUS_CHSW_SHIFT 0x0000000f +#define GPU_FIFO_PBDMA_STATUS_CHSW_FIELDMASK 0x00000001 +#define GPU_FIFO_PBDMA_STATUS_CHSW_IN_PROGRESS_V 0x00000001 + +#define GPU_FLUSH_L2_SYSTEM_INVALIDATE 0x00070004 +#define GPU_FLUSH_L2_SYSTEM_INVALIDATE_PENDING_SHIFT 0x00000000 +#define GPU_FLUSH_L2_SYSTEM_INVALIDATE_PENDING_FIELDMASK 0x00000001 +#define GPU_FLUSH_L2_SYSTEM_INVALIDATE_PENDING_BUSY_V 0x00000001 +#define GPU_FLUSH_L2_SYSTEM_INVALIDATE_PENDING_BUSY_F 0x00000001 +#define GPU_FLUSH_L2_SYSTEM_INVALIDATE_OUTSTANDING_SHIFT 0x00000001 +#define GPU_FLUSH_L2_SYSTEM_INVALIDATE_OUTSTANDING_FIELDMASK 0x00000001 +#define GPU_FLUSH_L2_SYSTEM_INVALIDATE_OUTSTANDING_TRUE_V 0x00000001 +#define GPU_FLUSH_L2_FLUSH_DIRTY 0x00070010 +#define GPU_FLUSH_L2_FLUSH_DIRTY_PENDING_SHIFT 0x00000000 +#define GPU_FLUSH_L2_FLUSH_DIRTY_PENDING_FIELDMASK 0x00000001 +#define GPU_FLUSH_L2_FLUSH_DIRTY_PENDING_EMPTY_V 0x00000000 +#define GPU_FLUSH_L2_FLUSH_DIRTY_PENDING_EMPTY_F 0x00000000 +#define GPU_FLUSH_L2_FLUSH_DIRTY_PENDING_BUSY_V 0x00000001 +#define GPU_FLUSH_L2_FLUSH_DIRTY_PENDING_BUSY_F 0x00000001 +#define GPU_FLUSH_L2_FLUSH_DIRTY_OUTSTANDING_SHIFT 0x00000001 +#define GPU_FLUSH_L2_FLUSH_DIRTY_OUTSTANDING_FIELDMASK 0x00000001 +#define GPU_FLUSH_L2_FLUSH_DIRTY_OUTSTANDING_FALSE_V 0x00000000 +#define GPU_FLUSH_L2_FLUSH_DIRTY_OUTSTANDING_FALSE_F 0x00000000 +#define GPU_FLUSH_L2_FLUSH_DIRTY_OUTSTANDING_TRUE_V 0x00000001 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS 0x0007000c +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_PENDING_SHIFT 0x00000000 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_PENDING_FIELDMASK 0x00000001 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_PENDING_EMPTY_V 0x00000000 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_PENDING_EMPTY_F 0x00000000 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_PENDING_BUSY_V 0x00000001 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_PENDING_BUSY_F 0x00000001 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_OUTSTANDING_SHIFT 0x00000001 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_OUTSTANDING_FIELDMASK 0x00000001 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_OUTSTANDING_FALSE_V 0x00000000 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_OUTSTANDING_FALSE_F 0x00000000 +#define GPU_FLUSH_L2_CLEAN_COMPTAGS_OUTSTANDING_TRUE_V 0x00000001 +#define GPU_FLUSH_FB_FLUSH 0x00070000 +#define GPU_FLUSH_FB_FLUSH_PENDING_SHIFT 0x00000000 +#define GPU_FLUSH_FB_FLUSH_PENDING_FIELDMASK 0x00000001 +#define GPU_FLUSH_FB_FLUSH_PENDING_BUSY_V 0x00000001 +#define GPU_FLUSH_FB_FLUSH_PENDING_BUSY_F 0x00000001 +#define GPU_FLUSH_FB_FLUSH_OUTSTANDING_SHIFT 0x00000001 +#define GPU_FLUSH_FB_FLUSH_OUTSTANDING_FIELDMASK 0x00000001 +#define GPU_FLUSH_FB_FLUSH_OUTSTANDING_TRUE_V 0x00000001 + +#define GPU_FUSE_STATUS_OPT_TPC_GPC__BASE 0x00021c38 +#define GPU_FUSE_STATUS_OPT_TPC_GPC__STRIDE 0x00000004 +#define GPU_FUSE_STATUS_OPT_TPC_GPC(i) (0x00021c38 + (i) * 0x00000004) +#define GPU_FUSE_CTRL_OPT_TPC_GPC__BASE 0x00021838 +#define GPU_FUSE_CTRL_OPT_TPC_GPC__STRIDE 0x00000004 +#define GPU_FUSE_CTRL_OPT_TPC_GPC(i) (0x00021838 + (i) * 0x00000004) +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP 0x00021944 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_DATA_SHIFT 0x00000000 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_DATA_FIELDMASK 0x00000003 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_DATA_MASK 0x00000003 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_OVERRIDE 0x00021948 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_OVERRIDE_DATA_SHIFT 0x00000000 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_OVERRIDE_DATA_FIELDMASK 0x00000001 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_OVERRIDE_DATA_MASK 0x00000001 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_OVERRIDE_DATA_YES_F 0x00000001 +#define GPU_FUSE_CTRL_OPT_RAM_SVOP_PDP_OVERRIDE_DATA_NO_F 0x00000000 +#define GPU_FUSE_STATUS_OPT_FBIO 0x00021c14 +#define GPU_FUSE_STATUS_OPT_FBIO_DATA_SHIFT 0x00000000 +#define GPU_FUSE_STATUS_OPT_FBIO_DATA_FIELDMASK 0x0000ffff +#define GPU_FUSE_STATUS_OPT_FBIO_DATA_MASK 0x0000ffff +#define GPU_FUSE_STATUS_OPT_ROP_L2_FBP__BASE 0x00021d70 +#define GPU_FUSE_STATUS_OPT_ROP_L2_FBP__STRIDE 0x00000004 +#define GPU_FUSE_STATUS_OPT_ROP_L2_FBP(i) (0x00021d70 + (i) * 0x00000004) +#define GPU_FUSE_STATUS_OPT_FBP 0x00021d38 +#define GPU_FUSE_STATUS_OPT_FBP_IDX_FIELDMASK 0x00000001 +#define GPU_FUSE_STATUS_OPT_FBP_IDX__SHIFT_BASE 0x00000000 +#define GPU_FUSE_STATUS_OPT_FBP_IDX__SHIFT_STRIDE 0x00000000 +#define GPU_FUSE_STATUS_OPT_FBP_IDX__SHIFT_I(i) (0 + (i) * 0) +#define GPU_FUSE_OPT_SEC_DEBUG_EN 0x00021218 +#define GPU_FUSE_OPT_PRIV_SEC_EN 0x00021434 + +#define GPU_GMMU_PDE_APERTURE_BIG_W 0x00000000 +#define GPU_GMMU_PDE_APERTURE_BIG_INVALID_F 0x00000000 +#define GPU_GMMU_PDE_APERTURE_BIG_VIDEO_MEMORY_F 0x00000001 +#define GPU_GMMU_PDE_APERTURE_BIG_SYS_MEM_COH_F 0x00000002 +#define GPU_GMMU_PDE_APERTURE_BIG_SYS_MEM_NCOH_F 0x00000003 +#define GPU_GMMU_PDE_SIZE_W 0x00000000 +#define GPU_GMMU_PDE_SIZE_FULL_F 0x00000000 +#define GPU_GMMU_PDE_ADDRESS_BIG_SYS_SHIFT 0x00000004 +#define GPU_GMMU_PDE_ADDRESS_BIG_SYS_FIELDMASK 0x0fffffff +#define GPU_GMMU_PDE_ADDRESS_BIG_SYS_W 0x00000000 +#define GPU_GMMU_PDE_APERTURE_SMALL_W 0x00000001 +#define GPU_GMMU_PDE_APERTURE_SMALL_INVALID_F 0x00000000 +#define GPU_GMMU_PDE_APERTURE_SMALL_VIDEO_MEMORY_F 0x00000001 +#define GPU_GMMU_PDE_APERTURE_SMALL_SYS_MEM_COH_F 0x00000002 +#define GPU_GMMU_PDE_APERTURE_SMALL_SYS_MEM_NCOH_F 0x00000003 +#define GPU_GMMU_PDE_VOL_SMALL_W 0x00000001 +#define GPU_GMMU_PDE_VOL_SMALL_TRUE_F 0x00000004 +#define GPU_GMMU_PDE_VOL_SMALL_FALSE_F 0x00000000 +#define GPU_GMMU_PDE_VOL_BIG_W 0x00000001 +#define GPU_GMMU_PDE_VOL_BIG_TRUE_F 0x00000008 +#define GPU_GMMU_PDE_VOL_BIG_FALSE_F 0x00000000 +#define GPU_GMMU_PDE_ADDRESS_SMALL_SYS_SHIFT 0x00000004 +#define GPU_GMMU_PDE_ADDRESS_SMALL_SYS_FIELDMASK 0x0fffffff +#define GPU_GMMU_PDE_ADDRESS_SMALL_SYS_W 0x00000001 +#define GPU_GMMU_PDE_ADDRESS_SHIFT_V 0x0000000c +#define GPU_GMMU_PDE__SIZE_V 0x00000008 +#define GPU_GMMU_PTE__SIZE_V 0x00000008 +#define GPU_GMMU_PTE_VALID_W 0x00000000 +#define GPU_GMMU_PTE_VALID_TRUE_F 0x00000001 +#define GPU_GMMU_PTE_VALID_FALSE_F 0x00000000 +#define GPU_GMMU_PTE_PRIVILEGE_W 0x00000000 +#define GPU_GMMU_PTE_PRIVILEGE_TRUE_F 0x00000002 +#define GPU_GMMU_PTE_PRIVILEGE_FALSE_F 0x00000000 +#define GPU_GMMU_PTE_ADDRESS_SYS_SHIFT 0x00000004 +#define GPU_GMMU_PTE_ADDRESS_SYS_FIELDMASK 0x0fffffff +#define GPU_GMMU_PTE_ADDRESS_SYS_W 0x00000000 +#define GPU_GMMU_PTE_VOL_W 0x00000001 +#define GPU_GMMU_PTE_VOL_TRUE_F 0x00000001 +#define GPU_GMMU_PTE_VOL_FALSE_F 0x00000000 +#define GPU_GMMU_PTE_APERTURE_W 0x00000001 +#define GPU_GMMU_PTE_APERTURE_VIDEO_MEMORY_F 0x00000000 +#define GPU_GMMU_PTE_APERTURE_SYS_MEM_COH_F 0x00000004 +#define GPU_GMMU_PTE_APERTURE_SYS_MEM_NCOH_F 0x00000006 +#define GPU_GMMU_PTE_READ_ONLY_W 0x00000000 +#define GPU_GMMU_PTE_READ_ONLY_TRUE_F 0x00000004 +#define GPU_GMMU_PTE_WRITE_DISABLE_W 0x00000001 +#define GPU_GMMU_PTE_WRITE_DISABLE_TRUE_F 0x80000000 +#define GPU_GMMU_PTE_READ_DISABLE_W 0x00000001 +#define GPU_GMMU_PTE_READ_DISABLE_TRUE_F 0x40000000 +#define GPU_GMMU_PTE_COMPTAGLINE_SIZE 0x00000011 +#define GPU_GMMU_PTE_COMPTAGLINE_SHIFT 0x0000000c +#define GPU_GMMU_PTE_COMPTAGLINE_FIELDMASK 0x0001ffff +#define GPU_GMMU_PTE_COMPTAGLINE_W 0x00000001 +#define GPU_GMMU_PTE_ADDRESS_SHIFT_V 0x0000000c +#define GPU_GMMU_PTE_KIND_SHIFT 0x00000004 +#define GPU_GMMU_PTE_KIND_FIELDMASK 0x000000ff +#define GPU_GMMU_PTE_KIND_W 0x00000001 +#define GPU_GMMU_PTE_KIND_INVALID_V 0x000000ff +#define GPU_GMMU_PTE_KIND_PITCH_V 0x00000000 +#define GPU_GMMU_PTE_KIND_Z16_V 0x00000001 +#define GPU_GMMU_PTE_KIND_Z16_2C_V 0x00000002 +#define GPU_GMMU_PTE_KIND_Z16_MS2_2C_V 0x00000003 +#define GPU_GMMU_PTE_KIND_Z16_MS4_2C_V 0x00000004 +#define GPU_GMMU_PTE_KIND_Z16_MS8_2C_V 0x00000005 +#define GPU_GMMU_PTE_KIND_Z16_MS16_2C_V 0x00000006 +#define GPU_GMMU_PTE_KIND_Z16_2Z_V 0x00000007 +#define GPU_GMMU_PTE_KIND_Z16_MS2_2Z_V 0x00000008 +#define GPU_GMMU_PTE_KIND_Z16_MS4_2Z_V 0x00000009 +#define GPU_GMMU_PTE_KIND_Z16_MS8_2Z_V 0x0000000a +#define GPU_GMMU_PTE_KIND_Z16_MS16_2Z_V 0x0000000b +#define GPU_GMMU_PTE_KIND_Z16_4CZ_V 0x0000000c +#define GPU_GMMU_PTE_KIND_Z16_MS2_4CZ_V 0x0000000d +#define GPU_GMMU_PTE_KIND_Z16_MS4_4CZ_V 0x0000000e +#define GPU_GMMU_PTE_KIND_Z16_MS8_4CZ_V 0x0000000f +#define GPU_GMMU_PTE_KIND_Z16_MS16_4CZ_V 0x00000010 +#define GPU_GMMU_PTE_KIND_S8Z24_V 0x00000011 +#define GPU_GMMU_PTE_KIND_S8Z24_1Z_V 0x00000012 +#define GPU_GMMU_PTE_KIND_S8Z24_MS2_1Z_V 0x00000013 +#define GPU_GMMU_PTE_KIND_S8Z24_MS4_1Z_V 0x00000014 +#define GPU_GMMU_PTE_KIND_S8Z24_MS8_1Z_V 0x00000015 +#define GPU_GMMU_PTE_KIND_S8Z24_MS16_1Z_V 0x00000016 +#define GPU_GMMU_PTE_KIND_S8Z24_2CZ_V 0x00000017 +#define GPU_GMMU_PTE_KIND_S8Z24_MS2_2CZ_V 0x00000018 +#define GPU_GMMU_PTE_KIND_S8Z24_MS4_2CZ_V 0x00000019 +#define GPU_GMMU_PTE_KIND_S8Z24_MS8_2CZ_V 0x0000001a +#define GPU_GMMU_PTE_KIND_S8Z24_MS16_2CZ_V 0x0000001b +#define GPU_GMMU_PTE_KIND_S8Z24_2CS_V 0x0000001c +#define GPU_GMMU_PTE_KIND_S8Z24_MS2_2CS_V 0x0000001d +#define GPU_GMMU_PTE_KIND_S8Z24_MS4_2CS_V 0x0000001e +#define GPU_GMMU_PTE_KIND_S8Z24_MS8_2CS_V 0x0000001f +#define GPU_GMMU_PTE_KIND_S8Z24_MS16_2CS_V 0x00000020 +#define GPU_GMMU_PTE_KIND_S8Z24_4CSZV_V 0x00000021 +#define GPU_GMMU_PTE_KIND_S8Z24_MS2_4CSZV_V 0x00000022 +#define GPU_GMMU_PTE_KIND_S8Z24_MS4_4CSZV_V 0x00000023 +#define GPU_GMMU_PTE_KIND_S8Z24_MS8_4CSZV_V 0x00000024 +#define GPU_GMMU_PTE_KIND_S8Z24_MS16_4CSZV_V 0x00000025 +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC12_V 0x00000026 +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC4_V 0x00000027 +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC8_V 0x00000028 +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC24_V 0x00000029 +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC12_1ZV_V 0x0000002e +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC4_1ZV_V 0x0000002f +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC8_1ZV_V 0x00000030 +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC24_1ZV_V 0x00000031 +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC12_2CS_V 0x00000032 +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC4_2CS_V 0x00000033 +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC8_2CS_V 0x00000034 +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC24_2CS_V 0x00000035 +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC12_2CZV_V 0x0000003a +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC4_2CZV_V 0x0000003b +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC8_2CZV_V 0x0000003c +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC24_2CZV_V 0x0000003d +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC12_2ZV_V 0x0000003e +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC4_2ZV_V 0x0000003f +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC8_2ZV_V 0x00000040 +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC24_2ZV_V 0x00000041 +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC12_4CSZV_V 0x00000042 +#define GPU_GMMU_PTE_KIND_V8Z24_MS4_VC4_4CSZV_V 0x00000043 +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC8_4CSZV_V 0x00000044 +#define GPU_GMMU_PTE_KIND_V8Z24_MS8_VC24_4CSZV_V 0x00000045 +#define GPU_GMMU_PTE_KIND_Z24S8_V 0x00000046 +#define GPU_GMMU_PTE_KIND_Z24S8_1Z_V 0x00000047 +#define GPU_GMMU_PTE_KIND_Z24S8_MS2_1Z_V 0x00000048 +#define GPU_GMMU_PTE_KIND_Z24S8_MS4_1Z_V 0x00000049 +#define GPU_GMMU_PTE_KIND_Z24S8_MS8_1Z_V 0x0000004a +#define GPU_GMMU_PTE_KIND_Z24S8_MS16_1Z_V 0x0000004b +#define GPU_GMMU_PTE_KIND_Z24S8_2CS_V 0x0000004c +#define GPU_GMMU_PTE_KIND_Z24S8_MS2_2CS_V 0x0000004d +#define GPU_GMMU_PTE_KIND_Z24S8_MS4_2CS_V 0x0000004e +#define GPU_GMMU_PTE_KIND_Z24S8_MS8_2CS_V 0x0000004f +#define GPU_GMMU_PTE_KIND_Z24S8_MS16_2CS_V 0x00000050 +#define GPU_GMMU_PTE_KIND_Z24S8_2CZ_V 0x00000051 +#define GPU_GMMU_PTE_KIND_Z24S8_MS2_2CZ_V 0x00000052 +#define GPU_GMMU_PTE_KIND_Z24S8_MS4_2CZ_V 0x00000053 +#define GPU_GMMU_PTE_KIND_Z24S8_MS8_2CZ_V 0x00000054 +#define GPU_GMMU_PTE_KIND_Z24S8_MS16_2CZ_V 0x00000055 +#define GPU_GMMU_PTE_KIND_Z24S8_4CSZV_V 0x00000056 +#define GPU_GMMU_PTE_KIND_Z24S8_MS2_4CSZV_V 0x00000057 +#define GPU_GMMU_PTE_KIND_Z24S8_MS4_4CSZV_V 0x00000058 +#define GPU_GMMU_PTE_KIND_Z24S8_MS8_4CSZV_V 0x00000059 +#define GPU_GMMU_PTE_KIND_Z24S8_MS16_4CSZV_V 0x0000005a +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC12_V 0x0000005b +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC4_V 0x0000005c +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC8_V 0x0000005d +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC24_V 0x0000005e +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC12_1ZV_V 0x00000063 +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC4_1ZV_V 0x00000064 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC8_1ZV_V 0x00000065 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC24_1ZV_V 0x00000066 +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC12_2CS_V 0x00000067 +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC4_2CS_V 0x00000068 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC8_2CS_V 0x00000069 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC24_2CS_V 0x0000006a +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC12_2CZV_V 0x0000006f +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC4_2CZV_V 0x00000070 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC8_2CZV_V 0x00000071 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC24_2CZV_V 0x00000072 +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC12_2ZV_V 0x00000073 +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC4_2ZV_V 0x00000074 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC8_2ZV_V 0x00000075 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC24_2ZV_V 0x00000076 +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC12_4CSZV_V 0x00000077 +#define GPU_GMMU_PTE_KIND_Z24V8_MS4_VC4_4CSZV_V 0x00000078 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC8_4CSZV_V 0x00000079 +#define GPU_GMMU_PTE_KIND_Z24V8_MS8_VC24_4CSZV_V 0x0000007a +#define GPU_GMMU_PTE_KIND_ZF32_V 0x0000007b +#define GPU_GMMU_PTE_KIND_ZF32_1Z_V 0x0000007c +#define GPU_GMMU_PTE_KIND_ZF32_MS2_1Z_V 0x0000007d +#define GPU_GMMU_PTE_KIND_ZF32_MS4_1Z_V 0x0000007e +#define GPU_GMMU_PTE_KIND_ZF32_MS8_1Z_V 0x0000007f +#define GPU_GMMU_PTE_KIND_ZF32_MS16_1Z_V 0x00000080 +#define GPU_GMMU_PTE_KIND_ZF32_2CS_V 0x00000081 +#define GPU_GMMU_PTE_KIND_ZF32_MS2_2CS_V 0x00000082 +#define GPU_GMMU_PTE_KIND_ZF32_MS4_2CS_V 0x00000083 +#define GPU_GMMU_PTE_KIND_ZF32_MS8_2CS_V 0x00000084 +#define GPU_GMMU_PTE_KIND_ZF32_MS16_2CS_V 0x00000085 +#define GPU_GMMU_PTE_KIND_ZF32_2CZ_V 0x00000086 +#define GPU_GMMU_PTE_KIND_ZF32_MS2_2CZ_V 0x00000087 +#define GPU_GMMU_PTE_KIND_ZF32_MS4_2CZ_V 0x00000088 +#define GPU_GMMU_PTE_KIND_ZF32_MS8_2CZ_V 0x00000089 +#define GPU_GMMU_PTE_KIND_ZF32_MS16_2CZ_V 0x0000008a +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC12_V 0x0000008b +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC4_V 0x0000008c +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC8_V 0x0000008d +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC24_V 0x0000008e +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC12_1CS_V 0x0000008f +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC4_1CS_V 0x00000090 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC8_1CS_V 0x00000091 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC24_1CS_V 0x00000092 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC12_1ZV_V 0x00000097 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC4_1ZV_V 0x00000098 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC8_1ZV_V 0x00000099 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC24_1ZV_V 0x0000009a +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC12_1CZV_V 0x0000009b +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC4_1CZV_V 0x0000009c +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC8_1CZV_V 0x0000009d +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC24_1CZV_V 0x0000009e +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC12_2CS_V 0x0000009f +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC4_2CS_V 0x000000a0 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC8_2CS_V 0x000000a1 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC24_2CS_V 0x000000a2 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC12_2CSZV_V 0x000000a3 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS4_VC4_2CSZV_V 0x000000a4 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC8_2CSZV_V 0x000000a5 +#define GPU_GMMU_PTE_KIND_X8Z24_X16V8S8_MS8_VC24_2CSZV_V 0x000000a6 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC12_V 0x000000a7 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC4_V 0x000000a8 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC8_V 0x000000a9 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC24_V 0x000000aa +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC12_1CS_V 0x000000ab +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC4_1CS_V 0x000000ac +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC8_1CS_V 0x000000ad +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC24_1CS_V 0x000000ae +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC12_1ZV_V 0x000000b3 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC4_1ZV_V 0x000000b4 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC8_1ZV_V 0x000000b5 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC24_1ZV_V 0x000000b6 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC12_1CZV_V 0x000000b7 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC4_1CZV_V 0x000000b8 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC8_1CZV_V 0x000000b9 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC24_1CZV_V 0x000000ba +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC12_2CS_V 0x000000bb +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC4_2CS_V 0x000000bc +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC8_2CS_V 0x000000bd +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC24_2CS_V 0x000000be +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC12_2CSZV_V 0x000000bf +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS4_VC4_2CSZV_V 0x000000c0 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC8_2CSZV_V 0x000000c1 +#define GPU_GMMU_PTE_KIND_ZF32_X16V8S8_MS8_VC24_2CSZV_V 0x000000c2 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_V 0x000000c3 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_1CS_V 0x000000c4 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS2_1CS_V 0x000000c5 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS4_1CS_V 0x000000c6 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS8_1CS_V 0x000000c7 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS16_1CS_V 0x000000c8 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_2CSZV_V 0x000000ce +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS2_2CSZV_V 0x000000cf +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS4_2CSZV_V 0x000000d0 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS8_2CSZV_V 0x000000d1 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS16_2CSZV_V 0x000000d2 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_2CS_V 0x000000d3 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS2_2CS_V 0x000000d4 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS4_2CS_V 0x000000d5 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS8_2CS_V 0x000000d6 +#define GPU_GMMU_PTE_KIND_ZF32_X24S8_MS16_2CS_V 0x000000d7 +#define GPU_GMMU_PTE_KIND_GENERIC_16BX2_V 0x000000fe +#define GPU_GMMU_PTE_KIND_C32_2C_V 0x000000d8 +#define GPU_GMMU_PTE_KIND_C32_2CBR_V 0x000000d9 +#define GPU_GMMU_PTE_KIND_C32_2CBA_V 0x000000da +#define GPU_GMMU_PTE_KIND_C32_2CRA_V 0x000000db +#define GPU_GMMU_PTE_KIND_C32_2BRA_V 0x000000dc +#define GPU_GMMU_PTE_KIND_C32_MS2_2C_V 0x000000dd +#define GPU_GMMU_PTE_KIND_C32_MS2_2CBR_V 0x000000de +#define GPU_GMMU_PTE_KIND_C32_MS2_2CRA_V 0x000000cc +#define GPU_GMMU_PTE_KIND_C32_MS4_2C_V 0x000000df +#define GPU_GMMU_PTE_KIND_C32_MS4_2CBR_V 0x000000e0 +#define GPU_GMMU_PTE_KIND_C32_MS4_2CBA_V 0x000000e1 +#define GPU_GMMU_PTE_KIND_C32_MS4_2CRA_V 0x000000e2 +#define GPU_GMMU_PTE_KIND_C32_MS4_2BRA_V 0x000000e3 +#define GPU_GMMU_PTE_KIND_C32_MS8_MS16_2C_V 0x000000e4 +#define GPU_GMMU_PTE_KIND_C32_MS8_MS16_2CRA_V 0x000000e5 +#define GPU_GMMU_PTE_KIND_C64_2C_V 0x000000e6 +#define GPU_GMMU_PTE_KIND_C64_2CBR_V 0x000000e7 +#define GPU_GMMU_PTE_KIND_C64_2CBA_V 0x000000e8 +#define GPU_GMMU_PTE_KIND_C64_2CRA_V 0x000000e9 +#define GPU_GMMU_PTE_KIND_C64_2BRA_V 0x000000ea +#define GPU_GMMU_PTE_KIND_C64_MS2_2C_V 0x000000eb +#define GPU_GMMU_PTE_KIND_C64_MS2_2CBR_V 0x000000ec +#define GPU_GMMU_PTE_KIND_C64_MS2_2CRA_V 0x000000cd +#define GPU_GMMU_PTE_KIND_C64_MS4_2C_V 0x000000ed +#define GPU_GMMU_PTE_KIND_C64_MS4_2CBR_V 0x000000ee +#define GPU_GMMU_PTE_KIND_C64_MS4_2CBA_V 0x000000ef +#define GPU_GMMU_PTE_KIND_C64_MS4_2CRA_V 0x000000f0 +#define GPU_GMMU_PTE_KIND_C64_MS4_2BRA_V 0x000000f1 +#define GPU_GMMU_PTE_KIND_C64_MS8_MS16_2C_V 0x000000f2 +#define GPU_GMMU_PTE_KIND_C64_MS8_MS16_2CRA_V 0x000000f3 +#define GPU_GMMU_PTE_KIND_C128_2C_V 0x000000f4 +#define GPU_GMMU_PTE_KIND_C128_2CR_V 0x000000f5 +#define GPU_GMMU_PTE_KIND_C128_MS2_2C_V 0x000000f6 +#define GPU_GMMU_PTE_KIND_C128_MS2_2CR_V 0x000000f7 +#define GPU_GMMU_PTE_KIND_C128_MS4_2C_V 0x000000f8 +#define GPU_GMMU_PTE_KIND_C128_MS4_2CR_V 0x000000f9 +#define GPU_GMMU_PTE_KIND_C128_MS8_MS16_2C_V 0x000000fa +#define GPU_GMMU_PTE_KIND_C128_MS8_MS16_2CR_V 0x000000fb +#define GPU_GMMU_PTE_KIND_X8C24_V 0x000000fc +#define GPU_GMMU_PTE_KIND_PITCH_NO_SWIZZLE_V 0x000000fd +#define GPU_GMMU_PTE_KIND_SMSKED_MESSAGE_V 0x000000ca +#define GPU_GMMU_PTE_KIND_SMHOST_MESSAGE_V 0x000000cb +#define GPU_GMMU_PTE_KIND_S8_V 0x0000002a +#define GPU_GMMU_PTE_KIND_S8_2S_V 0x0000002b + +#define GPU_GR_INTR 0x00400100 +#define GPU_GR_INTR_NOTIFY_PENDING_F 0x00000001 +#define GPU_GR_INTR_NOTIFY_RESET_F 0x00000001 +#define GPU_GR_INTR_SEMAPHORE_PENDING_F 0x00000002 +#define GPU_GR_INTR_SEMAPHORE_RESET_F 0x00000002 +#define GPU_GR_INTR_ILLEGAL_METHOD_PENDING_F 0x00000010 +#define GPU_GR_INTR_ILLEGAL_METHOD_RESET_F 0x00000010 +#define GPU_GR_INTR_ILLEGAL_NOTIFY_PENDING_F 0x00000040 +#define GPU_GR_INTR_ILLEGAL_NOTIFY_RESET_F 0x00000040 +#define GPU_GR_INTR_FIRMWARE_METHOD_SHIFT 0x00000008 +#define GPU_GR_INTR_FIRMWARE_METHOD_FIELDMASK 0x00000001 +#define GPU_GR_INTR_FIRMWARE_METHOD_PENDING_F 0x00000100 +#define GPU_GR_INTR_FIRMWARE_METHOD_RESET_F 0x00000100 +#define GPU_GR_INTR_ILLEGAL_CLASS_PENDING_F 0x00000020 +#define GPU_GR_INTR_ILLEGAL_CLASS_RESET_F 0x00000020 +#define GPU_GR_INTR_FECS_ERROR_PENDING_F 0x00080000 +#define GPU_GR_INTR_FECS_ERROR_RESET_F 0x00080000 +#define GPU_GR_INTR_CLASS_ERROR_PENDING_F 0x00100000 +#define GPU_GR_INTR_CLASS_ERROR_RESET_F 0x00100000 +#define GPU_GR_INTR_EXCEPTION_PENDING_F 0x00200000 +#define GPU_GR_INTR_EXCEPTION_RESET_F 0x00200000 +#define GPU_GR_FECS_INTR 0x00400144 +#define GPU_GR_CLASS_ERROR 0x00400110 +#define GPU_GR_CLASS_ERROR_CODE_SHIFT 0x00000000 +#define GPU_GR_CLASS_ERROR_CODE_FIELDMASK 0x0000ffff +#define GPU_GR_INTR_NONSTALL 0x00400120 +#define GPU_GR_INTR_NONSTALL_TRAP_PENDING_F 0x00000002 +#define GPU_GR_INTR_EN 0x0040013c +#define GPU_GR_EXCEPTION 0x00400108 +#define GPU_GR_EXCEPTION_FE_MASK 0x00000001 +#define GPU_GR_EXCEPTION_FE_SHIFT 0x00000000 +#define GPU_GR_EXCEPTION_FE_FIELDMASK 0x00000001 +#define GPU_GR_EXCEPTION_GPC_MASK 0x01000000 +#define GPU_GR_EXCEPTION_GPC_SHIFT 0x00000018 +#define GPU_GR_EXCEPTION_GPC_FIELDMASK 0x00000001 +#define GPU_GR_EXCEPTION_MEMFMT_MASK 0x00000002 +#define GPU_GR_EXCEPTION_MEMFMT_SHIFT 0x00000001 +#define GPU_GR_EXCEPTION_MEMFMT_FIELDMASK 0x00000001 +#define GPU_GR_EXCEPTION_DS_MASK 0x00000010 +#define GPU_GR_EXCEPTION_DS_SHIFT 0x00000004 +#define GPU_GR_EXCEPTION_DS_FIELDMASK 0x00000001 +#define GPU_GR_EXCEPTION1 0x00400118 +#define GPU_GR_EXCEPTION1_GPC_0_PENDING_F 0x00000001 +#define GPU_GR_EXCEPTION2 0x0040011c +#define GPU_GR_EXCEPTION_EN 0x00400138 +#define GPU_GR_EXCEPTION_EN_FE_MASK 0x00000001 +#define GPU_GR_EXCEPTION_EN_FE_SHIFT 0x00000000 +#define GPU_GR_EXCEPTION_EN_FE_FIELDMASK 0x00000001 +#define GPU_GR_EXCEPTION1_EN 0x00400130 +#define GPU_GR_EXCEPTION2_EN 0x00400134 +#define GPU_GR_GPFIFO_CTL 0x00400500 +#define GPU_GR_GPFIFO_CTL_ACCESS_SHIFT 0x00000000 +#define GPU_GR_GPFIFO_CTL_ACCESS_FIELDMASK 0x00000001 +#define GPU_GR_GPFIFO_CTL_ACCESS_DISABLED_F 0x00000000 +#define GPU_GR_GPFIFO_CTL_ACCESS_ENABLED_F 0x00000001 +#define GPU_GR_GPFIFO_CTL_SEMAPHORE_ACCESS_SHIFT 0x00000010 +#define GPU_GR_GPFIFO_CTL_SEMAPHORE_ACCESS_FIELDMASK 0x00000001 +#define GPU_GR_GPFIFO_CTL_SEMAPHORE_ACCESS_ENABLED_V 0x00000001 +#define GPU_GR_GPFIFO_CTL_SEMAPHORE_ACCESS_ENABLED_F 0x00010000 +#define GPU_GR_GPFIFO_STATUS 0x00400504 +#define GPU_GR_TRAPPED_ADDR 0x00400704 +#define GPU_GR_TRAPPED_ADDR_MTHD_SHIFT 0x00000002 +#define GPU_GR_TRAPPED_ADDR_MTHD_FIELDMASK 0x00000fff +#define GPU_GR_TRAPPED_ADDR_SUBCH_SHIFT 0x00000010 +#define GPU_GR_TRAPPED_ADDR_SUBCH_FIELDMASK 0x00000007 +#define GPU_GR_TRAPPED_DATA_LO 0x00400708 +#define GPU_GR_TRAPPED_DATA_HI 0x0040070c +#define GPU_GR_STATUS 0x00400700 +#define GPU_GR_STATUS_FE_METHOD_UPPER_SHIFT 0x00000001 +#define GPU_GR_STATUS_FE_METHOD_UPPER_FIELDMASK 0x00000001 +#define GPU_GR_STATUS_FE_METHOD_LOWER_SHIFT 0x00000002 +#define GPU_GR_STATUS_FE_METHOD_LOWER_FIELDMASK 0x00000001 +#define GPU_GR_STATUS_FE_METHOD_LOWER_IDLE_V 0x00000000 +#define GPU_GR_STATUS_FE_GI_SHIFT 0x00000015 +#define GPU_GR_STATUS_FE_GI_FIELDMASK 0x00000001 +#define GPU_GR_STATUS_MASK 0x00400610 +#define GPU_GR_STATUS_1 0x00400604 +#define GPU_GR_STATUS_2 0x00400608 +#define GPU_GR_ENGINE_STATUS 0x0040060c +#define GPU_GR_ENGINE_STATUS_VALUE_BUSY_F 0x00000001 +#define GPU_GR_PRI_BE0_BECS_BE_EXCEPTION 0x00410204 +#define GPU_GR_PRI_BE0_BECS_BE_EXCEPTION_EN 0x00410208 +#define GPU_GR_PRI_GPC0_GPCCS_GPC_EXCEPTION 0x00502c90 +#define GPU_GR_PRI_GPC0_GPCCS_GPC_EXCEPTION_EN 0x00502c94 +#define GPU_GR_PRI_GPC0_TPC0_TPCCS_TPC_EXCEPTION 0x00504508 +#define GPU_GR_PRI_GPC0_TPC0_TPCCS_TPC_EXCEPTION_EN 0x0050450c +#define GPU_GR_ACTIVITY_0 0x00400380 +#define GPU_GR_ACTIVITY_1 0x00400384 +#define GPU_GR_ACTIVITY_2 0x00400388 +#define GPU_GR_ACTIVITY_4 0x00400390 +#define GPU_GR_PRI_GPC0_GCC_DBG 0x00501000 +#define GPU_GR_PRI_GPCS_GCC_DBG 0x00419000 +#define GPU_GR_PRI_GPCS_GCC_DBG_INVALIDATE_MASK 0x00000002 +#define GPU_GR_PRI_GPCS_GCC_DBG_INVALIDATE_SHIFT 0x00000001 +#define GPU_GR_PRI_GPCS_GCC_DBG_INVALIDATE_FIELDMASK 0x00000001 +#define GPU_GR_PRI_GPC0_TPC0_SM_CACHE_CONTROL 0x005046a4 +#define GPU_GR_PRI_GPCS_TPCS_SM_CACHE_CONTROL 0x00419ea4 +#define GPU_GR_PRI_GPCS_TPCS_SM_CACHE_CONTROL_INVALIDATE_CACHE_MASK 0x00000001 +#define GPU_GR_PRI_GPCS_TPCS_SM_CACHE_CONTROL_INVALIDATE_CACHE_SHIFT 0x00000000 +#define GPU_GR_PRI_GPCS_TPCS_SM_CACHE_CONTROL_INVALIDATE_CACHE_FIELDMASK 0x00000001 +#define GPU_GR_PRI_SKED_ACTIVITY 0x00407054 +#define GPU_GR_PRI_GPC0_GPCCS_GPC_ACTIVITY0 0x00502c80 +#define GPU_GR_PRI_GPC0_GPCCS_GPC_ACTIVITY1 0x00502c84 +#define GPU_GR_PRI_GPC0_GPCCS_GPC_ACTIVITY2 0x00502c88 +#define GPU_GR_PRI_GPC0_GPCCS_GPC_ACTIVITY3 0x00502c8c +#define GPU_GR_PRI_GPC0_TPC0_TPCCS_TPC_ACTIVITY_0 0x00504500 +#define GPU_GR_PRI_GPC0_TPC1_TPCCS_TPC_ACTIVITY_0 0x00504d00 +#define GPU_GR_PRI_GPC0_TPCS_TPCCS_TPC_ACTIVITY_0 0x00501d00 +#define GPU_GR_PRI_GPCS_GPCCS_GPC_ACTIVITY_0 0x0041ac80 +#define GPU_GR_PRI_GPCS_GPCCS_GPC_ACTIVITY_1 0x0041ac84 +#define GPU_GR_PRI_GPCS_GPCCS_GPC_ACTIVITY_2 0x0041ac88 +#define GPU_GR_PRI_GPCS_GPCCS_GPC_ACTIVITY_3 0x0041ac8c +#define GPU_GR_PRI_GPCS_TPC0_TPCCS_TPC_ACTIVITY_0 0x0041c500 +#define GPU_GR_PRI_GPCS_TPC1_TPCCS_TPC_ACTIVITY_0 0x0041cd00 +#define GPU_GR_PRI_GPCS_TPCS_TPCCS_TPC_ACTIVITY_0 0x00419d00 +#define GPU_GR_PRI_BE0_BECS_BE_ACTIVITY0 0x00410200 +#define GPU_GR_PRI_BE1_BECS_BE_ACTIVITY0 0x00410600 +#define GPU_GR_PRI_BES_BECS_BE_ACTIVITY0 0x00408a00 +#define GPU_GR_PRI_DS_MPIPE_STATUS 0x00405858 +#define GPU_GR_PRI_FE_GO_IDLE_ON_STATUS 0x00404150 +#define GPU_GR_PRI_FE_GO_IDLE_CHECK 0x00404158 +#define GPU_GR_PRI_FE_GO_IDLE_INFO 0x00404194 +#define GPU_GR_PRI_GPC0_TPC0_TEX_M_TEX_SUBUNITS_STATUS 0x00504238 +#define GPU_GR_PRI_BE0_CROP_STATUS1 0x00410134 +#define GPU_GR_PRI_BES_CROP_STATUS1 0x00408934 +#define GPU_GR_PRI_BE0_ZROP_STATUS 0x00410048 +#define GPU_GR_PRI_BE0_ZROP_STATUS2 0x0041004c +#define GPU_GR_PRI_BES_ZROP_STATUS 0x00408848 +#define GPU_GR_PRI_BES_ZROP_STATUS2 0x0040884c +#define GPU_GR_PIPE_BUNDLE_ADDRESS 0x00400200 +#define GPU_GR_PIPE_BUNDLE_ADDRESS_VALUE_SHIFT 0x00000000 +#define GPU_GR_PIPE_BUNDLE_ADDRESS_VALUE_FIELDMASK 0x0000ffff +#define GPU_GR_PIPE_BUNDLE_DATA 0x00400204 +#define GPU_GR_PIPE_BUNDLE_CONFIG 0x00400208 +#define GPU_GR_PIPE_BUNDLE_CONFIG_OVERRIDE_PIPE_MODE_DISABLED_F 0x00000000 +#define GPU_GR_PIPE_BUNDLE_CONFIG_OVERRIDE_PIPE_MODE_ENABLED_F 0x80000000 +#define GPU_GR_FE_HWW_ESR 0x00404000 +#define GPU_GR_FE_HWW_ESR_RESET_ACTIVE_F 0x40000000 +#define GPU_GR_FE_HWW_ESR_EN_ENABLE_F 0x80000000 +#define GPU_GR_FE_GO_IDLE_TIMEOUT 0x00404154 +#define GPU_GR_FE_GO_IDLE_TIMEOUT_COUNT_SHIFT 0x00000000 +#define GPU_GR_FE_GO_IDLE_TIMEOUT_COUNT_FIELDMASK 0xffffffff +#define GPU_GR_FE_GO_IDLE_TIMEOUT_COUNT_DISABLED_F 0x00000000 +#define GPU_GR_FE_GO_IDLE_TIMEOUT_COUNT_PROD_F 0x00000800 +#define GPU_GR_FE_OBJECT_TABLE__BASE 0x00404200 +#define GPU_GR_FE_OBJECT_TABLE__STRIDE 0x00000004 +#define GPU_GR_FE_OBJECT_TABLE(i) (0x00404200 + (i) * 0x00000004) +#define GPU_GR_FE_OBJECT_TABLE_NVCLASS_SHIFT 0x00000000 +#define GPU_GR_FE_OBJECT_TABLE_NVCLASS_FIELDMASK 0x0000ffff +#define GPU_GR_FE_TPC_FS 0x004041c4 +#define GPU_GR_PRI_MME_SHADOW_RAW_INDEX 0x00404488 +#define GPU_GR_PRI_MME_SHADOW_RAW_INDEX_WRITE_TRIGGER_F 0x80000000 +#define GPU_GR_PRI_MME_SHADOW_RAW_DATA 0x0040448c +#define GPU_GR_MME_HWW_ESR 0x00404490 +#define GPU_GR_MME_HWW_ESR_RESET_ACTIVE_F 0x40000000 +#define GPU_GR_MME_HWW_ESR_EN_ENABLE_F 0x80000000 +#define GPU_GR_MEMFMT_HWW_ESR 0x00404600 +#define GPU_GR_MEMFMT_HWW_ESR_RESET_ACTIVE_F 0x40000000 +#define GPU_GR_MEMFMT_HWW_ESR_EN_ENABLE_F 0x80000000 +#define GPU_GR_FECS_CPUCTL 0x00409100 +#define GPU_GR_FECS_CPUCTL_STARTCPU_SHIFT 0x00000001 +#define GPU_GR_FECS_CPUCTL_STARTCPU_FIELDMASK 0x00000001 +#define GPU_GR_FECS_CPUCTL_ALIAS 0x00409130 +#define GPU_GR_FECS_CPUCTL_ALIAS_STARTCPU_SHIFT 0x00000001 +#define GPU_GR_FECS_CPUCTL_ALIAS_STARTCPU_FIELDMASK 0x00000001 +#define GPU_GR_FECS_DMACTL 0x0040910c +#define GPU_GR_FECS_DMACTL_REQUIRE_CTX_SHIFT 0x00000000 +#define GPU_GR_FECS_DMACTL_REQUIRE_CTX_FIELDMASK 0x00000001 +#define GPU_GR_FECS_DMACTL_DMEM_SCRUBBING_MASK 0x00000002 +#define GPU_GR_FECS_DMACTL_DMEM_SCRUBBING_SHIFT 0x00000001 +#define GPU_GR_FECS_DMACTL_DMEM_SCRUBBING_FIELDMASK 0x00000001 +#define GPU_GR_FECS_DMACTL_IMEM_SCRUBBING_MASK 0x00000004 +#define GPU_GR_FECS_DMACTL_IMEM_SCRUBBING_SHIFT 0x00000002 +#define GPU_GR_FECS_DMACTL_IMEM_SCRUBBING_FIELDMASK 0x00000001 +#define GPU_GR_FECS_OS 0x00409080 +#define GPU_GR_FECS_IDLESTATE 0x0040904c +#define GPU_GR_FECS_MAILBOX0 0x00409040 +#define GPU_GR_FECS_MAILBOX1 0x00409044 +#define GPU_GR_FECS_IRQSTAT 0x00409008 +#define GPU_GR_FECS_IRQMODE 0x0040900c +#define GPU_GR_FECS_IRQMASK 0x00409018 +#define GPU_GR_FECS_IRQDEST 0x0040901c +#define GPU_GR_FECS_CURCTX 0x00409050 +#define GPU_GR_FECS_NXTCTX 0x00409054 +#define GPU_GR_FECS_ENGCTL 0x004090a4 +#define GPU_GR_FECS_DEBUG1 0x00409090 +#define GPU_GR_FECS_DEBUGINFO 0x00409094 +#define GPU_GR_FECS_ICD_CMD 0x00409200 +#define GPU_GR_FECS_ICD_CMD_OPC_SIZE 0x00000004 +#define GPU_GR_FECS_ICD_CMD_OPC_SHIFT 0x00000000 +#define GPU_GR_FECS_ICD_CMD_OPC_FIELDMASK 0x0000000f +#define GPU_GR_FECS_ICD_CMD_OPC_MASK 0x0000000f +#define GPU_GR_FECS_ICD_CMD_OPC_RREG_F 0x00000008 +#define GPU_GR_FECS_ICD_CMD_OPC_RSTAT_F 0x0000000e +#define GPU_GR_FECS_ICD_CMD_IDX_SHIFT 0x00000008 +#define GPU_GR_FECS_ICD_CMD_IDX_FIELDMASK 0x0000001f +#define GPU_GR_FECS_ICD_RDATA 0x0040920c +#define GPU_GR_FECS_IMEMC__BASE 0x00409180 +#define GPU_GR_FECS_IMEMC__STRIDE 0x00000010 +#define GPU_GR_FECS_IMEMC(i) (0x00409180 + (i) * 0x00000010) +#define GPU_GR_FECS_IMEMC_OFFS_SHIFT 0x00000002 +#define GPU_GR_FECS_IMEMC_OFFS_FIELDMASK 0x0000003f +#define GPU_GR_FECS_IMEMC_BLK_SHIFT 0x00000008 +#define GPU_GR_FECS_IMEMC_BLK_FIELDMASK 0x000000ff +#define GPU_GR_FECS_IMEMC_AINCW_SHIFT 0x00000018 +#define GPU_GR_FECS_IMEMC_AINCW_FIELDMASK 0x00000001 +#define GPU_GR_FECS_IMEMD__BASE 0x00409184 +#define GPU_GR_FECS_IMEMD__STRIDE 0x00000010 +#define GPU_GR_FECS_IMEMD(i) (0x00409184 + (i) * 0x00000010) +#define GPU_GR_FECS_IMEMT__BASE 0x00409188 +#define GPU_GR_FECS_IMEMT__STRIDE 0x00000010 +#define GPU_GR_FECS_IMEMT(i) (0x00409188 + (i) * 0x00000010) +#define GPU_GR_FECS_IMEMT_TAG_SHIFT 0x00000000 +#define GPU_GR_FECS_IMEMT_TAG_FIELDMASK 0x0000ffff +#define GPU_GR_FECS_DMEMC__BASE 0x004091c0 +#define GPU_GR_FECS_DMEMC__STRIDE 0x00000008 +#define GPU_GR_FECS_DMEMC(i) (0x004091c0 + (i) * 0x00000008) +#define GPU_GR_FECS_DMEMC_OFFS_SIZE 0x00000006 +#define GPU_GR_FECS_DMEMC_OFFS_SHIFT 0x00000002 +#define GPU_GR_FECS_DMEMC_OFFS_FIELDMASK 0x0000003f +#define GPU_GR_FECS_DMEMC_OFFS_MASK 0x000000fc +#define GPU_GR_FECS_DMEMC_BLK_SHIFT 0x00000008 +#define GPU_GR_FECS_DMEMC_BLK_FIELDMASK 0x000000ff +#define GPU_GR_FECS_DMEMC_AINCW_SHIFT 0x00000018 +#define GPU_GR_FECS_DMEMC_AINCW_FIELDMASK 0x00000001 +#define GPU_GR_FECS_DMEMD__BASE 0x004091c4 +#define GPU_GR_FECS_DMEMD__STRIDE 0x00000008 +#define GPU_GR_FECS_DMEMD(i) (0x004091c4 + (i) * 0x00000008) +#define GPU_GR_FECS_DMATRFBASE 0x00409110 +#define GPU_GR_FECS_DMATRFMOFFS 0x00409114 +#define GPU_GR_FECS_DMATRFFBOFFS 0x0040911c +#define GPU_GR_FECS_DMATRFCMD 0x00409118 +#define GPU_GR_FECS_DMATRFCMD_IMEM_SHIFT 0x00000004 +#define GPU_GR_FECS_DMATRFCMD_IMEM_FIELDMASK 0x00000001 +#define GPU_GR_FECS_DMATRFCMD_WRITE_SHIFT 0x00000005 +#define GPU_GR_FECS_DMATRFCMD_WRITE_FIELDMASK 0x00000001 +#define GPU_GR_FECS_DMATRFCMD_SIZE_SHIFT 0x00000008 +#define GPU_GR_FECS_DMATRFCMD_SIZE_FIELDMASK 0x00000007 +#define GPU_GR_FECS_DMATRFCMD_CTXDMA_SHIFT 0x0000000c +#define GPU_GR_FECS_DMATRFCMD_CTXDMA_FIELDMASK 0x00000007 +#define GPU_GR_FECS_BOOTVEC 0x00409104 +#define GPU_GR_FECS_BOOTVEC_VEC_SHIFT 0x00000000 +#define GPU_GR_FECS_BOOTVEC_VEC_FIELDMASK 0xffffffff +#define GPU_GR_FECS_FALCON_HWCFG 0x00409108 +#define GPU_GR_GPCS_GPCCS_FALCON_HWCFG 0x0041a108 +#define GPU_GR_FECS_FALCON_RM 0x00409084 +#define GPU_GR_FECS_CURRENT_CTX 0x00409b00 +#define GPU_GR_FECS_CURRENT_CTX_PTR_SHIFT 0x00000000 +#define GPU_GR_FECS_CURRENT_CTX_PTR_FIELDMASK 0x0fffffff +#define GPU_GR_FECS_CURRENT_CTX_TARGET_SIZE 0x00000002 +#define GPU_GR_FECS_CURRENT_CTX_TARGET_SHIFT 0x0000001c +#define GPU_GR_FECS_CURRENT_CTX_TARGET_FIELDMASK 0x00000003 +#define GPU_GR_FECS_CURRENT_CTX_TARGET_MASK 0x30000000 +#define GPU_GR_FECS_CURRENT_CTX_TARGET_VID_MEM_F 0x00000000 +#define GPU_GR_FECS_CURRENT_CTX_TARGET_SYS_MEM_COH_F 0x20000000 +#define GPU_GR_FECS_CURRENT_CTX_TARGET_SYS_MEM_NCOH_F 0x30000000 +#define GPU_GR_FECS_CURRENT_CTX_VALID_SIZE 0x00000001 +#define GPU_GR_FECS_CURRENT_CTX_VALID_SHIFT 0x0000001f +#define GPU_GR_FECS_CURRENT_CTX_VALID_FIELDMASK 0x00000001 +#define GPU_GR_FECS_CURRENT_CTX_VALID_MASK 0x80000000 +#define GPU_GR_FECS_CURRENT_CTX_VALID_FALSE_F 0x00000000 +#define GPU_GR_FECS_METHOD_DATA 0x00409500 +#define GPU_GR_FECS_METHOD_PUSH 0x00409504 +#define GPU_GR_FECS_METHOD_PUSH_ADR_SHIFT 0x00000000 +#define GPU_GR_FECS_METHOD_PUSH_ADR_FIELDMASK 0x00000fff +#define GPU_GR_FECS_METHOD_PUSH_ADR_BIND_POINTER_V 0x00000003 +#define GPU_GR_FECS_METHOD_PUSH_ADR_BIND_POINTER_F 0x00000003 +#define GPU_GR_FECS_METHOD_PUSH_ADR_DISCOVER_IMAGE_SIZE_V 0x00000010 +#define GPU_GR_FECS_METHOD_PUSH_ADR_WFI_GOLDEN_SAVE_V 0x00000009 +#define GPU_GR_FECS_METHOD_PUSH_ADR_RESTORE_GOLDEN_V 0x00000015 +#define GPU_GR_FECS_METHOD_PUSH_ADR_DISCOVER_ZCULL_IMAGE_SIZE_V 0x00000016 +#define GPU_GR_FECS_METHOD_PUSH_ADR_DISCOVER_PM_IMAGE_SIZE_V 0x00000025 +#define GPU_GR_FECS_METHOD_PUSH_ADR_DISCOVER_REGLIST_IMAGE_SIZE_V 0x00000030 +#define GPU_GR_FECS_METHOD_PUSH_ADR_SET_REGLIST_BIND_INSTANCE_V 0x00000031 +#define GPU_GR_FECS_METHOD_PUSH_ADR_SET_REGLIST_VIRTUAL_ADDRESS_V 0x00000032 +#define GPU_GR_FECS_METHOD_PUSH_ADR_STOP_CTXSW_V 0x00000038 +#define GPU_GR_FECS_METHOD_PUSH_ADR_START_CTXSW_V 0x00000039 +#define GPU_GR_FECS_METHOD_PUSH_ADR_SET_WATCHDOG_TIMEOUT_F 0x00000021 +#define GPU_GR_FECS_METHOD_PUSH_ADR_WRITE_TIMESTAMP_RECORD_V 0x0000003d +#define GPU_GR_FECS_METHOD_PUSH_ADR_HALT_PIPELINE_V 0x00000004 +#define GPU_GR_FECS_HOST_INT_STATUS 0x00409c18 +#define GPU_GR_FECS_HOST_INT_STATUS_FAULT_DURING_CTXSW_SHIFT 0x00000010 +#define GPU_GR_FECS_HOST_INT_STATUS_FAULT_DURING_CTXSW_FIELDMASK 0x00000001 +#define GPU_GR_FECS_HOST_INT_STATUS_UMIMP_FIRMWARE_METHOD_SHIFT 0x00000011 +#define GPU_GR_FECS_HOST_INT_STATUS_UMIMP_FIRMWARE_METHOD_FIELDMASK 0x00000001 +#define GPU_GR_FECS_HOST_INT_STATUS_UMIMP_ILLEGAL_METHOD_SHIFT 0x00000012 +#define GPU_GR_FECS_HOST_INT_STATUS_UMIMP_ILLEGAL_METHOD_FIELDMASK 0x00000001 +#define GPU_GR_FECS_HOST_INT_STATUS_CTXSW_INTR_SHIFT 0x00000000 +#define GPU_GR_FECS_HOST_INT_STATUS_CTXSW_INTR_FIELDMASK 0x0000ffff +#define GPU_GR_FECS_HOST_INT_CLEAR 0x00409c20 +#define GPU_GR_FECS_HOST_INT_CLEAR_CTXSW_INTR1_SHIFT 0x00000001 +#define GPU_GR_FECS_HOST_INT_CLEAR_CTXSW_INTR1_FIELDMASK 0x00000001 +#define GPU_GR_FECS_HOST_INT_CLEAR_CTXSW_INTR1_CLEAR_F 0x00000002 +#define GPU_GR_FECS_HOST_INT_ENABLE 0x00409c24 +#define GPU_GR_FECS_HOST_INT_ENABLE_CTXSW_INTR1_ENABLE_F 0x00000002 +#define GPU_GR_FECS_HOST_INT_ENABLE_FAULT_DURING_CTXSW_ENABLE_F 0x00010000 +#define GPU_GR_FECS_HOST_INT_ENABLE_UMIMP_FIRMWARE_METHOD_ENABLE_F 0x00020000 +#define GPU_GR_FECS_HOST_INT_ENABLE_UMIMP_ILLEGAL_METHOD_ENABLE_F 0x00040000 +#define GPU_GR_FECS_HOST_INT_ENABLE_WATCHDOG_ENABLE_F 0x00080000 +#define GPU_GR_FECS_CTXSW_RESET_CTL 0x00409614 +#define GPU_GR_FECS_CTXSW_RESET_CTL_SYS_HALT_DISABLED_F 0x00000000 +#define GPU_GR_FECS_CTXSW_RESET_CTL_GPC_HALT_DISABLED_F 0x00000000 +#define GPU_GR_FECS_CTXSW_RESET_CTL_BE_HALT_DISABLED_F 0x00000000 +#define GPU_GR_FECS_CTXSW_RESET_CTL_SYS_ENGINE_RESET_DISABLED_F 0x00000010 +#define GPU_GR_FECS_CTXSW_RESET_CTL_GPC_ENGINE_RESET_DISABLED_F 0x00000020 +#define GPU_GR_FECS_CTXSW_RESET_CTL_BE_ENGINE_RESET_DISABLED_F 0x00000040 +#define GPU_GR_FECS_CTXSW_RESET_CTL_SYS_CONTEXT_RESET_ENABLED_F 0x00000000 +#define GPU_GR_FECS_CTXSW_RESET_CTL_SYS_CONTEXT_RESET_DISABLED_F 0x00000100 +#define GPU_GR_FECS_CTXSW_RESET_CTL_GPC_CONTEXT_RESET_ENABLED_F 0x00000000 +#define GPU_GR_FECS_CTXSW_RESET_CTL_GPC_CONTEXT_RESET_DISABLED_F 0x00000200 +#define GPU_GR_FECS_CTXSW_RESET_CTL_BE_CONTEXT_RESET_SIZE 0x00000001 +#define GPU_GR_FECS_CTXSW_RESET_CTL_BE_CONTEXT_RESET_SHIFT 0x0000000a +#define GPU_GR_FECS_CTXSW_RESET_CTL_BE_CONTEXT_RESET_FIELDMASK 0x00000001 +#define GPU_GR_FECS_CTXSW_RESET_CTL_BE_CONTEXT_RESET_MASK 0x00000400 +#define GPU_GR_FECS_CTXSW_RESET_CTL_BE_CONTEXT_RESET_ENABLED_F 0x00000000 +#define GPU_GR_FECS_CTXSW_RESET_CTL_BE_CONTEXT_RESET_DISABLED_F 0x00000400 +#define GPU_GR_FECS_CTX_STATE_STORE_MAJOR_REV_ID 0x0040960c +#define GPU_GR_FECS_CTXSW_MAILBOX__BASE 0x00409800 +#define GPU_GR_FECS_CTXSW_MAILBOX__STRIDE 0x00000004 +#define GPU_GR_FECS_CTXSW_MAILBOX(i) (0x00409800 + (i) * 0x00000004) +#define GPU_GR_FECS_CTXSW_MAILBOX__SIZE_1_V 0x00000010 +#define GPU_GR_FECS_CTXSW_MAILBOX_VALUE_SHIFT 0x00000000 +#define GPU_GR_FECS_CTXSW_MAILBOX_VALUE_FIELDMASK 0xffffffff +#define GPU_GR_FECS_CTXSW_MAILBOX_VALUE_PASS_V 0x00000001 +#define GPU_GR_FECS_CTXSW_MAILBOX_VALUE_FAIL_V 0x00000002 +#define GPU_GR_FECS_CTXSW_MAILBOX_SET__BASE 0x004098c0 +#define GPU_GR_FECS_CTXSW_MAILBOX_SET__STRIDE 0x00000004 +#define GPU_GR_FECS_CTXSW_MAILBOX_SET(i) (0x004098c0 + (i) * 0x00000004) +#define GPU_GR_FECS_CTXSW_MAILBOX_SET_VALUE_SHIFT 0x00000000 +#define GPU_GR_FECS_CTXSW_MAILBOX_SET_VALUE_FIELDMASK 0xffffffff +#define GPU_GR_FECS_CTXSW_MAILBOX_CLEAR__BASE 0x00409840 +#define GPU_GR_FECS_CTXSW_MAILBOX_CLEAR__STRIDE 0x00000004 +#define GPU_GR_FECS_CTXSW_MAILBOX_CLEAR(i) (0x00409840 + (i) * 0x00000004) +#define GPU_GR_FECS_CTXSW_MAILBOX_CLEAR_VALUE_SHIFT 0x00000000 +#define GPU_GR_FECS_CTXSW_MAILBOX_CLEAR_VALUE_FIELDMASK 0xffffffff +#define GPU_GR_FECS_FS 0x00409604 +#define GPU_GR_FECS_FS_NUM_AVAILABLE_GPCS_SIZE 0x00000005 +#define GPU_GR_FECS_FS_NUM_AVAILABLE_GPCS_SHIFT 0x00000000 +#define GPU_GR_FECS_FS_NUM_AVAILABLE_GPCS_FIELDMASK 0x0000001f +#define GPU_GR_FECS_FS_NUM_AVAILABLE_GPCS_MASK 0x0000001f +#define GPU_GR_FECS_FS_NUM_AVAILABLE_FBPS_SIZE 0x00000005 +#define GPU_GR_FECS_FS_NUM_AVAILABLE_FBPS_SHIFT 0x00000010 +#define GPU_GR_FECS_FS_NUM_AVAILABLE_FBPS_FIELDMASK 0x0000001f +#define GPU_GR_FECS_FS_NUM_AVAILABLE_FBPS_MASK 0x001f0000 +#define GPU_GR_FECS_CFG 0x00409620 +#define GPU_GR_FECS_CFG_IMEM_SZ_SHIFT 0x00000000 +#define GPU_GR_FECS_CFG_IMEM_SZ_FIELDMASK 0x000000ff +#define GPU_GR_FECS_RC_LANES 0x00409880 +#define GPU_GR_FECS_RC_LANES_NUM_CHAINS_SIZE 0x00000006 +#define GPU_GR_FECS_RC_LANES_NUM_CHAINS_SHIFT 0x00000000 +#define GPU_GR_FECS_RC_LANES_NUM_CHAINS_FIELDMASK 0x0000003f +#define GPU_GR_FECS_RC_LANES_NUM_CHAINS_MASK 0x0000003f +#define GPU_GR_FECS_CTXSW_STATUS_1 0x00409400 +#define GPU_GR_FECS_CTXSW_STATUS_1_ARB_BUSY_SIZE 0x00000001 +#define GPU_GR_FECS_CTXSW_STATUS_1_ARB_BUSY_SHIFT 0x0000000c +#define GPU_GR_FECS_CTXSW_STATUS_1_ARB_BUSY_FIELDMASK 0x00000001 +#define GPU_GR_FECS_CTXSW_STATUS_1_ARB_BUSY_MASK 0x00001000 +#define GPU_GR_FECS_ARB_CTX_ADR 0x00409a24 +#define GPU_GR_FECS_NEW_CTX 0x00409b04 +#define GPU_GR_FECS_NEW_CTX_PTR_SIZE 0x0000001c +#define GPU_GR_FECS_NEW_CTX_PTR_SHIFT 0x00000000 +#define GPU_GR_FECS_NEW_CTX_PTR_FIELDMASK 0x0fffffff +#define GPU_GR_FECS_NEW_CTX_PTR_MASK 0x0fffffff +#define GPU_GR_FECS_NEW_CTX_TARGET_SIZE 0x00000002 +#define GPU_GR_FECS_NEW_CTX_TARGET_SHIFT 0x0000001c +#define GPU_GR_FECS_NEW_CTX_TARGET_FIELDMASK 0x00000003 +#define GPU_GR_FECS_NEW_CTX_TARGET_MASK 0x30000000 +#define GPU_GR_FECS_NEW_CTX_TARGET_VID_MEM_F 0x00000000 +#define GPU_GR_FECS_NEW_CTX_TARGET_SYS_MEM_NCOH_F 0x30000000 +#define GPU_GR_FECS_NEW_CTX_VALID_SIZE 0x00000001 +#define GPU_GR_FECS_NEW_CTX_VALID_SHIFT 0x0000001f +#define GPU_GR_FECS_NEW_CTX_VALID_FIELDMASK 0x00000001 +#define GPU_GR_FECS_NEW_CTX_VALID_MASK 0x80000000 +#define GPU_GR_FECS_ARB_CTX_PTR 0x00409a0c +#define GPU_GR_FECS_ARB_CTX_PTR_PTR_SIZE 0x0000001c +#define GPU_GR_FECS_ARB_CTX_PTR_PTR_SHIFT 0x00000000 +#define GPU_GR_FECS_ARB_CTX_PTR_PTR_FIELDMASK 0x0fffffff +#define GPU_GR_FECS_ARB_CTX_PTR_PTR_MASK 0x0fffffff +#define GPU_GR_FECS_ARB_CTX_PTR_TARGET_SIZE 0x00000002 +#define GPU_GR_FECS_ARB_CTX_PTR_TARGET_SHIFT 0x0000001c +#define GPU_GR_FECS_ARB_CTX_PTR_TARGET_FIELDMASK 0x00000003 +#define GPU_GR_FECS_ARB_CTX_PTR_TARGET_MASK 0x30000000 +#define GPU_GR_FECS_ARB_CTX_PTR_TARGET_VID_MEM_F 0x00000000 +#define GPU_GR_FECS_ARB_CTX_PTR_TARGET_SYS_MEM_NCOH_F 0x30000000 +#define GPU_GR_FECS_ARB_CTX_CMD 0x00409a10 +#define GPU_GR_FECS_ARB_CTX_CMD_CMD_SIZE 0x00000005 +#define GPU_GR_FECS_ARB_CTX_CMD_CMD_SHIFT 0x00000000 +#define GPU_GR_FECS_ARB_CTX_CMD_CMD_FIELDMASK 0x0000001f +#define GPU_GR_FECS_ARB_CTX_CMD_CMD_MASK 0x0000001f +#define GPU_GR_FECS_CTXSW_STATUS_FE_0 0x00409c00 +#define GPU_GR_GPC0_GPCCS_CTXSW_STATUS_GPC_0 0x00502c04 +#define GPU_GR_GPC0_GPCCS_CTXSW_STATUS_1 0x00502400 +#define GPU_GR_FECS_CTXSW_IDLESTATE 0x00409420 +#define GPU_GR_GPC0_GPCCS_CTXSW_IDLESTATE 0x00502420 +#define GPU_GR_RSTR2D_GPC_MAP0 0x0040780c +#define GPU_GR_RSTR2D_GPC_MAP1 0x00407810 +#define GPU_GR_RSTR2D_GPC_MAP2 0x00407814 +#define GPU_GR_RSTR2D_GPC_MAP3 0x00407818 +#define GPU_GR_RSTR2D_GPC_MAP4 0x0040781c +#define GPU_GR_RSTR2D_GPC_MAP5 0x00407820 +#define GPU_GR_RSTR2D_MAP_TABLE_CFG 0x004078bc +#define GPU_GR_RSTR2D_MAP_TABLE_CFG_ROW_OFFSET_SHIFT 0x00000000 +#define GPU_GR_RSTR2D_MAP_TABLE_CFG_ROW_OFFSET_FIELDMASK 0x000000ff +#define GPU_GR_RSTR2D_MAP_TABLE_CFG_NUM_ENTRIES_SHIFT 0x00000008 +#define GPU_GR_RSTR2D_MAP_TABLE_CFG_NUM_ENTRIES_FIELDMASK 0x000000ff +#define GPU_GR_PD_HWW_ESR 0x00406018 +#define GPU_GR_PD_HWW_ESR_RESET_ACTIVE_F 0x40000000 +#define GPU_GR_PD_HWW_ESR_EN_ENABLE_F 0x80000000 +#define GPU_GR_PD_NUM_TPC_PER_GPC__BASE 0x00406028 +#define GPU_GR_PD_NUM_TPC_PER_GPC__STRIDE 0x00000004 +#define GPU_GR_PD_NUM_TPC_PER_GPC(i) (0x00406028 + (i) * 0x00000004) +#define GPU_GR_PD_NUM_TPC_PER_GPC__SIZE_1_V 0x00000004 +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT0_SHIFT 0x00000000 +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT0_FIELDMASK 0x0000000f +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT1_SHIFT 0x00000004 +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT1_FIELDMASK 0x0000000f +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT2_SHIFT 0x00000008 +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT2_FIELDMASK 0x0000000f +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT3_SHIFT 0x0000000c +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT3_FIELDMASK 0x0000000f +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT4_SHIFT 0x00000010 +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT4_FIELDMASK 0x0000000f +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT5_SHIFT 0x00000014 +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT5_FIELDMASK 0x0000000f +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT6_SHIFT 0x00000018 +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT6_FIELDMASK 0x0000000f +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT7_SHIFT 0x0000001c +#define GPU_GR_PD_NUM_TPC_PER_GPC_COUNT7_FIELDMASK 0x0000000f +#define GPU_GR_PD_AB_DIST_CFG0 0x004064c0 +#define GPU_GR_PD_AB_DIST_CFG0_TIMESLICE_ENABLE_EN_F 0x80000000 +#define GPU_GR_PD_AB_DIST_CFG0_TIMESLICE_ENABLE_DIS_F 0x00000000 +#define GPU_GR_PD_AB_DIST_CFG1 0x004064c4 +#define GPU_GR_PD_AB_DIST_CFG1_MAX_BATCHES_INIT_F 0x0000ffff +#define GPU_GR_PD_AB_DIST_CFG1_MAX_OUTPUT_SHIFT 0x00000010 +#define GPU_GR_PD_AB_DIST_CFG1_MAX_OUTPUT_FIELDMASK 0x0000ffff +#define GPU_GR_PD_AB_DIST_CFG1_MAX_OUTPUT_GRANULARITY_V 0x00000080 +#define GPU_GR_PD_AB_DIST_CFG2 0x004064c8 +#define GPU_GR_PD_AB_DIST_CFG2_TOKEN_LIMIT_SHIFT 0x00000000 +#define GPU_GR_PD_AB_DIST_CFG2_TOKEN_LIMIT_FIELDMASK 0x00000fff +#define GPU_GR_PD_AB_DIST_CFG2_TOKEN_LIMIT_INIT_V 0x000001c0 +#define GPU_GR_PD_AB_DIST_CFG2_STATE_LIMIT_SHIFT 0x00000010 +#define GPU_GR_PD_AB_DIST_CFG2_STATE_LIMIT_FIELDMASK 0x00000fff +#define GPU_GR_PD_AB_DIST_CFG2_STATE_LIMIT_SCC_BUNDLE_GRANULARITY_V 0x00000020 +#define GPU_GR_PD_AB_DIST_CFG2_STATE_LIMIT_MIN_GPM_FIFO_DEPTHS_V 0x00000182 +#define GPU_GR_PD_PAGEPOOL 0x004064cc +#define GPU_GR_PD_PAGEPOOL_TOTAL_PAGES_SHIFT 0x00000000 +#define GPU_GR_PD_PAGEPOOL_TOTAL_PAGES_FIELDMASK 0x000000ff +#define GPU_GR_PD_PAGEPOOL_VALID_TRUE_F 0x80000000 +#define GPU_GR_PD_DIST_SKIP_TABLE__BASE 0x004064d0 +#define GPU_GR_PD_DIST_SKIP_TABLE__STRIDE 0x00000004 +#define GPU_GR_PD_DIST_SKIP_TABLE(i) (0x004064d0 + (i) * 0x00000004) +#define GPU_GR_PD_DIST_SKIP_TABLE__SIZE_1_V 0x00000008 +#define GPU_GR_PD_DIST_SKIP_TABLE_GPC_4N0_MASK_SHIFT 0x00000000 +#define GPU_GR_PD_DIST_SKIP_TABLE_GPC_4N0_MASK_FIELDMASK 0x000000ff +#define GPU_GR_PD_DIST_SKIP_TABLE_GPC_4N1_MASK_SHIFT 0x00000008 +#define GPU_GR_PD_DIST_SKIP_TABLE_GPC_4N1_MASK_FIELDMASK 0x000000ff +#define GPU_GR_PD_DIST_SKIP_TABLE_GPC_4N2_MASK_SHIFT 0x00000010 +#define GPU_GR_PD_DIST_SKIP_TABLE_GPC_4N2_MASK_FIELDMASK 0x000000ff +#define GPU_GR_PD_DIST_SKIP_TABLE_GPC_4N3_MASK_SHIFT 0x00000018 +#define GPU_GR_PD_DIST_SKIP_TABLE_GPC_4N3_MASK_FIELDMASK 0x000000ff +#define GPU_GR_DS_DEBUG 0x00405800 +#define GPU_GR_DS_DEBUG_TIMESLICE_MODE_DISABLE_F 0x00000000 +#define GPU_GR_DS_DEBUG_TIMESLICE_MODE_ENABLE_F 0x08000000 +#define GPU_GR_DS_ZBC_COLOR_R 0x00405804 +#define GPU_GR_DS_ZBC_COLOR_R_VAL_SHIFT 0x00000000 +#define GPU_GR_DS_ZBC_COLOR_R_VAL_FIELDMASK 0xffffffff +#define GPU_GR_DS_ZBC_COLOR_G 0x00405808 +#define GPU_GR_DS_ZBC_COLOR_G_VAL_SHIFT 0x00000000 +#define GPU_GR_DS_ZBC_COLOR_G_VAL_FIELDMASK 0xffffffff +#define GPU_GR_DS_ZBC_COLOR_B 0x0040580c +#define GPU_GR_DS_ZBC_COLOR_B_VAL_SHIFT 0x00000000 +#define GPU_GR_DS_ZBC_COLOR_B_VAL_FIELDMASK 0xffffffff +#define GPU_GR_DS_ZBC_COLOR_A 0x00405810 +#define GPU_GR_DS_ZBC_COLOR_A_VAL_SHIFT 0x00000000 +#define GPU_GR_DS_ZBC_COLOR_A_VAL_FIELDMASK 0xffffffff +#define GPU_GR_DS_ZBC_COLOR_FMT 0x00405814 +#define GPU_GR_DS_ZBC_COLOR_FMT_VAL_SHIFT 0x00000000 +#define GPU_GR_DS_ZBC_COLOR_FMT_VAL_FIELDMASK 0x0000007f +#define GPU_GR_DS_ZBC_COLOR_FMT_VAL_INVALID_F 0x00000000 +#define GPU_GR_DS_ZBC_COLOR_FMT_VAL_ZERO_V 0x00000001 +#define GPU_GR_DS_ZBC_COLOR_FMT_VAL_UNORM_ONE_V 0x00000002 +#define GPU_GR_DS_ZBC_COLOR_FMT_VAL_RF32_GF32_BF32_AF32_V 0x00000004 +#define GPU_GR_DS_ZBC_COLOR_FMT_VAL_A8_B8_G8_R8_V 0x00000028 +#define GPU_GR_DS_ZBC_Z 0x00405818 +#define GPU_GR_DS_ZBC_Z_VAL_SIZE 0x00000020 +#define GPU_GR_DS_ZBC_Z_VAL_SHIFT 0x00000000 +#define GPU_GR_DS_ZBC_Z_VAL_FIELDMASK 0xffffffff +#define GPU_GR_DS_ZBC_Z_VAL_MASK 0xffffffff +#define GPU_GR_DS_ZBC_Z_VAL__INIT_V 0x00000000 +#define GPU_GR_DS_ZBC_Z_VAL__INIT_F 0x00000000 +#define GPU_GR_DS_ZBC_Z_FMT 0x0040581c +#define GPU_GR_DS_ZBC_Z_FMT_VAL_SHIFT 0x00000000 +#define GPU_GR_DS_ZBC_Z_FMT_VAL_FIELDMASK 0x00000001 +#define GPU_GR_DS_ZBC_Z_FMT_VAL_INVALID_F 0x00000000 +#define GPU_GR_DS_ZBC_Z_FMT_VAL_FP32_V 0x00000001 +#define GPU_GR_DS_ZBC_TBL_INDEX 0x00405820 +#define GPU_GR_DS_ZBC_TBL_INDEX_VAL_SHIFT 0x00000000 +#define GPU_GR_DS_ZBC_TBL_INDEX_VAL_FIELDMASK 0x0000000f +#define GPU_GR_DS_ZBC_TBL_LD 0x00405824 +#define GPU_GR_DS_ZBC_TBL_LD_SELECT_C_F 0x00000000 +#define GPU_GR_DS_ZBC_TBL_LD_SELECT_Z_F 0x00000001 +#define GPU_GR_DS_ZBC_TBL_LD_ACTION_WRITE_F 0x00000000 +#define GPU_GR_DS_ZBC_TBL_LD_TRIGGER_ACTIVE_F 0x00000004 +#define GPU_GR_DS_TGA_CONSTRAINTLOGIC 0x00405830 +#define GPU_GR_DS_TGA_CONSTRAINTLOGIC_BETA_CBSIZE_SHIFT 0x00000010 +#define GPU_GR_DS_TGA_CONSTRAINTLOGIC_BETA_CBSIZE_FIELDMASK 0x0000ffff +#define GPU_GR_DS_TGA_CONSTRAINTLOGIC_ALPHA_CBSIZE_SHIFT 0x00000000 +#define GPU_GR_DS_TGA_CONSTRAINTLOGIC_ALPHA_CBSIZE_FIELDMASK 0x0000ffff +#define GPU_GR_DS_HWW_ESR 0x00405840 +#define GPU_GR_DS_HWW_ESR_RESET_SIZE 0x00000001 +#define GPU_GR_DS_HWW_ESR_RESET_SHIFT 0x0000001e +#define GPU_GR_DS_HWW_ESR_RESET_FIELDMASK 0x00000001 +#define GPU_GR_DS_HWW_ESR_RESET_MASK 0x40000000 +#define GPU_GR_DS_HWW_ESR_RESET_TASK_V 0x00000001 +#define GPU_GR_DS_HWW_ESR_RESET_TASK_F 0x40000000 +#define GPU_GR_DS_HWW_ESR_EN_ENABLED_F 0x80000000 +#define GPU_GR_DS_HWW_ESR_2 0x00405848 +#define GPU_GR_DS_HWW_ESR_2_RESET_SIZE 0x00000001 +#define GPU_GR_DS_HWW_ESR_2_RESET_SHIFT 0x0000001e +#define GPU_GR_DS_HWW_ESR_2_RESET_FIELDMASK 0x00000001 +#define GPU_GR_DS_HWW_ESR_2_RESET_MASK 0x40000000 +#define GPU_GR_DS_HWW_ESR_2_RESET_TASK_V 0x00000001 +#define GPU_GR_DS_HWW_ESR_2_RESET_TASK_F 0x40000000 +#define GPU_GR_DS_HWW_ESR_2_EN_ENABLED_F 0x80000000 +#define GPU_GR_DS_HWW_REPORT_MASK 0x00405844 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH0_ERR_REPORT_F 0x00000001 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH1_ERR_REPORT_F 0x00000002 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH2_ERR_REPORT_F 0x00000004 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH3_ERR_REPORT_F 0x00000008 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH4_ERR_REPORT_F 0x00000010 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH5_ERR_REPORT_F 0x00000020 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH6_ERR_REPORT_F 0x00000040 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH7_ERR_REPORT_F 0x00000080 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH8_ERR_REPORT_F 0x00000100 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH9_ERR_REPORT_F 0x00000200 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH10_ERR_REPORT_F 0x00000400 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH11_ERR_REPORT_F 0x00000800 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH12_ERR_REPORT_F 0x00001000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH13_ERR_REPORT_F 0x00002000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH14_ERR_REPORT_F 0x00004000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH15_ERR_REPORT_F 0x00008000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH16_ERR_REPORT_F 0x00010000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH17_ERR_REPORT_F 0x00020000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH18_ERR_REPORT_F 0x00040000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH19_ERR_REPORT_F 0x00080000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH20_ERR_REPORT_F 0x00100000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH21_ERR_REPORT_F 0x00200000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH22_ERR_REPORT_F 0x00400000 +#define GPU_GR_DS_HWW_REPORT_MASK_SPH23_ERR_REPORT_F 0x00800000 +#define GPU_GR_DS_HWW_REPORT_MASK_2 0x0040584c +#define GPU_GR_DS_HWW_REPORT_MASK_2_SPH24_ERR_REPORT_F 0x00000001 +#define GPU_GR_DS_NUM_TPC_PER_GPC__BASE 0x00405870 +#define GPU_GR_DS_NUM_TPC_PER_GPC__STRIDE 0x00000004 +#define GPU_GR_DS_NUM_TPC_PER_GPC(i) (0x00405870 + (i) * 0x00000004) +#define GPU_GR_SCC_BUNDLE_CB_BASE 0x00408004 +#define GPU_GR_SCC_BUNDLE_CB_BASE_ADDR_39_8_SHIFT 0x00000000 +#define GPU_GR_SCC_BUNDLE_CB_BASE_ADDR_39_8_FIELDMASK 0xffffffff +#define GPU_GR_SCC_BUNDLE_CB_BASE_ADDR_39_8_ALIGN_BITS_V 0x00000008 +#define GPU_GR_SCC_BUNDLE_CB_SIZE 0x00408008 +#define GPU_GR_SCC_BUNDLE_CB_SIZE_DIV_256B_SHIFT 0x00000000 +#define GPU_GR_SCC_BUNDLE_CB_SIZE_DIV_256B_FIELDMASK 0x000007ff +#define GPU_GR_SCC_BUNDLE_CB_SIZE_DIV_256B__PROD_V 0x00000018 +#define GPU_GR_SCC_BUNDLE_CB_SIZE_DIV_256B_BYTE_GRANULARITY_V 0x00000100 +#define GPU_GR_SCC_BUNDLE_CB_SIZE_VALID_FALSE_V 0x00000000 +#define GPU_GR_SCC_BUNDLE_CB_SIZE_VALID_FALSE_F 0x00000000 +#define GPU_GR_SCC_BUNDLE_CB_SIZE_VALID_TRUE_F 0x80000000 +#define GPU_GR_SCC_PAGEPOOL_BASE 0x0040800c +#define GPU_GR_SCC_PAGEPOOL_BASE_ADDR_39_8_SHIFT 0x00000000 +#define GPU_GR_SCC_PAGEPOOL_BASE_ADDR_39_8_FIELDMASK 0xffffffff +#define GPU_GR_SCC_PAGEPOOL_BASE_ADDR_39_8_ALIGN_BITS_V 0x00000008 +#define GPU_GR_SCC_PAGEPOOL 0x00408010 +#define GPU_GR_SCC_PAGEPOOL_TOTAL_PAGES_SHIFT 0x00000000 +#define GPU_GR_SCC_PAGEPOOL_TOTAL_PAGES_FIELDMASK 0x000000ff +#define GPU_GR_SCC_PAGEPOOL_TOTAL_PAGES_HWMAX_V 0x00000000 +#define GPU_GR_SCC_PAGEPOOL_TOTAL_PAGES_HWMAX_VALUE_V 0x00000080 +#define GPU_GR_SCC_PAGEPOOL_TOTAL_PAGES_BYTE_GRANULARITY_V 0x00000100 +#define GPU_GR_SCC_PAGEPOOL_MAX_VALID_PAGES_SIZE 0x00000008 +#define GPU_GR_SCC_PAGEPOOL_MAX_VALID_PAGES_SHIFT 0x00000008 +#define GPU_GR_SCC_PAGEPOOL_MAX_VALID_PAGES_FIELDMASK 0x000000ff +#define GPU_GR_SCC_PAGEPOOL_MAX_VALID_PAGES_MASK 0x0000ff00 +#define GPU_GR_SCC_PAGEPOOL_VALID_TRUE_F 0x80000000 +#define GPU_GR_SCC_INIT 0x0040802c +#define GPU_GR_SCC_INIT_RAM_TRIGGER_F 0x00000001 +#define GPU_GR_SCC_HWW_ESR 0x00408030 +#define GPU_GR_SCC_HWW_ESR_RESET_ACTIVE_F 0x40000000 +#define GPU_GR_SCC_HWW_ESR_EN_ENABLE_F 0x80000000 +#define GPU_GR_SKED_HWW_ESR 0x00407020 +#define GPU_GR_SKED_HWW_ESR_RESET_ACTIVE_F 0x40000000 +#define GPU_GR_CWD_FS 0x00405b00 +#define GPU_GR_CWD_FS_NUM_GPCS_SHIFT 0x00000000 +#define GPU_GR_CWD_FS_NUM_GPCS_FIELDMASK 0x000000ff +#define GPU_GR_CWD_FS_NUM_TPCS_SHIFT 0x00000008 +#define GPU_GR_CWD_FS_NUM_TPCS_FIELDMASK 0x000000ff +#define GPU_GR_CWD_GPC_TPC_ID__BASE 0x00405b60 +#define GPU_GR_CWD_GPC_TPC_ID__STRIDE 0x00000004 +#define GPU_GR_CWD_GPC_TPC_ID(i) (0x00405b60 + (i) * 0x00000004) +#define GPU_GR_CWD_GPC_TPC_ID_TPC0_SIZE 0x00000004 +#define GPU_GR_CWD_GPC_TPC_ID_TPC0_SHIFT 0x00000000 +#define GPU_GR_CWD_GPC_TPC_ID_TPC0_FIELDMASK 0x0000000f +#define GPU_GR_CWD_GPC_TPC_ID_GPC0_SIZE 0x00000004 +#define GPU_GR_CWD_GPC_TPC_ID_GPC0_SHIFT 0x00000004 +#define GPU_GR_CWD_GPC_TPC_ID_GPC0_FIELDMASK 0x0000000f +#define GPU_GR_CWD_GPC_TPC_ID_TPC1_SHIFT 0x00000008 +#define GPU_GR_CWD_GPC_TPC_ID_TPC1_FIELDMASK 0x0000000f +#define GPU_GR_CWD_SM_ID__BASE 0x00405ba0 +#define GPU_GR_CWD_SM_ID__STRIDE 0x00000004 +#define GPU_GR_CWD_SM_ID(i) (0x00405ba0 + (i) * 0x00000004) +#define GPU_GR_CWD_SM_ID__SIZE_1_V 0x00000006 +#define GPU_GR_CWD_SM_ID_TPC0_SHIFT 0x00000000 +#define GPU_GR_CWD_SM_ID_TPC0_FIELDMASK 0x000000ff +#define GPU_GR_CWD_SM_ID_TPC1_SHIFT 0x00000008 +#define GPU_GR_CWD_SM_ID_TPC1_FIELDMASK 0x000000ff +#define GPU_GR_GPC0_FS_GPC 0x00502608 +#define GPU_GR_GPC0_FS_GPC_NUM_AVAILABLE_TPCS_SHIFT 0x00000000 +#define GPU_GR_GPC0_FS_GPC_NUM_AVAILABLE_TPCS_FIELDMASK 0x0000001f +#define GPU_GR_GPC0_FS_GPC_NUM_AVAILABLE_ZCULLS_SHIFT 0x00000010 +#define GPU_GR_GPC0_FS_GPC_NUM_AVAILABLE_ZCULLS_FIELDMASK 0x0000001f +#define GPU_GR_GPC0_CFG 0x00502620 +#define GPU_GR_GPC0_CFG_IMEM_SZ_SHIFT 0x00000000 +#define GPU_GR_GPC0_CFG_IMEM_SZ_FIELDMASK 0x000000ff +#define GPU_GR_GPCCS_RC_LANES 0x00502880 +#define GPU_GR_GPCCS_RC_LANES_NUM_CHAINS_SIZE 0x00000006 +#define GPU_GR_GPCCS_RC_LANES_NUM_CHAINS_SHIFT 0x00000000 +#define GPU_GR_GPCCS_RC_LANES_NUM_CHAINS_FIELDMASK 0x0000003f +#define GPU_GR_GPCCS_RC_LANES_NUM_CHAINS_MASK 0x0000003f +#define GPU_GR_GPCCS_RC_LANE_SIZE__BASE 0x00502910 +#define GPU_GR_GPCCS_RC_LANE_SIZE__STRIDE 0x00000000 +#define GPU_GR_GPCCS_RC_LANE_SIZE(i) (0x00502910 + (i) * 0x00000000) +#define GPU_GR_GPCCS_RC_LANE_SIZE__SIZE_1_V 0x00000010 +#define GPU_GR_GPCCS_RC_LANE_SIZE_V_SIZE 0x00000018 +#define GPU_GR_GPCCS_RC_LANE_SIZE_V_SHIFT 0x00000000 +#define GPU_GR_GPCCS_RC_LANE_SIZE_V_FIELDMASK 0x00ffffff +#define GPU_GR_GPCCS_RC_LANE_SIZE_V_MASK 0x00ffffff +#define GPU_GR_GPCCS_RC_LANE_SIZE_V_0_V 0x00000000 +#define GPU_GR_GPCCS_RC_LANE_SIZE_V_0_F 0x00000000 +#define GPU_GR_GPC0_ZCULL_FS 0x00500910 +#define GPU_GR_GPC0_ZCULL_FS_NUM_SMS_SHIFT 0x00000000 +#define GPU_GR_GPC0_ZCULL_FS_NUM_SMS_FIELDMASK 0x000001ff +#define GPU_GR_GPC0_ZCULL_FS_NUM_ACTIVE_BANKS_SHIFT 0x00000010 +#define GPU_GR_GPC0_ZCULL_FS_NUM_ACTIVE_BANKS_FIELDMASK 0x0000000f +#define GPU_GR_GPC0_ZCULL_RAM_ADDR 0x00500914 +#define GPU_GR_GPC0_ZCULL_RAM_ADDR_TILES_PER_HYPERTILE_ROW_PER_GPC_SHIFT 0x00000000 +#define GPU_GR_GPC0_ZCULL_RAM_ADDR_TILES_PER_HYPERTILE_ROW_PER_GPC_FIELDMASK 0x0000000f +#define GPU_GR_GPC0_ZCULL_RAM_ADDR_ROW_OFFSET_SHIFT 0x00000008 +#define GPU_GR_GPC0_ZCULL_RAM_ADDR_ROW_OFFSET_FIELDMASK 0x0000000f +#define GPU_GR_GPC0_ZCULL_SM_NUM_RCP 0x00500918 +#define GPU_GR_GPC0_ZCULL_SM_NUM_RCP_CONSERVATIVE_SHIFT 0x00000000 +#define GPU_GR_GPC0_ZCULL_SM_NUM_RCP_CONSERVATIVE_FIELDMASK 0x00ffffff +#define GPU_GR_GPC0_ZCULL_SM_NUM_RCP_CONSERVATIVE__MAX_V 0x00800000 +#define GPU_GR_GPC0_ZCULL_TOTAL_RAM_SIZE 0x00500920 +#define GPU_GR_GPC0_ZCULL_TOTAL_RAM_SIZE_NUM_ALIQUOTS_SHIFT 0x00000000 +#define GPU_GR_GPC0_ZCULL_TOTAL_RAM_SIZE_NUM_ALIQUOTS_FIELDMASK 0x0000ffff +#define GPU_GR_GPC0_ZCULL_ZCSIZE__BASE 0x00500a04 +#define GPU_GR_GPC0_ZCULL_ZCSIZE__STRIDE 0x00000020 +#define GPU_GR_GPC0_ZCULL_ZCSIZE(i) (0x00500a04 + (i) * 0x00000020) +#define GPU_GR_GPC0_ZCULL_ZCSIZE_HEIGHT_SUBREGION__MULTIPLE_V 0x00000040 +#define GPU_GR_GPC0_ZCULL_ZCSIZE_WIDTH_SUBREGION__MULTIPLE_V 0x00000010 +#define GPU_GR_GPC0_GPM_PD_SM_ID__BASE 0x00500c10 +#define GPU_GR_GPC0_GPM_PD_SM_ID__STRIDE 0x00000004 +#define GPU_GR_GPC0_GPM_PD_SM_ID(i) (0x00500c10 + (i) * 0x00000004) +#define GPU_GR_GPC0_GPM_PD_SM_ID_ID_SHIFT 0x00000000 +#define GPU_GR_GPC0_GPM_PD_SM_ID_ID_FIELDMASK 0x000000ff +#define GPU_GR_GPC0_GPM_PD_PES_TPC_ID_MASK__BASE 0x00500c30 +#define GPU_GR_GPC0_GPM_PD_PES_TPC_ID_MASK__STRIDE 0x00000004 +#define GPU_GR_GPC0_GPM_PD_PES_TPC_ID_MASK(i) (0x00500c30 + (i) * 0x00000004) +#define GPU_GR_GPC0_GPM_PD_PES_TPC_ID_MASK_MASK_SHIFT 0x00000000 +#define GPU_GR_GPC0_GPM_PD_PES_TPC_ID_MASK_MASK_FIELDMASK 0x000000ff +#define GPU_GR_GPC0_TPC0_PE_CFG_SMID 0x00504088 +#define GPU_GR_GPC0_TPC0_PE_CFG_SMID_VALUE_SHIFT 0x00000000 +#define GPU_GR_GPC0_TPC0_PE_CFG_SMID_VALUE_FIELDMASK 0x0000ffff +#define GPU_GR_GPC0_TPC0_SM_CFG 0x00504698 +#define GPU_GR_GPC0_TPC0_SM_CFG_SM_ID_SHIFT 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_CFG_SM_ID_FIELDMASK 0x0000ffff +#define GPU_GR_GPC0_TPC0_SM_ARCH 0x0050469c +#define GPU_GR_GPC0_TPC0_SM_ARCH_WARP_COUNT_SHIFT 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_ARCH_WARP_COUNT_FIELDMASK 0x000000ff +#define GPU_GR_GPC0_TPC0_SM_ARCH_SPA_VERSION_SHIFT 0x00000008 +#define GPU_GR_GPC0_TPC0_SM_ARCH_SPA_VERSION_FIELDMASK 0x00000fff +#define GPU_GR_GPC0_TPC0_SM_ARCH_SM_VERSION_SHIFT 0x00000014 +#define GPU_GR_GPC0_TPC0_SM_ARCH_SM_VERSION_FIELDMASK 0x00000fff +#define GPU_GR_GPC0_PPC0_PES_VSC_STREM 0x00503018 +#define GPU_GR_GPC0_PPC0_PES_VSC_STREM_MASTER_PE_MASK 0x00000001 +#define GPU_GR_GPC0_PPC0_PES_VSC_STREM_MASTER_PE_SHIFT 0x00000000 +#define GPU_GR_GPC0_PPC0_PES_VSC_STREM_MASTER_PE_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_PPC0_PES_VSC_STREM_MASTER_PE_TRUE_F 0x00000001 +#define GPU_GR_GPC0_PPC0_CBM_BETA_CB_SIZE 0x005030c0 +#define GPU_GR_GPC0_PPC0_CBM_BETA_CB_SIZE_V_SHIFT 0x00000000 +#define GPU_GR_GPC0_PPC0_CBM_BETA_CB_SIZE_V_FIELDMASK 0x0000ffff +#define GPU_GR_GPC0_PPC0_CBM_BETA_CB_SIZE_V_MASK 0x0000ffff +#define GPU_GR_GPC0_PPC0_CBM_BETA_CB_SIZE_V_DEFAULT_V 0x00000400 +#define GPU_GR_GPC0_PPC0_CBM_BETA_CB_SIZE_V_GRANULARITY_V 0x00000020 +#define GPU_GR_GPC0_PPC0_CBM_BETA_CB_OFFSET 0x005030f4 +#define GPU_GR_GPC0_PPC0_CBM_ALPHA_CB_SIZE 0x005030e4 +#define GPU_GR_GPC0_PPC0_CBM_ALPHA_CB_SIZE_V_SHIFT 0x00000000 +#define GPU_GR_GPC0_PPC0_CBM_ALPHA_CB_SIZE_V_FIELDMASK 0x0000ffff +#define GPU_GR_GPC0_PPC0_CBM_ALPHA_CB_SIZE_V_MASK 0x0000ffff +#define GPU_GR_GPC0_PPC0_CBM_ALPHA_CB_SIZE_V_DEFAULT_V 0x00000800 +#define GPU_GR_GPC0_PPC0_CBM_ALPHA_CB_SIZE_V_GRANULARITY_V 0x00000020 +#define GPU_GR_GPC0_PPC0_CBM_ALPHA_CB_OFFSET 0x005030f8 +#define GPU_GR_GPCS_TPCS_TEX_M_DBG2 0x00419a3c +#define GPU_GR_GPCS_TPCS_TEX_M_DBG2_LG_RD_COALESCE_EN_SHIFT 0x00000002 +#define GPU_GR_GPCS_TPCS_TEX_M_DBG2_LG_RD_COALESCE_EN_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_TEX_M_DBG2_LG_RD_COALESCE_EN_MASK 0x00000004 +#define GPU_GR_GPCS_TPCS_TEX_M_DBG2_SU_RD_COALESCE_EN_SHIFT 0x00000004 +#define GPU_GR_GPCS_TPCS_TEX_M_DBG2_SU_RD_COALESCE_EN_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_TEX_M_DBG2_SU_RD_COALESCE_EN_MASK 0x00000010 +#define GPU_GR_GPCCS_FALCON_ADDR 0x0041a0ac +#define GPU_GR_GPCCS_FALCON_ADDR_LSB_SIZE 0x00000006 +#define GPU_GR_GPCCS_FALCON_ADDR_LSB_SHIFT 0x00000000 +#define GPU_GR_GPCCS_FALCON_ADDR_LSB_FIELDMASK 0x0000003f +#define GPU_GR_GPCCS_FALCON_ADDR_LSB_MASK 0x0000003f +#define GPU_GR_GPCCS_FALCON_ADDR_LSB_INIT_V 0x00000000 +#define GPU_GR_GPCCS_FALCON_ADDR_LSB_INIT_F 0x00000000 +#define GPU_GR_GPCCS_FALCON_ADDR_MSB_SIZE 0x00000006 +#define GPU_GR_GPCCS_FALCON_ADDR_MSB_SHIFT 0x00000006 +#define GPU_GR_GPCCS_FALCON_ADDR_MSB_FIELDMASK 0x0000003f +#define GPU_GR_GPCCS_FALCON_ADDR_MSB_MASK 0x00000fc0 +#define GPU_GR_GPCCS_FALCON_ADDR_MSB_INIT_V 0x00000000 +#define GPU_GR_GPCCS_FALCON_ADDR_MSB_INIT_F 0x00000000 +#define GPU_GR_GPCCS_FALCON_ADDR_EXT_SIZE 0x0000000c +#define GPU_GR_GPCCS_FALCON_ADDR_EXT_SHIFT 0x00000000 +#define GPU_GR_GPCCS_FALCON_ADDR_EXT_FIELDMASK 0x00000fff +#define GPU_GR_GPCCS_FALCON_ADDR_EXT_MASK 0x00000fff +#define GPU_GR_GPCCS_CPUCTL 0x0041a100 +#define GPU_GR_GPCCS_CPUCTL_STARTCPU_SHIFT 0x00000001 +#define GPU_GR_GPCCS_CPUCTL_STARTCPU_FIELDMASK 0x00000001 +#define GPU_GR_GPCCS_DMACTL 0x0041a10c +#define GPU_GR_GPCCS_DMACTL_REQUIRE_CTX_SHIFT 0x00000000 +#define GPU_GR_GPCCS_DMACTL_REQUIRE_CTX_FIELDMASK 0x00000001 +#define GPU_GR_GPCCS_DMACTL_DMEM_SCRUBBING_MASK 0x00000002 +#define GPU_GR_GPCCS_DMACTL_DMEM_SCRUBBING_SHIFT 0x00000001 +#define GPU_GR_GPCCS_DMACTL_DMEM_SCRUBBING_FIELDMASK 0x00000001 +#define GPU_GR_GPCCS_DMACTL_IMEM_SCRUBBING_MASK 0x00000004 +#define GPU_GR_GPCCS_DMACTL_IMEM_SCRUBBING_SHIFT 0x00000002 +#define GPU_GR_GPCCS_DMACTL_IMEM_SCRUBBING_FIELDMASK 0x00000001 +#define GPU_GR_GPCCS_IMEMC__BASE 0x0041a180 +#define GPU_GR_GPCCS_IMEMC__STRIDE 0x00000010 +#define GPU_GR_GPCCS_IMEMC(i) (0x0041a180 + (i) * 0x00000010) +#define GPU_GR_GPCCS_IMEMC_OFFS_SHIFT 0x00000002 +#define GPU_GR_GPCCS_IMEMC_OFFS_FIELDMASK 0x0000003f +#define GPU_GR_GPCCS_IMEMC_BLK_SHIFT 0x00000008 +#define GPU_GR_GPCCS_IMEMC_BLK_FIELDMASK 0x000000ff +#define GPU_GR_GPCCS_IMEMC_AINCW_SHIFT 0x00000018 +#define GPU_GR_GPCCS_IMEMC_AINCW_FIELDMASK 0x00000001 +#define GPU_GR_GPCCS_IMEMD__BASE 0x0041a184 +#define GPU_GR_GPCCS_IMEMD__STRIDE 0x00000010 +#define GPU_GR_GPCCS_IMEMD(i) (0x0041a184 + (i) * 0x00000010) +#define GPU_GR_GPCCS_IMEMT__BASE 0x0041a188 +#define GPU_GR_GPCCS_IMEMT__STRIDE 0x00000010 +#define GPU_GR_GPCCS_IMEMT(i) (0x0041a188 + (i) * 0x00000010) +#define GPU_GR_GPCCS_IMEMT__SIZE_1_V 0x00000004 +#define GPU_GR_GPCCS_IMEMT_TAG_SHIFT 0x00000000 +#define GPU_GR_GPCCS_IMEMT_TAG_FIELDMASK 0x0000ffff +#define GPU_GR_GPCCS_DMEMC__BASE 0x0041a1c0 +#define GPU_GR_GPCCS_DMEMC__STRIDE 0x00000008 +#define GPU_GR_GPCCS_DMEMC(i) (0x0041a1c0 + (i) * 0x00000008) +#define GPU_GR_GPCCS_DMEMC_OFFS_SHIFT 0x00000002 +#define GPU_GR_GPCCS_DMEMC_OFFS_FIELDMASK 0x0000003f +#define GPU_GR_GPCCS_DMEMC_BLK_SHIFT 0x00000008 +#define GPU_GR_GPCCS_DMEMC_BLK_FIELDMASK 0x000000ff +#define GPU_GR_GPCCS_DMEMC_AINCW_SHIFT 0x00000018 +#define GPU_GR_GPCCS_DMEMC_AINCW_FIELDMASK 0x00000001 +#define GPU_GR_GPCCS_DMEMD__BASE 0x0041a1c4 +#define GPU_GR_GPCCS_DMEMD__STRIDE 0x00000008 +#define GPU_GR_GPCCS_DMEMD(i) (0x0041a1c4 + (i) * 0x00000008) +#define GPU_GR_GPCCS_CTXSW_MAILBOX__BASE 0x0041a800 +#define GPU_GR_GPCCS_CTXSW_MAILBOX__STRIDE 0x00000004 +#define GPU_GR_GPCCS_CTXSW_MAILBOX(i) (0x0041a800 + (i) * 0x00000004) +#define GPU_GR_GPCCS_CTXSW_MAILBOX_VALUE_SHIFT 0x00000000 +#define GPU_GR_GPCCS_CTXSW_MAILBOX_VALUE_FIELDMASK 0xffffffff +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_BASE 0x00418e24 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_BASE_ADDR_39_8_SIZE 0x00000020 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_BASE_ADDR_39_8_SHIFT 0x00000000 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_BASE_ADDR_39_8_FIELDMASK 0xffffffff +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_BASE_ADDR_39_8_MASK 0xffffffff +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_BASE_ADDR_39_8_INIT_V 0x00000000 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_BASE_ADDR_39_8_INIT_F 0x00000000 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE 0x00418e28 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_DIV_256B_SIZE 0x0000000b +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_DIV_256B_SHIFT 0x00000000 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_DIV_256B_FIELDMASK 0x000007ff +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_DIV_256B_MASK 0x000007ff +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_DIV_256B_INIT_V 0x00000018 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_DIV_256B_INIT_F 0x00000018 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_VALID_SIZE 0x00000001 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_VALID_SHIFT 0x0000001f +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_VALID_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_VALID_MASK 0x80000000 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_VALID_FALSE_V 0x00000000 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_VALID_FALSE_F 0x00000000 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_VALID_TRUE_V 0x00000001 +#define GPU_GR_GPCS_SWDX_BUNDLE_CB_SIZE_VALID_TRUE_F 0x80000000 +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE__BASE 0x00418ea0 +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE__STRIDE 0x00000004 +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE(i) (0x00418ea0 + (i) * 0x00000004) +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE_V_SHIFT 0x00000000 +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE_V_FIELDMASK 0x0000ffff +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE_V_MASK 0x0000ffff +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE_DIV3_SHIFT 0x00000010 +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE_DIV3_FIELDMASK 0x0000ffff +#define GPU_GR_GPCS_SWDX_TC_BETA_CB_SIZE_DIV3_MASK 0xffff0000 +#define GPU_GR_GPCS_SWDX_RM_PAGEPOOL 0x00418e30 +#define GPU_GR_GPCS_SWDX_RM_PAGEPOOL_TOTAL_PAGES_SHIFT 0x00000000 +#define GPU_GR_GPCS_SWDX_RM_PAGEPOOL_TOTAL_PAGES_FIELDMASK 0x000000ff +#define GPU_GR_GPCS_SWDX_RM_PAGEPOOL_VALID_TRUE_F 0x80000000 +#define GPU_GR_GPCS_SETUP_ATTRIB_CB_BASE 0x00418810 +#define GPU_GR_GPCS_SETUP_ATTRIB_CB_BASE_ADDR_39_12_SHIFT 0x00000000 +#define GPU_GR_GPCS_SETUP_ATTRIB_CB_BASE_ADDR_39_12_FIELDMASK 0x0fffffff +#define GPU_GR_GPCS_SETUP_ATTRIB_CB_BASE_ADDR_39_12_ALIGN_BITS_V 0x0000000c +#define GPU_GR_GPCS_SETUP_ATTRIB_CB_BASE_VALID_TRUE_F 0x80000000 +#define GPU_GR_CRSTR_GPC_MAP0 0x00418b08 +#define GPU_GR_CRSTR_GPC_MAP0_TILE0_SHIFT 0x00000000 +#define GPU_GR_CRSTR_GPC_MAP0_TILE0_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP0_TILE1_SHIFT 0x00000005 +#define GPU_GR_CRSTR_GPC_MAP0_TILE1_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP0_TILE2_SHIFT 0x0000000a +#define GPU_GR_CRSTR_GPC_MAP0_TILE2_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP0_TILE3_SHIFT 0x0000000f +#define GPU_GR_CRSTR_GPC_MAP0_TILE3_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP0_TILE4_SHIFT 0x00000014 +#define GPU_GR_CRSTR_GPC_MAP0_TILE4_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP0_TILE5_SHIFT 0x00000019 +#define GPU_GR_CRSTR_GPC_MAP0_TILE5_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP1 0x00418b0c +#define GPU_GR_CRSTR_GPC_MAP1_TILE6_SHIFT 0x00000000 +#define GPU_GR_CRSTR_GPC_MAP1_TILE6_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP1_TILE7_SHIFT 0x00000005 +#define GPU_GR_CRSTR_GPC_MAP1_TILE7_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP1_TILE8_SHIFT 0x0000000a +#define GPU_GR_CRSTR_GPC_MAP1_TILE8_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP1_TILE9_SHIFT 0x0000000f +#define GPU_GR_CRSTR_GPC_MAP1_TILE9_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP1_TILE10_SHIFT 0x00000014 +#define GPU_GR_CRSTR_GPC_MAP1_TILE10_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP1_TILE11_SHIFT 0x00000019 +#define GPU_GR_CRSTR_GPC_MAP1_TILE11_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP2 0x00418b10 +#define GPU_GR_CRSTR_GPC_MAP2_TILE12_SHIFT 0x00000000 +#define GPU_GR_CRSTR_GPC_MAP2_TILE12_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP2_TILE13_SHIFT 0x00000005 +#define GPU_GR_CRSTR_GPC_MAP2_TILE13_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP2_TILE14_SHIFT 0x0000000a +#define GPU_GR_CRSTR_GPC_MAP2_TILE14_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP2_TILE15_SHIFT 0x0000000f +#define GPU_GR_CRSTR_GPC_MAP2_TILE15_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP2_TILE16_SHIFT 0x00000014 +#define GPU_GR_CRSTR_GPC_MAP2_TILE16_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP2_TILE17_SHIFT 0x00000019 +#define GPU_GR_CRSTR_GPC_MAP2_TILE17_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP3 0x00418b14 +#define GPU_GR_CRSTR_GPC_MAP3_TILE18_SHIFT 0x00000000 +#define GPU_GR_CRSTR_GPC_MAP3_TILE18_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP3_TILE19_SHIFT 0x00000005 +#define GPU_GR_CRSTR_GPC_MAP3_TILE19_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP3_TILE20_SHIFT 0x0000000a +#define GPU_GR_CRSTR_GPC_MAP3_TILE20_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP3_TILE21_SHIFT 0x0000000f +#define GPU_GR_CRSTR_GPC_MAP3_TILE21_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP3_TILE22_SHIFT 0x00000014 +#define GPU_GR_CRSTR_GPC_MAP3_TILE22_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP3_TILE23_SHIFT 0x00000019 +#define GPU_GR_CRSTR_GPC_MAP3_TILE23_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP4 0x00418b18 +#define GPU_GR_CRSTR_GPC_MAP4_TILE24_SHIFT 0x00000000 +#define GPU_GR_CRSTR_GPC_MAP4_TILE24_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP4_TILE25_SHIFT 0x00000005 +#define GPU_GR_CRSTR_GPC_MAP4_TILE25_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP4_TILE26_SHIFT 0x0000000a +#define GPU_GR_CRSTR_GPC_MAP4_TILE26_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP4_TILE27_SHIFT 0x0000000f +#define GPU_GR_CRSTR_GPC_MAP4_TILE27_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP4_TILE28_SHIFT 0x00000014 +#define GPU_GR_CRSTR_GPC_MAP4_TILE28_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP4_TILE29_SHIFT 0x00000019 +#define GPU_GR_CRSTR_GPC_MAP4_TILE29_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP5 0x00418b1c +#define GPU_GR_CRSTR_GPC_MAP5_TILE30_SHIFT 0x00000000 +#define GPU_GR_CRSTR_GPC_MAP5_TILE30_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP5_TILE31_SHIFT 0x00000005 +#define GPU_GR_CRSTR_GPC_MAP5_TILE31_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP5_TILE32_SHIFT 0x0000000a +#define GPU_GR_CRSTR_GPC_MAP5_TILE32_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP5_TILE33_SHIFT 0x0000000f +#define GPU_GR_CRSTR_GPC_MAP5_TILE33_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP5_TILE34_SHIFT 0x00000014 +#define GPU_GR_CRSTR_GPC_MAP5_TILE34_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_GPC_MAP5_TILE35_SHIFT 0x00000019 +#define GPU_GR_CRSTR_GPC_MAP5_TILE35_FIELDMASK 0x00000007 +#define GPU_GR_CRSTR_MAP_TABLE_CFG 0x00418bb8 +#define GPU_GR_CRSTR_MAP_TABLE_CFG_ROW_OFFSET_SHIFT 0x00000000 +#define GPU_GR_CRSTR_MAP_TABLE_CFG_ROW_OFFSET_FIELDMASK 0x000000ff +#define GPU_GR_CRSTR_MAP_TABLE_CFG_NUM_ENTRIES_SHIFT 0x00000008 +#define GPU_GR_CRSTR_MAP_TABLE_CFG_NUM_ENTRIES_FIELDMASK 0x000000ff +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0 0x00418980 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_0_SHIFT 0x00000000 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_0_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_1_SHIFT 0x00000004 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_1_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_2_SHIFT 0x00000008 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_2_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_3_SHIFT 0x0000000c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_3_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_4_SHIFT 0x00000010 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_4_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_5_SHIFT 0x00000014 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_5_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_6_SHIFT 0x00000018 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_6_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_7_SHIFT 0x0000001c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP0_TILE_7_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1 0x00418984 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_8_SHIFT 0x00000000 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_8_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_9_SHIFT 0x00000004 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_9_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_10_SHIFT 0x00000008 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_10_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_11_SHIFT 0x0000000c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_11_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_12_SHIFT 0x00000010 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_12_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_13_SHIFT 0x00000014 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_13_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_14_SHIFT 0x00000018 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_14_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_15_SHIFT 0x0000001c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP1_TILE_15_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2 0x00418988 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_16_SHIFT 0x00000000 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_16_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_17_SHIFT 0x00000004 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_17_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_18_SHIFT 0x00000008 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_18_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_19_SHIFT 0x0000000c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_19_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_20_SHIFT 0x00000010 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_20_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_21_SHIFT 0x00000014 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_21_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_22_SHIFT 0x00000018 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_22_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_23_SIZE 0x00000003 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_23_SHIFT 0x0000001c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_23_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP2_TILE_23_MASK 0x70000000 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3 0x0041898c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_24_SHIFT 0x00000000 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_24_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_25_SHIFT 0x00000004 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_25_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_26_SHIFT 0x00000008 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_26_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_27_SHIFT 0x0000000c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_27_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_28_SHIFT 0x00000010 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_28_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_29_SHIFT 0x00000014 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_29_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_30_SHIFT 0x00000018 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_30_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_31_SHIFT 0x0000001c +#define GPU_GR_GPCS_ZCULL_SM_IN_GPC_NUMBER_MAP3_TILE_31_FIELDMASK 0x00000007 +#define GPU_GR_GPCS_GPM_PD_CFG 0x00418c6c +#define GPU_GR_GPCS_GPM_PD_CFG_TIMESLICE_MODE_DISABLE_F 0x00000000 +#define GPU_GR_GPCS_GPM_PD_CFG_TIMESLICE_MODE_ENABLE_F 0x00000001 +#define GPU_GR_GPCS_GCC_PAGEPOOL_BASE 0x00419004 +#define GPU_GR_GPCS_GCC_PAGEPOOL_BASE_ADDR_39_8_SHIFT 0x00000000 +#define GPU_GR_GPCS_GCC_PAGEPOOL_BASE_ADDR_39_8_FIELDMASK 0xffffffff +#define GPU_GR_GPCS_GCC_PAGEPOOL 0x00419008 +#define GPU_GR_GPCS_GCC_PAGEPOOL_TOTAL_PAGES_SHIFT 0x00000000 +#define GPU_GR_GPCS_GCC_PAGEPOOL_TOTAL_PAGES_FIELDMASK 0x000000ff +#define GPU_GR_GPCS_TPCS_PE_VAF 0x0041980c +#define GPU_GR_GPCS_TPCS_PE_VAF_FAST_MODE_SWITCH_TRUE_F 0x00000010 +#define GPU_GR_GPCS_TPCS_PE_PIN_CB_GLOBAL_BASE_ADDR 0x00419848 +#define GPU_GR_GPCS_TPCS_PE_PIN_CB_GLOBAL_BASE_ADDR_V_SHIFT 0x00000000 +#define GPU_GR_GPCS_TPCS_PE_PIN_CB_GLOBAL_BASE_ADDR_V_FIELDMASK 0x0fffffff +#define GPU_GR_GPCS_TPCS_PE_PIN_CB_GLOBAL_BASE_ADDR_VALID_SHIFT 0x0000001c +#define GPU_GR_GPCS_TPCS_PE_PIN_CB_GLOBAL_BASE_ADDR_VALID_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_PE_PIN_CB_GLOBAL_BASE_ADDR_VALID_TRUE_F 0x10000000 +#define GPU_GR_GPCS_TPCS_MPC_VTG_DEBUG 0x00419c00 +#define GPU_GR_GPCS_TPCS_MPC_VTG_DEBUG_TIMESLICE_MODE_DISABLED_F 0x00000000 +#define GPU_GR_GPCS_TPCS_MPC_VTG_DEBUG_TIMESLICE_MODE_ENABLED_F 0x00000008 +#define GPU_GR_GPCS_TPCS_MPC_VTG_CB_GLOBAL_BASE_ADDR 0x00419c2c +#define GPU_GR_GPCS_TPCS_MPC_VTG_CB_GLOBAL_BASE_ADDR_V_SHIFT 0x00000000 +#define GPU_GR_GPCS_TPCS_MPC_VTG_CB_GLOBAL_BASE_ADDR_V_FIELDMASK 0x0fffffff +#define GPU_GR_GPCS_TPCS_MPC_VTG_CB_GLOBAL_BASE_ADDR_VALID_SHIFT 0x0000001c +#define GPU_GR_GPCS_TPCS_MPC_VTG_CB_GLOBAL_BASE_ADDR_VALID_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_MPC_VTG_CB_GLOBAL_BASE_ADDR_VALID_TRUE_F 0x10000000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK 0x00419e44 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_STACK_ERROR_REPORT_F 0x00000002 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_API_STACK_ERROR_REPORT_F 0x00000004 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_RET_EMPTY_STACK_ERROR_REPORT_F 0x00000008 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_PC_WRAP_REPORT_F 0x00000010 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_MISALIGNED_PC_REPORT_F 0x00000020 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_PC_OVERFLOW_REPORT_F 0x00000040 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_MISALIGNED_IMMC_ADDR_REPORT_F 0x00000080 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_MISALIGNED_REG_REPORT_F 0x00000100 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_ILLEGAL_INSTR_ENCODING_REPORT_F 0x00000200 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_ILLEGAL_SPH_INSTR_COMBO_REPORT_F 0x00000400 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_ILLEGAL_INSTR_PARAM_REPORT_F 0x00000800 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_INVALID_CONST_ADDR_REPORT_F 0x00001000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_OOR_REG_REPORT_F 0x00002000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_OOR_ADDR_REPORT_F 0x00004000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_MISALIGNED_ADDR_REPORT_F 0x00008000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_INVALID_ADDR_SPACE_REPORT_F 0x00010000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_ILLEGAL_INSTR_PARAM2_REPORT_F 0x00020000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_INVALID_CONST_ADDR_LDC_REPORT_F 0x00040000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_MMU_FAULT_REPORT_F 0x00800000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_STACK_OVERFLOW_REPORT_F 0x00400000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_GEOMETRY_SM_ERROR_REPORT_F 0x00080000 +#define GPU_GR_GPCS_TPCS_SM_HWW_WARP_ESR_REPORT_MASK_DIVERGENT_REPORT_F 0x00100000 +#define GPU_GR_GPC0_TPC0_SM_HWW_WARP_ESR_REPORT_MASK 0x00504644 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_REPORT_MASK 0x00419e4c +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_REPORT_MASK_SM_TO_SM_FAULT_REPORT_F 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_REPORT_MASK_L1_ERROR_REPORT_F 0x00000002 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_REPORT_MASK_MULTIPLE_WARP_ERRORS_REPORT_F 0x00000004 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_REPORT_MASK_PHYSICAL_STACK_OVERFLOW_ERROR_REPORT_F 0x00000008 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_REPORT_MASK_BPT_INT_REPORT_F 0x00000010 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_REPORT_MASK_BPT_PAUSE_REPORT_F 0x00000020 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_REPORT_MASK_SINGLE_STEP_COMPLETE_REPORT_F 0x00000040 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_REPORT_MASK 0x0050464c +#define GPU_GR_GPCS_TPCS_TPCCS_TPC_EXCEPTION_EN 0x00419d0c +#define GPU_GR_GPCS_TPCS_TPCCS_TPC_EXCEPTION_EN_SM_ENABLED_F 0x00000002 +#define GPU_GR_GPCS_TPCS_TPCCS_TPC_EXCEPTION_EN_TEX_ENABLED_F 0x00000001 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_EN 0x0050450c +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_EN_SM_ENABLED_F 0x00000002 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_EN_SM_SHIFT 0x00000001 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_EN_SM_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_GPCCS_GPC_EXCEPTION_EN 0x0041ac94 +#define GPU_GR_GPCS_GPCCS_GPC_EXCEPTION_EN_TPC_SHIFT 0x00000010 +#define GPU_GR_GPCS_GPCCS_GPC_EXCEPTION_EN_TPC_FIELDMASK 0x000000ff +#define GPU_GR_GPC0_GPCCS_GPC_EXCEPTION 0x00502c90 +#define GPU_GR_GPC0_GPCCS_GPC_EXCEPTION_TPC_SHIFT 0x00000010 +#define GPU_GR_GPC0_GPCCS_GPC_EXCEPTION_TPC_FIELDMASK 0x000000ff +#define GPU_GR_GPC0_GPCCS_GPC_EXCEPTION_TPC_0_PENDING_V 0x00000001 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION 0x00504508 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_TEX_SHIFT 0x00000000 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_TEX_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_TEX_PENDING_V 0x00000001 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_SM_SHIFT 0x00000001 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_SM_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_TPC0_TPCCS_TPC_EXCEPTION_SM_PENDING_V 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0 0x00504610 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_DEBUGGER_MODE_MASK 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_DEBUGGER_MODE_SHIFT 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_DEBUGGER_MODE_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_DEBUGGER_MODE_ON_V 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_DEBUGGER_MODE_ON_F 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_DEBUGGER_MODE_OFF_V 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_DEBUGGER_MODE_OFF_F 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_TRIGGER_ENABLE_F 0x80000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_TRIGGER_DISABLE_F 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_SINGLE_STEP_MODE_ENABLE_F 0x00000008 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_SINGLE_STEP_MODE_DISABLE_F 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_RUN_TRIGGER_TASK_F 0x40000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_WARP_MASK 0x00000002 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_WARP_SHIFT 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_WARP_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_WARP_DISABLE_F 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_SM_MASK 0x00000004 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_SM_SHIFT 0x00000002 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_SM_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_SM_DISABLE_F 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_SM_STOP_ON_ANY_WARP_DISABLE_V 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_CONTROL0_STOP_ON_ANY_SM_STOP_ON_ANY_SM_DISABLE_V 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_WARP_VALID_MASK 0x00504614 +#define GPU_GR_GPC0_TPC0_SM_WARP_VALID_MASK_1 0x00504618 +#define GPU_GR_GPC0_TPC0_SM_WARP_VALID_MASK_2 0x0050461c +#define GPU_GR_GPC0_TPC0_SM_DBGR_BPT_PAUSE_MASK 0x00504624 +#define GPU_GR_GPC0_TPC0_SM_DBGR_BPT_PAUSE_MASK_1 0x00504628 +#define GPU_GR_GPC0_TPC0_SM_DBGR_BPT_PAUSE_MASK_2 0x00504750 +#define GPU_GR_GPC0_TPC0_SM_DBGR_BPT_TRAP_MASK 0x00504634 +#define GPU_GR_GPC0_TPC0_SM_DBGR_BPT_TRAP_MASK_1 0x00504638 +#define GPU_GR_GPC0_TPC0_SM_DBGR_BPT_TRAP_MASK_2 0x00504758 +#define GPU_GR_GPCS_TPCS_SM_DBGR_BPT_PAUSE_MASK 0x00419e24 +#define GPU_GR_GPC0_TPC0_SM_DBGR_STATUS0 0x0050460c +#define GPU_GR_GPC0_TPC0_SM_DBGR_STATUS0_SM_IN_TRAP_MODE_SHIFT 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_DBGR_STATUS0_SM_IN_TRAP_MODE_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_STATUS0_LOCKED_DOWN_SHIFT 0x00000004 +#define GPU_GR_GPC0_TPC0_SM_DBGR_STATUS0_LOCKED_DOWN_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DBGR_STATUS0_LOCKED_DOWN_TRUE_V 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR 0x00419e50 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_BPT_INT_PENDING_F 0x00000010 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_BPT_PAUSE_PENDING_F 0x00000020 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_SINGLE_STEP_COMPLETE_PENDING_F 0x00000040 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_SM_TO_SM_FAULT_PENDING_F 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_L1_ERROR_PENDING_F 0x00000002 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_MULTIPLE_WARP_ERRORS_PENDING_F 0x00000004 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_PHYSICAL_STACK_OVERFLOW_ERROR_PENDING_F 0x00000008 +#define GPU_GR_GPCS_TPCS_SM_HWW_GLOBAL_ESR_TIMEOUT_ERROR_PENDING_F 0x80000000 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR 0x00504650 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_BPT_INT_PENDING_F 0x00000010 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_BPT_PAUSE_PENDING_F 0x00000020 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_SINGLE_STEP_COMPLETE_PENDING_F 0x00000040 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_SM_TO_SM_FAULT_PENDING_F 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_L1_ERROR_PENDING_F 0x00000002 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_MULTIPLE_WARP_ERRORS_PENDING_F 0x00000004 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_PHYSICAL_STACK_OVERFLOW_ERROR_PENDING_F 0x00000008 +#define GPU_GR_GPC0_TPC0_SM_HWW_GLOBAL_ESR_TIMEOUT_ERROR_PENDING_F 0x80000000 +#define GPU_GR_GPC0_TPC0_TEX_M_HWW_ESR 0x00504224 +#define GPU_GR_GPC0_TPC0_TEX_M_HWW_ESR_INTR_PENDING_F 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_HWW_WARP_ESR 0x00504648 +#define GPU_GR_GPC0_TPC0_SM_HWW_WARP_ESR_ERROR_SHIFT 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_HWW_WARP_ESR_ERROR_FIELDMASK 0x0000ffff +#define GPU_GR_GPC0_TPC0_SM_HWW_WARP_ESR_ERROR_NONE_V 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_HWW_WARP_ESR_ERROR_NONE_F 0x00000000 +#define GPU_GR_GPC0_TPC0_SM_HWW_WARP_ESR_PC 0x00504654 +#define GPU_GR_GPC0_TPC0_SM_HALFCTL_CTRL 0x00504770 +#define GPU_GR_GPCS_TPCS_SM_HALFCTL_CTRL 0x00419f70 +#define GPU_GR_GPCS_TPCS_SM_HALFCTL_CTRL_SCTL_READ_QUAD_CTL_MASK 0x00000010 +#define GPU_GR_GPCS_TPCS_SM_HALFCTL_CTRL_SCTL_READ_QUAD_CTL_SHIFT 0x00000004 +#define GPU_GR_GPCS_TPCS_SM_HALFCTL_CTRL_SCTL_READ_QUAD_CTL_FIELDMASK 0x00000001 +#define GPU_GR_GPC0_TPC0_SM_DEBUG_SFE_CONTROL 0x0050477c +#define GPU_GR_GPCS_TPCS_SM_DEBUG_SFE_CONTROL 0x00419f7c +#define GPU_GR_GPCS_TPCS_SM_DEBUG_SFE_CONTROL_READ_HALF_CTL_MASK 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_DEBUG_SFE_CONTROL_READ_HALF_CTL_SHIFT 0x00000000 +#define GPU_GR_GPCS_TPCS_SM_DEBUG_SFE_CONTROL_READ_HALF_CTL_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_PES_VSC_VPC 0x0041be08 +#define GPU_GR_GPCS_TPCS_PES_VSC_VPC_FAST_MODE_SWITCH_TRUE_F 0x00000004 +#define GPU_GR_PPCS_WWDX_MAP_GPC_MAP0 0x0041bf00 +#define GPU_GR_PPCS_WWDX_MAP_GPC_MAP1 0x0041bf04 +#define GPU_GR_PPCS_WWDX_MAP_GPC_MAP2 0x0041bf08 +#define GPU_GR_PPCS_WWDX_MAP_GPC_MAP3 0x0041bf0c +#define GPU_GR_PPCS_WWDX_MAP_GPC_MAP4 0x0041bf10 +#define GPU_GR_PPCS_WWDX_MAP_GPC_MAP5 0x0041bf14 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG 0x0041bfd0 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_ROW_OFFSET_SHIFT 0x00000000 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_ROW_OFFSET_FIELDMASK 0x000000ff +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_NUM_ENTRIES_SHIFT 0x00000008 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_NUM_ENTRIES_FIELDMASK 0x000000ff +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_NORMALIZED_NUM_ENTRIES_SHIFT 0x00000010 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_NORMALIZED_NUM_ENTRIES_FIELDMASK 0x0000001f +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_NORMALIZED_SHIFT_VALUE_SHIFT 0x00000015 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_NORMALIZED_SHIFT_VALUE_FIELDMASK 0x00000007 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_COEFF5_MOD_VALUE_SHIFT 0x00000018 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG_COEFF5_MOD_VALUE_FIELDMASK 0x0000001f +#define GPU_GR_GPCS_PPCS_WWDX_SM_NUM_RCP 0x0041bfd4 +#define GPU_GR_GPCS_PPCS_WWDX_SM_NUM_RCP_CONSERVATIVE_SHIFT 0x00000000 +#define GPU_GR_GPCS_PPCS_WWDX_SM_NUM_RCP_CONSERVATIVE_FIELDMASK 0x00ffffff +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2 0x0041bfe4 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF6_MOD_VALUE_SHIFT 0x00000000 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF6_MOD_VALUE_FIELDMASK 0x0000001f +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF7_MOD_VALUE_SHIFT 0x00000005 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF7_MOD_VALUE_FIELDMASK 0x0000001f +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF8_MOD_VALUE_SHIFT 0x0000000a +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF8_MOD_VALUE_FIELDMASK 0x0000001f +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF9_MOD_VALUE_SHIFT 0x0000000f +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF9_MOD_VALUE_FIELDMASK 0x0000001f +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF10_MOD_VALUE_SHIFT 0x00000014 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF10_MOD_VALUE_FIELDMASK 0x0000001f +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF11_MOD_VALUE_SHIFT 0x00000019 +#define GPU_GR_PPCS_WWDX_MAP_TABLE_CFG2_COEFF11_MOD_VALUE_FIELDMASK 0x0000001f +#define GPU_GR_BES_ZROP_SETTINGS 0x00408850 +#define GPU_GR_BES_ZROP_SETTINGS_NUM_ACTIVE_LTCS_SHIFT 0x00000000 +#define GPU_GR_BES_ZROP_SETTINGS_NUM_ACTIVE_LTCS_FIELDMASK 0x0000000f +#define GPU_GR_BE0_CROP_DEBUG3 0x00410108 +#define GPU_GR_BES_CROP_DEBUG3 0x00408908 +#define GPU_GR_BES_CROP_DEBUG3_COMP_VDC_4TO2_DISABLE_MASK 0x80000000 +#define GPU_GR_BES_CROP_DEBUG3_COMP_VDC_4TO2_DISABLE_SHIFT 0x0000001f +#define GPU_GR_BES_CROP_DEBUG3_COMP_VDC_4TO2_DISABLE_FIELDMASK 0x00000001 +#define GPU_GR_BES_CROP_SETTINGS 0x00408958 +#define GPU_GR_BES_CROP_SETTINGS_NUM_ACTIVE_LTCS_SHIFT 0x00000000 +#define GPU_GR_BES_CROP_SETTINGS_NUM_ACTIVE_LTCS_FIELDMASK 0x0000000f +#define GPU_GR_ZCULL_BYTES_PER_ALIQUOT_PER_GPU_V 0x00000020 +#define GPU_GR_ZCULL_SAVE_RESTORE_HEADER_BYTES_PER_GPC_V 0x00000020 +#define GPU_GR_ZCULL_SAVE_RESTORE_SUBREGION_HEADER_BYTES_PER_GPC_V 0x000000c0 +#define GPU_GR_ZCULL_SUBREGION_QTY_V 0x00000010 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_CONTROL_SEL0 0x00504604 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_CONTROL_SEL1 0x00504608 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_CONTROL0 0x0050465c +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_CONTROL1 0x00504660 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_CONTROL2 0x00504664 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_CONTROL3 0x00504668 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_CONTROL4 0x0050466c +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_CONTROL5 0x00504658 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER0_CONTROL 0x00504730 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER1_CONTROL 0x00504734 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER2_CONTROL 0x00504738 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER3_CONTROL 0x0050473c +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER4_CONTROL 0x00504740 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER5_CONTROL 0x00504744 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER6_CONTROL 0x00504748 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER7_CONTROL 0x0050474c +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_STATUS_S1 0x00504678 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER_STATUS1 0x00504694 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER0_S0 0x005046f0 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER0_S1 0x00504700 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER1_S0 0x005046f4 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER1_S1 0x00504704 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER2_S0 0x005046f8 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER2_S1 0x00504708 +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER3_S0 0x005046fc +#define GPU_GR_PRI_GPC0_TPC0_SM_DSM_PERF_COUNTER3_S1 0x0050470c +#define GPU_GR_FE_PWR_MODE 0x00404170 +#define GPU_GR_FE_PWR_MODE_MODE_AUTO_F 0x00000000 +#define GPU_GR_FE_PWR_MODE_MODE_FORCE_ON_F 0x00000002 +#define GPU_GR_FE_PWR_MODE_REQ_SHIFT 0x00000004 +#define GPU_GR_FE_PWR_MODE_REQ_FIELDMASK 0x00000001 +#define GPU_GR_FE_PWR_MODE_REQ_SEND_F 0x00000010 +#define GPU_GR_FE_PWR_MODE_REQ_DONE_V 0x00000000 +#define GPU_GR_GPCS_PRI_MMU_CTRL 0x00418880 +#define GPU_GR_GPCS_PRI_MMU_CTRL_VM_PG_SIZE_MASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_CTRL_VM_PG_SIZE_SHIFT 0x00000000 +#define GPU_GR_GPCS_PRI_MMU_CTRL_VM_PG_SIZE_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_CTRL_USE_PDB_BIG_PAGE_SIZE_MASK 0x00000800 +#define GPU_GR_GPCS_PRI_MMU_CTRL_USE_PDB_BIG_PAGE_SIZE_SHIFT 0x0000000b +#define GPU_GR_GPCS_PRI_MMU_CTRL_USE_PDB_BIG_PAGE_SIZE_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_CTRL_USE_FULL_COMP_TAG_LINE_MASK 0x00001000 +#define GPU_GR_GPCS_PRI_MMU_CTRL_USE_FULL_COMP_TAG_LINE_SHIFT 0x0000000c +#define GPU_GR_GPCS_PRI_MMU_CTRL_USE_FULL_COMP_TAG_LINE_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_CTRL_VOL_FAULT_MASK 0x00000002 +#define GPU_GR_GPCS_PRI_MMU_CTRL_VOL_FAULT_SHIFT 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_CTRL_VOL_FAULT_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_CTRL_COMP_FAULT_MASK 0x00000004 +#define GPU_GR_GPCS_PRI_MMU_CTRL_COMP_FAULT_SHIFT 0x00000002 +#define GPU_GR_GPCS_PRI_MMU_CTRL_COMP_FAULT_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MISS_GRAN_MASK 0x00000018 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MISS_GRAN_SHIFT 0x00000003 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MISS_GRAN_FIELDMASK 0x00000003 +#define GPU_GR_GPCS_PRI_MMU_CTRL_CACHE_MODE_MASK 0x00000060 +#define GPU_GR_GPCS_PRI_MMU_CTRL_CACHE_MODE_SHIFT 0x00000005 +#define GPU_GR_GPCS_PRI_MMU_CTRL_CACHE_MODE_FIELDMASK 0x00000003 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_APERTURE_MASK 0x30000000 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_APERTURE_SHIFT 0x0000001c +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_APERTURE_FIELDMASK 0x00000003 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_VOL_MASK 0x40000000 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_VOL_SHIFT 0x0000001e +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_VOL_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_DISABLE_MASK 0x80000000 +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_DISABLE_SHIFT 0x0000001f +#define GPU_GR_GPCS_PRI_MMU_CTRL_MMU_DISABLE_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_PM_UNIT_MASK 0x00418890 +#define GPU_GR_GPCS_PRI_MMU_PM_REQ_MASK 0x00418894 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_CTRL 0x004188b0 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_CTRL_DEBUG_MASK 0x00010000 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_CTRL_DEBUG_SHIFT 0x00000010 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_CTRL_DEBUG_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_CTRL_DEBUG_ENABLED_V 0x00000001 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_CTRL_DEBUG_ENABLED_F 0x00010000 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_CTRL_DEBUG_DISABLED_V 0x00000000 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_CTRL_DEBUG_DISABLED_F 0x00000000 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_WR 0x004188b4 +#define GPU_GR_GPCS_PRI_MMU_DEBUG_RD 0x004188b8 +#define GPU_GR_GPCS_MMU_NUM_ACTIVE_LTCS 0x004188ac +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0 0x00419e10 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_DEBUGGER_MODE_SHIFT 0x00000000 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_DEBUGGER_MODE_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_DEBUGGER_MODE_ON_V 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_STOP_TRIGGER_MASK 0x80000000 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_STOP_TRIGGER_SHIFT 0x0000001f +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_STOP_TRIGGER_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_STOP_TRIGGER_ENABLE_F 0x80000000 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_STOP_TRIGGER_DISABLE_F 0x00000000 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_SINGLE_STEP_MODE_MASK 0x00000008 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_SINGLE_STEP_MODE_SHIFT 0x00000003 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_SINGLE_STEP_MODE_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_SINGLE_STEP_MODE_ENABLE_F 0x00000008 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_SINGLE_STEP_MODE_DISABLE_F 0x00000000 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_RUN_TRIGGER_MASK 0x40000000 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_RUN_TRIGGER_SHIFT 0x0000001e +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_RUN_TRIGGER_FIELDMASK 0x00000001 +#define GPU_GR_GPCS_TPCS_SM_DBGR_CONTROL0_RUN_TRIGGER_TASK_F 0x40000000 + +#define GPU_LTC_PLTCG_BASE_V 0x00140000 +#define GPU_LTC_PLTCG_EXTENT_V 0x0017ffff +#define GPU_LTC_LTC0_LTSS_V 0x00140200 +#define GPU_LTC_LTC0_LTS0_V 0x00140400 +#define GPU_LTC_LTCS_LTSS_V 0x0017e200 +#define GPU_LTC_LTCS_LTS0_CBC_CTRL1 0x0014046c +#define GPU_LTC_LTC0_LTS0_DSTG_CFG0 0x00140518 +#define GPU_LTC_LTCS_LTSS_DSTG_CFG0 0x0017e318 +#define GPU_LTC_LTCS_LTSS_DSTG_CFG0_VDC_4TO2_DISABLE_MASK 0x00008000 +#define GPU_LTC_LTCS_LTSS_DSTG_CFG0_VDC_4TO2_DISABLE_SHIFT 0x0000000f +#define GPU_LTC_LTCS_LTSS_DSTG_CFG0_VDC_4TO2_DISABLE_FIELDMASK 0x00000001 +#define GPU_LTC_LTC0_LTS0_TSTG_CFG1 0x00140494 +#define GPU_LTC_LTC0_LTS0_TSTG_CFG1_ACTIVE_WAYS_SHIFT 0x00000000 +#define GPU_LTC_LTC0_LTS0_TSTG_CFG1_ACTIVE_WAYS_FIELDMASK 0x0000ffff +#define GPU_LTC_LTC0_LTS0_TSTG_CFG1_ACTIVE_SETS_SHIFT 0x00000010 +#define GPU_LTC_LTC0_LTS0_TSTG_CFG1_ACTIVE_SETS_FIELDMASK 0x00000003 +#define GPU_LTC_LTC0_LTS0_TSTG_CFG1_ACTIVE_SETS_ALL_V 0x00000000 +#define GPU_LTC_LTC0_LTS0_TSTG_CFG1_ACTIVE_SETS_HALF_V 0x00000001 +#define GPU_LTC_LTC0_LTS0_TSTG_CFG1_ACTIVE_SETS_QUARTER_V 0x00000002 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL1 0x0017e26c +#define GPU_LTC_LTCS_LTSS_CBC_CTRL1_CLEAN_ACTIVE_F 0x00000001 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL1_INVALIDATE_ACTIVE_F 0x00000002 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL1_CLEAR_SHIFT 0x00000002 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL1_CLEAR_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL1_CLEAR_ACTIVE_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL1_CLEAR_ACTIVE_F 0x00000004 +#define GPU_LTC_LTC0_LTS0_CBC_CTRL1 0x0014046c +#define GPU_LTC_LTCS_LTSS_CBC_CTRL2 0x0017e270 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL2_CLEAR_LOWER_BOUND_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL2_CLEAR_LOWER_BOUND_FIELDMASK 0x0001ffff +#define GPU_LTC_LTCS_LTSS_CBC_CTRL3 0x0017e274 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL3_CLEAR_UPPER_BOUND_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_CBC_CTRL3_CLEAR_UPPER_BOUND_FIELDMASK 0x0001ffff +#define GPU_LTC_LTCS_LTSS_CBC_CTRL3_CLEAR_UPPER_BOUND_INIT_V 0x0001ffff +#define GPU_LTC_LTCS_LTSS_CBC_BASE 0x0017e278 +#define GPU_LTC_LTCS_LTSS_CBC_BASE_ALIGNMENT_SHIFT_V 0x0000000b +#define GPU_LTC_LTCS_LTSS_CBC_BASE_ADDRESS_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_CBC_BASE_ADDRESS_FIELDMASK 0x03ffffff +#define GPU_LTC_LTCS_LTSS_CBC_NUM_ACTIVE_LTCS 0x0017e27c +#define GPU_LTC_LTCS_MISC_LTC_NUM_ACTIVE_LTCS 0x0017e000 +#define GPU_LTC_LTCS_LTSS_CBC_PARAM 0x0017e280 +#define GPU_LTC_LTCS_LTSS_CBC_PARAM_COMPTAGS_PER_CACHE_LINE_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_CBC_PARAM_COMPTAGS_PER_CACHE_LINE_FIELDMASK 0x0000ffff +#define GPU_LTC_LTCS_LTSS_CBC_PARAM_CACHE_LINE_SIZE_SHIFT 0x00000018 +#define GPU_LTC_LTCS_LTSS_CBC_PARAM_CACHE_LINE_SIZE_FIELDMASK 0x0000000f +#define GPU_LTC_LTCS_LTSS_CBC_PARAM_SLICES_PER_LTC_SHIFT 0x0000001c +#define GPU_LTC_LTCS_LTSS_CBC_PARAM_SLICES_PER_LTC_FIELDMASK 0x0000000f +#define GPU_LTC_LTCS_LTSS_TSTG_SET_MGMT 0x0017e2ac +#define GPU_LTC_LTCS_LTSS_TSTG_SET_MGMT_MAX_WAYS_EVICT_LAST_SHIFT 0x00000010 +#define GPU_LTC_LTCS_LTSS_TSTG_SET_MGMT_MAX_WAYS_EVICT_LAST_FIELDMASK 0x0000001f +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_INDEX 0x0017e338 +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_INDEX_ADDRESS_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_INDEX_ADDRESS_FIELDMASK 0x0000000f +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_COLOR_CLEAR_VALUE__BASE 0x0017e33c +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_COLOR_CLEAR_VALUE__STRIDE 0x00000004 +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_COLOR_CLEAR_VALUE(i) (0x0017e33c + (i) * 0x00000004) +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_COLOR_CLEAR_VALUE__SIZE_1_V 0x00000004 +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_DEPTH_CLEAR_VALUE 0x0017e34c +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_DEPTH_CLEAR_VALUE_FIELD_SIZE 0x00000020 +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_DEPTH_CLEAR_VALUE_FIELD_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_DEPTH_CLEAR_VALUE_FIELD_FIELDMASK 0xffffffff +#define GPU_LTC_LTCS_LTSS_DSTG_ZBC_DEPTH_CLEAR_VALUE_FIELD_MASK 0xffffffff +#define GPU_LTC_LTCS_LTSS_TSTG_SET_MGMT_2 0x0017e2b0 +#define GPU_LTC_LTCS_LTSS_TSTG_SET_MGMT_2_L2_BYPASS_MODE_ENABLED_F 0x10000000 +#define GPU_LTC_LTCS_LTSS_G_ELPG 0x0017e214 +#define GPU_LTC_LTCS_LTSS_G_ELPG_FLUSH_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_G_ELPG_FLUSH_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_G_ELPG_FLUSH_PENDING_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_G_ELPG_FLUSH_PENDING_F 0x00000001 +#define GPU_LTC_LTC0_LTSS_G_ELPG 0x00140214 +#define GPU_LTC_LTC0_LTSS_G_ELPG_FLUSH_SHIFT 0x00000000 +#define GPU_LTC_LTC0_LTSS_G_ELPG_FLUSH_FIELDMASK 0x00000001 +#define GPU_LTC_LTC0_LTSS_G_ELPG_FLUSH_PENDING_V 0x00000001 +#define GPU_LTC_LTC0_LTSS_G_ELPG_FLUSH_PENDING_F 0x00000001 +#define GPU_LTC_LTC1_LTSS_G_ELPG 0x00142214 +#define GPU_LTC_LTC1_LTSS_G_ELPG_FLUSH_SHIFT 0x00000000 +#define GPU_LTC_LTC1_LTSS_G_ELPG_FLUSH_FIELDMASK 0x00000001 +#define GPU_LTC_LTC1_LTSS_G_ELPG_FLUSH_PENDING_V 0x00000001 +#define GPU_LTC_LTC1_LTSS_G_ELPG_FLUSH_PENDING_F 0x00000001 +#define GPU_LTC_LTCS_LTSS_INTR 0x0017e20c +#define GPU_LTC_LTCS_LTSS_INTR_EN_EVICTED_CB_MASK 0x00100000 +#define GPU_LTC_LTCS_LTSS_INTR_EN_EVICTED_CB_SHIFT 0x00000014 +#define GPU_LTC_LTCS_LTSS_INTR_EN_EVICTED_CB_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_INTR_EN_ILLEGAL_COMPSTAT_ACCESS_MASK 0x40000000 +#define GPU_LTC_LTCS_LTSS_INTR_EN_ILLEGAL_COMPSTAT_ACCESS_SHIFT 0x0000001e +#define GPU_LTC_LTCS_LTSS_INTR_EN_ILLEGAL_COMPSTAT_ACCESS_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_INTR_EN_ILLEGAL_COMPSTAT_MASK 0x00200000 +#define GPU_LTC_LTCS_LTSS_INTR_EN_ILLEGAL_COMPSTAT_SHIFT 0x00000015 +#define GPU_LTC_LTCS_LTSS_INTR_EN_ILLEGAL_COMPSTAT_FIELDMASK 0x00000001 +#define GPU_LTC_LTC0_LTS0_INTR 0x0014040c +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0 0x0017e2a0 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_PENDING_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_PENDING_F 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_MAX_CYCLES_BETWEEN_INVALIDATES_SHIFT 0x00000008 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_MAX_CYCLES_BETWEEN_INVALIDATES_FIELDMASK 0x0000000f +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_MAX_CYCLES_BETWEEN_INVALIDATES_3_V 0x00000003 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_MAX_CYCLES_BETWEEN_INVALIDATES_3_F 0x00000300 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_LAST_CLASS_SHIFT 0x0000001c +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_LAST_CLASS_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_LAST_CLASS_TRUE_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_LAST_CLASS_TRUE_F 0x10000000 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_NORMAL_CLASS_SHIFT 0x0000001d +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_NORMAL_CLASS_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_NORMAL_CLASS_TRUE_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_NORMAL_CLASS_TRUE_F 0x20000000 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_FIRST_CLASS_SHIFT 0x0000001e +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_FIRST_CLASS_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_FIRST_CLASS_TRUE_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT0_INVALIDATE_EVICT_FIRST_CLASS_TRUE_F 0x40000000 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1 0x0017e2a4 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_SHIFT 0x00000000 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_PENDING_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_PENDING_F 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_MAX_CYCLES_BETWEEN_CLEANS_SHIFT 0x00000008 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_MAX_CYCLES_BETWEEN_CLEANS_FIELDMASK 0x0000000f +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_MAX_CYCLES_BETWEEN_CLEANS_3_V 0x00000003 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_MAX_CYCLES_BETWEEN_CLEANS_3_F 0x00000300 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_WAIT_FOR_FB_TO_PULL_SHIFT 0x00000010 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_WAIT_FOR_FB_TO_PULL_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_WAIT_FOR_FB_TO_PULL_TRUE_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_WAIT_FOR_FB_TO_PULL_TRUE_F 0x00010000 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_LAST_CLASS_SHIFT 0x0000001c +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_LAST_CLASS_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_LAST_CLASS_TRUE_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_LAST_CLASS_TRUE_F 0x10000000 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_NORMAL_CLASS_SHIFT 0x0000001d +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_NORMAL_CLASS_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_NORMAL_CLASS_TRUE_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_NORMAL_CLASS_TRUE_F 0x20000000 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_FIRST_CLASS_SHIFT 0x0000001e +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_FIRST_CLASS_FIELDMASK 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_FIRST_CLASS_TRUE_V 0x00000001 +#define GPU_LTC_LTCS_LTSS_TSTG_CMGMT1_CLEAN_EVICT_FIRST_CLASS_TRUE_F 0x40000000 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT0 0x001402a0 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT0_INVALIDATE_SHIFT 0x00000000 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT0_INVALIDATE_FIELDMASK 0x00000001 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT0_INVALIDATE_PENDING_V 0x00000001 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT0_INVALIDATE_PENDING_F 0x00000001 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT1 0x001402a4 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT1_CLEAN_SHIFT 0x00000000 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT1_CLEAN_FIELDMASK 0x00000001 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT1_CLEAN_PENDING_V 0x00000001 +#define GPU_LTC_LTC0_LTSS_TSTG_CMGMT1_CLEAN_PENDING_F 0x00000001 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT0 0x001422a0 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT0_INVALIDATE_SHIFT 0x00000000 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT0_INVALIDATE_FIELDMASK 0x00000001 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT0_INVALIDATE_PENDING_V 0x00000001 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT0_INVALIDATE_PENDING_F 0x00000001 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT1 0x001422a4 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT1_CLEAN_SHIFT 0x00000000 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT1_CLEAN_FIELDMASK 0x00000001 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT1_CLEAN_PENDING_V 0x00000001 +#define GPU_LTC_LTC1_LTSS_TSTG_CMGMT1_CLEAN_PENDING_F 0x00000001 + +#define GPU_MC_BOOT_0 0x00000000 +#define GPU_MC_BOOT_0_ARCHITECTURE_SHIFT 0x00000018 +#define GPU_MC_BOOT_0_ARCHITECTURE_FIELDMASK 0x0000001f +#define GPU_MC_BOOT_0_IMPLEMENTATION_SHIFT 0x00000014 +#define GPU_MC_BOOT_0_IMPLEMENTATION_FIELDMASK 0x0000000f +#define GPU_MC_BOOT_0_MAJOR_REVISION_SHIFT 0x00000004 +#define GPU_MC_BOOT_0_MAJOR_REVISION_FIELDMASK 0x0000000f +#define GPU_MC_BOOT_0_MINOR_REVISION_SHIFT 0x00000000 +#define GPU_MC_BOOT_0_MINOR_REVISION_FIELDMASK 0x0000000f +#define GPU_MC_INTR__BASE 0x00000100 +#define GPU_MC_INTR__STRIDE 0x00000004 +#define GPU_MC_INTR(i) (0x00000100 + (i) * 0x00000004) +#define GPU_MC_INTR_PFIFO_PENDING_F 0x00000100 +#define GPU_MC_INTR_PMU_PENDING_F 0x01000000 +#define GPU_MC_INTR_LTC_PENDING_F 0x02000000 +#define GPU_MC_INTR_PRIV_RING_PENDING_F 0x40000000 +#define GPU_MC_INTR_PBUS_PENDING_F 0x10000000 +#define GPU_MC_INTR_MASK_0 0x00000640 +#define GPU_MC_INTR_MASK_0_PMU_ENABLED_F 0x01000000 +#define GPU_MC_INTR_EN_0 0x00000140 +#define GPU_MC_INTR_EN_0_INTA_DISABLED_F 0x00000000 +#define GPU_MC_INTR_EN_0_INTA_HARDWARE_F 0x00000001 +#define GPU_MC_INTR_MASK_1 0x00000644 +#define GPU_MC_INTR_MASK_1_PMU_SIZE 0x00000001 +#define GPU_MC_INTR_MASK_1_PMU_SHIFT 0x00000018 +#define GPU_MC_INTR_MASK_1_PMU_FIELDMASK 0x00000001 +#define GPU_MC_INTR_MASK_1_PMU_MASK 0x01000000 +#define GPU_MC_INTR_MASK_1_PMU_ENABLED_F 0x01000000 +#define GPU_MC_INTR_EN_1 0x00000144 +#define GPU_MC_INTR_EN_1_INTA_DISABLED_F 0x00000000 +#define GPU_MC_INTR_EN_1_INTA_HARDWARE_F 0x00000001 +#define GPU_MC_ENABLE 0x00000200 +#define GPU_MC_ENABLE_XBAR_ENABLED_F 0x00000004 +#define GPU_MC_ENABLE_L2_ENABLED_F 0x00000008 +#define GPU_MC_ENABLE_PMEDIA_SIZE 0x00000001 +#define GPU_MC_ENABLE_PMEDIA_SHIFT 0x00000004 +#define GPU_MC_ENABLE_PMEDIA_FIELDMASK 0x00000001 +#define GPU_MC_ENABLE_PMEDIA_MASK 0x00000010 +#define GPU_MC_ENABLE_PRIV_RING_ENABLED_F 0x00000020 +#define GPU_MC_ENABLE_CE0_MASK 0x00000040 +#define GPU_MC_ENABLE_CE0_SHIFT 0x00000006 +#define GPU_MC_ENABLE_CE0_FIELDMASK 0x00000001 +#define GPU_MC_ENABLE_PFIFO_ENABLED_F 0x00000100 +#define GPU_MC_ENABLE_PGRAPH_ENABLED_F 0x00001000 +#define GPU_MC_ENABLE_PWR_SHIFT 0x0000000d +#define GPU_MC_ENABLE_PWR_FIELDMASK 0x00000001 +#define GPU_MC_ENABLE_PWR_DISABLED_V 0x00000000 +#define GPU_MC_ENABLE_PWR_ENABLED_F 0x00002000 +#define GPU_MC_ENABLE_PFB_ENABLED_F 0x00100000 +#define GPU_MC_ENABLE_CE2_MASK 0x00200000 +#define GPU_MC_ENABLE_CE2_SHIFT 0x00000015 +#define GPU_MC_ENABLE_CE2_FIELDMASK 0x00000001 +#define GPU_MC_ENABLE_CE2_ENABLED_F 0x00200000 +#define GPU_MC_ENABLE_BLG_ENABLED_F 0x08000000 +#define GPU_MC_ENABLE_PERFMON_ENABLED_F 0x10000000 +#define GPU_MC_ENABLE_HUB_ENABLED_F 0x20000000 +#define GPU_MC_INTR_LTC 0x0000017c +#define GPU_MC_ENABLE_PB 0x00000204 +#define GPU_MC_ENABLE_PB_0_SIZE 0x00000001 +#define GPU_MC_ENABLE_PB_0_SHIFT 0x00000000 +#define GPU_MC_ENABLE_PB_0_FIELDMASK 0x00000001 +#define GPU_MC_ENABLE_PB_0_MASK 0x00000001 +#define GPU_MC_ENABLE_PB_0_ENABLED_V 0x00000001 +#define GPU_MC_ENABLE_PB_SEL_FIELDMASK 0x00000001 +#define GPU_MC_ENABLE_PB_SEL__SHIFT_BASE 0x00000000 +#define GPU_MC_ENABLE_PB_SEL__SHIFT_STRIDE 0x00000001 +#define GPU_MC_ENABLE_PB_SEL__SHIFT_I(i) (0 + (i) * 1) +#define GPU_MC_ELPG_ENABLE 0x0000020c +#define GPU_MC_ELPG_ENABLE_XBAR_ENABLED_F 0x00000004 +#define GPU_MC_ELPG_ENABLE_PFB_ENABLED_F 0x00100000 +#define GPU_MC_ELPG_ENABLE_HUB_ENABLED_F 0x20000000 + +#define GPU_PBDMA_GP_ENTRY1 0x10000004 +#define GPU_PBDMA_GP_ENTRY1_GET_HI_SHIFT 0x00000000 +#define GPU_PBDMA_GP_ENTRY1_GET_HI_FIELDMASK 0x000000ff +#define GPU_PBDMA_GP_ENTRY1_LENGTH_SHIFT 0x0000000a +#define GPU_PBDMA_GP_ENTRY1_LENGTH_FIELDMASK 0x001fffff +#define GPU_PBDMA_GP_BASE__BASE 0x00040048 +#define GPU_PBDMA_GP_BASE__STRIDE 0x00002000 +#define GPU_PBDMA_GP_BASE(i) (0x00040048 + (i) * 0x00002000) +#define GPU_PBDMA_GP_BASE__SIZE_1_V 0x00000001 +#define GPU_PBDMA_GP_BASE_OFFSET_SHIFT 0x00000003 +#define GPU_PBDMA_GP_BASE_OFFSET_FIELDMASK 0x1fffffff +#define GPU_PBDMA_GP_BASE_RSVD_SIZE 0x00000003 +#define GPU_PBDMA_GP_BASE_HI__BASE 0x0004004c +#define GPU_PBDMA_GP_BASE_HI__STRIDE 0x00002000 +#define GPU_PBDMA_GP_BASE_HI(i) (0x0004004c + (i) * 0x00002000) +#define GPU_PBDMA_GP_BASE_HI_OFFSET_SHIFT 0x00000000 +#define GPU_PBDMA_GP_BASE_HI_OFFSET_FIELDMASK 0x000000ff +#define GPU_PBDMA_GP_BASE_HI_LIMIT2_SHIFT 0x00000010 +#define GPU_PBDMA_GP_BASE_HI_LIMIT2_FIELDMASK 0x0000001f +#define GPU_PBDMA_GP_FETCH__BASE 0x00040050 +#define GPU_PBDMA_GP_FETCH__STRIDE 0x00002000 +#define GPU_PBDMA_GP_FETCH(i) (0x00040050 + (i) * 0x00002000) +#define GPU_PBDMA_GP_GET__BASE 0x00040014 +#define GPU_PBDMA_GP_GET__STRIDE 0x00002000 +#define GPU_PBDMA_GP_GET(i) (0x00040014 + (i) * 0x00002000) +#define GPU_PBDMA_GP_PUT__BASE 0x00040000 +#define GPU_PBDMA_GP_PUT__STRIDE 0x00002000 +#define GPU_PBDMA_GP_PUT(i) (0x00040000 + (i) * 0x00002000) +#define GPU_PBDMA_PB_FETCH__BASE 0x00040054 +#define GPU_PBDMA_PB_FETCH__STRIDE 0x00002000 +#define GPU_PBDMA_PB_FETCH(i) (0x00040054 + (i) * 0x00002000) +#define GPU_PBDMA_PB_FETCH_HI__BASE 0x00040058 +#define GPU_PBDMA_PB_FETCH_HI__STRIDE 0x00002000 +#define GPU_PBDMA_PB_FETCH_HI(i) (0x00040058 + (i) * 0x00002000) +#define GPU_PBDMA_GET__BASE 0x00040018 +#define GPU_PBDMA_GET__STRIDE 0x00002000 +#define GPU_PBDMA_GET(i) (0x00040018 + (i) * 0x00002000) +#define GPU_PBDMA_GET_HI__BASE 0x0004001c +#define GPU_PBDMA_GET_HI__STRIDE 0x00002000 +#define GPU_PBDMA_GET_HI(i) (0x0004001c + (i) * 0x00002000) +#define GPU_PBDMA_PUT__BASE 0x0004005c +#define GPU_PBDMA_PUT__STRIDE 0x00002000 +#define GPU_PBDMA_PUT(i) (0x0004005c + (i) * 0x00002000) +#define GPU_PBDMA_PUT_HI__BASE 0x00040060 +#define GPU_PBDMA_PUT_HI__STRIDE 0x00002000 +#define GPU_PBDMA_PUT_HI(i) (0x00040060 + (i) * 0x00002000) +#define GPU_PBDMA_FORMATS__BASE 0x0004009c +#define GPU_PBDMA_FORMATS__STRIDE 0x00002000 +#define GPU_PBDMA_FORMATS(i) (0x0004009c + (i) * 0x00002000) +#define GPU_PBDMA_FORMATS_GP_FERMI0_F 0x00000000 +#define GPU_PBDMA_FORMATS_PB_FERMI1_F 0x00000100 +#define GPU_PBDMA_FORMATS_MP_FERMI0_F 0x00000000 +#define GPU_PBDMA_PB_HEADER__BASE 0x00040084 +#define GPU_PBDMA_PB_HEADER__STRIDE 0x00002000 +#define GPU_PBDMA_PB_HEADER(i) (0x00040084 + (i) * 0x00002000) +#define GPU_PBDMA_PB_HEADER_PRIV_USER_F 0x00000000 +#define GPU_PBDMA_PB_HEADER_METHOD_ZERO_F 0x00000000 +#define GPU_PBDMA_PB_HEADER_SUBCHANNEL_ZERO_F 0x00000000 +#define GPU_PBDMA_PB_HEADER_LEVEL_MAIN_F 0x00000000 +#define GPU_PBDMA_PB_HEADER_FIRST_TRUE_F 0x00400000 +#define GPU_PBDMA_PB_HEADER_TYPE_INC_F 0x20000000 +#define GPU_PBDMA_PB_HEADER_TYPE_NON_INC_F 0x60000000 +#define GPU_PBDMA_HDR_SHADOW__BASE 0x00040118 +#define GPU_PBDMA_HDR_SHADOW__STRIDE 0x00002000 +#define GPU_PBDMA_HDR_SHADOW(i) (0x00040118 + (i) * 0x00002000) +#define GPU_PBDMA_SUBDEVICE__BASE 0x00040094 +#define GPU_PBDMA_SUBDEVICE__STRIDE 0x00002000 +#define GPU_PBDMA_SUBDEVICE(i) (0x00040094 + (i) * 0x00002000) +#define GPU_PBDMA_SUBDEVICE_ID_SHIFT 0x00000000 +#define GPU_PBDMA_SUBDEVICE_ID_FIELDMASK 0x00000fff +#define GPU_PBDMA_SUBDEVICE_STATUS_ACTIVE_F 0x10000000 +#define GPU_PBDMA_SUBDEVICE_CHANNEL_DMA_ENABLE_F 0x20000000 +#define GPU_PBDMA_METHOD0__BASE 0x000400c0 +#define GPU_PBDMA_METHOD0__STRIDE 0x00002000 +#define GPU_PBDMA_METHOD0(i) (0x000400c0 + (i) * 0x00002000) +#define GPU_PBDMA_METHOD0_FIFO_SIZE_V 0x00000004 +#define GPU_PBDMA_METHOD0_ADDR_SHIFT 0x00000002 +#define GPU_PBDMA_METHOD0_ADDR_FIELDMASK 0x00000fff +#define GPU_PBDMA_METHOD0_SUBCH_SHIFT 0x00000010 +#define GPU_PBDMA_METHOD0_SUBCH_FIELDMASK 0x00000007 +#define GPU_PBDMA_METHOD0_FIRST_TRUE_F 0x00400000 +#define GPU_PBDMA_METHOD0_VALID_TRUE_F 0x80000000 +#define GPU_PBDMA_METHOD1__BASE 0x000400c8 +#define GPU_PBDMA_METHOD1__STRIDE 0x00002000 +#define GPU_PBDMA_METHOD1(i) (0x000400c8 + (i) * 0x00002000) +#define GPU_PBDMA_METHOD2__BASE 0x000400d0 +#define GPU_PBDMA_METHOD2__STRIDE 0x00002000 +#define GPU_PBDMA_METHOD2(i) (0x000400d0 + (i) * 0x00002000) +#define GPU_PBDMA_METHOD3__BASE 0x000400d8 +#define GPU_PBDMA_METHOD3__STRIDE 0x00002000 +#define GPU_PBDMA_METHOD3(i) (0x000400d8 + (i) * 0x00002000) +#define GPU_PBDMA_DATA0__BASE 0x000400c4 +#define GPU_PBDMA_DATA0__STRIDE 0x00002000 +#define GPU_PBDMA_DATA0(i) (0x000400c4 + (i) * 0x00002000) +#define GPU_PBDMA_TARGET__BASE 0x000400ac +#define GPU_PBDMA_TARGET__STRIDE 0x00002000 +#define GPU_PBDMA_TARGET(i) (0x000400ac + (i) * 0x00002000) +#define GPU_PBDMA_TARGET_ENGINE_SW_F 0x0000001f +#define GPU_PBDMA_ACQUIRE__BASE 0x00040030 +#define GPU_PBDMA_ACQUIRE__STRIDE 0x00002000 +#define GPU_PBDMA_ACQUIRE(i) (0x00040030 + (i) * 0x00002000) +#define GPU_PBDMA_ACQUIRE_RETRY_MAN_2_F 0x00000002 +#define GPU_PBDMA_ACQUIRE_RETRY_EXP_2_F 0x00000100 +#define GPU_PBDMA_ACQUIRE_TIMEOUT_EXP_SHIFT 0x0000000b +#define GPU_PBDMA_ACQUIRE_TIMEOUT_EXP_FIELDMASK 0x0000000f +#define GPU_PBDMA_ACQUIRE_TIMEOUT_EXP_MAX_V 0x0000000f +#define GPU_PBDMA_ACQUIRE_TIMEOUT_EXP_MAX_F 0x00007800 +#define GPU_PBDMA_ACQUIRE_TIMEOUT_MAN_SHIFT 0x0000000f +#define GPU_PBDMA_ACQUIRE_TIMEOUT_MAN_FIELDMASK 0x0000ffff +#define GPU_PBDMA_ACQUIRE_TIMEOUT_MAN_MAX_V 0x0000ffff +#define GPU_PBDMA_ACQUIRE_TIMEOUT_MAN_MAX_F 0x7fff8000 +#define GPU_PBDMA_ACQUIRE_TIMEOUT_EN_ENABLE_F 0x80000000 +#define GPU_PBDMA_ACQUIRE_TIMEOUT_EN_DISABLE_F 0x00000000 +#define GPU_PBDMA_STATUS__BASE 0x00040100 +#define GPU_PBDMA_STATUS__STRIDE 0x00002000 +#define GPU_PBDMA_STATUS(i) (0x00040100 + (i) * 0x00002000) +#define GPU_PBDMA_CHANNEL__BASE 0x00040120 +#define GPU_PBDMA_CHANNEL__STRIDE 0x00002000 +#define GPU_PBDMA_CHANNEL(i) (0x00040120 + (i) * 0x00002000) +#define GPU_PBDMA_SIGNATURE__BASE 0x00040010 +#define GPU_PBDMA_SIGNATURE__STRIDE 0x00002000 +#define GPU_PBDMA_SIGNATURE(i) (0x00040010 + (i) * 0x00002000) +#define GPU_PBDMA_SIGNATURE_HW_VALID_F 0x0000face +#define GPU_PBDMA_SIGNATURE_SW_ZERO_F 0x00000000 +#define GPU_PBDMA_USERD__BASE 0x00040008 +#define GPU_PBDMA_USERD__STRIDE 0x00002000 +#define GPU_PBDMA_USERD(i) (0x00040008 + (i) * 0x00002000) +#define GPU_PBDMA_USERD_TARGET_VID_MEM_F 0x00000000 +#define GPU_PBDMA_USERD_TARGET_SYS_MEM_COH_F 0x00000002 +#define GPU_PBDMA_USERD_TARGET_SYS_MEM_NCOH_F 0x00000003 +#define GPU_PBDMA_USERD_ADDR_SHIFT 0x00000009 +#define GPU_PBDMA_USERD_ADDR_FIELDMASK 0x007fffff +#define GPU_PBDMA_USERD_HI__BASE 0x0004000c +#define GPU_PBDMA_USERD_HI__STRIDE 0x00002000 +#define GPU_PBDMA_USERD_HI(i) (0x0004000c + (i) * 0x00002000) +#define GPU_PBDMA_USERD_HI_ADDR_SHIFT 0x00000000 +#define GPU_PBDMA_USERD_HI_ADDR_FIELDMASK 0x000000ff +#define GPU_PBDMA_HCE_CTRL__BASE 0x000400e4 +#define GPU_PBDMA_HCE_CTRL__STRIDE 0x00002000 +#define GPU_PBDMA_HCE_CTRL(i) (0x000400e4 + (i) * 0x00002000) +#define GPU_PBDMA_HCE_CTRL_HCE_PRIV_MODE_YES_F 0x00000020 +#define GPU_PBDMA_INTR_0__BASE 0x00040108 +#define GPU_PBDMA_INTR_0__STRIDE 0x00002000 +#define GPU_PBDMA_INTR_0(i) (0x00040108 + (i) * 0x00002000) +#define GPU_PBDMA_INTR_0_MEMREQ_SHIFT 0x00000000 +#define GPU_PBDMA_INTR_0_MEMREQ_FIELDMASK 0x00000001 +#define GPU_PBDMA_INTR_0_MEMREQ_PENDING_F 0x00000001 +#define GPU_PBDMA_INTR_0_MEMACK_TIMEOUT_PENDING_F 0x00000002 +#define GPU_PBDMA_INTR_0_MEMACK_EXTRA_PENDING_F 0x00000004 +#define GPU_PBDMA_INTR_0_MEMDAT_TIMEOUT_PENDING_F 0x00000008 +#define GPU_PBDMA_INTR_0_MEMDAT_EXTRA_PENDING_F 0x00000010 +#define GPU_PBDMA_INTR_0_MEMFLUSH_PENDING_F 0x00000020 +#define GPU_PBDMA_INTR_0_MEMOP_PENDING_F 0x00000040 +#define GPU_PBDMA_INTR_0_LBCONNECT_PENDING_F 0x00000080 +#define GPU_PBDMA_INTR_0_LBREQ_PENDING_F 0x00000100 +#define GPU_PBDMA_INTR_0_LBACK_TIMEOUT_PENDING_F 0x00000200 +#define GPU_PBDMA_INTR_0_LBACK_EXTRA_PENDING_F 0x00000400 +#define GPU_PBDMA_INTR_0_LBDAT_TIMEOUT_PENDING_F 0x00000800 +#define GPU_PBDMA_INTR_0_LBDAT_EXTRA_PENDING_F 0x00001000 +#define GPU_PBDMA_INTR_0_GPFIFO_PENDING_F 0x00002000 +#define GPU_PBDMA_INTR_0_GPPTR_PENDING_F 0x00004000 +#define GPU_PBDMA_INTR_0_GPENTRY_PENDING_F 0x00008000 +#define GPU_PBDMA_INTR_0_GPCRC_PENDING_F 0x00010000 +#define GPU_PBDMA_INTR_0_PBPTR_PENDING_F 0x00020000 +#define GPU_PBDMA_INTR_0_PBENTRY_PENDING_F 0x00040000 +#define GPU_PBDMA_INTR_0_PBCRC_PENDING_F 0x00080000 +#define GPU_PBDMA_INTR_0_XBARCONNECT_PENDING_F 0x00100000 +#define GPU_PBDMA_INTR_0_METHOD_PENDING_F 0x00200000 +#define GPU_PBDMA_INTR_0_METHODCRC_PENDING_F 0x00400000 +#define GPU_PBDMA_INTR_0_DEVICE_PENDING_F 0x00800000 +#define GPU_PBDMA_INTR_0_SEMAPHORE_PENDING_F 0x02000000 +#define GPU_PBDMA_INTR_0_ACQUIRE_PENDING_F 0x04000000 +#define GPU_PBDMA_INTR_0_PRI_PENDING_F 0x08000000 +#define GPU_PBDMA_INTR_0_NO_CTXSW_SEG_PENDING_F 0x20000000 +#define GPU_PBDMA_INTR_0_PBSEG_PENDING_F 0x40000000 +#define GPU_PBDMA_INTR_0_SIGNATURE_PENDING_F 0x80000000 +#define GPU_PBDMA_INTR_1__BASE 0x00040148 +#define GPU_PBDMA_INTR_1__STRIDE 0x00002000 +#define GPU_PBDMA_INTR_1(i) (0x00040148 + (i) * 0x00002000) +#define GPU_PBDMA_INTR_EN_0__BASE 0x0004010c +#define GPU_PBDMA_INTR_EN_0__STRIDE 0x00002000 +#define GPU_PBDMA_INTR_EN_0(i) (0x0004010c + (i) * 0x00002000) +#define GPU_PBDMA_INTR_EN_0_LBREQ_ENABLED_F 0x00000100 +#define GPU_PBDMA_INTR_EN_1__BASE 0x0004014c +#define GPU_PBDMA_INTR_EN_1__STRIDE 0x00002000 +#define GPU_PBDMA_INTR_EN_1(i) (0x0004014c + (i) * 0x00002000) +#define GPU_PBDMA_INTR_STALL__BASE 0x0004013c +#define GPU_PBDMA_INTR_STALL__STRIDE 0x00002000 +#define GPU_PBDMA_INTR_STALL(i) (0x0004013c + (i) * 0x00002000) +#define GPU_PBDMA_INTR_STALL_LBREQ_ENABLED_F 0x00000100 +#define GPU_PBDMA_UDMA_NOP 0x00000008 +#define GPU_PBDMA_SYNCPOINTA__BASE 0x000400a4 +#define GPU_PBDMA_SYNCPOINTA__STRIDE 0x00002000 +#define GPU_PBDMA_SYNCPOINTA(i) (0x000400a4 + (i) * 0x00002000) +#define GPU_PBDMA_SYNCPOINTA_PAYLOAD_SHIFT 0x00000000 +#define GPU_PBDMA_SYNCPOINTA_PAYLOAD_FIELDMASK 0xffffffff +#define GPU_PBDMA_SYNCPOINTB__BASE 0x000400a8 +#define GPU_PBDMA_SYNCPOINTB__STRIDE 0x00002000 +#define GPU_PBDMA_SYNCPOINTB(i) (0x000400a8 + (i) * 0x00002000) +#define GPU_PBDMA_SYNCPOINTB_OP_SHIFT 0x00000000 +#define GPU_PBDMA_SYNCPOINTB_OP_FIELDMASK 0x00000003 +#define GPU_PBDMA_SYNCPOINTB_OP_WAIT_V 0x00000000 +#define GPU_PBDMA_SYNCPOINTB_WAIT_SWITCH_SHIFT 0x00000004 +#define GPU_PBDMA_SYNCPOINTB_WAIT_SWITCH_FIELDMASK 0x00000001 +#define GPU_PBDMA_SYNCPOINTB_WAIT_SWITCH_EN_V 0x00000001 +#define GPU_PBDMA_SYNCPOINTB_SYNCPT_INDEX_SHIFT 0x00000008 +#define GPU_PBDMA_SYNCPOINTB_SYNCPT_INDEX_FIELDMASK 0x000000ff +#define GPU_PBDMA_RUNLIST_TIMESLICE__BASE 0x000400f8 +#define GPU_PBDMA_RUNLIST_TIMESLICE__STRIDE 0x00002000 +#define GPU_PBDMA_RUNLIST_TIMESLICE(i) (0x000400f8 + (i) * 0x00002000) +#define GPU_PBDMA_RUNLIST_TIMESLICE_TIMEOUT_128_F 0x00000080 +#define GPU_PBDMA_RUNLIST_TIMESLICE_TIMESCALE_3_F 0x00003000 +#define GPU_PBDMA_RUNLIST_TIMESLICE_ENABLE_TRUE_F 0x10000000 + +#define GPU_PERF_PMASYS_CONTROL 0x001b4000 +#define GPU_PERF_PMASYS_CONTROL_MEMBUF_STATUS_SHIFT 0x00000004 +#define GPU_PERF_PMASYS_CONTROL_MEMBUF_STATUS_FIELDMASK 0x00000001 +#define GPU_PERF_PMASYS_CONTROL_MEMBUF_STATUS_OVERFLOWED_V 0x00000001 +#define GPU_PERF_PMASYS_CONTROL_MEMBUF_STATUS_OVERFLOWED_F 0x00000010 +#define GPU_PERF_PMASYS_CONTROL_MEMBUF_CLEAR_STATUS_SHIFT 0x00000005 +#define GPU_PERF_PMASYS_CONTROL_MEMBUF_CLEAR_STATUS_FIELDMASK 0x00000001 +#define GPU_PERF_PMASYS_CONTROL_MEMBUF_CLEAR_STATUS_DOIT_V 0x00000001 +#define GPU_PERF_PMASYS_CONTROL_MEMBUF_CLEAR_STATUS_DOIT_F 0x00000020 +#define GPU_PERF_PMASYS_MEM_BLOCK 0x001b4070 +#define GPU_PERF_PMASYS_MEM_BLOCK_BASE_SHIFT 0x00000000 +#define GPU_PERF_PMASYS_MEM_BLOCK_BASE_FIELDMASK 0x0fffffff +#define GPU_PERF_PMASYS_MEM_BLOCK_TARGET_SHIFT 0x0000001c +#define GPU_PERF_PMASYS_MEM_BLOCK_TARGET_FIELDMASK 0x00000003 +#define GPU_PERF_PMASYS_MEM_BLOCK_TARGET_LFB_V 0x00000000 +#define GPU_PERF_PMASYS_MEM_BLOCK_TARGET_LFB_F 0x00000000 +#define GPU_PERF_PMASYS_MEM_BLOCK_TARGET_SYS_COH_V 0x00000002 +#define GPU_PERF_PMASYS_MEM_BLOCK_TARGET_SYS_COH_F 0x20000000 +#define GPU_PERF_PMASYS_MEM_BLOCK_TARGET_SYS_NCOH_V 0x00000003 +#define GPU_PERF_PMASYS_MEM_BLOCK_TARGET_SYS_NCOH_F 0x30000000 +#define GPU_PERF_PMASYS_MEM_BLOCK_VALID_SHIFT 0x0000001f +#define GPU_PERF_PMASYS_MEM_BLOCK_VALID_FIELDMASK 0x00000001 +#define GPU_PERF_PMASYS_MEM_BLOCK_VALID_TRUE_V 0x00000001 +#define GPU_PERF_PMASYS_MEM_BLOCK_VALID_TRUE_F 0x80000000 +#define GPU_PERF_PMASYS_MEM_BLOCK_VALID_FALSE_V 0x00000000 +#define GPU_PERF_PMASYS_MEM_BLOCK_VALID_FALSE_F 0x00000000 +#define GPU_PERF_PMASYS_OUTBASE 0x001b4074 +#define GPU_PERF_PMASYS_OUTBASE_PTR_SHIFT 0x00000005 +#define GPU_PERF_PMASYS_OUTBASE_PTR_FIELDMASK 0x07ffffff +#define GPU_PERF_PMASYS_OUTBASEUPPER 0x001b4078 +#define GPU_PERF_PMASYS_OUTBASEUPPER_PTR_SHIFT 0x00000000 +#define GPU_PERF_PMASYS_OUTBASEUPPER_PTR_FIELDMASK 0x000000ff +#define GPU_PERF_PMASYS_OUTSIZE 0x001b407c +#define GPU_PERF_PMASYS_OUTSIZE_NUMBYTES_SHIFT 0x00000005 +#define GPU_PERF_PMASYS_OUTSIZE_NUMBYTES_FIELDMASK 0x07ffffff +#define GPU_PERF_PMASYS_MEM_BYTES 0x001b4084 +#define GPU_PERF_PMASYS_MEM_BYTES_NUMBYTES_SHIFT 0x00000004 +#define GPU_PERF_PMASYS_MEM_BYTES_NUMBYTES_FIELDMASK 0x0fffffff +#define GPU_PERF_PMASYS_MEM_BUMP 0x001b4088 +#define GPU_PERF_PMASYS_MEM_BUMP_NUMBYTES_SHIFT 0x00000004 +#define GPU_PERF_PMASYS_MEM_BUMP_NUMBYTES_FIELDMASK 0x0fffffff +#define GPU_PERF_PMASYS_ENGINESTATUS 0x001b40a4 +#define GPU_PERF_PMASYS_ENGINESTATUS_RBUFEMPTY_SHIFT 0x00000004 +#define GPU_PERF_PMASYS_ENGINESTATUS_RBUFEMPTY_FIELDMASK 0x00000001 +#define GPU_PERF_PMASYS_ENGINESTATUS_RBUFEMPTY_EMPTY_V 0x00000001 +#define GPU_PERF_PMASYS_ENGINESTATUS_RBUFEMPTY_EMPTY_F 0x00000010 + +#define GPU_PRAM_DATA032__BASE 0x00700000 +#define GPU_PRAM_DATA032__STRIDE 0x00000004 +#define GPU_PRAM_DATA032(i) (0x00700000 + (i) * 0x00000004) + +#define GPU_PRI_RINGMASTER_COMMAND 0x0012004c +#define GPU_PRI_RINGMASTER_COMMAND_CMD_MASK 0x0000003f +#define GPU_PRI_RINGMASTER_COMMAND_CMD_SHIFT 0x00000000 +#define GPU_PRI_RINGMASTER_COMMAND_CMD_FIELDMASK 0x0000003f +#define GPU_PRI_RINGMASTER_COMMAND_CMD_NO_CMD_V 0x00000000 +#define GPU_PRI_RINGMASTER_COMMAND_CMD_START_RING_F 0x00000001 +#define GPU_PRI_RINGMASTER_COMMAND_CMD_ACK_INTERRUPT_F 0x00000002 +#define GPU_PRI_RINGMASTER_COMMAND_CMD_ENUMERATE_STATIONS_F 0x00000003 +#define GPU_PRI_RINGMASTER_COMMAND_CMD_ENUMERATE_STATIONS_BC_GRP_ALL_F 0x00000000 +#define GPU_PRI_RINGMASTER_COMMAND_DATA 0x00120048 +#define GPU_PRI_RINGMASTER_START_RESULTS 0x00120050 +#define GPU_PRI_RINGMASTER_START_RESULTS_CONNECTIVITY_SHIFT 0x00000000 +#define GPU_PRI_RINGMASTER_START_RESULTS_CONNECTIVITY_FIELDMASK 0x00000001 +#define GPU_PRI_RINGMASTER_START_RESULTS_CONNECTIVITY_PASS_V 0x00000001 +#define GPU_PRI_RINGMASTER_INTR_STATUS0 0x00120058 +#define GPU_PRI_RINGMASTER_INTR_STATUS0_RING_START_CONN_FAULT_SHIFT 0x00000000 +#define GPU_PRI_RINGMASTER_INTR_STATUS0_RING_START_CONN_FAULT_FIELDMASK 0x00000001 +#define GPU_PRI_RINGMASTER_INTR_STATUS0_DISCONNECT_FAULT_SHIFT 0x00000001 +#define GPU_PRI_RINGMASTER_INTR_STATUS0_DISCONNECT_FAULT_FIELDMASK 0x00000001 +#define GPU_PRI_RINGMASTER_INTR_STATUS0_OVERFLOW_FAULT_SHIFT 0x00000002 +#define GPU_PRI_RINGMASTER_INTR_STATUS0_OVERFLOW_FAULT_FIELDMASK 0x00000001 +#define GPU_PRI_RINGMASTER_INTR_STATUS0_GBL_WRITE_ERROR_SYS_SHIFT 0x00000008 +#define GPU_PRI_RINGMASTER_INTR_STATUS0_GBL_WRITE_ERROR_SYS_FIELDMASK 0x00000001 +#define GPU_PRI_RINGMASTER_INTR_STATUS1 0x0012005c +#define GPU_PRI_RINGMASTER_GLOBAL_CTL 0x00120060 +#define GPU_PRI_RINGMASTER_GLOBAL_CTL_RING_RESET_ASSERTED_F 0x00000001 +#define GPU_PRI_RINGMASTER_GLOBAL_CTL_RING_RESET_DEASSERTED_F 0x00000000 +#define GPU_PRI_RINGMASTER_ENUM_FBP 0x00120074 +#define GPU_PRI_RINGMASTER_ENUM_FBP_COUNT_SHIFT 0x00000000 +#define GPU_PRI_RINGMASTER_ENUM_FBP_COUNT_FIELDMASK 0x0000001f +#define GPU_PRI_RINGMASTER_ENUM_GPC 0x00120078 +#define GPU_PRI_RINGMASTER_ENUM_GPC_COUNT_SHIFT 0x00000000 +#define GPU_PRI_RINGMASTER_ENUM_GPC_COUNT_FIELDMASK 0x0000001f +#define GPU_PRI_RINGMASTER_ENUM_LTC 0x0012006c +#define GPU_PRI_RINGMASTER_ENUM_LTC_COUNT_SHIFT 0x00000000 +#define GPU_PRI_RINGMASTER_ENUM_LTC_COUNT_FIELDMASK 0x0000001f + +#define GPU_PRI_RINGSTATION_GPC_MASTER_CONFIG__BASE 0x00128300 +#define GPU_PRI_RINGSTATION_GPC_MASTER_CONFIG__STRIDE 0x00000004 +#define GPU_PRI_RINGSTATION_GPC_MASTER_CONFIG(i) (0x00128300 + (i) * 0x00000004) +#define GPU_PRI_RINGSTATION_GPC_GPC0_PRIV_ERROR_ADR 0x00128120 +#define GPU_PRI_RINGSTATION_GPC_GPC0_PRIV_ERROR_WRDAT 0x00128124 +#define GPU_PRI_RINGSTATION_GPC_GPC0_PRIV_ERROR_INFO 0x00128128 +#define GPU_PRI_RINGSTATION_GPC_GPC0_PRIV_ERROR_CODE 0x0012812c + +#define GPU_PRI_RINGSTATION_SYS_MASTER_CONFIG__BASE 0x00122300 +#define GPU_PRI_RINGSTATION_SYS_MASTER_CONFIG__STRIDE 0x00000004 +#define GPU_PRI_RINGSTATION_SYS_MASTER_CONFIG(i) (0x00122300 + (i) * 0x00000004) +#define GPU_PRI_RINGSTATION_SYS_DECODE_CONFIG 0x00122204 +#define GPU_PRI_RINGSTATION_SYS_DECODE_CONFIG_RING_MASK 0x00000007 +#define GPU_PRI_RINGSTATION_SYS_DECODE_CONFIG_RING_SHIFT 0x00000000 +#define GPU_PRI_RINGSTATION_SYS_DECODE_CONFIG_RING_FIELDMASK 0x00000007 +#define GPU_PRI_RINGSTATION_SYS_DECODE_CONFIG_RING_DROP_ON_RING_NOT_STARTED_F 0x00000001 +#define GPU_PRI_RINGSTATION_SYS_PRIV_ERROR_ADR 0x00122120 +#define GPU_PRI_RINGSTATION_SYS_PRIV_ERROR_WRDAT 0x00122124 +#define GPU_PRI_RINGSTATION_SYS_PRIV_ERROR_INFO 0x00122128 +#define GPU_PRI_RINGSTATION_SYS_PRIV_ERROR_CODE 0x0012212c + +#define GPU_PROJ_GPC_BASE_V 0x00500000 +#define GPU_PROJ_GPC_SHARED_BASE_V 0x00418000 +#define GPU_PROJ_GPC_STRIDE_V 0x00008000 +#define GPU_PROJ_LTC_STRIDE_V 0x00002000 +#define GPU_PROJ_LTS_STRIDE_V 0x00000200 +#define GPU_PROJ_FBPA_STRIDE_V 0x00001000 +#define GPU_PROJ_PPC_IN_GPC_BASE_V 0x00003000 +#define GPU_PROJ_PPC_IN_GPC_SHARED_BASE_V 0x00003e00 +#define GPU_PROJ_PPC_IN_GPC_STRIDE_V 0x00000200 +#define GPU_PROJ_ROP_BASE_V 0x00410000 +#define GPU_PROJ_ROP_SHARED_BASE_V 0x00408800 +#define GPU_PROJ_ROP_STRIDE_V 0x00000400 +#define GPU_PROJ_TPC_IN_GPC_BASE_V 0x00004000 +#define GPU_PROJ_TPC_IN_GPC_STRIDE_V 0x00000800 +#define GPU_PROJ_TPC_IN_GPC_SHARED_BASE_V 0x00001800 +#define GPU_PROJ_HOST_NUM_ENGINES_V 0x00000002 +#define GPU_PROJ_HOST_NUM_PBDMA_V 0x00000001 +#define GPU_PROJ_SCAL_LITTER_NUM_TPC_PER_GPC_V 0x00000002 +#define GPU_PROJ_SCAL_LITTER_NUM_FBPS_V 0x00000001 +#define GPU_PROJ_SCAL_LITTER_NUM_FBPAS_V 0x00000001 +#define GPU_PROJ_SCAL_LITTER_NUM_GPCS_V 0x00000001 +#define GPU_PROJ_SCAL_LITTER_NUM_PES_PER_GPC_V 0x00000001 +#define GPU_PROJ_SCAL_LITTER_NUM_TPCS_PER_PES_V 0x00000002 +#define GPU_PROJ_SCAL_LITTER_NUM_ZCULL_BANKS_V 0x00000004 +#define GPU_PROJ_SCAL_MAX_GPCS_V 0x00000020 +#define GPU_PROJ_SCAL_MAX_TPC_PER_GPC_V 0x00000008 + +#define GPU_PWR_FALCON_IRQSSET 0x0010a000 +#define GPU_PWR_FALCON_IRQSSET_SWGEN0_SET_F 0x00000040 +#define GPU_PWR_FALCON_IRQSCLR 0x0010a004 +#define GPU_PWR_FALCON_IRQSTAT 0x0010a008 +#define GPU_PWR_FALCON_IRQSTAT_HALT_TRUE_F 0x00000010 +#define GPU_PWR_FALCON_IRQSTAT_EXTERR_TRUE_F 0x00000020 +#define GPU_PWR_FALCON_IRQSTAT_SWGEN0_TRUE_F 0x00000040 +#define GPU_PWR_FALCON_IRQMODE 0x0010a00c +#define GPU_PWR_FALCON_IRQMSET 0x0010a010 +#define GPU_PWR_FALCON_IRQMSET_GPTMR_SHIFT 0x00000000 +#define GPU_PWR_FALCON_IRQMSET_GPTMR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMSET_WDTMR_SHIFT 0x00000001 +#define GPU_PWR_FALCON_IRQMSET_WDTMR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMSET_MTHD_SHIFT 0x00000002 +#define GPU_PWR_FALCON_IRQMSET_MTHD_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMSET_CTXSW_SHIFT 0x00000003 +#define GPU_PWR_FALCON_IRQMSET_CTXSW_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMSET_HALT_SHIFT 0x00000004 +#define GPU_PWR_FALCON_IRQMSET_HALT_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMSET_EXTERR_SHIFT 0x00000005 +#define GPU_PWR_FALCON_IRQMSET_EXTERR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMSET_SWGEN0_SHIFT 0x00000006 +#define GPU_PWR_FALCON_IRQMSET_SWGEN0_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMSET_SWGEN1_SHIFT 0x00000007 +#define GPU_PWR_FALCON_IRQMSET_SWGEN1_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR 0x0010a014 +#define GPU_PWR_FALCON_IRQMCLR_GPTMR_SHIFT 0x00000000 +#define GPU_PWR_FALCON_IRQMCLR_GPTMR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_WDTMR_SHIFT 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_WDTMR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_MTHD_SHIFT 0x00000002 +#define GPU_PWR_FALCON_IRQMCLR_MTHD_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_CTXSW_SHIFT 0x00000003 +#define GPU_PWR_FALCON_IRQMCLR_CTXSW_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_HALT_SHIFT 0x00000004 +#define GPU_PWR_FALCON_IRQMCLR_HALT_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_EXTERR_SHIFT 0x00000005 +#define GPU_PWR_FALCON_IRQMCLR_EXTERR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_SWGEN0_SHIFT 0x00000006 +#define GPU_PWR_FALCON_IRQMCLR_SWGEN0_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_SWGEN1_SHIFT 0x00000007 +#define GPU_PWR_FALCON_IRQMCLR_SWGEN1_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQMCLR_EXT_SHIFT 0x00000008 +#define GPU_PWR_FALCON_IRQMCLR_EXT_FIELDMASK 0x000000ff +#define GPU_PWR_FALCON_IRQMASK 0x0010a018 +#define GPU_PWR_FALCON_IRQDEST 0x0010a01c +#define GPU_PWR_FALCON_IRQDEST_HOST_GPTMR_SHIFT 0x00000000 +#define GPU_PWR_FALCON_IRQDEST_HOST_GPTMR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_WDTMR_SHIFT 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_WDTMR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_MTHD_SHIFT 0x00000002 +#define GPU_PWR_FALCON_IRQDEST_HOST_MTHD_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_CTXSW_SHIFT 0x00000003 +#define GPU_PWR_FALCON_IRQDEST_HOST_CTXSW_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_HALT_SHIFT 0x00000004 +#define GPU_PWR_FALCON_IRQDEST_HOST_HALT_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_EXTERR_SHIFT 0x00000005 +#define GPU_PWR_FALCON_IRQDEST_HOST_EXTERR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_SWGEN0_SHIFT 0x00000006 +#define GPU_PWR_FALCON_IRQDEST_HOST_SWGEN0_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_SWGEN1_SHIFT 0x00000007 +#define GPU_PWR_FALCON_IRQDEST_HOST_SWGEN1_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_HOST_EXT_SHIFT 0x00000008 +#define GPU_PWR_FALCON_IRQDEST_HOST_EXT_FIELDMASK 0x000000ff +#define GPU_PWR_FALCON_IRQDEST_TARGET_GPTMR_SHIFT 0x00000010 +#define GPU_PWR_FALCON_IRQDEST_TARGET_GPTMR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_TARGET_WDTMR_SHIFT 0x00000011 +#define GPU_PWR_FALCON_IRQDEST_TARGET_WDTMR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_TARGET_MTHD_SHIFT 0x00000012 +#define GPU_PWR_FALCON_IRQDEST_TARGET_MTHD_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_TARGET_CTXSW_SHIFT 0x00000013 +#define GPU_PWR_FALCON_IRQDEST_TARGET_CTXSW_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_TARGET_HALT_SHIFT 0x00000014 +#define GPU_PWR_FALCON_IRQDEST_TARGET_HALT_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_TARGET_EXTERR_SHIFT 0x00000015 +#define GPU_PWR_FALCON_IRQDEST_TARGET_EXTERR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_TARGET_SWGEN0_SHIFT 0x00000016 +#define GPU_PWR_FALCON_IRQDEST_TARGET_SWGEN0_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_TARGET_SWGEN1_SHIFT 0x00000017 +#define GPU_PWR_FALCON_IRQDEST_TARGET_SWGEN1_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IRQDEST_TARGET_EXT_SHIFT 0x00000018 +#define GPU_PWR_FALCON_IRQDEST_TARGET_EXT_FIELDMASK 0x000000ff +#define GPU_PWR_FALCON_CURCTX 0x0010a050 +#define GPU_PWR_FALCON_NXTCTX 0x0010a054 +#define GPU_PWR_FALCON_MAILBOX0 0x0010a040 +#define GPU_PWR_FALCON_MAILBOX1 0x0010a044 +#define GPU_PWR_FALCON_ITFEN 0x0010a048 +#define GPU_PWR_FALCON_ITFEN_CTXEN_ENABLE_F 0x00000001 +#define GPU_PWR_FALCON_IDLESTATE 0x0010a04c +#define GPU_PWR_FALCON_IDLESTATE_FALCON_BUSY_SHIFT 0x00000000 +#define GPU_PWR_FALCON_IDLESTATE_FALCON_BUSY_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IDLESTATE_EXT_BUSY_SHIFT 0x00000001 +#define GPU_PWR_FALCON_IDLESTATE_EXT_BUSY_FIELDMASK 0x00007fff +#define GPU_PWR_FALCON_OS 0x0010a080 +#define GPU_PWR_FALCON_ENGCTL 0x0010a0a4 +#define GPU_PWR_FALCON_CPUCTL 0x0010a100 +#define GPU_PWR_FALCON_CPUCTL_STARTCPU_SHIFT 0x00000001 +#define GPU_PWR_FALCON_CPUCTL_STARTCPU_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_CPUCTL_HALT_INTR_SHIFT 0x00000004 +#define GPU_PWR_FALCON_CPUCTL_HALT_INTR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_CPUCTL_HALT_INTR_MASK 0x00000010 +#define GPU_PWR_FALCON_CPUCTL_CPUCTL_ALIAS_EN_SHIFT 0x00000006 +#define GPU_PWR_FALCON_CPUCTL_CPUCTL_ALIAS_EN_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_CPUCTL_CPUCTL_ALIAS_EN_MASK 0x00000040 +#define GPU_PWR_FALCON_CPUCTL_ALIAS 0x0010a130 +#define GPU_PWR_FALCON_CPUCTL_ALIAS_STARTCPU_SHIFT 0x00000001 +#define GPU_PWR_FALCON_CPUCTL_ALIAS_STARTCPU_FIELDMASK 0x00000001 +#define GPU_PWR_PMU_SCPCTL_STAT 0x0010ac08 +#define GPU_PWR_PMU_SCPCTL_STAT_DEBUG_MODE_SHIFT 0x00000014 +#define GPU_PWR_PMU_SCPCTL_STAT_DEBUG_MODE_FIELDMASK 0x00000001 +#define GPU_PWR_PMU_SCPCTL_STAT_DEBUG_MODE_MASK 0x00100000 +#define GPU_PWR_FALCON_IMEMC__BASE 0x0010a180 +#define GPU_PWR_FALCON_IMEMC__STRIDE 0x00000010 +#define GPU_PWR_FALCON_IMEMC(i) (0x0010a180 + (i) * 0x00000010) +#define GPU_PWR_FALCON_IMEMC_OFFS_SHIFT 0x00000002 +#define GPU_PWR_FALCON_IMEMC_OFFS_FIELDMASK 0x0000003f +#define GPU_PWR_FALCON_IMEMC_BLK_SHIFT 0x00000008 +#define GPU_PWR_FALCON_IMEMC_BLK_FIELDMASK 0x000000ff +#define GPU_PWR_FALCON_IMEMC_AINCW_SHIFT 0x00000018 +#define GPU_PWR_FALCON_IMEMC_AINCW_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_IMEMD__BASE 0x0010a184 +#define GPU_PWR_FALCON_IMEMD__STRIDE 0x00000010 +#define GPU_PWR_FALCON_IMEMD(i) (0x0010a184 + (i) * 0x00000010) +#define GPU_PWR_FALCON_IMEMT__BASE 0x0010a188 +#define GPU_PWR_FALCON_IMEMT__STRIDE 0x00000010 +#define GPU_PWR_FALCON_IMEMT(i) (0x0010a188 + (i) * 0x00000010) +#define GPU_PWR_FALCON_SCTL 0x0010a240 +#define GPU_PWR_FALCON_MMU_PHYS_SEC 0x00100ce4 +#define GPU_PWR_FALCON_BOOTVEC 0x0010a104 +#define GPU_PWR_FALCON_BOOTVEC_VEC_SHIFT 0x00000000 +#define GPU_PWR_FALCON_BOOTVEC_VEC_FIELDMASK 0xffffffff +#define GPU_PWR_FALCON_DMACTL 0x0010a10c +#define GPU_PWR_FALCON_DMACTL_DMEM_SCRUBBING_MASK 0x00000002 +#define GPU_PWR_FALCON_DMACTL_DMEM_SCRUBBING_SHIFT 0x00000001 +#define GPU_PWR_FALCON_DMACTL_DMEM_SCRUBBING_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_DMACTL_IMEM_SCRUBBING_MASK 0x00000004 +#define GPU_PWR_FALCON_DMACTL_IMEM_SCRUBBING_SHIFT 0x00000002 +#define GPU_PWR_FALCON_DMACTL_IMEM_SCRUBBING_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_HWCFG 0x0010a108 +#define GPU_PWR_FALCON_HWCFG_IMEM_SIZE_SHIFT 0x00000000 +#define GPU_PWR_FALCON_HWCFG_IMEM_SIZE_FIELDMASK 0x000001ff +#define GPU_PWR_FALCON_HWCFG_DMEM_SIZE_SHIFT 0x00000009 +#define GPU_PWR_FALCON_HWCFG_DMEM_SIZE_FIELDMASK 0x000001ff +#define GPU_PWR_FALCON_DMATRFBASE 0x0010a110 +#define GPU_PWR_FALCON_DMATRFMOFFS 0x0010a114 +#define GPU_PWR_FALCON_DMATRFCMD 0x0010a118 +#define GPU_PWR_FALCON_DMATRFCMD_IMEM_SHIFT 0x00000004 +#define GPU_PWR_FALCON_DMATRFCMD_IMEM_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_DMATRFCMD_WRITE_SHIFT 0x00000005 +#define GPU_PWR_FALCON_DMATRFCMD_WRITE_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_DMATRFCMD_SIZE_SHIFT 0x00000008 +#define GPU_PWR_FALCON_DMATRFCMD_SIZE_FIELDMASK 0x00000007 +#define GPU_PWR_FALCON_DMATRFCMD_CTXDMA_SHIFT 0x0000000c +#define GPU_PWR_FALCON_DMATRFCMD_CTXDMA_FIELDMASK 0x00000007 +#define GPU_PWR_FALCON_DMATRFFBOFFS 0x0010a11c +#define GPU_PWR_FALCON_EXTERRADDR 0x0010a168 +#define GPU_PWR_FALCON_EXTERRSTAT 0x0010a16c +#define GPU_PWR_FALCON_EXTERRSTAT_VALID_MASK 0x80000000 +#define GPU_PWR_FALCON_EXTERRSTAT_VALID_SHIFT 0x0000001f +#define GPU_PWR_FALCON_EXTERRSTAT_VALID_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_EXTERRSTAT_VALID_TRUE_V 0x00000001 +#define GPU_PWR_PMU_FALCON_ICD_CMD 0x0010a200 +#define GPU_PWR_PMU_FALCON_ICD_CMD_OPC_SIZE 0x00000004 +#define GPU_PWR_PMU_FALCON_ICD_CMD_OPC_SHIFT 0x00000000 +#define GPU_PWR_PMU_FALCON_ICD_CMD_OPC_FIELDMASK 0x0000000f +#define GPU_PWR_PMU_FALCON_ICD_CMD_OPC_MASK 0x0000000f +#define GPU_PWR_PMU_FALCON_ICD_CMD_OPC_RREG_F 0x00000008 +#define GPU_PWR_PMU_FALCON_ICD_CMD_OPC_RSTAT_F 0x0000000e +#define GPU_PWR_PMU_FALCON_ICD_CMD_IDX_SHIFT 0x00000008 +#define GPU_PWR_PMU_FALCON_ICD_CMD_IDX_FIELDMASK 0x0000001f +#define GPU_PWR_PMU_FALCON_ICD_RDATA 0x0010a20c +#define GPU_PWR_FALCON_DMEMC__BASE 0x0010a1c0 +#define GPU_PWR_FALCON_DMEMC__STRIDE 0x00000008 +#define GPU_PWR_FALCON_DMEMC(i) (0x0010a1c0 + (i) * 0x00000008) +#define GPU_PWR_FALCON_DMEMC_OFFS_SHIFT 0x00000002 +#define GPU_PWR_FALCON_DMEMC_OFFS_FIELDMASK 0x0000003f +#define GPU_PWR_FALCON_DMEMC_OFFS_MASK 0x000000fc +#define GPU_PWR_FALCON_DMEMC_BLK_SHIFT 0x00000008 +#define GPU_PWR_FALCON_DMEMC_BLK_FIELDMASK 0x000000ff +#define GPU_PWR_FALCON_DMEMC_BLK_MASK 0x0000ff00 +#define GPU_PWR_FALCON_DMEMC_AINCW_SHIFT 0x00000018 +#define GPU_PWR_FALCON_DMEMC_AINCW_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_DMEMC_AINCR_SHIFT 0x00000019 +#define GPU_PWR_FALCON_DMEMC_AINCR_FIELDMASK 0x00000001 +#define GPU_PWR_FALCON_DMEMD__BASE 0x0010a1c4 +#define GPU_PWR_FALCON_DMEMD__STRIDE 0x00000008 +#define GPU_PWR_FALCON_DMEMD(i) (0x0010a1c4 + (i) * 0x00000008) +#define GPU_PWR_PMU_NEW_INSTBLK 0x0010a480 +#define GPU_PWR_PMU_NEW_INSTBLK_PTR_SHIFT 0x00000000 +#define GPU_PWR_PMU_NEW_INSTBLK_PTR_FIELDMASK 0x0fffffff +#define GPU_PWR_PMU_NEW_INSTBLK_TARGET_FB_F 0x00000000 +#define GPU_PWR_PMU_NEW_INSTBLK_TARGET_SYS_COH_F 0x20000000 +#define GPU_PWR_PMU_NEW_INSTBLK_TARGET_SYS_NCOH_F 0x30000000 +#define GPU_PWR_PMU_NEW_INSTBLK_VALID_SHIFT 0x0000001e +#define GPU_PWR_PMU_NEW_INSTBLK_VALID_FIELDMASK 0x00000001 +#define GPU_PWR_PMU_MUTEX_ID 0x0010a488 +#define GPU_PWR_PMU_MUTEX_ID_VALUE_SHIFT 0x00000000 +#define GPU_PWR_PMU_MUTEX_ID_VALUE_FIELDMASK 0x000000ff +#define GPU_PWR_PMU_MUTEX_ID_VALUE_INIT_V 0x00000000 +#define GPU_PWR_PMU_MUTEX_ID_VALUE_NOT_AVAIL_V 0x000000ff +#define GPU_PWR_PMU_MUTEX_ID_RELEASE 0x0010a48c +#define GPU_PWR_PMU_MUTEX_ID_RELEASE_VALUE_SHIFT 0x00000000 +#define GPU_PWR_PMU_MUTEX_ID_RELEASE_VALUE_FIELDMASK 0x000000ff +#define GPU_PWR_PMU_MUTEX_ID_RELEASE_VALUE_MASK 0x000000ff +#define GPU_PWR_PMU_MUTEX_ID_RELEASE_VALUE_INIT_V 0x00000000 +#define GPU_PWR_PMU_MUTEX_ID_RELEASE_VALUE_INIT_F 0x00000000 +#define GPU_PWR_PMU_MUTEX__BASE 0x0010a580 +#define GPU_PWR_PMU_MUTEX__STRIDE 0x00000004 +#define GPU_PWR_PMU_MUTEX(i) (0x0010a580 + (i) * 0x00000004) +#define GPU_PWR_PMU_MUTEX__SIZE_1_V 0x00000010 +#define GPU_PWR_PMU_MUTEX_VALUE_SHIFT 0x00000000 +#define GPU_PWR_PMU_MUTEX_VALUE_FIELDMASK 0x000000ff +#define GPU_PWR_PMU_MUTEX_VALUE_INITIAL_LOCK_F 0x00000000 +#define GPU_PWR_PMU_QUEUE_HEAD__BASE 0x0010a4a0 +#define GPU_PWR_PMU_QUEUE_HEAD__STRIDE 0x00000004 +#define GPU_PWR_PMU_QUEUE_HEAD(i) (0x0010a4a0 + (i) * 0x00000004) +#define GPU_PWR_PMU_QUEUE_HEAD__SIZE_1_V 0x00000004 +#define GPU_PWR_PMU_QUEUE_HEAD_ADDRESS_SHIFT 0x00000000 +#define GPU_PWR_PMU_QUEUE_HEAD_ADDRESS_FIELDMASK 0xffffffff +#define GPU_PWR_PMU_QUEUE_TAIL__BASE 0x0010a4b0 +#define GPU_PWR_PMU_QUEUE_TAIL__STRIDE 0x00000004 +#define GPU_PWR_PMU_QUEUE_TAIL(i) (0x0010a4b0 + (i) * 0x00000004) +#define GPU_PWR_PMU_QUEUE_TAIL__SIZE_1_V 0x00000004 +#define GPU_PWR_PMU_QUEUE_TAIL_ADDRESS_SHIFT 0x00000000 +#define GPU_PWR_PMU_QUEUE_TAIL_ADDRESS_FIELDMASK 0xffffffff +#define GPU_PWR_PMU_MSGQ_HEAD 0x0010a4c8 +#define GPU_PWR_PMU_MSGQ_HEAD_VAL_SHIFT 0x00000000 +#define GPU_PWR_PMU_MSGQ_HEAD_VAL_FIELDMASK 0xffffffff +#define GPU_PWR_PMU_MSGQ_TAIL 0x0010a4cc +#define GPU_PWR_PMU_MSGQ_TAIL_VAL_SHIFT 0x00000000 +#define GPU_PWR_PMU_MSGQ_TAIL_VAL_FIELDMASK 0xffffffff +#define GPU_PWR_PMU_IDLE_MASK__BASE 0x0010a504 +#define GPU_PWR_PMU_IDLE_MASK__STRIDE 0x00000010 +#define GPU_PWR_PMU_IDLE_MASK(i) (0x0010a504 + (i) * 0x00000010) +#define GPU_PWR_PMU_IDLE_MASK_GR_ENABLED_F 0x00000001 +#define GPU_PWR_PMU_IDLE_MASK_CE_2_ENABLED_F 0x00200000 +#define GPU_PWR_PMU_IDLE_COUNT__BASE 0x0010a508 +#define GPU_PWR_PMU_IDLE_COUNT__STRIDE 0x00000010 +#define GPU_PWR_PMU_IDLE_COUNT(i) (0x0010a508 + (i) * 0x00000010) +#define GPU_PWR_PMU_IDLE_COUNT_VALUE_SHIFT 0x00000000 +#define GPU_PWR_PMU_IDLE_COUNT_VALUE_FIELDMASK 0x7fffffff +#define GPU_PWR_PMU_IDLE_COUNT_RESET_SHIFT 0x0000001f +#define GPU_PWR_PMU_IDLE_COUNT_RESET_FIELDMASK 0x00000001 +#define GPU_PWR_PMU_IDLE_CTRL__BASE 0x0010a50c +#define GPU_PWR_PMU_IDLE_CTRL__STRIDE 0x00000010 +#define GPU_PWR_PMU_IDLE_CTRL(i) (0x0010a50c + (i) * 0x00000010) +#define GPU_PWR_PMU_IDLE_CTRL_VALUE_MASK 0x00000003 +#define GPU_PWR_PMU_IDLE_CTRL_VALUE_SHIFT 0x00000000 +#define GPU_PWR_PMU_IDLE_CTRL_VALUE_FIELDMASK 0x00000003 +#define GPU_PWR_PMU_IDLE_CTRL_VALUE_BUSY_F 0x00000002 +#define GPU_PWR_PMU_IDLE_CTRL_VALUE_ALWAYS_F 0x00000003 +#define GPU_PWR_PMU_IDLE_CTRL_FILTER_MASK 0x00000004 +#define GPU_PWR_PMU_IDLE_CTRL_FILTER_SHIFT 0x00000002 +#define GPU_PWR_PMU_IDLE_CTRL_FILTER_FIELDMASK 0x00000001 +#define GPU_PWR_PMU_IDLE_CTRL_FILTER_DISABLED_F 0x00000000 +#define GPU_PWR_PMU_IDLE_MASK_SUPP__BASE 0x0010a9f0 +#define GPU_PWR_PMU_IDLE_MASK_SUPP__STRIDE 0x00000008 +#define GPU_PWR_PMU_IDLE_MASK_SUPP(i) (0x0010a9f0 + (i) * 0x00000008) +#define GPU_PWR_PMU_IDLE_MASK_1_SUPP__BASE 0x0010a9f4 +#define GPU_PWR_PMU_IDLE_MASK_1_SUPP__STRIDE 0x00000008 +#define GPU_PWR_PMU_IDLE_MASK_1_SUPP(i) (0x0010a9f4 + (i) * 0x00000008) +#define GPU_PWR_PMU_IDLE_CTRL_SUPP__BASE 0x0010aa30 +#define GPU_PWR_PMU_IDLE_CTRL_SUPP__STRIDE 0x00000008 +#define GPU_PWR_PMU_IDLE_CTRL_SUPP(i) (0x0010aa30 + (i) * 0x00000008) +#define GPU_PWR_PMU_DEBUG__BASE 0x0010a5c0 +#define GPU_PWR_PMU_DEBUG__STRIDE 0x00000004 +#define GPU_PWR_PMU_DEBUG(i) (0x0010a5c0 + (i) * 0x00000004) +#define GPU_PWR_PMU_DEBUG__SIZE_1_V 0x00000004 +#define GPU_PWR_PMU_MAILBOX__BASE 0x0010a450 +#define GPU_PWR_PMU_MAILBOX__STRIDE 0x00000004 +#define GPU_PWR_PMU_MAILBOX(i) (0x0010a450 + (i) * 0x00000004) +#define GPU_PWR_PMU_MAILBOX__SIZE_1_V 0x0000000c +#define GPU_PWR_PMU_BAR0_ADDR 0x0010a7a0 +#define GPU_PWR_PMU_BAR0_DATA 0x0010a7a4 +#define GPU_PWR_PMU_BAR0_CTL 0x0010a7ac +#define GPU_PWR_PMU_BAR0_TIMEOUT 0x0010a7a8 +#define GPU_PWR_PMU_BAR0_FECS_ERROR 0x0010a988 +#define GPU_PWR_PMU_BAR0_ERROR_STATUS 0x0010a7b0 +#define GPU_PWR_PMU_PG_IDLEFILTH__BASE 0x0010a6c0 +#define GPU_PWR_PMU_PG_IDLEFILTH__STRIDE 0x00000004 +#define GPU_PWR_PMU_PG_IDLEFILTH(i) (0x0010a6c0 + (i) * 0x00000004) +#define GPU_PWR_PMU_PG_PPUIDLEFILTH__BASE 0x0010a6e8 +#define GPU_PWR_PMU_PG_PPUIDLEFILTH__STRIDE 0x00000004 +#define GPU_PWR_PMU_PG_PPUIDLEFILTH(i) (0x0010a6e8 + (i) * 0x00000004) +#define GPU_PWR_PMU_PG_IDLE_CNT__BASE 0x0010a710 +#define GPU_PWR_PMU_PG_IDLE_CNT__STRIDE 0x00000004 +#define GPU_PWR_PMU_PG_IDLE_CNT(i) (0x0010a710 + (i) * 0x00000004) +#define GPU_PWR_PMU_PG_INTREN__BASE 0x0010a760 +#define GPU_PWR_PMU_PG_INTREN__STRIDE 0x00000004 +#define GPU_PWR_PMU_PG_INTREN(i) (0x0010a760 + (i) * 0x00000004) +#define GPU_PWR_FBIF_TRANSCFG__BASE 0x0010ae00 +#define GPU_PWR_FBIF_TRANSCFG__STRIDE 0x00000004 +#define GPU_PWR_FBIF_TRANSCFG(i) (0x0010ae00 + (i) * 0x00000004) +#define GPU_PWR_FBIF_TRANSCFG_TARGET_LOCAL_FB_F 0x00000000 +#define GPU_PWR_FBIF_TRANSCFG_TARGET_COHERENT_SYSMEM_F 0x00000001 +#define GPU_PWR_FBIF_TRANSCFG_TARGET_NONCOHERENT_SYSMEM_F 0x00000002 +#define GPU_PWR_FBIF_TRANSCFG_MEM_TYPE_SIZE 0x00000001 +#define GPU_PWR_FBIF_TRANSCFG_MEM_TYPE_SHIFT 0x00000002 +#define GPU_PWR_FBIF_TRANSCFG_MEM_TYPE_FIELDMASK 0x00000001 +#define GPU_PWR_FBIF_TRANSCFG_MEM_TYPE_MASK 0x00000004 +#define GPU_PWR_FBIF_TRANSCFG_MEM_TYPE_VIRTUAL_F 0x00000000 +#define GPU_PWR_FBIF_TRANSCFG_MEM_TYPE_PHYSICAL_F 0x00000004 + +#define GPU_RAM_IN_RAMFC_SIZE 0x00001000 +#define GPU_RAM_IN_RAMFC_W 0x00000000 +#define GPU_RAM_IN_PAGE_DIR_BASE_TARGET_SHIFT 0x00000000 +#define GPU_RAM_IN_PAGE_DIR_BASE_TARGET_FIELDMASK 0x00000003 +#define GPU_RAM_IN_PAGE_DIR_BASE_TARGET_W 0x00000080 +#define GPU_RAM_IN_PAGE_DIR_BASE_TARGET_VID_MEM_F 0x00000000 +#define GPU_RAM_IN_PAGE_DIR_BASE_TARGET_SYS_MEM_COH_F 0x00000002 +#define GPU_RAM_IN_PAGE_DIR_BASE_TARGET_SYS_MEM_NCOH_F 0x00000003 +#define GPU_RAM_IN_PAGE_DIR_BASE_VOL_W 0x00000080 +#define GPU_RAM_IN_PAGE_DIR_BASE_VOL_TRUE_F 0x00000004 +#define GPU_RAM_IN_BIG_PAGE_SIZE_SHIFT 0x0000000b +#define GPU_RAM_IN_BIG_PAGE_SIZE_FIELDMASK 0x00000001 +#define GPU_RAM_IN_BIG_PAGE_SIZE_MASK 0x00000800 +#define GPU_RAM_IN_BIG_PAGE_SIZE_W 0x00000080 +#define GPU_RAM_IN_BIG_PAGE_SIZE_128KB_F 0x00000000 +#define GPU_RAM_IN_BIG_PAGE_SIZE_64KB_F 0x00000800 +#define GPU_RAM_IN_PAGE_DIR_BASE_LO_SHIFT 0x0000000c +#define GPU_RAM_IN_PAGE_DIR_BASE_LO_FIELDMASK 0x000fffff +#define GPU_RAM_IN_PAGE_DIR_BASE_LO_W 0x00000080 +#define GPU_RAM_IN_PAGE_DIR_BASE_HI_SHIFT 0x00000000 +#define GPU_RAM_IN_PAGE_DIR_BASE_HI_FIELDMASK 0x000000ff +#define GPU_RAM_IN_PAGE_DIR_BASE_HI_W 0x00000081 +#define GPU_RAM_IN_ADR_LIMIT_LO_SHIFT 0x0000000c +#define GPU_RAM_IN_ADR_LIMIT_LO_FIELDMASK 0x000fffff +#define GPU_RAM_IN_ADR_LIMIT_LO_W 0x00000082 +#define GPU_RAM_IN_ADR_LIMIT_HI_SHIFT 0x00000000 +#define GPU_RAM_IN_ADR_LIMIT_HI_FIELDMASK 0x000000ff +#define GPU_RAM_IN_ADR_LIMIT_HI_W 0x00000083 +#define GPU_RAM_IN_ENGINE_CS_W 0x00000084 +#define GPU_RAM_IN_ENGINE_CS_WFI_V 0x00000000 +#define GPU_RAM_IN_ENGINE_CS_WFI_F 0x00000000 +#define GPU_RAM_IN_ENGINE_CS_FG_V 0x00000001 +#define GPU_RAM_IN_ENGINE_CS_FG_F 0x00000008 +#define GPU_RAM_IN_GR_CS_W 0x00000084 +#define GPU_RAM_IN_GR_CS_WFI_F 0x00000000 +#define GPU_RAM_IN_GR_WFI_TARGET_W 0x00000084 +#define GPU_RAM_IN_GR_WFI_MODE_W 0x00000084 +#define GPU_RAM_IN_GR_WFI_MODE_PHYSICAL_V 0x00000000 +#define GPU_RAM_IN_GR_WFI_MODE_PHYSICAL_F 0x00000000 +#define GPU_RAM_IN_GR_WFI_MODE_VIRTUAL_V 0x00000001 +#define GPU_RAM_IN_GR_WFI_MODE_VIRTUAL_F 0x00000004 +#define GPU_RAM_IN_GR_WFI_PTR_LO_SHIFT 0x0000000c +#define GPU_RAM_IN_GR_WFI_PTR_LO_FIELDMASK 0x000fffff +#define GPU_RAM_IN_GR_WFI_PTR_LO_W 0x00000084 +#define GPU_RAM_IN_GR_WFI_PTR_HI_SHIFT 0x00000000 +#define GPU_RAM_IN_GR_WFI_PTR_HI_FIELDMASK 0x000000ff +#define GPU_RAM_IN_GR_WFI_PTR_HI_W 0x00000085 +#define GPU_RAM_IN_BASE_SHIFT_V 0x0000000c +#define GPU_RAM_IN_ALLOC_SIZE_V 0x00001000 +#define GPU_RAM_FC_SIZE_VAL_V 0x00000200 +#define GPU_RAM_FC_GP_PUT_W 0x00000000 +#define GPU_RAM_FC_USERD_W 0x00000002 +#define GPU_RAM_FC_USERD_HI_W 0x00000003 +#define GPU_RAM_FC_SIGNATURE_W 0x00000004 +#define GPU_RAM_FC_GP_GET_W 0x00000005 +#define GPU_RAM_FC_PB_GET_W 0x00000006 +#define GPU_RAM_FC_PB_GET_HI_W 0x00000007 +#define GPU_RAM_FC_PB_TOP_LEVEL_GET_W 0x00000008 +#define GPU_RAM_FC_PB_TOP_LEVEL_GET_HI_W 0x00000009 +#define GPU_RAM_FC_ACQUIRE_W 0x0000000c +#define GPU_RAM_FC_SEMAPHOREA_W 0x0000000e +#define GPU_RAM_FC_SEMAPHOREB_W 0x0000000f +#define GPU_RAM_FC_SEMAPHOREC_W 0x00000010 +#define GPU_RAM_FC_SEMAPHORED_W 0x00000011 +#define GPU_RAM_FC_GP_BASE_W 0x00000012 +#define GPU_RAM_FC_GP_BASE_HI_W 0x00000013 +#define GPU_RAM_FC_GP_FETCH_W 0x00000014 +#define GPU_RAM_FC_PB_FETCH_W 0x00000015 +#define GPU_RAM_FC_PB_FETCH_HI_W 0x00000016 +#define GPU_RAM_FC_PB_PUT_W 0x00000017 +#define GPU_RAM_FC_PB_PUT_HI_W 0x00000018 +#define GPU_RAM_FC_PB_HEADER_W 0x00000021 +#define GPU_RAM_FC_PB_COUNT_W 0x00000022 +#define GPU_RAM_FC_SUBDEVICE_W 0x00000025 +#define GPU_RAM_FC_FORMATS_W 0x00000027 +#define GPU_RAM_FC_SYNCPOINTA_W 0x00000029 +#define GPU_RAM_FC_SYNCPOINTB_W 0x0000002a +#define GPU_RAM_FC_TARGET_W 0x0000002b +#define GPU_RAM_FC_HCE_CTRL_W 0x00000039 +#define GPU_RAM_FC_CHID_W 0x0000003a +#define GPU_RAM_FC_CHID_ID_SHIFT 0x00000000 +#define GPU_RAM_FC_CHID_ID_FIELDMASK 0x00000fff +#define GPU_RAM_FC_CHID_ID_W 0x00000000 +#define GPU_RAM_FC_RUNLIST_TIMESLICE_W 0x0000003e +#define GPU_RAM_USERD_BASE_SHIFT_V 0x00000009 +#define GPU_RAM_USERD_CHAN_SIZE_V 0x00000200 +#define GPU_RAM_USERD_PUT_W 0x00000010 +#define GPU_RAM_USERD_GET_W 0x00000011 +#define GPU_RAM_USERD_REF_W 0x00000012 +#define GPU_RAM_USERD_PUT_HI_W 0x00000013 +#define GPU_RAM_USERD_REF_THRESHOLD_W 0x00000014 +#define GPU_RAM_USERD_TOP_LEVEL_GET_W 0x00000016 +#define GPU_RAM_USERD_TOP_LEVEL_GET_HI_W 0x00000017 +#define GPU_RAM_USERD_GET_HI_W 0x00000018 +#define GPU_RAM_USERD_GP_GET_W 0x00000022 +#define GPU_RAM_USERD_GP_PUT_W 0x00000023 +#define GPU_RAM_USERD_GP_TOP_LEVEL_GET_W 0x00000016 +#define GPU_RAM_USERD_GP_TOP_LEVEL_GET_HI_W 0x00000017 +#define GPU_RAM_RL_ENTRY_SIZE_V 0x00000008 +#define GPU_RAM_RL_ENTRY_CHID_SHIFT 0x00000000 +#define GPU_RAM_RL_ENTRY_CHID_FIELDMASK 0x00000fff +#define GPU_RAM_RL_ENTRY_ID_SHIFT 0x00000000 +#define GPU_RAM_RL_ENTRY_ID_FIELDMASK 0x00000fff +#define GPU_RAM_RL_ENTRY_TYPE_SHIFT 0x0000000d +#define GPU_RAM_RL_ENTRY_TYPE_FIELDMASK 0x00000001 +#define GPU_RAM_RL_ENTRY_TYPE_CHID_F 0x00000000 +#define GPU_RAM_RL_ENTRY_TYPE_TSG_F 0x00002000 +#define GPU_RAM_RL_ENTRY_TIMESLICE_SCALE_SHIFT 0x0000000e +#define GPU_RAM_RL_ENTRY_TIMESLICE_SCALE_FIELDMASK 0x0000000f +#define GPU_RAM_RL_ENTRY_TIMESLICE_SCALE_3_F 0x0000c000 +#define GPU_RAM_RL_ENTRY_TIMESLICE_TIMEOUT_SHIFT 0x00000012 +#define GPU_RAM_RL_ENTRY_TIMESLICE_TIMEOUT_FIELDMASK 0x000000ff +#define GPU_RAM_RL_ENTRY_TIMESLICE_TIMEOUT_128_F 0x02000000 +#define GPU_RAM_RL_ENTRY_TSG_LENGTH_SHIFT 0x0000001a +#define GPU_RAM_RL_ENTRY_TSG_LENGTH_FIELDMASK 0x0000003f + +#define GPU_THERM_USE_A 0x00020798 +#define GPU_THERM_USE_A_EXT_THERM_0_ENABLE_F 0x00000001 +#define GPU_THERM_USE_A_EXT_THERM_1_ENABLE_F 0x00000002 +#define GPU_THERM_USE_A_EXT_THERM_2_ENABLE_F 0x00000004 +#define GPU_THERM_EVT_EXT_THERM_0 0x00020700 +#define GPU_THERM_EVT_EXT_THERM_0_SLOW_FACTOR_SHIFT 0x00000008 +#define GPU_THERM_EVT_EXT_THERM_0_SLOW_FACTOR_FIELDMASK 0x0000003f +#define GPU_THERM_EVT_EXT_THERM_0_SLOW_FACTOR_INIT_V 0x00000000 +#define GPU_THERM_EVT_EXT_THERM_1 0x00020704 +#define GPU_THERM_EVT_EXT_THERM_1_SLOW_FACTOR_SHIFT 0x00000008 +#define GPU_THERM_EVT_EXT_THERM_1_SLOW_FACTOR_FIELDMASK 0x0000003f +#define GPU_THERM_EVT_EXT_THERM_1_SLOW_FACTOR_INIT_V 0x00000000 +#define GPU_THERM_EVT_EXT_THERM_2 0x00020708 +#define GPU_THERM_EVT_EXT_THERM_2_SLOW_FACTOR_SHIFT 0x00000008 +#define GPU_THERM_EVT_EXT_THERM_2_SLOW_FACTOR_FIELDMASK 0x0000003f +#define GPU_THERM_EVT_EXT_THERM_2_SLOW_FACTOR_INIT_V 0x00000000 +#define GPU_THERM_WEIGHT_1 0x00020024 +#define GPU_THERM_CONFIG1 0x00020050 +#define GPU_THERM_CONFIG2 0x00020130 +#define GPU_THERM_CONFIG2_SLOWDOWN_FACTOR_EXTENDED_SHIFT 0x00000018 +#define GPU_THERM_CONFIG2_SLOWDOWN_FACTOR_EXTENDED_FIELDMASK 0x00000001 +#define GPU_THERM_CONFIG2_GRAD_ENABLE_SHIFT 0x0000001f +#define GPU_THERM_CONFIG2_GRAD_ENABLE_FIELDMASK 0x00000001 +#define GPU_THERM_GATE_CTRL__BASE 0x00020200 +#define GPU_THERM_GATE_CTRL__STRIDE 0x00000004 +#define GPU_THERM_GATE_CTRL(i) (0x00020200 + (i) * 0x00000004) +#define GPU_THERM_GATE_CTRL_ENG_CLK_MASK 0x00000003 +#define GPU_THERM_GATE_CTRL_ENG_CLK_SHIFT 0x00000000 +#define GPU_THERM_GATE_CTRL_ENG_CLK_FIELDMASK 0x00000003 +#define GPU_THERM_GATE_CTRL_ENG_CLK_RUN_F 0x00000000 +#define GPU_THERM_GATE_CTRL_ENG_CLK_AUTO_F 0x00000001 +#define GPU_THERM_GATE_CTRL_ENG_CLK_STOP_F 0x00000002 +#define GPU_THERM_GATE_CTRL_BLK_CLK_MASK 0x0000000c +#define GPU_THERM_GATE_CTRL_BLK_CLK_SHIFT 0x00000002 +#define GPU_THERM_GATE_CTRL_BLK_CLK_FIELDMASK 0x00000003 +#define GPU_THERM_GATE_CTRL_BLK_CLK_RUN_F 0x00000000 +#define GPU_THERM_GATE_CTRL_BLK_CLK_AUTO_F 0x00000004 +#define GPU_THERM_GATE_CTRL_ENG_PWR_MASK 0x00000030 +#define GPU_THERM_GATE_CTRL_ENG_PWR_SHIFT 0x00000004 +#define GPU_THERM_GATE_CTRL_ENG_PWR_FIELDMASK 0x00000003 +#define GPU_THERM_GATE_CTRL_ENG_PWR_AUTO_F 0x00000010 +#define GPU_THERM_GATE_CTRL_ENG_PWR_OFF_V 0x00000002 +#define GPU_THERM_GATE_CTRL_ENG_PWR_OFF_F 0x00000020 +#define GPU_THERM_GATE_CTRL_ENG_IDLE_FILT_EXP_SHIFT 0x00000008 +#define GPU_THERM_GATE_CTRL_ENG_IDLE_FILT_EXP_FIELDMASK 0x0000001f +#define GPU_THERM_GATE_CTRL_ENG_IDLE_FILT_EXP_MASK 0x00001f00 +#define GPU_THERM_GATE_CTRL_ENG_IDLE_FILT_MANT_SHIFT 0x0000000d +#define GPU_THERM_GATE_CTRL_ENG_IDLE_FILT_MANT_FIELDMASK 0x00000007 +#define GPU_THERM_GATE_CTRL_ENG_IDLE_FILT_MANT_MASK 0x0000e000 +#define GPU_THERM_GATE_CTRL_ENG_DELAY_BEFORE_SHIFT 0x00000010 +#define GPU_THERM_GATE_CTRL_ENG_DELAY_BEFORE_FIELDMASK 0x0000000f +#define GPU_THERM_GATE_CTRL_ENG_DELAY_BEFORE_MASK 0x000f0000 +#define GPU_THERM_GATE_CTRL_ENG_DELAY_AFTER_SHIFT 0x00000014 +#define GPU_THERM_GATE_CTRL_ENG_DELAY_AFTER_FIELDMASK 0x0000000f +#define GPU_THERM_GATE_CTRL_ENG_DELAY_AFTER_MASK 0x00f00000 +#define GPU_THERM_FECS_IDLE_FILTER 0x00020288 +#define GPU_THERM_FECS_IDLE_FILTER_VALUE_MASK 0xffffffff +#define GPU_THERM_FECS_IDLE_FILTER_VALUE_SHIFT 0x00000000 +#define GPU_THERM_FECS_IDLE_FILTER_VALUE_FIELDMASK 0xffffffff +#define GPU_THERM_HUBMMU_IDLE_FILTER 0x0002028c +#define GPU_THERM_HUBMMU_IDLE_FILTER_VALUE_MASK 0xffffffff +#define GPU_THERM_HUBMMU_IDLE_FILTER_VALUE_SHIFT 0x00000000 +#define GPU_THERM_HUBMMU_IDLE_FILTER_VALUE_FIELDMASK 0xffffffff +#define GPU_THERM_CLK_SLOWDOWN__BASE 0x00020160 +#define GPU_THERM_CLK_SLOWDOWN__STRIDE 0x00000004 +#define GPU_THERM_CLK_SLOWDOWN(i) (0x00020160 + (i) * 0x00000004) +#define GPU_THERM_CLK_SLOWDOWN_IDLE_FACTOR_SHIFT 0x00000010 +#define GPU_THERM_CLK_SLOWDOWN_IDLE_FACTOR_FIELDMASK 0x0000003f +#define GPU_THERM_CLK_SLOWDOWN_IDLE_FACTOR_MASK 0x003f0000 +#define GPU_THERM_CLK_SLOWDOWN_IDLE_FACTOR_DISABLED_F 0x00000000 +#define GPU_THERM_GRAD_STEPPING_TABLE__BASE 0x000202c8 +#define GPU_THERM_GRAD_STEPPING_TABLE__STRIDE 0x00000004 +#define GPU_THERM_GRAD_STEPPING_TABLE(i) (0x000202c8 + (i) * 0x00000004) +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR0_SHIFT 0x00000000 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR0_FIELDMASK 0x0000003f +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR0_MASK 0x0000003f +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR0_FPDIV_BY1P5_F 0x00000001 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR0_FPDIV_BY2_F 0x00000002 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR0_FPDIV_BY4_F 0x00000006 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR0_FPDIV_BY8_F 0x0000000e +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR1_SHIFT 0x00000006 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR1_FIELDMASK 0x0000003f +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR1_MASK 0x00000fc0 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR2_SHIFT 0x0000000c +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR2_FIELDMASK 0x0000003f +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR2_MASK 0x0003f000 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR3_SHIFT 0x00000012 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR3_FIELDMASK 0x0000003f +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR3_MASK 0x00fc0000 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR4_SHIFT 0x00000018 +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR4_FIELDMASK 0x0000003f +#define GPU_THERM_GRAD_STEPPING_TABLE_SLOWDOWN_FACTOR4_MASK 0x3f000000 +#define GPU_THERM_GRAD_STEPPING0 0x000202c0 +#define GPU_THERM_GRAD_STEPPING0_FEATURE_SIZE 0x00000001 +#define GPU_THERM_GRAD_STEPPING0_FEATURE_SHIFT 0x00000000 +#define GPU_THERM_GRAD_STEPPING0_FEATURE_FIELDMASK 0x00000001 +#define GPU_THERM_GRAD_STEPPING0_FEATURE_MASK 0x00000001 +#define GPU_THERM_GRAD_STEPPING0_FEATURE_ENABLE_F 0x00000001 +#define GPU_THERM_GRAD_STEPPING1 0x000202c4 +#define GPU_THERM_GRAD_STEPPING1_PDIV_DURATION_SHIFT 0x00000000 +#define GPU_THERM_GRAD_STEPPING1_PDIV_DURATION_FIELDMASK 0x0001ffff +#define GPU_THERM_CLK_TIMING__BASE 0x000203c0 +#define GPU_THERM_CLK_TIMING__STRIDE 0x00000004 +#define GPU_THERM_CLK_TIMING(i) (0x000203c0 + (i) * 0x00000004) +#define GPU_THERM_CLK_TIMING_GRAD_SLOWDOWN_SHIFT 0x00000010 +#define GPU_THERM_CLK_TIMING_GRAD_SLOWDOWN_FIELDMASK 0x00000001 +#define GPU_THERM_CLK_TIMING_GRAD_SLOWDOWN_MASK 0x00010000 +#define GPU_THERM_CLK_TIMING_GRAD_SLOWDOWN_ENABLED_F 0x00010000 + +#define GPU_TIMER_PRI_TIMEOUT 0x00009080 +#define GPU_TIMER_PRI_TIMEOUT_PERIOD_SHIFT 0x00000000 +#define GPU_TIMER_PRI_TIMEOUT_PERIOD_FIELDMASK 0x00ffffff +#define GPU_TIMER_PRI_TIMEOUT_PERIOD_MASK 0x00ffffff +#define GPU_TIMER_PRI_TIMEOUT_EN_SHIFT 0x0000001f +#define GPU_TIMER_PRI_TIMEOUT_EN_FIELDMASK 0x00000001 +#define GPU_TIMER_PRI_TIMEOUT_EN_MASK 0x80000000 +#define GPU_TIMER_PRI_TIMEOUT_EN_EN_ENABLED_F 0x80000000 +#define GPU_TIMER_PRI_TIMEOUT_EN_EN_DISABLED_F 0x00000000 +#define GPU_TIMER_PRI_TIMEOUT_SAVE_0 0x00009084 +#define GPU_TIMER_PRI_TIMEOUT_SAVE_1 0x00009088 +#define GPU_TIMER_PRI_TIMEOUT_FECS_ERRCODE 0x0000908c +#define GPU_TIMER_TIME_0 0x00009400 +#define GPU_TIMER_TIME_1 0x00009410 + +#define GPU_TOP_NUM_GPCS 0x00022430 +#define GPU_TOP_NUM_GPCS_VALUE_SHIFT 0x00000000 +#define GPU_TOP_NUM_GPCS_VALUE_FIELDMASK 0x0000001f +#define GPU_TOP_TPC_PER_GPC 0x00022434 +#define GPU_TOP_TPC_PER_GPC_VALUE_SHIFT 0x00000000 +#define GPU_TOP_TPC_PER_GPC_VALUE_FIELDMASK 0x0000001f +#define GPU_TOP_NUM_FBPS 0x00022438 +#define GPU_TOP_NUM_FBPS_VALUE_SHIFT 0x00000000 +#define GPU_TOP_NUM_FBPS_VALUE_FIELDMASK 0x0000001f +#define GPU_TOP_LTC_PER_FBP 0x00022450 +#define GPU_TOP_LTC_PER_FBP_VALUE_SHIFT 0x00000000 +#define GPU_TOP_LTC_PER_FBP_VALUE_FIELDMASK 0x0000001f +#define GPU_TOP_SLICES_PER_LTC 0x0002245c +#define GPU_TOP_SLICES_PER_LTC_VALUE_SHIFT 0x00000000 +#define GPU_TOP_SLICES_PER_LTC_VALUE_FIELDMASK 0x0000001f +#define GPU_TOP_NUM_LTCS 0x00022454 +#define GPU_TOP_DEVICE_INFO__BASE 0x00022700 +#define GPU_TOP_DEVICE_INFO__STRIDE 0x00000004 +#define GPU_TOP_DEVICE_INFO(i) (0x00022700 + (i) * 0x00000004) +#define GPU_TOP_DEVICE_INFO__SIZE_1_V 0x00000040 +#define GPU_TOP_DEVICE_INFO_CHAIN_SHIFT 0x0000001f +#define GPU_TOP_DEVICE_INFO_CHAIN_FIELDMASK 0x00000001 +#define GPU_TOP_DEVICE_INFO_CHAIN_ENABLE_V 0x00000001 +#define GPU_TOP_DEVICE_INFO_ENGINE_ENUM_SHIFT 0x0000001a +#define GPU_TOP_DEVICE_INFO_ENGINE_ENUM_FIELDMASK 0x0000000f +#define GPU_TOP_DEVICE_INFO_RUNLIST_ENUM_SHIFT 0x00000015 +#define GPU_TOP_DEVICE_INFO_RUNLIST_ENUM_FIELDMASK 0x0000000f +#define GPU_TOP_DEVICE_INFO_INTR_ENUM_SHIFT 0x0000000f +#define GPU_TOP_DEVICE_INFO_INTR_ENUM_FIELDMASK 0x0000001f +#define GPU_TOP_DEVICE_INFO_RESET_ENUM_SHIFT 0x00000009 +#define GPU_TOP_DEVICE_INFO_RESET_ENUM_FIELDMASK 0x0000001f +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_SHIFT 0x00000002 +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_FIELDMASK 0x1fffffff +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_GRAPHICS_V 0x00000000 +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_GRAPHICS_F 0x00000000 +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_COPY0_V 0x00000001 +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_COPY0_F 0x00000004 +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_COPY1_V 0x00000002 +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_COPY1_F 0x00000008 +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_COPY2_V 0x00000003 +#define GPU_TOP_DEVICE_INFO_TYPE_ENUM_COPY2_F 0x0000000c +#define GPU_TOP_DEVICE_INFO_ENGINE_SHIFT 0x00000005 +#define GPU_TOP_DEVICE_INFO_ENGINE_FIELDMASK 0x00000001 +#define GPU_TOP_DEVICE_INFO_RUNLIST_SHIFT 0x00000004 +#define GPU_TOP_DEVICE_INFO_RUNLIST_FIELDMASK 0x00000001 +#define GPU_TOP_DEVICE_INFO_INTR_SHIFT 0x00000003 +#define GPU_TOP_DEVICE_INFO_INTR_FIELDMASK 0x00000001 +#define GPU_TOP_DEVICE_INFO_RESET_SHIFT 0x00000002 +#define GPU_TOP_DEVICE_INFO_RESET_FIELDMASK 0x00000001 +#define GPU_TOP_DEVICE_INFO_ENTRY_SHIFT 0x00000000 +#define GPU_TOP_DEVICE_INFO_ENTRY_FIELDMASK 0x00000003 +#define GPU_TOP_DEVICE_INFO_ENTRY_NOT_VALID_V 0x00000000 +#define GPU_TOP_DEVICE_INFO_ENTRY_ENUM_V 0x00000002 +#define GPU_TOP_DEVICE_INFO_ENTRY_ENGINE_TYPE_V 0x00000003 +#define GPU_TOP_DEVICE_INFO_ENTRY_DATA_V 0x00000001 +#define GPU_TOP_DEVICE_INFO_DATA_TYPE_SHIFT 0x0000001e +#define GPU_TOP_DEVICE_INFO_DATA_TYPE_FIELDMASK 0x00000001 +#define GPU_TOP_DEVICE_INFO_DATA_TYPE_ENUM2_V 0x00000000 +#define GPU_TOP_DEVICE_INFO_DATA_PRI_BASE_SHIFT 0x0000000c +#define GPU_TOP_DEVICE_INFO_DATA_PRI_BASE_FIELDMASK 0x000007ff +#define GPU_TOP_DEVICE_INFO_DATA_PRI_BASE_ALIGN_V 0x0000000c +#define GPU_TOP_DEVICE_INFO_DATA_FAULT_ID_ENUM_SHIFT 0x00000003 +#define GPU_TOP_DEVICE_INFO_DATA_FAULT_ID_ENUM_FIELDMASK 0x0000001f +#define GPU_TOP_DEVICE_INFO_DATA_FAULT_ID_SHIFT 0x00000002 +#define GPU_TOP_DEVICE_INFO_DATA_FAULT_ID_FIELDMASK 0x00000001 +#define GPU_TOP_DEVICE_INFO_DATA_FAULT_ID_VALID_V 0x00000001 + +#define GPU_TRIM_SYS_GPCPLL_CFG 0x00137000 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENABLE_MASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENABLE_SHIFT 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENABLE_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENABLE_NO_F 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENABLE_YES_F 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_CFG_IDDQ_MASK 0x00000002 +#define GPU_TRIM_SYS_GPCPLL_CFG_IDDQ_SHIFT 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_CFG_IDDQ_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_CFG_IDDQ_POWER_ON_V 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_CFG_SYNC_MODE_MASK 0x00000004 +#define GPU_TRIM_SYS_GPCPLL_CFG_SYNC_MODE_SHIFT 0x00000002 +#define GPU_TRIM_SYS_GPCPLL_CFG_SYNC_MODE_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_CFG_SYNC_MODE_ENABLE_F 0x00000004 +#define GPU_TRIM_SYS_GPCPLL_CFG_SYNC_MODE_DISABLE_F 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENB_LCKDET_MASK 0x00000010 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENB_LCKDET_SHIFT 0x00000004 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENB_LCKDET_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENB_LCKDET_POWER_ON_F 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_CFG_ENB_LCKDET_POWER_OFF_F 0x00000010 +#define GPU_TRIM_SYS_GPCPLL_CFG_PLL_LOCK_SHIFT 0x00000011 +#define GPU_TRIM_SYS_GPCPLL_CFG_PLL_LOCK_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_CFG_PLL_LOCK_TRUE_F 0x00020000 +#define GPU_TRIM_SYS_GPCPLL_COEFF 0x00137004 +#define GPU_TRIM_SYS_GPCPLL_COEFF_MDIV_SHIFT 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_COEFF_MDIV_FIELDMASK 0x000000ff +#define GPU_TRIM_SYS_GPCPLL_COEFF_MDIV_MASK 0x000000ff +#define GPU_TRIM_SYS_GPCPLL_COEFF_NDIV_SHIFT 0x00000008 +#define GPU_TRIM_SYS_GPCPLL_COEFF_NDIV_FIELDMASK 0x000000ff +#define GPU_TRIM_SYS_GPCPLL_COEFF_NDIV_MASK 0x0000ff00 +#define GPU_TRIM_SYS_GPCPLL_COEFF_PLDIV_SHIFT 0x00000010 +#define GPU_TRIM_SYS_GPCPLL_COEFF_PLDIV_FIELDMASK 0x0000003f +#define GPU_TRIM_SYS_GPCPLL_COEFF_PLDIV_MASK 0x003f0000 +#define GPU_TRIM_SYS_SEL_VCO 0x00137100 +#define GPU_TRIM_SYS_SEL_VCO_GPC2CLK_OUT_MASK 0x00000001 +#define GPU_TRIM_SYS_SEL_VCO_GPC2CLK_OUT_SHIFT 0x00000000 +#define GPU_TRIM_SYS_SEL_VCO_GPC2CLK_OUT_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_SEL_VCO_GPC2CLK_OUT_INIT_V 0x00000000 +#define GPU_TRIM_SYS_SEL_VCO_GPC2CLK_OUT_INIT_F 0x00000000 +#define GPU_TRIM_SYS_SEL_VCO_GPC2CLK_OUT_BYPASS_F 0x00000000 +#define GPU_TRIM_SYS_SEL_VCO_GPC2CLK_OUT_VCO_F 0x00000001 +#define GPU_TRIM_SYS_GPC2CLK_OUT 0x00137250 +#define GPU_TRIM_SYS_GPC2CLK_OUT_BYPDIV_SIZE 0x00000006 +#define GPU_TRIM_SYS_GPC2CLK_OUT_BYPDIV_SHIFT 0x00000000 +#define GPU_TRIM_SYS_GPC2CLK_OUT_BYPDIV_FIELDMASK 0x0000003f +#define GPU_TRIM_SYS_GPC2CLK_OUT_BYPDIV_MASK 0x0000003f +#define GPU_TRIM_SYS_GPC2CLK_OUT_BYPDIV_BY31_F 0x0000003c +#define GPU_TRIM_SYS_GPC2CLK_OUT_VCODIV_SIZE 0x00000006 +#define GPU_TRIM_SYS_GPC2CLK_OUT_VCODIV_SHIFT 0x00000008 +#define GPU_TRIM_SYS_GPC2CLK_OUT_VCODIV_FIELDMASK 0x0000003f +#define GPU_TRIM_SYS_GPC2CLK_OUT_VCODIV_MASK 0x00003f00 +#define GPU_TRIM_SYS_GPC2CLK_OUT_VCODIV_BY1_F 0x00000000 +#define GPU_TRIM_SYS_GPC2CLK_OUT_SDIV14_MASK 0x80000000 +#define GPU_TRIM_SYS_GPC2CLK_OUT_SDIV14_SHIFT 0x0000001f +#define GPU_TRIM_SYS_GPC2CLK_OUT_SDIV14_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPC2CLK_OUT_SDIV14_INDIV4_MODE_F 0x80000000 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CFG__BASE 0x00134124 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CFG__STRIDE 0x00000200 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CFG(i) (0x00134124 + (i) * 0x00000200) +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CFG_NOOFIPCLKS_SHIFT 0x00000000 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CFG_NOOFIPCLKS_FIELDMASK 0x00003fff +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CFG_WRITE_EN_ASSERTED_F 0x00010000 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CFG_ENABLE_ASSERTED_F 0x00100000 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CFG_RESET_ASSERTED_F 0x01000000 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CNT__BASE 0x00134128 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CNT__STRIDE 0x00000200 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CNT(i) (0x00134128 + (i) * 0x00000200) +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CNT_VALUE_SHIFT 0x00000000 +#define GPU_TRIM_GPC_CLK_CNTR_NCGPCCLK_CNT_VALUE_FIELDMASK 0x000fffff +#define GPU_TRIM_SYS_GPCPLL_CFG2 0x0013700c +#define GPU_TRIM_SYS_GPCPLL_CFG2_SDM_DIN_SHIFT 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_CFG2_SDM_DIN_FIELDMASK 0x000000ff +#define GPU_TRIM_SYS_GPCPLL_CFG2_SDM_DIN_MASK 0x000000ff +#define GPU_TRIM_SYS_GPCPLL_CFG2_SDM_DIN_NEW_SHIFT 0x00000008 +#define GPU_TRIM_SYS_GPCPLL_CFG2_SDM_DIN_NEW_FIELDMASK 0x000000ff +#define GPU_TRIM_SYS_GPCPLL_CFG2_SDM_DIN_NEW_MASK 0x0000ff00 +#define GPU_TRIM_SYS_GPCPLL_CFG2_PLL_STEPA_SHIFT 0x00000018 +#define GPU_TRIM_SYS_GPCPLL_CFG2_PLL_STEPA_FIELDMASK 0x000000ff +#define GPU_TRIM_SYS_GPCPLL_CFG2_PLL_STEPA_MASK 0xff000000 +#define GPU_TRIM_SYS_GPCPLL_CFG3 0x00137018 +#define GPU_TRIM_SYS_GPCPLL_CFG3_VCO_CTRL_SHIFT 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_CFG3_VCO_CTRL_FIELDMASK 0x000001ff +#define GPU_TRIM_SYS_GPCPLL_CFG3_VCO_CTRL_MASK 0x000001ff +#define GPU_TRIM_SYS_GPCPLL_CFG3_PLL_STEPB_SHIFT 0x00000010 +#define GPU_TRIM_SYS_GPCPLL_CFG3_PLL_STEPB_FIELDMASK 0x000000ff +#define GPU_TRIM_SYS_GPCPLL_CFG3_PLL_STEPB_MASK 0x00ff0000 +#define GPU_TRIM_SYS_GPCPLL_CFG3_DFS_TESTOUT_SHIFT 0x00000018 +#define GPU_TRIM_SYS_GPCPLL_CFG3_DFS_TESTOUT_FIELDMASK 0x0000007f +#define GPU_TRIM_SYS_GPCPLL_DVFS0 0x00137010 +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_COEFF_SHIFT 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_COEFF_FIELDMASK 0x0000007f +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_COEFF_MASK 0x0000007f +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_DET_MAX_SHIFT 0x00000008 +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_DET_MAX_FIELDMASK 0x0000007f +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_DET_MAX_MASK 0x00007f00 +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_DC_OFFSET_SHIFT 0x00000010 +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_DC_OFFSET_FIELDMASK 0x0000003f +#define GPU_TRIM_SYS_GPCPLL_DVFS0_DFS_DC_OFFSET_MASK 0x003f0000 +#define GPU_TRIM_SYS_GPCPLL_DVFS0_MODE_MASK 0x10000000 +#define GPU_TRIM_SYS_GPCPLL_DVFS0_MODE_SHIFT 0x0000001c +#define GPU_TRIM_SYS_GPCPLL_DVFS0_MODE_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_DVFS0_MODE_DVFSPLL_F 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_DVFS1 0x00137014 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_DET_SHIFT 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_DET_FIELDMASK 0x0000007f +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_DET_MASK 0x0000007f +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_STRB_MASK 0x00000080 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_STRB_SHIFT 0x00000007 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_STRB_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_CAL_SHIFT 0x00000008 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_CAL_FIELDMASK 0x0000007f +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_CAL_MASK 0x00007f00 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_SEL_MASK 0x00008000 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_SEL_SHIFT 0x0000000f +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_EXT_SEL_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_CTRL_SHIFT 0x00000010 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_CTRL_FIELDMASK 0x00000fff +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_CTRL_MASK 0x0fff0000 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_SDM_MASK 0x10000000 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_SDM_SHIFT 0x0000001c +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_SDM_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_DFS_MASK 0x20000000 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_DFS_SHIFT 0x0000001d +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_DFS_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_DFS_CAL_MASK 0x40000000 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_DFS_CAL_SHIFT 0x0000001e +#define GPU_TRIM_SYS_GPCPLL_DVFS1_EN_DFS_CAL_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_CAL_DONE_SHIFT 0x0000001f +#define GPU_TRIM_SYS_GPCPLL_DVFS1_DFS_CAL_DONE_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_DVFS2 0x00137020 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN 0x0013701c +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_MASK 0x00400000 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_SHIFT 0x00000016 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_YES_F 0x00400000 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_SLOWDOWN_USING_PLL_NO_F 0x00000000 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_MASK 0x80000000 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_SHIFT 0x0000001f +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_YES_F 0x80000000 +#define GPU_TRIM_SYS_GPCPLL_NDIV_SLOWDOWN_EN_DYNRAMP_NO_F 0x00000000 +#define GPU_TRIM_GPC_BCAST_GPCPLL_NDIV_SLOWDOWN_DEBUG 0x001328a0 +#define GPU_TRIM_GPC_BCAST_GPCPLL_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_SHIFT 0x00000018 +#define GPU_TRIM_GPC_BCAST_GPCPLL_NDIV_SLOWDOWN_DEBUG_PLL_DYNRAMP_DONE_SYNCED_FIELDMASK 0x00000001 +#define GPU_TRIM_GPC_BCAST_GPCPLL_DVFS2 0x00132820 +#define GPU_TRIM_SYS_BYPASSCTRL 0x00137340 +#define GPU_TRIM_SYS_BYPASSCTRL_GPCPLL_MASK 0x00000001 +#define GPU_TRIM_SYS_BYPASSCTRL_GPCPLL_SHIFT 0x00000000 +#define GPU_TRIM_SYS_BYPASSCTRL_GPCPLL_FIELDMASK 0x00000001 +#define GPU_TRIM_SYS_BYPASSCTRL_GPCPLL_BYPASSCLK_F 0x00000001 +#define GPU_TRIM_SYS_BYPASSCTRL_GPCPLL_VCO_F 0x00000000 \ No newline at end of file diff --git a/Source/hoc-clk/sysmodule/src/tsensor/aotag.cpp b/Source/hoc-clk/sysmodule/src/tsensor/aotag.cpp index fbf03091..d1b028a5 100644 --- a/Source/hoc-clk/sysmodule/src/tsensor/aotag.cpp +++ b/Source/hoc-clk/sysmodule/src/tsensor/aotag.cpp @@ -205,7 +205,7 @@ namespace tsensor { SetBit(CFG_TAG_EN_POS, &r); ClearBit(CFG_DISABLE_CLK_POS, &r); WritePmcReg(r, PMC_AOTAG_CFG); - fileUtils::LogLine("[aotag] Init complete!"); + file::utils::LogLine("[aotag] Init complete!"); wasInit = true; } diff --git a/Source/hoc-clk/sysmodule/src/tsensor/bq24193.cpp b/Source/hoc-clk/sysmodule/src/tsensor/bq24193.cpp index 3cfad2e1..80cddc94 100644 --- a/Source/hoc-clk/sysmodule/src/tsensor/bq24193.cpp +++ b/Source/hoc-clk/sysmodule/src/tsensor/bq24193.cpp @@ -19,14 +19,14 @@ #include "bq24193.hpp" -namespace bq24193 { +namespace tsensor { static u8 bq24193_get_reg(u8 reg) { u8 out; I2cRead_OutU8(I2cDevice_Bq24193, reg, &out); return out; } - u8 getBQTemp() { + u8 GetBqTemp() { u8 regVal = bq24193_get_reg(BQ24193_FaultReg); return regVal & BQ24193_FAULT_THERM_MASK; } -} // namespace bq24193 +} // namespace tsensor diff --git a/Source/hoc-clk/sysmodule/src/tsensor/bq24193.hpp b/Source/hoc-clk/sysmodule/src/tsensor/bq24193.hpp index 2eac97a6..23b41fa7 100644 --- a/Source/hoc-clk/sysmodule/src/tsensor/bq24193.hpp +++ b/Source/hoc-clk/sysmodule/src/tsensor/bq24193.hpp @@ -23,7 +23,7 @@ #include "../i2c/i2cDrv.h" -namespace bq24193 { +namespace tsensor { #define BQ24193_I2C_ADDR 0x6B // REG 0 masks. @@ -126,5 +126,5 @@ namespace bq24193 { BQ24193_Temp_Cold = 5, BQ24193_Temp_Hot = 6, }; - u8 getBQTemp(); -} // namespace bq24193 + u8 GetBqTemp(); +} // namespace tsensor diff --git a/Source/hoc-clk/sysmodule/src/tsensor/soctherm.cpp b/Source/hoc-clk/sysmodule/src/tsensor/soctherm.cpp index 6a053f46..b483e8cf 100644 --- a/Source/hoc-clk/sysmodule/src/tsensor/soctherm.cpp +++ b/Source/hoc-clk/sysmodule/src/tsensor/soctherm.cpp @@ -24,6 +24,7 @@ #include #include "../board/board.hpp" +#include "../board/board_volt.hpp" #include "../file/file_utils.hpp" #include "../mapping/mem_map.hpp" #include "soctherm.hpp" @@ -480,8 +481,32 @@ namespace tsensor { if (!IsSensorEnabled()) { StartSensors(); + } + + /* Workaround for potential HW bug */ + /* Refer to TRM 40.3.1.3 TSOSC Vmin limitations */ + /* Vmins estimated. TODO: find the correct ones via community testing */ + + /* Get the CPU voltage*/ + u32 cpuVoltage = board::GetVoltage(HocClkVoltage_CPU) / 1000; + + /* Infered from stock voltage. We know that below stock is unreliable */ + constexpr u32 kEristaTSOSCVmin = 825; + constexpr u32 kMarikoTSOSCVmin = 620; + + /* Get the correct vmin for the hardware type currently used */ + u32 TSOSCVmin = board::GetSocType() == HocClkSocType_Mariko ? kMarikoTSOSCVmin : kEristaTSOSCVmin; + + /* Mark the sensor as invalid so HW can recalibrate it */ + if(cpuVoltage >= TSOSCVmin) { + WriteReg(socthermVa, SENSOR_VALID, 1); + } else { + WriteReg(socthermVa, SENSOR_VALID, 0); } + /* Wait for HW recalibration */ + svcSleepThread(25'000); + temps.cpu = TranslateTemp(ReadReg(socthermVa, SENSOR_TEMP1) >> 16); temps.gpu = TranslateTemp(ReadReg(socthermVa, SENSOR_TEMP1) & SENSOR_TEMP1_GPU_TEMP_MASK); temps.pllx = TranslateTemp(ReadReg(socthermVa, SENSOR_TEMP2) & SENSOR_TEMP2_PLLX_TEMP_MASK); @@ -522,7 +547,7 @@ namespace tsensor { StartSensors(); - fileUtils::LogLine("[Soctherm] Finished init."); + file::utils::LogLine("[Soctherm] Finished init."); } } // namespace tsensor diff --git a/Source/hoc-clk/sysmodule/src/util/crc32.cpp b/Source/hoc-clk/sysmodule/src/util/crc32.cpp index 7588192f..7fcd5666 100644 --- a/Source/hoc-clk/sysmodule/src/util/crc32.cpp +++ b/Source/hoc-clk/sysmodule/src/util/crc32.cpp @@ -17,8 +17,8 @@ #include -namespace crc32 { - uint32_t crc32(const uint8_t *data, size_t length) { +namespace util { + uint32_t Crc32(const uint8_t *data, size_t length) { uint32_t crc = 0xFFFFFFFF; for (size_t i = 0; i < length; i++) { @@ -30,7 +30,7 @@ namespace crc32 { return ~crc; } - uint32_t checksum_file(const char *filename) { + uint32_t ChecksumFile(const char *filename) { FILE *file = fopen(filename, "rb"); if (!file) { perror("[crc32] Error opening file"); @@ -53,4 +53,4 @@ namespace crc32 { fclose(file); return ~crc; } -} // namespace crc32 +} // namespace util diff --git a/Source/hoc-clk/sysmodule/src/util/crc32.h b/Source/hoc-clk/sysmodule/src/util/crc32.h index 05e1bc70..779185c9 100644 --- a/Source/hoc-clk/sysmodule/src/util/crc32.h +++ b/Source/hoc-clk/sysmodule/src/util/crc32.h @@ -18,7 +18,7 @@ #pragma once #include #include -namespace crc32 { - uint32_t crc32(const uint8_t *data, size_t length); - uint32_t checksum_file(const char *filename); -} // namespace crc32 +namespace util { + uint32_t Crc32(const uint8_t *data, size_t length); + uint32_t ChecksumFile(const char *filename); +} // namespace util diff --git a/Source/hoc-clk/templates/kip/current.ini.template b/Source/hoc-clk/templates/kip/current.ini.template new file mode 100644 index 00000000..762564df --- /dev/null +++ b/Source/hoc-clk/templates/kip/current.ini.template @@ -0,0 +1 @@ +; Customize values applied to hoc.kip diff --git a/Source/hoc-clk/templates/profiles/README.ini b/Source/hoc-clk/templates/profiles/README.ini new file mode 100644 index 00000000..69c29ac1 --- /dev/null +++ b/Source/hoc-clk/templates/profiles/README.ini @@ -0,0 +1,11 @@ +; Per-title overclock profiles in this folder (one .ini file per game). +; .ini + +; Example: +; BOTW: DRAM OC in handheld for free performance + +; The Legend of Zelda Breath of the Wild (01007EF00011E000) +; File: 01007EF00011E000.ini +; [values] +; handheld_mem=1996 + diff --git a/Source/hoc-clk/templates/settings.ini.template b/Source/hoc-clk/templates/settings.ini.template new file mode 100644 index 00000000..d517e2bf --- /dev/null +++ b/Source/hoc-clk/templates/settings.ini.template @@ -0,0 +1 @@ +; General sysmodule settings diff --git a/build.sh b/build.sh index c8040a74..dcd48476 100755 --- a/build.sh +++ b/build.sh @@ -5,7 +5,8 @@ LDR_MAKE="nx_release" LDR_SET=0 NO_EXO=0 JOBS="" -UART_LOGGING=0 +DEBUG_BUILD=0 +SKIP="" ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" DIST_DIR="$ROOT_DIR/dist" @@ -19,12 +20,41 @@ while [ $# -gt 0 ]; do LDR_MAKE="${1#*=}" LDR_SET=1 ;; - -u|--uart) - UART_LOGGING=1 + -d|--debug) + DEBUG_BUILD=1 ;; --no-exo) NO_EXO=1 ;; + -s|--skip) + shift + SKIP_GOT=0 + while [ $# -gt 0 ]; do + case "$1" in + -*) + break + ;; + *) + SKIP="$SKIP $(printf '%s' "$1" | tr ',A-Z' ' a-z')" + SKIP_GOT=1 + shift + ;; + esac + done + if [ "$SKIP_GOT" -eq 0 ]; then + echo "Missing value for -s/--skip: expected one or more of: ldr clk hek btb exos sm zip" >&2 + exit 1 + fi + continue + ;; + --skip=*) + SKIP_ADD="$(printf '%s' "${1#*=}" | tr ',A-Z' ' a-z')" + if [ -z "$(printf '%s' "$SKIP_ADD" | tr -d ' ')" ]; then + echo "Missing value for --skip: expected one or more of: ldr clk hek btb exos sm zip" >&2 + exit 1 + fi + SKIP="$SKIP $SKIP_ADD" + ;; -j) shift JOBS="$1" @@ -40,13 +70,84 @@ while [ $# -gt 0 ]; do shift done -if [ "$UART_LOGGING" -eq 1 ] && [ "$LDR_SET" -eq 0 ]; then +if [ "$DEBUG_BUILD" -eq 1 ] && [ "$LDR_SET" -eq 0 ]; then LDR_MAKE="nx_audit" fi +should_skip() { + case " $SKIP " in + *" $1 "*) + return 0 + ;; + esac + return 1 +} + +require_toolchain() { + _tk_var="$1" + _tk_gcc="$2" + _tk_extra="$3" + _tk_need="$4" + eval "_tk_dir=\$$_tk_var" + if [ -z "$_tk_dir" ] && [ -n "$DEVKITPRO" ]; then + _tk_cand="$DEVKITPRO/devkit${_tk_var#DEVKIT}" + if [ -d "$_tk_cand" ]; then + eval "export $_tk_var=""$_tk_cand""" + _tk_dir="$_tk_cand" + fi + fi + if [ -z "$_tk_dir" ]; then + echo "error: $_tk_var is not set, but it is required to build $_tk_need." >&2 + echo "Install devkitPro (https://devkitpro.org/wiki/Getting_Started) and export $_tk_var." >&2 + exit 1 + fi + if [ ! -d "$_tk_dir" ]; then + echo "error: $_tk_var points to a missing directory: $_tk_dir" >&2 + exit 1 + fi + if [ -n "$_tk_extra" ] && [ ! -e "$_tk_dir/$_tk_extra" ]; then + echo "error: $_tk_dir/$_tk_extra not found. your devkitPro install looks incomplete." >&2 + exit 1 + fi + if ! command -v "$_tk_gcc" >/dev/null 2>&1 && [ ! -x "$_tk_dir/bin/$_tk_gcc" ]; then + echo "error: $_tk_gcc not found. Add $_tk_dir/bin to your PATH." >&2 + exit 1 + fi + unset _tk_var _tk_gcc _tk_extra _tk_need _tk_dir _tk_cand +} + +for _s in $SKIP; do + case "$_s" in + ldr|clk|hek|btb|exos|sm|zip) + ;; + *) + echo "Unknown skip component: $_s (valid components: ldr clk hek btb exos sm zip)" >&2 + exit 1 + ;; + esac +done +unset _s + +if should_skip exos; then + NO_EXO=1 +fi + +_NEED_A64=0 +if ! should_skip ldr; then _NEED_A64=1; fi +if ! should_skip clk; then _NEED_A64=1; fi +if [ "$EXT" -eq 1 ] && ! should_skip btb; then _NEED_A64=1; fi +if [ "$NO_EXO" -eq 0 ]; then _NEED_A64=1; fi +if [ "$_NEED_A64" -eq 1 ]; then + require_toolchain DEVKITA64 aarch64-none-elf-gcc "" "loader/exosphere/hoc-clk/benchmark-toolbox (devkitA64)" +fi +unset _NEED_A64 + LDR_BUILD_PATH="${LDR_MAKE#nx_}" echo +if [ -n "$SKIP" ]; then + echo "SKIP =$SKIP" +fi if [ "$EXT" -eq 1 ]; then echo "EXT = 1" fi @@ -55,8 +156,8 @@ if [ "$NO_EXO" -eq 1 ]; then echo "NO_EXO = 1" fi -if [ "$UART_LOGGING" -eq 1 ]; then - echo "UART_LOGGING = 1 (loader build: $LDR_MAKE, UART logging enabled)" +if [ "$DEBUG_BUILD" -eq 1 ]; then + echo "DEBUG_BUILD = 1 (loader build: $LDR_MAKE, debug build =)" fi CORES="$(nproc --all)" @@ -101,15 +202,18 @@ if [ "$NO_EXO" -eq 0 ]; then echo "*** Patching exosphere ***" EXO_SRC="Source/Atmosphere-Patches" EXO_DEST="build/atmosphere/exosphere/program/source/smc" + EXO_PROGRAM_DEST="build/atmosphere/exosphere/program/source" LIBEXO_DEST="build/atmosphere/libraries/libexosphere/include/exosphere/secmon" - cp -v "$EXO_SRC/secmon_emc_access_table_data.inc" "$EXO_DEST/" - cp -v "$EXO_SRC/secmon_define_emc_access_table.inc" "$EXO_DEST/" - cp -v "$EXO_SRC/secmon_rtc_pmc_access_table_data.inc" "$EXO_DEST/" - cp -v "$EXO_SRC/secmon_define_rtc_pmc_access_table.inc" "$EXO_DEST/" - cp -v "$EXO_SRC/secmon_smc_register_access.cpp" "$EXO_DEST/" - cp -v "$EXO_SRC/secmon_smc_handler.cpp" "$EXO_DEST/" - cp -v "$EXO_SRC/secmon_memory_layout.hpp" "$LIBEXO_DEST/" + cp -v "$EXO_SRC/secmon_define_emc_access_table.inc" "$EXO_DEST/" + cp -v "$EXO_SRC/secmon_emc_access_table_data.inc" "$EXO_DEST/" + cp -v "$EXO_SRC/secmon_define_emc01_access_table.inc" "$EXO_DEST/" + cp -v "$EXO_SRC/secmon_emc01_access_table_data.inc" "$EXO_DEST/" + cp -v "$EXO_SRC/secmon_define_rtc_pmc_access_table.inc" "$EXO_DEST/" + cp -v "$EXO_SRC/secmon_rtc_pmc_access_table_data.inc" "$EXO_DEST/" + cp -v "$EXO_SRC/secmon_smc_register_access.cpp" "$EXO_DEST/" + cp -v "$EXO_SRC/secmon_smc_handler.cpp" "$EXO_DEST/" + cp -v "$EXO_SRC/secmon_memory_layout.hpp" "$LIBEXO_DEST/" fi CCACHE_MKS="build/atmosphere/libraries/config/common.mk @@ -134,13 +238,18 @@ EOF fi done -echo -echo "*** Compiling loader ***" -cd build/atmosphere/stratosphere/loader || exit 1 -make -j$JOBS HOC_UART_LOG=$UART_LOGGING "$LDR_MAKE" -hactool -t kip1 "out/nintendo_nx_arm64_armv8a/$LDR_BUILD_PATH/loader.kip" --uncompress=hoc.kip -cd "$ROOT_DIR" # exit -cp -v build/atmosphere/stratosphere/loader/hoc.kip dist/atmosphere/kips/hoc.kip +if should_skip ldr; then + echo + echo "*** Skipping loader ***" +else + echo + echo "*** Compiling loader ***" + cd build/atmosphere/stratosphere/loader || exit 1 + make -j$JOBS HOC_UART_LOG=$DEBUG_BUILD "$LDR_MAKE" + hactool -t kip1 "out/nintendo_nx_arm64_armv8a/$LDR_BUILD_PATH/loader.kip" --uncompress=hoc.kip + cd "$ROOT_DIR" # exit + cp -v build/atmosphere/stratosphere/loader/hoc.kip dist/atmosphere/kips/hoc.kip +fi if [ "$NO_EXO" -eq 0 ]; then echo @@ -157,63 +266,97 @@ if [ -n "$ATMOSPHERE_CCACHE" ]; then ccache --show-stats fi -cd Source/hoc-clk/ -./build.sh -cp -r dist/ ../../ +if should_skip clk; then + echo + echo "*** Skipping hoc-clk ***" +else + cd Source/hoc-clk/ || exit 1 + if [ "$DEBUG_BUILD" -eq 1 ]; then + ./build.sh "" -d + else + ./build.sh + fi + cp -r dist/ ../../ -cd "$ROOT_DIR" + cd "$ROOT_DIR" +fi -echo "*** Downloading Status-Monitor ***" -wget "https://github.com/ppkantorski/Status-monitor-overlay/releases/latest/download/Status-Monitor-Overlay.ovl" -mv -v Status-Monitor-Overlay.ovl "$DIST_DIR"/switch/.overlays/Status-Monitor-Overlay.ovl +if should_skip sm; then + echo + echo "*** Skipping Status-Monitor ***" +else + echo "*** Downloading Status-Monitor ***" + wget "https://github.com/ppkantorski/Status-monitor-overlay/releases/latest/download/Status-Monitor-Overlay.ovl" + mv -v Status-Monitor-Overlay.ovl "$DIST_DIR"/switch/.overlays/Status-Monitor-Overlay.ovl +fi if [ "$EXT" -eq 1 ]; then - cd Source/ - echo echo "*** Compiling extensions ***" - HEKATE_DIR="hekate" - HEKATE_URL="https://github.com/Horizon-OC/hekate.git" - - if [ ! -d "$HEKATE_DIR" ]; then + if should_skip hek; then echo - echo "*** Cloning custom Hekate ***" - git clone "$HEKATE_URL" "$HEKATE_DIR" + echo "*** Skipping custom Hekate ***" + else + require_toolchain DEVKITARM arm-none-eabi-gcc base_rules "custom Hekate (devkitARM)" + + HEKATE_DIR="$ROOT_DIR/Source/hekate" + HEKATE_URL="https://github.com/Horizon-OC/hekate.git" + + if [ ! -d "$HEKATE_DIR" ]; then + echo + echo "*** Cloning custom Hekate ***" + git clone "$HEKATE_URL" "$HEKATE_DIR" || exit 1 + else + echo + echo "*** Updating custom Hekate ***" + git -C "$HEKATE_DIR" pull --ff-only || exit 1 + fi + + cd "$HEKATE_DIR" || exit 1 + echo + echo "*** Compiling custom Hekate ***" + # Prevent crash on MSYS2 + make -j"$JOBS" SHELL=/usr/bin/bash || exit 1 + echo + + mkdir -p "$DIST_DIR/bootloader/sys/" + cp -v output/nyx.bin "$DIST_DIR/bootloader/sys/nyx.bin" + cp -v output/hekate.bin "$DIST_DIR/bootloader/update.bin" + cp -v output/hekate.bin "$DIST_DIR/payload.bin" fi - cd hekate/ - echo - echo "*** Compiling custom Hekate ***" - make -j$JOBS - echo - - mkdir -p "$DIST_DIR/bootloader/sys/" - cp -v output/nyx.bin "$ROOT_DIR"/dist/bootloader/sys/nyx.bin - cp -v output/hekate.bin "$ROOT_DIR"/dist/bootloader/update.bin - cp -v output/hekate.bin "$ROOT_DIR"/dist/payload.bin - - cd "$ROOT_DIR"/Source/Benchmark-Toolbox - echo - echo "*** Compiling Benchmark-Toolbox ***" - make -j$JOBS - cp -v Benchmark-Toolbox.nro "$DIST_DIR"/switch/Benchmark-Toolbox.nro + if should_skip btb; then + echo + echo "*** Skipping Benchmark-Toolbox ***" + else + cd "$ROOT_DIR/Source/Benchmark-Toolbox" || exit 1 + echo + echo "*** Compiling Benchmark-Toolbox ***" + make -j"$JOBS" || exit 1 + cp -v Benchmark-Toolbox.nro "$DIST_DIR/switch/Benchmark-Toolbox.nro" + fi fi -echo -echo "*** Packaging dist.zip ***" +if should_skip zip; then + echo + echo "*** Skipping dist.zip packaging ***" +else + echo + echo "*** Packaging dist.zip ***" -cd "$DIST_DIR" || exit 1 + cd "$DIST_DIR" || exit 1 -rm -f dist.zip -rm .gitignore + rm -f dist.zip + rm .gitignore -zip -r dist.zip . >/dev/null + zip -r dist.zip . >/dev/null -echo "*** dist.zip created ***" -echo + echo "*** dist.zip created ***" + echo -touch .gitignore + touch .gitignore -cd "$ROOT_DIR" || exit 1 + cd "$ROOT_DIR" || exit 1 +fi