hocmon: fix hocmon

This commit is contained in:
souldbminersmwc
2026-04-02 16:29:42 -04:00
parent 78a52df596
commit 234fb1655c
12 changed files with 966 additions and 414 deletions

View File

@@ -32,7 +32,7 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to
---
## Features
## Default clocks
* **CPU:** Up to 1963MHz (Mariko) / 1785MHz (Erista)
* **GPU:** Up to 1075MHz (Mariko) / 921MHz (Erista)
@@ -93,7 +93,8 @@ Refer to COMPILATION.md
* 665
### CPU clocks
* 2601 → mariko absolute max, very dangerous
* 2703 → mariko absolute max, dangerous
* 2601 → unsafe
* 2499
* 2397 → mariko safe max with UV (low speedo)
* 2295
@@ -114,9 +115,6 @@ Refer to COMPILATION.md
* 714
* 612 → sleep mode
**Notes:**
1. On Erista, CPU in handheld is capped to 1581MHz
### GPU clocks
* 1536 → absolute max clock on mariko. very dangerous
* 1459
@@ -142,27 +140,31 @@ Refer to COMPILATION.md
* 76 → boost mode
**Notes:**
1. GPU overclock is capped at 460MHz on erista in handheld
2. On Mariko, cap with No uv is 614MHz, with SLT it is 691MHz and with HiOPT it's 768MHz
3. Clocks higher than 768MHz on erista need the official charger is plugged in.
4. On Mariko, cap with No uv is 844MHz, with SLT it is 921MHz and with HiOPT it's 998MHz
1. On Erista, CPU in handheld is capped to 1581MHz
2. GPU overclock is capped at 460MHz on erista in handheld
3. On Mariko, cap with No uv is 614MHz, with SLT it is 691MHz and with HiOPT it's 768MHz
4. Clocks higher than 768MHz on erista need the official charger is plugged in.
5. On Mariko, cap with No uv is 844MHz, with SLT it is 921MHz and with HiOPT it's 998MHz
---
## Credits
* **Lightos's Cat** - Cat
* **Souldbminer** hoc-clk and loader development
* **Lightos** loader patches development
* **Souldbminer** - hoc-clk and loader development
* **Lightos** - Loader patches development, hoc-clk development, guides
* **SciresM** - Atmosphere CFW
* **CTCaer** - L4T, Hekate, perfect ram timings
* **KazushiMe** Switch OC Suite
* **hanai3bi (meha)** Switch OC Suite, EOS, sys-clk-eos
* **NaGaa95** L4T-OC-kernel
* **B3711 (halop)** EOS
* **sys-clk team (m4xw, p-sam, natinusala)** sys-clk
* **b0rd2death** Ultrahand sys-clk & Status Monitor fork
* **CTCaer** - L4T, Hekate, proper RAM timings
* **KazushiMe** - Switch OC Suite
* **Hanai3bi (Meha)** - Switch OC Suite, EOS, sys-clk-eos
* **NaGaa95** - L4T-OC kernel, Status Monitor fork
* **B3711 (halop)** - EOS
* **sys-clk team (m4xw, p-sam, natinusala)** - sys-clk
* **Dominatorul** - Soctherm driver, guides, general help
* **b0rd2death** - Ultrahand sys-clk & Status Monitor fork
* **MasaGratoR and ZachyCatGames** - General help
* **MasaGratoR** - Status Monitor & Display Refresh Rate Driver
* **Dom, Samybigio, Arcdelta, Miki, Happy, Flopsider, Winnerboi77, Blaise, Alvise, TDRR, agjeococh, frost, letum00 and Xenshen** - Testing
* **MasaGratoR** - Status Monitor & Display Refresh Rate driver
* **Dominatorul, Samybigio, Arcdelta, Miki, Happy, Flopsider, Winnerboi77, Blaise, Alvise, TDRR, agjeococh, frost, letum00, and Xenshen** - Testing
* **Samybigio2011** - Italian translations
* **Nvidia** - [Tegra X1 Technical Reference Manual](https://developer.nvidia.com/embedded/dlc/tegra-x1-technical-reference-manual), soctherm driver, L4T

View File

@@ -144,18 +144,18 @@ namespace ams::ldr::hoc::pcv {
using namespace ams::ldr::hoc::pcv;
sValidator validators[] = {
{ C.eristaCpuBoostClock, 1020'000, 2295'000, true, panic::Cpu },
{ C.eristaCpuBoostClock, 1020'000, 2397'000, true, panic::Cpu },
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true, panic::Cpu },
{ C.eristaCpuMaxVolt, 1000, 1260, false, panic::Cpu },
{ C.marikoCpuMaxVolt, 1000, 1200, false, panic::Cpu },
{ eristaCpuDvfsMaxFreq, 1785'000, 2295'000, false, panic::Cpu },
{ eristaCpuDvfsMaxFreq, 1785'000, 2397'000, false, panic::Cpu },
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu },
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
{ C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc },
{ C.marikoEmcVddqVolt, 250'000, 700'000, false, panic::Emc },
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu },
{ marikoGpuDvfsMaxFreq, 768'000, 1570'000, false, panic::Gpu },
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000, false, panic::Gpu },
{ C.marikoGpuVmax, 800, 960, false, panic::Gpu },
};

View File

@@ -0,0 +1 @@
Thanks to NaGa for Status Monitor Pro!

View File

@@ -83,7 +83,7 @@ Result nvdecCheck = 1;
Result nvencCheck = 1;
Result nvjpgCheck = 1;
Result nifmCheck = 1;
Result sysclkCheck = 0;
Result sysclkCheck = 1;
Result pwmDutyCycleCheck = 1;
//Wi-Fi
@@ -225,11 +225,15 @@ uint32_t realRAM_Hz = 0;
uint32_t partLoad[SysClkPartLoad_EnumMax];
uint32_t realCPU_mV = 0;
uint32_t realGPU_mV = 0;
uint32_t realVDD2_mV = 0;
uint32_t realVDDQ_mV = 0;
uint32_t realRAM_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;
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;
@@ -521,7 +525,6 @@ bool usingEOS() {
return versionString.find("eos") != std::string::npos;
}
// === ULTRA-FAST VOLTAGE READING ===
static constexpr PowerDomainId domains[] = {
PcvPowerDomainId_Max77621_Cpu, // [0] CPU
@@ -572,20 +575,29 @@ void Misc(void*) {
}
// Get sys-clk data
SysClkContext sysclkCTX;
if (R_SUCCEEDED(sysclkIpcGetCurrentContext(&sysclkCTX))) {
realCPU_Hz = sysclkCTX.realFreqs[SysClkModule_CPU];
realGPU_Hz = sysclkCTX.realFreqs[SysClkModule_GPU];
realRAM_Hz = sysclkCTX.realFreqs[SysClkModule_MEM];
partLoad[SysClkPartLoad_EMC] = sysclkCTX.partLoad[SysClkPartLoad_EMC];
partLoad[SysClkPartLoad_EMCCpu] = sysclkCTX.partLoad[SysClkPartLoad_EMCCpu];
realCPU_mV = sysclkCTX.voltages[HocClkVoltage_CPU];
realGPU_mV = sysclkCTX.voltages[HocClkVoltage_GPU];
realVDD2_mV = sysclkCTX.voltages[HocClkVoltage_EMCVDD2];
realVDDQ_mV = sysclkCTX.voltages[HocClkVoltage_EMCVDDQ];
realSOC_mV = sysclkCTX.voltages[HocClkVoltage_SOC];
if (R_SUCCEEDED(sysclkCheck)) {
SysClkContext sysclkCTX;
if (R_SUCCEEDED(sysclkIpcGetCurrentContext(&sysclkCTX))) {
realCPU_Hz = sysclkCTX.realFreqs[SysClkModule_CPU];
realGPU_Hz = sysclkCTX.realFreqs[SysClkModule_GPU];
realRAM_Hz = sysclkCTX.realFreqs[SysClkModule_MEM];
partLoad[SysClkPartLoad_EMC] = sysclkCTX.partLoad[SysClkPartLoad_EMC];
partLoad[SysClkPartLoad_EMCCpu] = sysclkCTX.partLoad[SysClkPartLoad_EMCCpu];
realCPU_Temp = sysclkCTX.temps[HorizonOCThermalSensor_CPU];
realGPU_Temp = sysclkCTX.temps[HorizonOCThermalSensor_GPU];
realRAM_Temp = sysclkCTX.temps[HorizonOCThermalSensor_MEM];
realCPU_mV = sysclkCTX.voltages[HocClkVoltage_CPU];
realGPU_mV = sysclkCTX.voltages[HocClkVoltage_GPU];
realRAM_mV = sysclkCTX.voltages[HocClkVoltage_EMCVDD2];
realSOC_mV = sysclkCTX.voltages[HocClkVoltage_SOC];
const u32 vdd2_mV = sysclkCTX.voltages[HocClkVoltage_EMCVDD2] / 1000; // µV to mV
const u32 vddq_mV = sysclkCTX.voltages[HocClkVoltage_EMCVDDQ] / 1000; // µV to mV
realRAM_mV = vdd2_mV * 100000 + vddq_mV * 10;
}
}
// Temperatures
if (R_SUCCEEDED(i2cCheck)) {
@@ -685,7 +697,7 @@ void Misc2(void*) {
void Misc3(void*) {
const bool isUsingEOS = usingEOS();
// Initialize voltage reading if needed
bool canReadVoltages = false;
if (!isUsingEOS && realVoltsPolling) {
@@ -694,10 +706,33 @@ void Misc3(void*) {
realVoltsPolling = false;
}
}
do {
mutexLock(&mutex_Misc);
// Get sys-clk data
if (R_SUCCEEDED(sysclkCheck)) {
SysClkContext sysclkCTX;
if (R_SUCCEEDED(sysclkIpcGetCurrentContext(&sysclkCTX))) {
partLoad[SysClkPartLoad_EMC] = sysclkCTX.partLoad[SysClkPartLoad_EMC];
partLoad[SysClkPartLoad_EMCCpu] = sysclkCTX.partLoad[SysClkPartLoad_EMCCpu];
realCPU_Temp = sysclkCTX.temps[HorizonOCThermalSensor_CPU];
realGPU_Temp = sysclkCTX.temps[HorizonOCThermalSensor_GPU];
realRAM_Temp = sysclkCTX.temps[HorizonOCThermalSensor_MEM];
realCPU_mV = sysclkCTX.voltages[HocClkVoltage_CPU];
realGPU_mV = sysclkCTX.voltages[HocClkVoltage_GPU];
realRAM_mV = sysclkCTX.voltages[HocClkVoltage_EMCVDD2];
realSOC_mV = sysclkCTX.voltages[HocClkVoltage_SOC];
const u32 vdd2_mV = sysclkCTX.voltages[HocClkVoltage_EMCVDD2] / 1000; // µV to mV
const u32 vddq_mV = sysclkCTX.voltages[HocClkVoltage_EMCVDDQ] / 1000; // µV to mV
realRAM_mV = vdd2_mV * 100000 + vddq_mV * 10;
}
}
// Temperatures
if (R_SUCCEEDED(i2cCheck)) {
Tmp451GetSocTemp(&SOC_temperatureF);
@@ -706,7 +741,7 @@ void Misc3(void*) {
if (R_SUCCEEDED(tcCheck)) {
tcGetSkinTemperatureMilliC(&skin_temperaturemiliC);
}
// Fan
if (R_SUCCEEDED(pwmCheck)) {
double temp = 0;
@@ -720,21 +755,16 @@ void Misc3(void*) {
}
}
}
// GPU Load
if (R_SUCCEEDED(nvCheck)) {
nvIoctl(fd, NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD, &GPU_Load_u);
}
SysClkContext sysclkCTX;
if (R_SUCCEEDED(sysclkIpcGetCurrentContext(&sysclkCTX))) {
partLoad[SysClkPartLoad_EMC] = sysclkCTX.partLoad[SysClkPartLoad_EMC];
}
mutexUnlock(&mutex_Misc);
} while (!leventWait(&threadexit, 1'000'000'000)); // 1 second timeout
// Cleanup voltage reading if initialized
if (canReadVoltages) {
rgltrExit();
@@ -1239,6 +1269,7 @@ struct FullSettings {
bool setPosRight;
bool showRealFreqs;
bool realVolts;
bool realTemps;
bool showDeltas;
bool showTargetFreqs;
bool showFPS;
@@ -1256,6 +1287,7 @@ struct MiniSettings {
uint8_t refreshRate;
bool realFrequencies;
bool realVolts;
bool realTemps;
bool showFullCPU;
bool showFullResolution;
bool showFanPercentage;
@@ -1276,8 +1308,8 @@ struct MiniSettings {
uint16_t catColor;
uint16_t textColor;
std::string show;
bool showRAMLoad;
bool showRAMLoadCPUGPU;
bool showpartLoad;
bool showpartLoadCPUGPU;
bool invertBatteryDisplay;
bool disableScreenshots;
bool sleepExit;
@@ -1291,6 +1323,7 @@ struct MicroSettings {
uint8_t refreshRate;
bool realFrequencies;
bool realVolts;
bool realTemps;
bool showFullCPU;
bool showFullResolution;
bool showSOCVoltage;
@@ -1310,7 +1343,7 @@ struct MicroSettings {
uint16_t catColor;
uint16_t textColor;
std::string show;
bool showRAMLoad;
bool showpartLoad;
bool setPosBottom;
bool disableScreenshots;
bool sleepExit;
@@ -1333,6 +1366,7 @@ struct FpsCounterSettings {
struct FpsGraphSettings {
bool showInfo;
bool realTemps;
uint8_t refreshRate;
uint16_t backgroundColor;
uint16_t focusBackgroundColor;
@@ -1373,6 +1407,7 @@ 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;
@@ -1394,8 +1429,8 @@ ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) {
convertStrToRGBA4444("#2DFF", &(settings->catColor));
convertStrToRGBA4444("#FFFF", &(settings->textColor));
settings->show = "DTC+BAT+CPU+GPU+RAM+TMP+FPS+RES";
settings->showRAMLoad = true;
settings->showRAMLoadCPUGPU = false;
settings->showpartLoad = true;
settings->showpartLoadCPUGPU = false;
settings->invertBatteryDisplay = true;
settings->refreshRate = 1;
settings->disableScreenshots = false;
@@ -1449,7 +1484,13 @@ ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) {
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;
@@ -1587,7 +1628,7 @@ ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) {
if (it != section.end()) {
key = it->second;
convertToUpper(key);
settings->showRAMLoad = (key != "FALSE");
settings->showpartLoad = (key != "FALSE");
}
// Process CPU/GPU RAM load flag
@@ -1595,7 +1636,7 @@ ALWAYS_INLINE void GetConfigSettings(MiniSettings* settings) {
if (it != section.end()) {
key = it->second;
convertToUpper(key);
settings->showRAMLoadCPUGPU = (key != "FALSE");
settings->showpartLoadCPUGPU = (key != "FALSE");
}
// Invert the battery display value
@@ -1665,6 +1706,7 @@ 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;
@@ -1684,7 +1726,7 @@ ALWAYS_INLINE void GetConfigSettings(MicroSettings* settings) {
convertStrToRGBA4444("#2DFF", &(settings->catColor));
convertStrToRGBA4444("#FFFF", &(settings->textColor));
settings->show = "FPS+CPU+GPU+RAM+SOC+BAT+DTC";
settings->showRAMLoad = true;
settings->showpartLoad = true;
settings->setPosBottom = false;
settings->disableScreenshots = false;
settings->sleepExit = false;
@@ -1734,6 +1776,13 @@ ALWAYS_INLINE void GetConfigSettings(MicroSettings* settings) {
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()) {
@@ -1874,7 +1923,7 @@ ALWAYS_INLINE void GetConfigSettings(MicroSettings* settings) {
if (it != section.end()) {
key = it->second;
convertToUpper(key);
settings->showRAMLoad = (key != "FALSE");
settings->showpartLoad = (key != "FALSE");
}
// Process show string
@@ -2046,6 +2095,7 @@ ALWAYS_INLINE void GetConfigSettings(FpsCounterSettings* settings) {
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));
@@ -2124,6 +2174,15 @@ ALWAYS_INLINE void GetConfigSettings(FpsGraphSettings* settings) {
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()) {
@@ -2192,6 +2251,7 @@ ALWAYS_INLINE void GetConfigSettings(FullSettings* settings) {
settings->setPosRight = false;
settings->refreshRate = 1;
settings->showRealFreqs = true;
settings->realTemps = false;
settings->showDeltas = true;
settings->showTargetFreqs = true;
settings->showFPS = true;
@@ -2250,6 +2310,13 @@ ALWAYS_INLINE void GetConfigSettings(FullSettings* settings) {
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;
@@ -2458,4 +2525,4 @@ ALWAYS_INLINE void GetConfigSettings(ResolutionSettings* settings) {
convertToUpper(key);
settings->disableScreenshots = (key != "FALSE");
}
}
}

View File

@@ -129,10 +129,8 @@ public:
//}
//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()) {
if (!lastSelectedItem.empty())
list->jumpToItem(lastSelectedItem);
}
lastSelectedItem = "Other";
rootFrame->setContent(list);
@@ -158,7 +156,7 @@ public:
}
if (keysDown & KEY_B) {
lastSelectedItem = "Other";
tsl::swapTo<MainMenu>();
triggerRumbleDoubleClick.store(true, std::memory_order_release);
triggerExitSound.store(true, std::memory_order_release);
@@ -369,11 +367,8 @@ public:
});
list->addItem(Other);
if (!lastSelectedItem.empty()) {
if (!lastSelectedItem.empty())
list->jumpToItem(lastSelectedItem);
lastSelectedItem = "";
}
//list->disableCaching();
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION);
@@ -446,6 +441,14 @@ public:
if (SaltySD) {
LoadSharedMemoryAndRefreshRate();
}
if (sysclkIpcRunning() && R_SUCCEEDED(sysclkIpcInitialize())) {
uint32_t sysClkApiVer = 0;
sysclkIpcGetAPIVersion(&sysClkApiVer);
if (sysClkApiVer != SYSCLK_IPC_API_VERSION) {
sysclkIpcExit();
}
else sysclkCheck = 0;
}
if (R_SUCCEEDED(splInitialize())) {
u64 sku = 0;
splGetConfig(SplConfigItem_HardwareType, &sku);
@@ -458,14 +461,16 @@ public:
}
}
splExit();
sysclkIpcInitialize();
});
Hinted = envIsSyscallHinted(0x6F);
}
virtual void exitServices() override {
CloseThreads();
sysclkIpcExit();
if (R_SUCCEEDED(sysclkCheck)) {
sysclkIpcExit();
}
shmemClose(&_sharedmemory);
//Exit services
clkrstExit();
@@ -520,6 +525,14 @@ public:
if (SaltySD) {
LoadSharedMemory();
}
if (sysclkIpcRunning() && R_SUCCEEDED(sysclkIpcInitialize())) {
uint32_t sysClkApiVer = 0;
sysclkIpcGetAPIVersion(&sysClkApiVer);
if (sysClkApiVer != SYSCLK_IPC_API_VERSION) {
sysclkIpcExit();
}
else sysclkCheck = 0;
}
if (R_SUCCEEDED(splInitialize())) {
u64 sku = 0;
splGetConfig(SplConfigItem_HardwareType, &sku);
@@ -532,7 +545,6 @@ public:
}
}
splExit();
sysclkIpcInitialize();
});
Hinted = envIsSyscallHinted(0x6F);
}
@@ -540,7 +552,9 @@ public:
virtual void exitServices() override {
CloseThreads();
shmemClose(&_sharedmemory);
sysclkIpcExit();
if (R_SUCCEEDED(sysclkCheck)) {
sysclkIpcExit();
}
//Exit services
clkrstExit();
pcvExit();
@@ -598,6 +612,14 @@ public:
if (SaltySD) {
LoadSharedMemory();
}
if (sysclkIpcRunning() && R_SUCCEEDED(sysclkIpcInitialize())) {
uint32_t sysClkApiVer = 0;
sysclkIpcGetAPIVersion(&sysClkApiVer);
if (sysClkApiVer != SYSCLK_IPC_API_VERSION) {
sysclkIpcExit();
}
else sysclkCheck = 0;
}
if (R_SUCCEEDED(splInitialize())) {
u64 sku = 0;
splGetConfig(SplConfigItem_HardwareType, &sku);
@@ -610,7 +632,6 @@ public:
}
}
splExit();
sysclkIpcInitialize();
});
Hinted = envIsSyscallHinted(0x6F);
@@ -619,7 +640,9 @@ public:
virtual void exitServices() override {
CloseThreads();
shmemClose(&_sharedmemory);
sysclkIpcExit();
if (R_SUCCEEDED(sysclkCheck)) {
sysclkIpcExit();
}
// Exit services
clkrstExit();
pcvExit();
@@ -679,6 +702,14 @@ public:
if (SaltySD) {
LoadSharedMemoryAndRefreshRate();
}
if (sysclkIpcRunning() && R_SUCCEEDED(sysclkIpcInitialize())) {
uint32_t sysClkApiVer = 0;
sysclkIpcGetAPIVersion(&sysClkApiVer);
if (sysClkApiVer != SYSCLK_IPC_API_VERSION) {
sysclkIpcExit();
}
else sysclkCheck = 0;
}
if (R_SUCCEEDED(splInitialize())) {
u64 sku = 0;
splGetConfig(SplConfigItem_HardwareType, &sku);
@@ -691,7 +722,6 @@ public:
}
}
splExit();
sysclkIpcInitialize();
});
Hinted = envIsSyscallHinted(0x6F);
}
@@ -699,7 +729,9 @@ public:
virtual void exitServices() override {
CloseThreads();
shmemClose(&_sharedmemory);
sysclkIpcExit();
if (R_SUCCEEDED(sysclkCheck)) {
sysclkIpcExit();
}
clkrstExit();
pcvExit();
tsExit();
@@ -753,6 +785,14 @@ public:
if (SaltySD) {
LoadSharedMemoryAndRefreshRate();
}
if (sysclkIpcRunning() && R_SUCCEEDED(sysclkIpcInitialize())) {
uint32_t sysClkApiVer = 0;
sysclkIpcGetAPIVersion(&sysClkApiVer);
if (sysClkApiVer != SYSCLK_IPC_API_VERSION) {
sysclkIpcExit();
}
else sysclkCheck = 0;
}
if (R_SUCCEEDED(splInitialize())) {
u64 sku = 0;
splGetConfig(SplConfigItem_HardwareType, &sku);
@@ -765,7 +805,6 @@ public:
}
}
splExit();
sysclkIpcInitialize();
});
Hinted = envIsSyscallHinted(0x6F);
}
@@ -773,7 +812,9 @@ public:
virtual void exitServices() override {
CloseThreads();
shmemClose(&_sharedmemory);
sysclkIpcExit();
if (R_SUCCEEDED(sysclkCheck)) {
sysclkIpcExit();
}
clkrstExit();
pcvExit();
tsExit();
@@ -827,6 +868,14 @@ public:
if (SaltySD) {
LoadSharedMemoryAndRefreshRate();
}
if (sysclkIpcRunning() && R_SUCCEEDED(sysclkIpcInitialize())) {
uint32_t sysClkApiVer = 0;
sysclkIpcGetAPIVersion(&sysClkApiVer);
if (sysClkApiVer != SYSCLK_IPC_API_VERSION) {
sysclkIpcExit();
}
else sysclkCheck = 0;
}
if (R_SUCCEEDED(splInitialize())) {
u64 sku = 0;
splGetConfig(SplConfigItem_HardwareType, &sku);
@@ -839,7 +888,6 @@ public:
}
}
splExit();
sysclkIpcInitialize();
});
Hinted = envIsSyscallHinted(0x6F);
}
@@ -847,7 +895,9 @@ public:
virtual void exitServices() override {
CloseThreads();
shmemClose(&_sharedmemory);
sysclkIpcExit();
if (R_SUCCEEDED(sysclkCheck)) {
sysclkIpcExit();
}
clkrstExit();
pcvExit();
tsExit();
@@ -931,7 +981,7 @@ inline void setupMode(const std::string& modeType = "") {
// 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 Horizon OC Monitor directive)
// 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;

View File

@@ -30,7 +30,7 @@ public:
disableJumpTo = true;
mutexInit(&mutex_BatteryChecker);
StartBatteryThread();
//tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
// tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
}
~BatteryOverlay() {
CloseBatteryThread();
@@ -141,8 +141,8 @@ public:
}
});
//tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION, true);
// tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Status Monitor Pro", APP_VERSION, true);
rootFrame->setContent(Status);
return rootFrame;

File diff suppressed because it is too large Load Diff

View File

@@ -13,6 +13,9 @@ private:
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;
@@ -402,19 +405,37 @@ public:
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: SOC (with gradient color)
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: PCB (with gradient color)
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: SKIN (with gradient color)
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);
}
});
// 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);
@@ -470,6 +491,16 @@ public:
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);

View File

@@ -20,6 +20,9 @@ private:
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] = "";
@@ -233,10 +236,12 @@ public:
else if (realRAM_Hz && settings.showDeltas && (settings.showRealFreqs || settings.showTargetFreqs)) {
renderer->drawString(DeltaRAM_c, false, COMMON_MARGIN + deltaOffset, height_offset, 15, (settings.textColor));
}
static std::vector<std::string> PartLoadColoredChars = {"CPU", "GPU"};
//static auto loadLabelWidth = renderer->getTextDimensions("Load: ", false, 15).first;
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(sysclkCheck)) {
static std::vector<std::string> partLoadColoredChars = {"CPU", "GPU"};
//static auto loadLabelWidth = renderer->getTextDimensions("Load: ", false, 15).first;
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)) {
//static auto textWidth = renderer->getTextDimensions("Total \nApplication \nApplet \nSystem \nSystem Unsafe ", false, 15).first;
@@ -289,6 +294,41 @@ public:
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) {
@@ -458,6 +498,17 @@ public:
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);

View File

@@ -18,6 +18,9 @@ private:
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];
@@ -539,7 +542,127 @@ public:
if (settings.useDynamicColors) {
// Draw data with temperature gradient support
if (item.type == 3) { // SOC temperature
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("°");
@@ -758,6 +881,12 @@ public:
"%.0f%%%s%u.%u",
maxUsage, cpuDiff, cpuFreq / 1000000, (cpuFreq / 100000) % 10);
}
if (settings.realTemps && realCPU_Temp != 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",
@@ -782,6 +911,12 @@ public:
"%u%%%s%u.%u",
GPU_Load_u / 10,
gpuDiff, gpuFreq / 1000000, (gpuFreq / 100000) % 10);
if (settings.realTemps && realGPU_Temp != 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",
@@ -811,7 +946,7 @@ public:
// RAM usage and frequency
char MICRO_RAM_all_c[16];
if (!settings.showRAMLoad) {
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);
@@ -826,8 +961,8 @@ public:
// 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 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);
}
}
@@ -841,6 +976,12 @@ public:
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) {
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;
@@ -857,8 +998,8 @@ public:
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; // VDD2
const uint32_t mv_vddq = realVDDQ_mV / 1000; // VDDQ
const float mv_vdd2 = (realRAM_mV / 10000) / 10.0f; // VDD2
const uint32_t mv_vddq = (realRAM_mV % 100000) / 10; // VDDQ
// Build voltage string based on settings
RAM_volt_c[0] = '\0'; // Start with empty string
@@ -955,6 +1096,18 @@ public:
} 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), " %.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);
}
}
// Resolution processing
//char RES_var_compressed_c[32] = "";

View File

@@ -8,6 +8,9 @@ private:
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];
@@ -354,10 +357,13 @@ public:
else
width = renderer->getTextDimensions("100%@4444.4444 mV", false, fontsize).first;
}
} else if (key == "GPU" || (key == "RAM" && settings.showRAMLoad)) {
if (settings.realTemps) {
width += renderer->getTextDimensions(" 888.8°C", false, fontsize).first;
}
} else if (key == "GPU" || (key == "RAM" && settings.showpartLoad && R_SUCCEEDED(sysclkCheck))) {
//dimensions = renderer->drawString("100.0%@4444.4", false, 0, 0, fontsize, renderer->a(0x0000));
if (!settings.showRAMLoadCPUGPU) {
if (!settings.showpartLoadCPUGPU) {
if (!settings.realVolts) {
width = renderer->getTextDimensions("100%@4444.4", false, fontsize).first;
} else {
@@ -370,10 +376,16 @@ public:
width = renderer->getTextDimensions("100%[100%,100%]@4444.4444 mV", false, fontsize).first;
}
}
} else if (key == "RAM" && (!settings.showRAMLoad)) {
if (key == "GPU" && settings.realTemps) {
width += renderer->getTextDimensions(" 88.8°C", false, fontsize).first;
}
} else if (key == "RAM" && (!settings.showpartLoad || R_FAILED(sysclkCheck))) {
//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)
@@ -676,7 +688,130 @@ public:
const int baseY = currentY + frameOffsetY + clippingOffsetY;
if (settings.useDynamicColors) {
if (labelIndex < labelLines.size() && labelLines[labelIndex] == "SOC") {
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) {
@@ -867,7 +1002,7 @@ public:
// Variables to store formatted strings
char MINI_CPU_compressed_c[42] = "";
char MINI_CPU_volt_c[16] = "";
char MINI_GPU_Load_c[20] = "";
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] = "";
@@ -934,6 +1069,12 @@ public:
snprintf(MINI_CPU_volt_c, sizeof(MINI_CPU_volt_c), "%u mV", mv);
}
}
if (settings.realTemps && realCPU_Temp != 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")) {
@@ -968,10 +1109,16 @@ public:
snprintf(MINI_GPU_volt_c, sizeof(MINI_GPU_volt_c), "%u mV", mv);
}
}
if (settings.realTemps && realGPU_Temp != 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.showRAMLoad) {
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);
@@ -991,43 +1138,61 @@ public:
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
}
} else {
unsigned PartLoadInt;
unsigned partLoadInt;
PartLoadInt = partLoad[SysClkPartLoad_EMC] / 10;
if (settings.showRAMLoadCPUGPU) {
unsigned ramCpuLoadInt = partLoad[SysClkPartLoad_EMCCpu] / 10;
int RAM_GPU_Load = partLoad[SysClkPartLoad_EMC] - partLoad[SysClkPartLoad_EMCCpu];
unsigned ramGpuLoadInt = RAM_GPU_Load / 10;
if (R_SUCCEEDED(sysclkCheck)) {
partLoadInt = partLoad[SysClkPartLoad_EMC] / 10;
if (settings.showpartLoadCPUGPU) {
unsigned ramCpuLoadInt = partLoad[SysClkPartLoad_EMCCpu] / 10;
int RAM_GPU_Load = partLoad[SysClkPartLoad_EMC] - partLoad[SysClkPartLoad_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%%[%u%%,%u%%]@%hu.%hhu",
PartLoadInt, ramCpuLoadInt, ramGpuLoadInt,
realRAM_Hz / 1000000, (realRAM_Hz / 100000) % 10);
"%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%%[%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);
"%u%%@%hu.%hhu", partLoadInt,
RAM_Hz / 1000000, (RAM_Hz / 100000) % 10);
}
}
}
if (settings.realVolts) {
const float mv_vdd2_f = realVDD2_mV / 100000.0f;
const uint32_t mv_vdd2_i = realVDD2_mV / 1000;
const uint32_t mv_vddq = realVDDQ_mV / 1000;
const float mv_vdd2_f = realRAM_mV / 100000.0f;
const uint32_t mv_vdd2_i = realRAM_mV / 100000;
const uint32_t mv_vddq = (realRAM_mV % 100000) / 10;
if (isMariko) {
if (settings.showVDDQ && settings.showVDD2) {
@@ -1053,6 +1218,11 @@ public:
}
}
}
if (settings.realTemps && realRAM_Temp != 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")) {
@@ -1117,6 +1287,18 @@ public:
}
}
}
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);
}
}
// Only process resolution if RES is active and game is running
if (isActive("RES") && GameRunning && NxFps) {

View File

@@ -50,7 +50,7 @@ public:
smExit();
StartMiscThread();
//tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
// tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
}
~MiscOverlay() {
@@ -121,8 +121,8 @@ public:
});
//tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Horizon OC Monitor", APP_VERSION, true);
// tsl::elm::g_disableMenuCacheOnReturn.store(true, std::memory_order_release);
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("Status Monitor Pro", APP_VERSION, true);
rootFrame->setContent(Status);
return rootFrame;