From 234fb1655c9192ee5d7286811f3ca962cc5421ae Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Thu, 2 Apr 2026 16:29:42 -0400 Subject: [PATCH] hocmon: fix hocmon --- README.md | 42 +- .../stratosphere/loader/source/oc/pcv/pcv.cpp | 6 +- Source/Horizon-OC-Monitor/README.md | 1 + Source/Horizon-OC-Monitor/source/Utils.hpp | 147 +++-- Source/Horizon-OC-Monitor/source/main.cpp | 92 ++- .../source/modes/Battery.hpp | 6 +- .../source/modes/Configurator.hpp | 553 +++++++++--------- .../source/modes/FPS_Graph.hpp | 57 +- .../Horizon-OC-Monitor/source/modes/Full.hpp | 59 +- .../Horizon-OC-Monitor/source/modes/Micro.hpp | 165 +++++- .../Horizon-OC-Monitor/source/modes/Mini.hpp | 246 +++++++- .../Horizon-OC-Monitor/source/modes/Misc.hpp | 6 +- 12 files changed, 966 insertions(+), 414 deletions(-) create mode 100644 Source/Horizon-OC-Monitor/README.md diff --git a/README.md b/README.md index 6b62de66..debdf262 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp index 85f23a34..10d2f1a1 100644 --- a/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp +++ b/Source/Atmosphere/stratosphere/loader/source/oc/pcv/pcv.cpp @@ -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 }, }; diff --git a/Source/Horizon-OC-Monitor/README.md b/Source/Horizon-OC-Monitor/README.md new file mode 100644 index 00000000..998a85a4 --- /dev/null +++ b/Source/Horizon-OC-Monitor/README.md @@ -0,0 +1 @@ +Thanks to NaGa for Status Monitor Pro! \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor/source/Utils.hpp b/Source/Horizon-OC-Monitor/source/Utils.hpp index 46de32f9..8c299036 100644 --- a/Source/Horizon-OC-Monitor/source/Utils.hpp +++ b/Source/Horizon-OC-Monitor/source/Utils.hpp @@ -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"); } -} +} \ No newline at end of file diff --git a/Source/Horizon-OC-Monitor/source/main.cpp b/Source/Horizon-OC-Monitor/source/main.cpp index 7ab37cfb..be548d09 100644 --- a/Source/Horizon-OC-Monitor/source/main.cpp +++ b/Source/Horizon-OC-Monitor/source/main.cpp @@ -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(); 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; diff --git a/Source/Horizon-OC-Monitor/source/modes/Battery.hpp b/Source/Horizon-OC-Monitor/source/modes/Battery.hpp index 685fc998..847b1f2e 100644 --- a/Source/Horizon-OC-Monitor/source/modes/Battery.hpp +++ b/Source/Horizon-OC-Monitor/source/modes/Battery.hpp @@ -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; diff --git a/Source/Horizon-OC-Monitor/source/modes/Configurator.hpp b/Source/Horizon-OC-Monitor/source/modes/Configurator.hpp index 3c2e365b..30adbb64 100644 --- a/Source/Horizon-OC-Monitor/source/modes/Configurator.hpp +++ b/Source/Horizon-OC-Monitor/source/modes/Configurator.hpp @@ -1,24 +1,24 @@ /* * 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), + * + * 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, + * + * 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.), + * + * 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, + * + * 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), + * + * 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), + * + * Game Resolutions: Refresh Rate, Colors (background, category, text only), * Horizontal/Vertical Position - NO toggles, fonts, or elements */ @@ -81,9 +81,9 @@ private: bool isFPSCounterMode; bool isFPSGraphMode; bool isGameResolutionsMode; - + public: - AlphaSelector(const std::string& mode, const std::string& key, const std::string& displayTitle) + 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"); @@ -94,7 +94,7 @@ public: ~AlphaSelector() { lastSelectedListItem = nullptr; } - + virtual tsl::elm::Element* createUI() override { auto* list = new tsl::elm::List(); list->addItem(new tsl::elm::CategoryHeader(title)); @@ -105,14 +105,14 @@ public: 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'}, @@ -127,7 +127,7 @@ public: {"90%", 'E'}, {"Opaque", 'F'} }; - + for (const auto& option : alphaOptions) { auto* alphaItem = new tsl::elm::ListItem(option.first); if (currentAlpha[0] == option.second) { @@ -139,10 +139,10 @@ public: // 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(""); @@ -154,14 +154,14 @@ public: }); 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); @@ -169,7 +169,7 @@ public: jumpItemName = title; jumpItemValue = ""; jumpItemExactMatch = false; - + tsl::swapTo(SwapDepth(2), modeName); return true; } @@ -214,7 +214,7 @@ private: std::string modeName; bool isMiniMode; bool isMicroMode; - + public: DTCFormatConfig(const std::string& mode) : modeName(mode) { isMiniMode = (mode == "Mini"); @@ -223,20 +223,20 @@ public: ~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); @@ -258,15 +258,15 @@ public: }); 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); @@ -274,7 +274,7 @@ public: jumpItemName = "DTC Format"; jumpItemValue = ""; jumpItemExactMatch = false; - + tsl::swapTo(SwapDepth(2), modeName); return true; } @@ -292,7 +292,7 @@ private: bool isFPSGraphMode; bool isGameResolutionsMode; bool isFPSCounterMode; - + public: TogglesConfig(const std::string& mode) : modeName(mode) { isMiniMode = (mode == "Mini"); @@ -302,11 +302,11 @@ public: 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()); @@ -314,6 +314,12 @@ public: 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) { @@ -326,7 +332,7 @@ public: 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()); @@ -334,31 +340,37 @@ public: 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"); @@ -376,36 +388,42 @@ public: 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()); + + auto* showVDDQ = new tsl::elm::ToggleListItem("VDD2", 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()); + auto* showVDD2 = new tsl::elm::ToggleListItem("VDDQ", getCurrentShowVDD2()); showVDD2->setStateChangedListener([this, section](bool state) { ult::setIniFileValue(configIniPath, section, "show_vdd2", state ? "true" : "false"); }); @@ -416,7 +434,7 @@ public: 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"); @@ -424,11 +442,11 @@ public: list->addItem(socVoltage); if (isMiniMode) { - auto* PartLoadCPUGPU = new tsl::elm::ToggleListItem("RAM Load CPU/GPU", getCurrentShowRAMLoadCPUGPU()); - PartLoadCPUGPU->setStateChangedListener([this, section](bool state) { + 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); + list->addItem(partLoadCPUGPU); } if (isMiniMode || isMicroMode) { @@ -438,7 +456,7 @@ public: }); 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"); @@ -462,7 +480,7 @@ public: 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")); @@ -470,7 +488,7 @@ public: 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")); @@ -486,7 +504,7 @@ public: }); list->addItem(disableScreenshots); } - + list->jumpToItem(jumpItemName, jumpItemValue, jumpItemExactMatch); { jumpItemName = ""; @@ -498,7 +516,7 @@ public: 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); @@ -508,7 +526,7 @@ public: } return false; } - + private: // Helper methods for getting current toggle states bool getCurrentShowInfo() { @@ -517,7 +535,14 @@ private: 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"); @@ -525,7 +550,7 @@ private: convertToUpper(value); return value == "TRUE"; } - + bool getCurrentRealVolts() { const std::string section = isMiniMode ? "mini" : "micro"; std::string value = ult::parseValueFromIniSection(configIniPath, section, "real_volts"); @@ -533,7 +558,15 @@ private: 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"); @@ -558,7 +591,7 @@ private: return value == "TRUE"; } - + bool getCurrentShowFullRes() { const std::string section = isMiniMode ? "mini" : "micro"; std::string value = ult::parseValueFromIniSection(configIniPath, section, "show_full_res"); @@ -566,7 +599,7 @@ private: convertToUpper(value); return value != "FALSE"; } - + bool getCurrentShowSOCVoltage() { const std::string section = isMiniMode ? "mini" : "micro"; std::string value = ult::parseValueFromIniSection(configIniPath, section, "show_soc_voltage"); @@ -575,7 +608,7 @@ private: return value != "FALSE"; } - bool getCurrentShowRAMLoadCPUGPU() { + 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 @@ -590,7 +623,7 @@ private: convertToUpper(value); return value != "FALSE"; } - + bool getCurrentUseDTCSymbol() { const std::string section = isMiniMode ? "mini" : "micro"; std::string value = ult::parseValueFromIniSection(configIniPath, section, "use_dtc_symbol"); @@ -627,7 +660,7 @@ private: 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"); @@ -635,35 +668,42 @@ private: 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; @@ -683,7 +723,7 @@ private: bool isFPSCounterMode; bool isFPSGraphMode; int currentRate; - + public: RefreshRateConfig(const std::string& mode) : modeName(mode) { isMiniMode = (mode == "Mini"); @@ -692,7 +732,7 @@ public: isGameResolutionsMode = (mode == "Game Resolutions"); isFPSCounterMode = (mode == "FPS Counter"); isFPSGraphMode = (mode == "FPS Graph"); - + std::string section; if (isMiniMode) section = "mini"; else if (isMicroMode) section = "micro"; @@ -700,7 +740,7 @@ public: 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); @@ -709,7 +749,7 @@ public: ~RefreshRateConfig() { lastSelectedListItem = nullptr; } - + virtual tsl::elm::Element* createUI() override { auto* list = new tsl::elm::List(); list->addItem(new tsl::elm::CategoryHeader("Refresh Rate")); @@ -730,7 +770,7 @@ public: 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) @@ -742,14 +782,14 @@ public: }); 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); @@ -757,7 +797,7 @@ public: jumpItemName = "Refresh Rate"; jumpItemValue = ""; jumpItemExactMatch = false; - + tsl::swapTo(SwapDepth(2), modeName); return true; } @@ -769,43 +809,22 @@ public: class FramePaddingConfig : public tsl::Gui { private: std::string modeName; - bool isMiniMode; - bool isGameResolutionsMode; - bool isFPSCounterMode; - bool isFPSGraphMode; int currentPadding; - + public: FramePaddingConfig(const std::string& mode) : modeName(mode) { - isMiniMode = (mode == "Mini"); - isGameResolutionsMode = (mode == "Game Resolutions"); - isFPSCounterMode = (mode == "FPS Counter"); - isFPSGraphMode = (mode == "FPS Graph"); - - std::string section; - if (isMiniMode) section = "mini"; - 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, "frame_padding"); - currentPadding = value.empty() ? 10 : std::clamp(atoi(value.c_str()), 0, 14); + 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")); - std::string section; - if (isMiniMode) section = "mini"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - 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"); @@ -813,9 +832,9 @@ public: paddingItem->setValue(ult::CHECKMARK_SYMBOL); lastSelectedListItem = paddingItem; } - paddingItem->setClickListener([this, paddingItem, padding, section](uint64_t keys) { + paddingItem->setClickListener([this, paddingItem, padding](uint64_t keys) { if (keys & KEY_A) { - ult::setIniFileValue(configIniPath, section, "frame_padding", std::to_string(padding)); + ult::setIniFileValue(configIniPath, "mini", "frame_padding", std::to_string(padding)); paddingItem->setValue(ult::CHECKMARK_SYMBOL); if (lastSelectedListItem && paddingItem != lastSelectedListItem) lastSelectedListItem->setValue(""); @@ -826,14 +845,14 @@ public: }); 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); @@ -841,7 +860,7 @@ public: jumpItemName = "Frame Padding"; jumpItemValue = ""; jumpItemExactMatch = false; - + tsl::swapTo(SwapDepth(2), modeName); return true; } @@ -859,9 +878,9 @@ private: bool isMicroMode; bool isFPSCounterMode; std::string title; - + public: - FontSizeSelector(const std::string& mode, const std::string& type) + FontSizeSelector(const std::string& mode, const std::string& type) : modeName(mode), fontType(type) { isMiniMode = (mode == "Mini"); isMicroMode = (mode == "Micro"); @@ -873,7 +892,7 @@ public: ~FontSizeSelector() { lastSelectedListItem = nullptr; } - + virtual tsl::elm::Element* createUI() override { auto* list = new tsl::elm::List(); list->addItem(new tsl::elm::CategoryHeader(title)); @@ -882,19 +901,19 @@ public: 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) { @@ -914,14 +933,14 @@ public: }); 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); @@ -929,7 +948,7 @@ public: jumpItemName = title; jumpItemValue = ""; jumpItemExactMatch = false; - + tsl::swapTo(SwapDepth(2), modeName); return true; } @@ -944,30 +963,30 @@ private: 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) { @@ -978,7 +997,7 @@ public: 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) { @@ -989,7 +1008,7 @@ public: 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); @@ -1000,7 +1019,7 @@ public: } 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); @@ -1027,9 +1046,9 @@ private: bool isFPSGraphMode; bool isBackgroundColor; bool isTextBasedColor; - + public: - ColorSelector(const std::string& mode, const std::string& title, const std::string& key, const std::string& def) + 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"); @@ -1037,25 +1056,25 @@ public: 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" || + 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" || + (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"; @@ -1063,13 +1082,13 @@ public: 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 @@ -1079,54 +1098,54 @@ public: {"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) { @@ -1136,9 +1155,9 @@ public: // 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) { @@ -1148,17 +1167,17 @@ public: // 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); @@ -1171,9 +1190,9 @@ public: 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 @@ -1190,7 +1209,7 @@ public: } lastSelectedListItem->setValue(oldDisplayValue); } - + // Set new checkmark colorItem->setValue(displayValue + " " + ult::CHECKMARK_SYMBOL); lastSelectedListItem = colorItem; @@ -1201,12 +1220,12 @@ public: 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); @@ -1232,7 +1251,7 @@ private: bool isGameResolutionsMode; bool isFPSCounterMode; bool isFPSGraphMode; - + public: ColorConfig(const std::string& mode) : modeName(mode) { isMiniMode = (mode == "Mini"); @@ -1241,18 +1260,18 @@ public: 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"; @@ -1261,18 +1280,18 @@ public: 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 @@ -1282,50 +1301,50 @@ public: {"#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 @@ -1338,7 +1357,7 @@ public: } 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]; @@ -1359,7 +1378,7 @@ public: } return "60%"; }; - + if (!isFullMode) { // Background Color (all modes) auto* bgColor = new tsl::elm::ListItem("Background Color"); @@ -1375,7 +1394,7 @@ public: return false; }); list->addItem(bgColor); - + // Background Alpha (new) auto* bgAlpha = new tsl::elm::ListItem("Background Alpha"); bgAlpha->setValue(getAlphaPercentage(bgCurrentColor)); @@ -1387,7 +1406,7 @@ public: return false; }); list->addItem(bgAlpha); - + if (isMiniMode || isFPSCounterMode || isFPSGraphMode || isGameResolutionsMode) { // Mini mode: has focus background auto* focusBgColor = new tsl::elm::ListItem("Focus Color"); @@ -1401,7 +1420,7 @@ public: return false; }); list->addItem(focusBgColor); - + // Focus Alpha (new) auto* focusAlpha = new tsl::elm::ListItem("Focus Alpha"); focusAlpha->setValue(getAlphaPercentage(focusCurrentColor)); @@ -1429,7 +1448,7 @@ public: return false; }); list->addItem(textColor); - + if (isFPSGraphMode) { // FPS Graph specific colors struct ColorSetting { @@ -1438,7 +1457,7 @@ public: 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"))); @@ -1461,11 +1480,11 @@ public: {"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)); @@ -1473,7 +1492,7 @@ public: // 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); @@ -1482,7 +1501,7 @@ public: return false; }); list->addItem(colorItem); - + // Add alpha selector for background-type colors if (color.isBackgroundType) { auto* alphaItem = new tsl::elm::ListItem(color.name + " Alpha"); @@ -1522,7 +1541,7 @@ public: 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"))); @@ -1546,7 +1565,7 @@ public: 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"))); @@ -1558,7 +1577,7 @@ public: return false; }); list->addItem(sepColor); - + } else if (isMicroMode) { auto* catColor = new tsl::elm::ListItem("Category Color"); catColor->setValue(getColorName(getCurrentColor("cat_color", "#2DFF"))); @@ -1570,7 +1589,7 @@ public: 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"))); @@ -1582,8 +1601,8 @@ public: return false; }); list->addItem(sepColor); - - + + } else if (isGameResolutionsMode) { // Game Resolutions: only category color (no separator) auto* catColor = new tsl::elm::ListItem("Category Color"); @@ -1599,20 +1618,20 @@ public: } // 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); @@ -1632,13 +1651,13 @@ private: 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")); @@ -1646,12 +1665,12 @@ public: 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; @@ -1660,7 +1679,7 @@ public: enabledElements.insert(item); } } - + elementOrder.clear(); if (!orderValue.empty()) { convertToUpper(orderValue); @@ -1679,19 +1698,19 @@ public: } } } - + 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); @@ -1711,14 +1730,14 @@ public: 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; @@ -1729,19 +1748,19 @@ public: 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; } @@ -1753,7 +1772,7 @@ public: break; } } - + if (keys & KEY_X) { if (currentPos > 0) { std::swap(elementOrder[currentPos], elementOrder[currentPos - 1]); @@ -1779,18 +1798,18 @@ public: 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); } @@ -1800,12 +1819,12 @@ public: 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); @@ -1815,21 +1834,21 @@ public: } 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 += "+"; @@ -1838,7 +1857,7 @@ private: showFirst = false; } } - + const std::string section = isMiniMode ? "mini" : "micro"; ult::setIniFileValue(configIniPath, section, "show", newShowValue); ult::setIniFileValue(configIniPath, section, "element_order", newOrderValue); @@ -1855,7 +1874,7 @@ private: bool isGameResolutionsMode; bool isFPSCounterMode; bool isFPSGraphMode; - + public: ConfiguratorOverlay(const std::string& mode) : modeName(mode) { isMiniMode = (mode == "Mini"); @@ -1865,11 +1884,11 @@ public: 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"); @@ -1911,8 +1930,8 @@ public: }); list->addItem(colors); //} - - + + // 4. Font Sizes (Mini/Micro/FPS Counter only) if (isMiniMode || isMicroMode || isFPSCounterMode) { auto* fontSizes = new tsl::elm::ListItem("Font Sizes"); @@ -1926,7 +1945,7 @@ public: }); list->addItem(fontSizes); } - + // 1. Refresh Rate (all modes) auto* refreshRate = new tsl::elm::ListItem("Refresh Rate"); refreshRate->setValue(std::to_string(getCurrentRefreshRate()) + " Hz"); @@ -1938,7 +1957,7 @@ public: return false; }); list->addItem(refreshRate); - + // 6. DTC Format (Mini/Micro only) - NEW ADDITION if (isMiniMode || isMicroMode) { auto* dtcFormat = new tsl::elm::ListItem("DTC Format"); @@ -1966,7 +1985,7 @@ public: }); list->addItem(framePadding); } - + // 7. Mode-specific positioning settings if (isMicroMode) { // Text Alignment for Micro @@ -1994,7 +2013,7 @@ public: return false; }); list->addItem(layerPos); - + } else if (isFullMode) { // Horizontal Position for Full (Left/Right only) auto* layerPos = new tsl::elm::ListItem("Horizontal Position"); @@ -2008,7 +2027,7 @@ public: return false; }); list->addItem(layerPos); - + //} else if (isGameResolutionsMode || isFPSCounterMode || isFPSGraphMode) { // // Both horizontal and vertical positioning // auto* layerPosH = new tsl::elm::ListItem("Horizontal Position"); @@ -2022,7 +2041,7 @@ public: // return false; // }); // list->addItem(layerPosH); - // + // // auto* layerPosV = new tsl::elm::ListItem("Vertical Position"); // layerPosV->setValue(getCurrentLayerPosBottom()); // layerPosV->setClickListener([this, layerPosV](uint64_t keys) { @@ -2035,19 +2054,19 @@ public: // }); // 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); @@ -2058,7 +2077,7 @@ public: } return false; } - + private: int getCurrentRefreshRate() { std::string section; @@ -2068,52 +2087,48 @@ private: 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() { - std::string section; - if (isMiniMode) section = "mini"; - else if (isGameResolutionsMode) section = "game_resolutions"; - else if (isFPSCounterMode) section = "fps-counter"; - else if (isFPSGraphMode) section = "fps-graph"; - else return 10; - - std::string value = ult::parseValueFromIniSection(configIniPath, section, "frame_padding"); - return value.empty() ? 10 : atoi(value.c_str()); + if (isMiniMode) { + std::string value = ult::parseValueFromIniSection(configIniPath, "mini", "frame_padding"); + return value.empty() ? 10 : atoi(value.c_str()); + } + return 10; } std::string getCurrentTextAlign() { @@ -2126,17 +2141,17 @@ private: } 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"; @@ -2155,10 +2170,10 @@ private: 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"; @@ -2170,7 +2185,7 @@ private: return "Top"; } } - + std::string cycleTextAlign() { if (isMicroMode) { const std::string current = getCurrentTextAlign(); @@ -2179,23 +2194,23 @@ private: 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"; @@ -2206,7 +2221,7 @@ private: 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; @@ -2218,10 +2233,10 @@ private: 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"; @@ -2232,7 +2247,7 @@ private: 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/source/modes/FPS_Graph.hpp b/Source/Horizon-OC-Monitor/source/modes/FPS_Graph.hpp index 56aa24b2..df5a22bc 100644 --- a/Source/Horizon-OC-Monitor/source/modes/FPS_Graph.hpp +++ b/Source/Horizon-OC-Monitor/source/modes/FPS_Graph.hpp @@ -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); diff --git a/Source/Horizon-OC-Monitor/source/modes/Full.hpp b/Source/Horizon-OC-Monitor/source/modes/Full.hpp index 6a9e5aea..a6b78003 100644 --- a/Source/Horizon-OC-Monitor/source/modes/Full.hpp +++ b/Source/Horizon-OC-Monitor/source/modes/Full.hpp @@ -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 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 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); diff --git a/Source/Horizon-OC-Monitor/source/modes/Micro.hpp b/Source/Horizon-OC-Monitor/source/modes/Micro.hpp index 50371d3e..0e1935ee 100644 --- a/Source/Horizon-OC-Monitor/source/modes/Micro.hpp +++ b/Source/Horizon-OC-Monitor/source/modes/Micro.hpp @@ -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] = ""; diff --git a/Source/Horizon-OC-Monitor/source/modes/Mini.hpp b/Source/Horizon-OC-Monitor/source/modes/Mini.hpp index 0a837a8d..173957fb 100644 --- a/Source/Horizon-OC-Monitor/source/modes/Mini.hpp +++ b/Source/Horizon-OC-Monitor/source/modes/Mini.hpp @@ -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) { diff --git a/Source/Horizon-OC-Monitor/source/modes/Misc.hpp b/Source/Horizon-OC-Monitor/source/modes/Misc.hpp index fc2c1249..ab055aac 100644 --- a/Source/Horizon-OC-Monitor/source/modes/Misc.hpp +++ b/Source/Horizon-OC-Monitor/source/modes/Misc.hpp @@ -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;