hoc-sys: change stuff

This commit is contained in:
souldbminersmwc
2025-11-09 16:07:13 -05:00
parent a76c2b33b6
commit e72f9d8e60
14 changed files with 406 additions and 397 deletions

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@@ -23,13 +27,20 @@
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors * stuff is worth it, you can buy us a beer in return. - The sys-clk authors
* -------------------------------------------------------------------------- * --------------------------------------------------------------------------
*/ */
#include "base_gui.h" #include "base_gui.h"
#include "../elements/base_frame.h" #include "../elements/base_frame.h"
#include "logo_rgba_bin.h" #include "logo_rgba_bin.h"
#define LOGO_X 20 #define LOGO_X 20
#define LOGO_Y 45 #define LOGO_Y 45
#define LOGO_LABEL_FONT_SIZE 35 #define LOGO_LABEL_FONT_SIZE 35
#define VERSION_X (LOGO_X + 250) #define VERSION_X (LOGO_X + 250)
#define VERSION_Y LOGO_Y-40 #define VERSION_Y LOGO_Y-40
#define VERSION_FONT_SIZE 15 #define VERSION_FONT_SIZE 15
@@ -45,12 +56,9 @@ std::string getVersionString() {
void BaseGui::preDraw(tsl::gfx::Renderer* renderer) void BaseGui::preDraw(tsl::gfx::Renderer* renderer)
{ {
// Draw "Horizon OC " in default color // renderer->drawBitmap(LOGO_X, LOGO_Y, LOGO_WIDTH, LOGO_HEIGHT, logo_rgba_bin);
renderer->drawString("Horizon OC ", false, LOGO_X, LOGO_Y, LOGO_LABEL_FONT_SIZE, renderer->a(TEXT_COLOR)); renderer->drawString("Horizon OC overlay", false, LOGO_X, LOGO_Y, LOGO_LABEL_FONT_SIZE, renderer->a(TEXT_COLOR));
// renderer->drawString(TARGET_VERSION, false, VERSION_X, VERSION_Y, VERSION_FONT_SIZE, tsl::bannerVersionTextColor);
// Draw "Gaea" in green
tsl::Color greenColor(40, 204, 40, 255); // Light green
renderer->drawString("Gaea", false, LOGO_X + 225, LOGO_Y, LOGO_LABEL_FONT_SIZE, greenColor);
} }
tsl::elm::Element* BaseGui::createUI() tsl::elm::Element* BaseGui::createUI()
@@ -63,4 +71,4 @@ tsl::elm::Element* BaseGui::createUI()
void BaseGui::update() void BaseGui::update()
{ {
this->refresh(); this->refresh();
} }

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,14 +1,7 @@
/* /*
* -------------------------------------------------------------------------- * Copyright (C) Switch-OC-Suite
* "THE BEER-WARE LICENSE" (Revision 42): *
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net> * Copyright (c) 2023 hanai3Bi
* wrote this file. As long as you retain this notice you can do whatever you
* want with this stuff. If you meet any of us some day, and you think this
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
* --------------------------------------------------------------------------
*/
/*
* *
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
@@ -23,322 +16,297 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
* wrote this file. As long as you retain this notice you can do whatever you
* want with this stuff. If you meet any of us some day, and you think this
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
* --------------------------------------------------------------------------
*/ */
#include "base_menu_gui.h"
#include "fatal_gui.h"
// Cache hardware model to avoid repeated syscalls
BaseMenuGui::BaseMenuGui()
{
tsl::initializeThemeVars();
this->context = nullptr;
this->lastContextUpdate = 0;
this->listElement = nullptr;
// Initialize all voltages to zero once
memset(&cpuVoltageUv, 0, sizeof(u32) * 5); // Zero all 5 voltage values at once
// Pre-cache hardware model during initialization
IsMariko();
// Initialize display strings
memset(displayStrings, 0, sizeof(displayStrings));
}
BaseMenuGui::~BaseMenuGui() {
delete this->context; // delete handles nullptr automatically
}
// Fast preDraw - just renders pre-computed strings
void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
BaseGui::preDraw(renderer);
if(!this->context) [[unlikely]] return;
// All constants pre-calculated and cached
static constexpr const char* const labels[] = {
"App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "CPU", "GPU", "PLL", "PMIC", "BAT"
};
static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1};
static u32 labelWidths[10];
static bool positionsInitialized = false;
if (!positionsInitialized) {
for (int i = 0; i < 10; i++) {
labelWidths[i] = renderer->getTextDimensions(labels[i], false, SMALL_TEXT_SIZE).first;
}
positionsInitialized = true;
}
static u32 positions[10] = {24-1, 310-labelWidths[1], 24-1, 192-labelWidths[3], 332-labelWidths[4], 24-1, 192 - labelWidths[6], 332-labelWidths[7], 192 - labelWidths[8], 332-labelWidths[9]};
static u32 maxProfileValueWidth = renderer->getTextDimensions("PD Charger", false, SMALL_TEXT_SIZE).first; // longest word
u32 y = 91;
// === TOP SECTION ===
// renderer->drawRoundedRect(14, 70-1, 420, 30+2, 10.0f, renderer->aWithOpacity(tsl::tableBGColor));
// App ID - use pre-formatted string
renderer->drawString(labels[0], false, positions[0], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(displayStrings[0], false, positions[0] + labelWidths[0] + 9, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
// Profile - use pre-formatted string
renderer->drawString(labels[1], false, 423 - maxProfileValueWidth - labelWidths[1] - 9, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(displayStrings[1], false, 423 - maxProfileValueWidth, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
y = y + 38; // Direct assignment instead of += 38
// === MAIN DATA SECTION ===
// renderer->drawRoundedRect(14, 106, 420, 116, 10.0f, renderer->aWithOpacity(tsl::tableBGColor));
// === FREQUENCY SECTION ===
// Labels first (better cache locality)
renderer->drawString(labels[2], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(labels[3], false, positions[3], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(labels[4], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
// Current frequencies - use pre-formatted strings
renderer->drawString(displayStrings[2], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU
renderer->drawString(displayStrings[3], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU
renderer->drawString(displayStrings[4], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM
y = y + 20; // Direct assignment (129 + 20)
// === REAL FREQUENCIES ===
renderer->drawString(displayStrings[5], false, positions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU real
renderer->drawString(displayStrings[6], false, positions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU real
renderer->drawString(displayStrings[7], false, positions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM real
y = y + 20; // Direct assignment (149 + 20)
// === VOLTAGES ===
renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage
renderer->drawString(displayStrings[9], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage
// Memory voltage - check if VDD is present
if (emcVoltageUv && vddVoltageUv) {
renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[5]-16, y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
} else if (vddVoltageUv) {
renderer->drawString(displayStrings[10], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
} else if (emcVoltageUv) {
renderer->drawString(displayStrings[10], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
}
// y = y + 20; // Direct assignment (169 + 22)
// renderer->drawString(displayStrings[17], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[3]); // CPU
// renderer->drawString(displayStrings[18], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[4]); // GPU
// renderer->drawString(displayStrings[19], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[5]); // PLL
y = y + 22; // Direct assignment (149 + 20)
// === TEMPERATURE SECTION ===
// Labels
renderer->drawString(labels[5], false, positions[5], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(labels[6], false, positions[6]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(labels[7], false, positions[7], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
// Temperatures with color - use pre-computed colors
renderer->drawString(displayStrings[11], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[0]); // SOC
renderer->drawString(displayStrings[12], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[1]); // PCB
renderer->drawString(displayStrings[13], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[2]); // Skin
y = y + 20; // Direct assignment (191 + 20)
// === SOC VOLTAGE & POWER ===
// SOC voltage (if available)
if (socVoltageUv) [[likely]] {
renderer->drawString(displayStrings[14], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
}
// Power labels and values
renderer->drawString(labels[8], false, positions[8]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(labels[9], false, positions[9], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(displayStrings[15], false, dataPositions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power now
renderer->drawString(displayStrings[16], false, dataPositions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power avg
y = y + 20; // Direct assignment (191 + 20)
renderer->drawString(displayStrings[20], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[4]); // BAT #include "base_menu_gui.h"
renderer->drawString(displayStrings[21], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[5]); // PMIC #include "fatal_gui.h"
y = y + 20; // Direct assignment (191 + 20) // Cache hardware model to avoid repeated syscalls
BaseMenuGui::BaseMenuGui() : tempColors{tsl::Color(0), tsl::Color(0), tsl::Color(0)}
} {
tsl::initializeThemeVars();
// Optimized refresh - now does all the string formatting once per second this->context = nullptr;
void BaseMenuGui::refresh() this->lastContextUpdate = 0;
{ this->listElement = nullptr;
const u64 ticks = armGetSystemTick(); // Initialize all voltages to zero once
// Use cached comparison - 1 billion nanoseconds memset(&cpuVoltageUv, 0, sizeof(u32) * 5); // Zero all 5 voltage values at once
if (armTicksToNs(ticks - this->lastContextUpdate) <= 1000000000UL) [[likely]] {
return; // Early exit for most calls // Pre-cache hardware model during initialization
} IsMariko();
this->lastContextUpdate = ticks; // Initialize display strings
memset(displayStrings, 0, sizeof(displayStrings));
// Lazy context allocation }
if (!this->context) [[unlikely]] {
this->context = new SysClkContext; BaseMenuGui::~BaseMenuGui() {
} delete this->context; // delete handles nullptr automatically
}
// === ULTRA-FAST VOLTAGE READING ===
// Pre-computed domain configuration based on hardware // Fast preDraw - just renders pre-computed strings
static const PowerDomainId domains[] = { void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
PcvPowerDomainId_Max77621_Cpu, // [0] CPU BaseGui::preDraw(renderer);
PcvPowerDomainId_Max77621_Gpu, // [1] GPU if(!this->context) [[unlikely]] return;
PcvPowerDomainId_Max77812_Dram, // [2] EMC/DRAM - Mariko only
PcvPowerDomainId_Max77620_Sd0, // [3] SOC // All constants pre-calculated and cached
PcvPowerDomainId_Max77620_Sd1 // [4] VDD2 static constexpr const char* const labels[10] = {
}; "App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg"
};
// Voltage array for direct indexing
u32* voltages[] = {&cpuVoltageUv, &gpuVoltageUv, &emcVoltageUv, &socVoltageUv, &vddVoltageUv}; static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1};
// Single regulator init/exit cycle static u32 labelWidths[10];
if (R_SUCCEEDED(rgltrInitialize())) [[likely]] { static bool positionsInitialized = false;
if (IsMariko()) {
// Mariko with EOS: all 5 domains if (!positionsInitialized) {
for (int i = 0; i < 5; ++i) { for (int i = 0; i < 10; i++) {
RgltrSession session; labelWidths[i] = renderer->getTextDimensions(labels[i], false, SMALL_TEXT_SIZE).first;
if (R_SUCCEEDED(rgltrOpenSession(&session, domains[i]))) [[likely]] { }
if (R_FAILED(rgltrGetVoltage(&session, voltages[i]))) { positionsInitialized = true;
*voltages[i] = 0; }
} static u32 positions[10] = {24-1, 310-labelWidths[1], 24-1, 192-labelWidths[3], 332-labelWidths[4], 24-1, 192 - labelWidths[6], 332-labelWidths[7], 192 - labelWidths[8], 332-labelWidths[9]};
rgltrCloseSession(&session);
} else { static u32 maxProfileValueWidth = renderer->getTextDimensions("PD Charger", false, SMALL_TEXT_SIZE).first; // longest word
*voltages[i] = 0;
} u32 y = 91;
}
} else { // === TOP SECTION ===
// Erista renderer->drawRoundedRect(14, 70-1, 420, 30+2, 10.0f, renderer->aWithOpacity(tsl::tableBGColor));
// Erista with EOS: CPU, GPU, SOC, VDD (no DRAM)
for (int i = 0; i < 5; ++i) { // App ID - use pre-formatted string
if (i == 2) continue; // Skip DRAM domain renderer->drawString(labels[0], false, positions[0], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
renderer->drawString(displayStrings[0], false, positions[0] + labelWidths[0] + 9, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
RgltrSession session;
if (R_SUCCEEDED(rgltrOpenSession(&session, domains[i]))) [[likely]] { // Profile - use pre-formatted string
if (R_FAILED(rgltrGetVoltage(&session, voltages[i]))) { renderer->drawString(labels[1], false, 423 - maxProfileValueWidth - labelWidths[1] - 9, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
*voltages[i] = 0; renderer->drawString(displayStrings[1], false, 423 - maxProfileValueWidth, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
}
rgltrCloseSession(&session); y = 129; // Direct assignment instead of += 38
} else {
*voltages[i] = 0; // === MAIN DATA SECTION ===
} renderer->drawRoundedRect(14, 106, 420, 116, 10.0f, renderer->aWithOpacity(tsl::tableBGColor));
emcVoltageUv = 0; // Erista never supports DRAM
} // === FREQUENCY SECTION ===
} // Labels first (better cache locality)
renderer->drawString(labels[2], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
rgltrExit(); renderer->drawString(labels[3], false, positions[3], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
} else { renderer->drawString(labels[4], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
// Zero all voltages on regulator failure
memset(&cpuVoltageUv, 0, sizeof(u32) * 5); // Current frequencies - use pre-formatted strings
} renderer->drawString(displayStrings[2], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU
renderer->drawString(displayStrings[3], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU
// === SYSCLK CONTEXT UPDATE === renderer->drawString(displayStrings[4], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM
const Result rc = sysclkIpcGetCurrentContext(this->context);
if (R_FAILED(rc)) [[unlikely]] { y = 149; // Direct assignment (129 + 20)
FatalGui::openWithResultCode("sysclkIpcGetCurrentContext", rc);
return; // === REAL FREQUENCIES ===
} renderer->drawString(displayStrings[5], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU real
renderer->drawString(displayStrings[6], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU real
// === FORMAT ALL DISPLAY STRINGS (once per second) === renderer->drawString(displayStrings[7], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM real
// App ID (hex conversion)
sprintf(displayStrings[0], "%016lX", context->applicationId); y = 169; // Direct assignment (149 + 20)
// Profile // === VOLTAGES ===
strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true)); renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage
renderer->drawString(displayStrings[9], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage
// Current frequencies
u32 hz = context->freqs[0]; // CPU // Memory voltage - check if VDD is present
if (emcVoltageUv && vddVoltageUv) {
sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[5]-16, y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
} else if (vddVoltageUv) {
hz = context->freqs[1]; // GPU renderer->drawString(displayStrings[10], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); } else if (emcVoltageUv) {
renderer->drawString(displayStrings[10], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
hz = context->freqs[2]; // MEM }
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
y = 191; // Direct assignment (169 + 22)
// Real frequencies
hz = context->realFreqs[0]; // CPU // === TEMPERATURE SECTION ===
sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); // Labels
renderer->drawString(labels[5], false, positions[5], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
hz = context->realFreqs[1]; // GPU renderer->drawString(labels[6], false, positions[6]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); renderer->drawString(labels[7], false, positions[7], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
hz = context->realFreqs[2]; // MEM // Temperatures with color - use pre-computed colors
sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); renderer->drawString(displayStrings[11], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[0]); // SOC
renderer->drawString(displayStrings[12], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[1]); // PCB
// Voltages renderer->drawString(displayStrings[13], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[2]); // Skin
sprintf(displayStrings[8], "%.1f mV", cpuVoltageUv / 1000.0);
sprintf(displayStrings[9], "%.1f mV", gpuVoltageUv / 1000.0); y = 211; // Direct assignment (191 + 20)
// Memory voltage (handle VDD case) // === SOC VOLTAGE & POWER ===
if (emcVoltageUv && vddVoltageUv) { // SOC voltage (if available)
//sprintf(displayStrings[10], "%u%u mV", vddVoltageUv / 1000U, emcVoltageUv / 1000U); if (socVoltageUv) [[likely]] {
//sprintf(displayStrings[10], "%u%.1f mV", vddVoltageUv / 1000U, emcVoltageUv / 1000.0f); renderer->drawString(displayStrings[14], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
sprintf(displayStrings[10], "%u.%u%u mV", vddVoltageUv / 1000U, (vddVoltageUv % 1000U) / 100U, emcVoltageUv / 1000U); }
} else if (vddVoltageUv) {
//sprintf(displayStrings[10], "%u mV", vddVoltageUv / 1000U); // Power labels and values
sprintf(displayStrings[10], "%u.%u mV", vddVoltageUv / 1000U, (vddVoltageUv % 1000U) / 100U); renderer->drawString(labels[8], false, positions[8]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
} else if (emcVoltageUv) { renderer->drawString(labels[9], false, positions[9], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
sprintf(displayStrings[10], "%u mV", emcVoltageUv / 1000U);
} renderer->drawString(displayStrings[15], false, dataPositions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power now
renderer->drawString(displayStrings[16], false, dataPositions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power avg
}
u32 millis = context->temps[SysClkThermalSensor_SOC]; // SOC
sprintf(displayStrings[11], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); // Optimized refresh - now does all the string formatting once per second
tempColors[0] = tsl::GradientColor(millis * 0.001f); void BaseMenuGui::refresh()
{
millis = context->temps[SysClkThermalSensor_PCB]; // PCB const u64 ticks = armGetSystemTick();
sprintf(displayStrings[12], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); // Use cached comparison - 1 billion nanoseconds
tempColors[1] = tsl::GradientColor(millis * 0.001f); if (armTicksToNs(ticks - this->lastContextUpdate) <= 1000000000UL) [[likely]] {
return; // Early exit for most calls
millis = context->temps[SysClkThermalSensor_Skin]; // Skin }
sprintf(displayStrings[13], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
tempColors[2] = tsl::GradientColor(millis * 0.001f); this->lastContextUpdate = ticks;
millis = context->temps[HocClkThermalSensor_Battery]; // // Lazy context allocation
sprintf(displayStrings[20], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); if (!this->context) [[unlikely]] {
tempColors[3] = tsl::GradientColor(millis * 0.001f); this->context = new SysClkContext;
}
millis = context->temps[HocClkThermalSensor_PMIC]; //
sprintf(displayStrings[21], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); // === ULTRA-FAST VOLTAGE READING ===
tempColors[4] = tsl::GradientColor(millis * 0.001f); // Pre-computed domain configuration based on hardware
static const PowerDomainId domains[] = {
// millis = context->temps[HocClkThermalSensor_GPU]; // Skin PcvPowerDomainId_Max77621_Cpu, // [0] CPU
// sprintf(displayStrings[18], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); PcvPowerDomainId_Max77621_Gpu, // [1] GPU
// tempColors[4] = tsl::GradientColor(millis * 0.001f); PcvPowerDomainId_Max77812_Dram, // [2] EMC/DRAM - Mariko only
PcvPowerDomainId_Max77620_Sd0, // [3] SOC - EOS only
// millis = context->temps[HocClkThermalSensor_PLL]; // Skin PcvPowerDomainId_Max77620_Sd1 // [4] VDD2 - EOS only
// sprintf(displayStrings[19], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); };
// tempColors[5] = tsl::GradientColor(millis * 0.001f);
// Voltage array for direct indexing
// SOC voltage (if available) u32* voltages[] = {&cpuVoltageUv, &gpuVoltageUv, &emcVoltageUv, &socVoltageUv, &vddVoltageUv};
if (socVoltageUv) {
sprintf(displayStrings[14], "%u mV", socVoltageUv / 1000U); // Single regulator init/exit cycle
} if (R_SUCCEEDED(rgltrInitialize())) [[likely]] {
if (IsMariko()) {
// Power // Mariko with EOS: all 5 domains
sprintf(displayStrings[15], "%d mW", context->power[0]); // Now for (int i = 0; i < 5; ++i) {
sprintf(displayStrings[16], "%d mW", context->power[1]); // Avg RgltrSession session;
if (R_SUCCEEDED(rgltrOpenSession(&session, domains[i]))) [[likely]] {
if (R_FAILED(rgltrGetVoltage(&session, voltages[i]))) {
} *voltages[i] = 0;
}
tsl::elm::Element* BaseMenuGui::baseUI() rgltrCloseSession(&session);
{ } else {
auto* list = new tsl::elm::List(); *voltages[i] = 0;
this->listElement = list; }
this->listUI(); }
} else {
return list; // Erista
} // Erista with EOS: CPU, GPU, SOC, VDD (no DRAM)
for (int i = 0; i < 5; ++i) {
if (i == 2) continue; // Skip DRAM domain
RgltrSession session;
if (R_SUCCEEDED(rgltrOpenSession(&session, domains[i]))) [[likely]] {
if (R_FAILED(rgltrGetVoltage(&session, voltages[i]))) {
*voltages[i] = 0;
}
rgltrCloseSession(&session);
} else {
*voltages[i] = 0;
}
emcVoltageUv = 0; // Erista never supports DRAM
}
}
rgltrExit();
} else {
// Zero all voltages on regulator failure
memset(&cpuVoltageUv, 0, sizeof(u32) * 5);
}
// === SYSCLK CONTEXT UPDATE ===
const Result rc = sysclkIpcGetCurrentContext(this->context);
if (R_FAILED(rc)) [[unlikely]] {
FatalGui::openWithResultCode("sysclkIpcGetCurrentContext", rc);
return;
}
// === FORMAT ALL DISPLAY STRINGS (once per second) ===
// App ID (hex conversion)
sprintf(displayStrings[0], "%016lX", context->applicationId);
// Profile
strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true));
// Current frequencies
u32 hz = context->freqs[0]; // CPU
sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
hz = context->freqs[1]; // GPU
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
hz = context->freqs[2]; // MEM
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
// Real frequencies
hz = context->realFreqs[0]; // CPU
sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
hz = context->realFreqs[1]; // GPU
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
hz = context->realFreqs[2]; // MEM
sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
// Voltages
sprintf(displayStrings[8], "%.1f mV", cpuVoltageUv / 1000.0);
sprintf(displayStrings[9], "%.1f mV", gpuVoltageUv / 1000.0);
// Memory voltage (handle VDD case)
if (emcVoltageUv && vddVoltageUv) {
//sprintf(displayStrings[10], "%u%u mV", vddVoltageUv / 1000U, emcVoltageUv / 1000U);
//sprintf(displayStrings[10], "%u%.1f mV", vddVoltageUv / 1000U, emcVoltageUv / 1000.0f);
sprintf(displayStrings[10], "%u.%u%u mV", vddVoltageUv / 1000U, (vddVoltageUv % 1000U) / 100U, emcVoltageUv / 1000U);
} else if (vddVoltageUv) {
//sprintf(displayStrings[10], "%u mV", vddVoltageUv / 1000U);
sprintf(displayStrings[10], "%u.%u mV", vddVoltageUv / 1000U, (vddVoltageUv % 1000U) / 100U);
} else if (emcVoltageUv) {
sprintf(displayStrings[10], "%u mV", emcVoltageUv / 1000U);
}
// Temperatures and pre-compute colors
u32 millis = context->temps[0]; // SOC
sprintf(displayStrings[11], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
tempColors[0] = tsl::GradientColor(millis * 0.001f);
millis = context->temps[1]; // PCB
sprintf(displayStrings[12], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
tempColors[1] = tsl::GradientColor(millis * 0.001f);
millis = context->temps[2]; // Skin
sprintf(displayStrings[13], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
tempColors[2] = tsl::GradientColor(millis * 0.001f);
// SOC voltage (if available)
if (socVoltageUv) {
sprintf(displayStrings[14], "%u mV", socVoltageUv / 1000U);
}
// Power
sprintf(displayStrings[15], "%d mW", context->power[0]); // Now
sprintf(displayStrings[16], "%d mW", context->power[1]); // Avg
}
tsl::elm::Element* BaseMenuGui::baseUI()
{
auto* list = new tsl::elm::List();
this->listElement = list;
this->listUI();
return list;
}

View File

@@ -1,14 +1,7 @@
/* /*
* -------------------------------------------------------------------------- * Copyright (C) Switch-OC-Suite
* "THE BEER-WARE LICENSE" (Revision 42): *
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net> * Copyright (c) 2023 hanai3Bi
* wrote this file. As long as you retain this notice you can do whatever you
* want with this stuff. If you meet any of us some day, and you think this
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
* --------------------------------------------------------------------------
*/
/*
* *
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
@@ -23,69 +16,65 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* --------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
* wrote this file. As long as you retain this notice you can do whatever you
* want with this stuff. If you meet any of us some day, and you think this
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
* --------------------------------------------------------------------------
*/ */
#pragma once
#include "../../rgltr_services.h" #pragma once
#include "../../ipc.h"
#include "base_gui.h"
class BaseMenuGui : public BaseGui
{
protected:
SysClkContext* context;
std::uint64_t lastContextUpdate;
std::uint32_t cpuVoltageUv;
std::uint32_t gpuVoltageUv;
std::uint32_t emcVoltageUv;
std::uint32_t socVoltageUv; //add soc voltage
std::uint32_t vddVoltageUv;//add vdd2 voltage
public:
uint64_t systemtickfrequency = 19200000;
bool g_hardwareModelCached = false;
bool g_isMariko = false;
bool g_isAula = false;
bool IsMariko() { #include "../../rgltr_services.h"
if (!g_hardwareModelCached) { #include "../../ipc.h"
SetSysProductModel model = SetSysProductModel_Invalid; #include "base_gui.h"
setsysGetProductModel(&model);
g_isMariko = (model == SetSysProductModel_Iowa ||
model == SetSysProductModel_Hoag ||
model == SetSysProductModel_Calcio ||
model == SetSysProductModel_Aula);
g_hardwareModelCached = true;
}
return g_isMariko;
}
bool IsAula() { class BaseMenuGui : public BaseGui
{
protected:
SysClkContext* context;
std::uint64_t lastContextUpdate;
std::uint32_t cpuVoltageUv;
std::uint32_t gpuVoltageUv;
std::uint32_t emcVoltageUv;
std::uint32_t socVoltageUv; //add soc voltage
std::uint32_t vddVoltageUv;//add vdd2 voltage
public:
bool g_hardwareModelCached = false;
bool g_isMariko = false;
bool IsMariko() {
if (!g_hardwareModelCached) { if (!g_hardwareModelCached) {
SetSysProductModel model = SetSysProductModel_Invalid; SetSysProductModel model = SetSysProductModel_Invalid;
setsysGetProductModel(&model); setsysGetProductModel(&model);
g_isMariko = (model == SetSysProductModel_Aula); g_isMariko = (model == SetSysProductModel_Iowa ||
model == SetSysProductModel_Hoag ||
model == SetSysProductModel_Calcio ||
model == SetSysProductModel_Aula);
g_hardwareModelCached = true;
} }
return g_isAula; return g_isMariko;
} }
bool IsErista() { bool IsErista() {
return !IsMariko(); return !IsMariko();
} }
BaseMenuGui(); BaseMenuGui();
~BaseMenuGui(); ~BaseMenuGui();
void preDraw(tsl::gfx::Renderer* renderer) override; void preDraw(tsl::gfx::Renderer* renderer) override;
tsl::elm::List* listElement; tsl::elm::List* listElement;
tsl::elm::Element* baseUI() override; tsl::elm::Element* baseUI() override;
void refresh() override; void refresh() override;
virtual void listUI() = 0; virtual void listUI() = 0;
private: private:
char displayStrings[32][32]; // Pre-formatted display strings char displayStrings[17][32]; // Pre-formatted display strings
tsl::Color tempColors[6] = { tsl::Color tempColors[3]; // Pre-computed temperature colors
tsl::Color(0), tsl::Color(0), tsl::Color(0), };
tsl::Color(0), tsl::Color(0), tsl::Color(0)
};
};

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it

View File

@@ -1,4 +1,8 @@
/* /*
* Copyright (C) Switch-OC-Suite
*
* Copyright (c) 2023 hanai3Bi
*
* Copyright (c) Souldbminer and Horizon OC Contributors * Copyright (c) Souldbminer and Horizon OC Contributors
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it