sysmodule/overlay: re-add part load, voltage readings and animated logo
This commit is contained in:
@@ -7,14 +7,14 @@
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||
@@ -24,39 +24,141 @@
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "base_gui.h"
|
||||
|
||||
#include "../elements/base_frame.h"
|
||||
#include "logo_rgba_bin.h"
|
||||
|
||||
|
||||
|
||||
#include <tesla.hpp>
|
||||
#include <math.h>
|
||||
|
||||
#define LOGO_X 20
|
||||
#define LOGO_Y 45
|
||||
#define LOGO_LABEL_FONT_SIZE 35
|
||||
#define LOGO_Y 50
|
||||
#define LOGO_LABEL_FONT_SIZE 45
|
||||
|
||||
#define VERSION_X (LOGO_X + 250)
|
||||
#define VERSION_Y LOGO_Y-40
|
||||
#define VERSION_Y (LOGO_Y - 40)
|
||||
#define VERSION_FONT_SIZE 15
|
||||
|
||||
std::string getVersionString() {
|
||||
char buf[0x100] = ""; // 256 bytes — safe for any expected version string
|
||||
char buf[0x100] = "";
|
||||
Result rc = sysclkIpcGetVersionString(buf, sizeof(buf));
|
||||
if (R_FAILED(rc) || buf[0] == '\0') {
|
||||
return "unknown";
|
||||
return "HorizonOC-Misc";
|
||||
}
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
void BaseGui::preDraw(tsl::gfx::Renderer* renderer)
|
||||
// ---------------------------------------------
|
||||
// AQUATIC BLUE COLORS (4-bit color space)
|
||||
// ---------------------------------------------
|
||||
static constexpr tsl::Color dynamicLogoRGB1 = tsl::Color(0, 4, 8, 15); // Deep ocean blue
|
||||
static constexpr tsl::Color dynamicLogoRGB2 = tsl::Color(7, 15, 15, 15); // Bright aqua cyan
|
||||
static constexpr tsl::Color STATIC_AQUA = tsl::Color(2, 10, 12, 15); // Mid aqua
|
||||
|
||||
// ---------------------------------------------
|
||||
// FULLY ENHANCED ANIMATED LOGO EFFECT
|
||||
// ---------------------------------------------
|
||||
static s32 drawDynamicUltraText(
|
||||
tsl::gfx::Renderer* renderer,
|
||||
s32 startX,
|
||||
s32 y,
|
||||
u32 fontSize,
|
||||
const tsl::Color& staticColor,
|
||||
bool useNotificationMethod = false)
|
||||
{
|
||||
// renderer->drawBitmap(LOGO_X, LOGO_Y, LOGO_WIDTH, LOGO_HEIGHT, logo_rgba_bin);
|
||||
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);
|
||||
static constexpr double cycleDuration = 1.6;
|
||||
|
||||
const std::string name = "Horizon OC Zeus";
|
||||
s32 currentX = startX;
|
||||
|
||||
const u64 currentTime_ns = armTicksToNs(armGetSystemTick());
|
||||
const double timeNow = static_cast<double>(currentTime_ns) / 1e9;
|
||||
const double timeBase = fmod(timeNow, cycleDuration);
|
||||
|
||||
const double waveScale = 2.0 * M_PI / cycleDuration;
|
||||
|
||||
for (size_t i = 0; i < name.size(); i++)
|
||||
{
|
||||
char letter = name[i];
|
||||
if (letter == '\0') break;
|
||||
|
||||
double phase = waveScale * (timeBase + i * 0.12);
|
||||
|
||||
double raw = cos(phase);
|
||||
double n = (raw + 1.0) * 0.5;
|
||||
double s1 = n * n * (3.0 - 2.0 * n);
|
||||
double blend = std::clamp(s1, 0.0, 1.0);
|
||||
|
||||
// ---------------------------------------------
|
||||
// Glow Pulse (brightness modulation)
|
||||
// ---------------------------------------------
|
||||
double glow = (cos(phase * 1.5) + 1.0) * 0.5;
|
||||
double brightness = 0.75 + glow * 0.25;
|
||||
|
||||
// ---------------------------------------------
|
||||
// Color interpolation (4-bit!)
|
||||
// ---------------------------------------------
|
||||
u8 r = static_cast<u8>(
|
||||
(dynamicLogoRGB1.r + (dynamicLogoRGB2.r - dynamicLogoRGB1.r) * blend) * brightness
|
||||
);
|
||||
u8 g = static_cast<u8>(
|
||||
(dynamicLogoRGB1.g + (dynamicLogoRGB2.g - dynamicLogoRGB1.g) * blend) * brightness
|
||||
);
|
||||
u8 b = static_cast<u8>(
|
||||
(dynamicLogoRGB1.b + (dynamicLogoRGB2.b - dynamicLogoRGB1.b) * blend) * brightness
|
||||
);
|
||||
|
||||
r = std::clamp<u8>(r, 0, 15);
|
||||
g = std::clamp<u8>(g, 0, 15);
|
||||
b = std::clamp<u8>(b, 0, 15);
|
||||
|
||||
// ---------------------------------------------
|
||||
// ZEUS Lightning Flash
|
||||
// ---------------------------------------------
|
||||
bool lightning = (fmod(timeNow, 5.0) < 0.15);
|
||||
if (lightning) {
|
||||
r = std::min<u8>(r + 4, 15);
|
||||
g = std::min<u8>(g + 4, 15);
|
||||
b = std::min<u8>(b + 15, 15); // strong blue spike
|
||||
}
|
||||
|
||||
tsl::Color color(r, g, b, 15);
|
||||
|
||||
// ---------------------------------------------
|
||||
// Vertical Water Wobble
|
||||
// ---------------------------------------------
|
||||
s32 wobbleY = y + sin(phase) * 3;
|
||||
|
||||
std::string ls(1, letter);
|
||||
|
||||
if (useNotificationMethod)
|
||||
currentX += renderer->drawNotificationString(ls, false, currentX, wobbleY, fontSize, color).first;
|
||||
else
|
||||
currentX += renderer->drawString(ls, false, currentX, wobbleY, fontSize, color).first;
|
||||
}
|
||||
|
||||
return currentX;
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
// PRE-DRAW HOOK
|
||||
// ---------------------------------------------
|
||||
void BaseGui::preDraw(tsl::gfx::Renderer* renderer)
|
||||
{
|
||||
drawDynamicUltraText(
|
||||
renderer,
|
||||
LOGO_X,
|
||||
LOGO_Y,
|
||||
LOGO_LABEL_FONT_SIZE,
|
||||
STATIC_AQUA,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
// UI SETUP
|
||||
// ---------------------------------------------
|
||||
tsl::elm::Element* BaseGui::createUI()
|
||||
{
|
||||
BaseFrame* rootFrame = new BaseFrame(this);
|
||||
@@ -64,6 +166,9 @@ tsl::elm::Element* BaseGui::createUI()
|
||||
return rootFrame;
|
||||
}
|
||||
|
||||
// ---------------------------------------------
|
||||
// LIVE UPDATE
|
||||
// ---------------------------------------------
|
||||
void BaseGui::update()
|
||||
{
|
||||
this->refresh();
|
||||
|
||||
@@ -37,8 +37,6 @@ BaseMenuGui::BaseMenuGui() : tempColors{tsl::Color(0), tsl::Color(0), tsl::Color
|
||||
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();
|
||||
@@ -104,9 +102,12 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||
renderer->drawString(displayStrings[2], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU
|
||||
renderer->drawString(displayStrings[3], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU
|
||||
renderer->drawString(displayStrings[4], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM
|
||||
|
||||
|
||||
y = 149; // Direct assignment (129 + 20)
|
||||
|
||||
|
||||
renderer->drawString(displayStrings[17], false, positions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU Usage
|
||||
renderer->drawString(displayStrings[18], false, positions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // RAM Usage
|
||||
|
||||
// === REAL FREQUENCIES ===
|
||||
renderer->drawString(displayStrings[5], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU real
|
||||
renderer->drawString(displayStrings[6], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU real
|
||||
@@ -117,15 +118,8 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||
// === 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);
|
||||
}
|
||||
|
||||
renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[5]-16, y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
|
||||
|
||||
y = 191; // Direct assignment (169 + 22)
|
||||
|
||||
@@ -142,11 +136,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||
|
||||
y = 211; // 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);
|
||||
}
|
||||
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);
|
||||
@@ -172,59 +162,6 @@ void BaseMenuGui::refresh()
|
||||
this->context = new SysClkContext;
|
||||
}
|
||||
|
||||
// === ULTRA-FAST VOLTAGE READING ===
|
||||
// Pre-computed domain configuration based on hardware
|
||||
static const PowerDomainId domains[] = {
|
||||
PcvPowerDomainId_Max77621_Cpu, // [0] CPU
|
||||
PcvPowerDomainId_Max77621_Gpu, // [1] GPU
|
||||
PcvPowerDomainId_Max77812_Dram, // [2] EMC/DRAM - Mariko only
|
||||
PcvPowerDomainId_Max77620_Sd0, // [3] SOC - EOS only
|
||||
PcvPowerDomainId_Max77620_Sd1 // [4] VDD2 - EOS only
|
||||
};
|
||||
|
||||
// Voltage array for direct indexing
|
||||
u32* voltages[] = {&cpuVoltageUv, &gpuVoltageUv, &emcVoltageUv, &socVoltageUv, &vddVoltageUv};
|
||||
|
||||
// Single regulator init/exit cycle
|
||||
if (R_SUCCEEDED(rgltrInitialize())) [[likely]] {
|
||||
if (IsMariko()) {
|
||||
// Mariko with EOS: all 5 domains
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 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]] {
|
||||
@@ -240,39 +177,37 @@ void BaseMenuGui::refresh()
|
||||
strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true));
|
||||
|
||||
// Current frequencies
|
||||
u32 hz = context->freqs[0]; // CPU
|
||||
u32 hz = context->freqs[SysClkModule_CPU]; // CPU
|
||||
sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
hz = context->freqs[1]; // GPU
|
||||
hz = context->freqs[SysClkModule_GPU]; // GPU
|
||||
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
hz = context->freqs[2]; // MEM
|
||||
|
||||
hz = context->freqs[SysClkModule_MEM]; // MEM
|
||||
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
// Real frequencies
|
||||
hz = context->realFreqs[0]; // CPU
|
||||
hz = context->realFreqs[SysClkModule_CPU]; // CPU
|
||||
sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
hz = context->realFreqs[1]; // GPU
|
||||
hz = context->realFreqs[SysClkModule_GPU]; // GPU
|
||||
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||
|
||||
hz = context->realFreqs[2]; // MEM
|
||||
hz = context->realFreqs[SysClkModule_MEM]; // 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);
|
||||
sprintf(displayStrings[8], "%.1f mV", context->voltages[HocClkVoltage_CPU] / 1000.0);
|
||||
sprintf(displayStrings[9], "%.1f mV", context->voltages[HocClkVoltage_GPU] / 1000.0);
|
||||
|
||||
// Memory voltage (handle VDD case)
|
||||
if (emcVoltageUv && vddVoltageUv) {
|
||||
if (IsMariko()) {
|
||||
//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.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ_MarikoOnly] / 1000U);
|
||||
} else {
|
||||
//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);
|
||||
sprintf(displayStrings[10], "%u.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDD2] / 1000U);
|
||||
}
|
||||
|
||||
// Temperatures and pre-compute colors
|
||||
@@ -289,13 +224,16 @@ void BaseMenuGui::refresh()
|
||||
tempColors[2] = tsl::GradientColor(millis * 0.001f);
|
||||
|
||||
// SOC voltage (if available)
|
||||
if (socVoltageUv) {
|
||||
sprintf(displayStrings[14], "%u mV", socVoltageUv / 1000U);
|
||||
}
|
||||
sprintf(displayStrings[14], "%u mV", context->voltages[HocClkVoltage_SOC] / 1000U);
|
||||
|
||||
// Power
|
||||
sprintf(displayStrings[15], "%d mW", context->power[0]); // Now
|
||||
sprintf(displayStrings[16], "%d mW", context->power[1]); // Avg
|
||||
|
||||
|
||||
sprintf(displayStrings[17], "%u%%", context->PartLoad[HocClkPartLoad_GPU] / 10);
|
||||
sprintf(displayStrings[18], "%u%%", context->PartLoad[SysClkPartLoad_EMC] / 10);
|
||||
|
||||
}
|
||||
|
||||
tsl::elm::Element* BaseMenuGui::baseUI()
|
||||
|
||||
@@ -36,11 +36,6 @@ 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;
|
||||
@@ -71,6 +66,6 @@ class BaseMenuGui : public BaseGui
|
||||
virtual void listUI() = 0;
|
||||
|
||||
private:
|
||||
char displayStrings[17][32]; // Pre-formatted display strings
|
||||
char displayStrings[32][32]; // Pre-formatted display strings
|
||||
tsl::Color tempColors[3]; // Pre-computed temperature colors
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user