Merge branch 'main' of https://github.com/Horizon-OC/Horizon-OC
This commit is contained in:
@@ -34,7 +34,7 @@ volatile CustomizeTable C = {
|
|||||||
/* Disables RAM powerdown */
|
/* Disables RAM powerdown */
|
||||||
.hpMode = DISABLED,
|
.hpMode = DISABLED,
|
||||||
|
|
||||||
.commonEmcMemVolt = 1175000, /* LPDDR4X JEDEC Specification */
|
.commonEmcMemVolt = 1175000, /* LPDDR4(X) JEDEC Specification */
|
||||||
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
|
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
|
||||||
.eristaEmcMaxClock1 = 1600000,
|
.eristaEmcMaxClock1 = 1600000,
|
||||||
.eristaEmcMaxClock2 = 1600000,
|
.eristaEmcMaxClock2 = 1600000,
|
||||||
@@ -103,10 +103,8 @@ volatile CustomizeTable C = {
|
|||||||
|
|
||||||
.marikoGpuUV = 0,
|
.marikoGpuUV = 0,
|
||||||
|
|
||||||
/* For automatic vmin detection, set this to AUTO. */
|
/* Vmin past 795mV won't work due boot voltage being 800mV. */
|
||||||
/* vmin past 795mV won't work due to HOS limitation */
|
.marikoGpuVmin = 610,
|
||||||
/* Vmin is automatically set to 800mV when SoC temperature is below 20C */
|
|
||||||
.marikoGpuVmin = AUTO,
|
|
||||||
|
|
||||||
.marikoGpuVmax = 800,
|
.marikoGpuVmax = 800,
|
||||||
|
|
||||||
|
|||||||
@@ -90,38 +90,6 @@ namespace ams::ldr::hoc::pcv {
|
|||||||
static const u32 gpuVoltThermalPattern[] = { 800, 1120, 0, 610, 1120, 20000, 610, 1120, 30000, 610, 1120, 50000, 610, 1120, 70000, 610, 1120, 90000, };
|
static const u32 gpuVoltThermalPattern[] = { 800, 1120, 0, 610, 1120, 20000, 610, 1120, 30000, 610, 1120, 50000, 610, 1120, 70000, 610, 1120, 90000, };
|
||||||
static_assert(sizeof(gpuVoltThermalPattern) == 72, "Invalid gpuVoltThermalPattern");
|
static_assert(sizeof(gpuVoltThermalPattern) == 72, "Invalid gpuVoltThermalPattern");
|
||||||
|
|
||||||
struct SpeedoVminTable {
|
|
||||||
u32 speedo;
|
|
||||||
u32 voltage;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RamVminOffsetTable {
|
|
||||||
u32 maxClock;
|
|
||||||
u32 offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const SpeedoVminTable vminTable[] {
|
|
||||||
{1400, 610}, // LOW SPEEDO -> use stock vmin
|
|
||||||
{1560, 590},
|
|
||||||
{1583, 570},
|
|
||||||
{1620, 565},
|
|
||||||
{1670, 560},
|
|
||||||
{1694, 555},
|
|
||||||
{1731, 550},
|
|
||||||
{1750, 540},
|
|
||||||
{0xFFFFFFFF, 530},
|
|
||||||
};
|
|
||||||
|
|
||||||
static const RamVminOffsetTable ramOffset[] {
|
|
||||||
{2400000, 5},
|
|
||||||
{2533000, 10},
|
|
||||||
{2666000, 15},
|
|
||||||
{2800000, 20},
|
|
||||||
{2933000, 25},
|
|
||||||
{3200000, 30},
|
|
||||||
{0xFFFFFFFF, 35},
|
|
||||||
};
|
|
||||||
|
|
||||||
/* GPU Max Clock asm Pattern:
|
/* GPU Max Clock asm Pattern:
|
||||||
*
|
*
|
||||||
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
|
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
|
||||||
|
|||||||
@@ -24,46 +24,6 @@
|
|||||||
|
|
||||||
namespace ams::ldr::hoc::pcv::mariko {
|
namespace ams::ldr::hoc::pcv::mariko {
|
||||||
|
|
||||||
u32 GetGpuVminVoltage() {
|
|
||||||
for (auto e : vminTable) {
|
|
||||||
if (C.gpuSpeedo <= e.speedo) {
|
|
||||||
return e.voltage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 530;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 GetRamVminAdjustment(u32 vmin) {
|
|
||||||
if (C.marikoEmcMaxClock < 2133000) {
|
|
||||||
return vmin;
|
|
||||||
}
|
|
||||||
|
|
||||||
const u32 ramScale = (((C.marikoEmcMaxClock / 1000) - 2133) / 33) * 5 + vmin;
|
|
||||||
|
|
||||||
for (auto r : ramOffset) {
|
|
||||||
if (C.marikoEmcMaxClock < r.maxClock) {
|
|
||||||
return ramScale + r.offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ramScale;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: EOS (probably?) has a bug in this function that always results in high vmin, this is fixed here. */
|
|
||||||
u32 GetAutoVoltage() {
|
|
||||||
u32 voltage = GetGpuVminVoltage();
|
|
||||||
voltage = GetRamVminAdjustment(voltage);
|
|
||||||
|
|
||||||
u32 voltageOffset = 590 - C.commonGpuVoltOffset;
|
|
||||||
|
|
||||||
if (voltageOffset < voltage) {
|
|
||||||
voltage = voltageOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
return voltage;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result GpuVoltDVFS(u32 *ptr) {
|
Result GpuVoltDVFS(u32 *ptr) {
|
||||||
/* Check for valid pattern. */
|
/* Check for valid pattern. */
|
||||||
for (size_t i = 0; i < std::size(gpuDVFSPattern); ++i) {
|
for (size_t i = 0; i < std::size(gpuDVFSPattern); ++i) {
|
||||||
@@ -77,15 +37,10 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
PATCH_OFFSET(ptr + 1, C.marikoGpuVmax);
|
PATCH_OFFSET(ptr + 1, C.marikoGpuVmax);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* C.marikoGpuVmin is non zero, user sets manual voltage. */
|
|
||||||
if (C.marikoGpuVmin) {
|
if (C.marikoGpuVmin) {
|
||||||
PATCH_OFFSET(ptr, C.marikoGpuVmin);
|
PATCH_OFFSET(ptr, C.marikoGpuVmin);
|
||||||
R_SUCCEED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* C.marikoGpuVmin is zero, auto voltage is applied. */
|
|
||||||
u32 autoVmin = GetAutoVoltage();
|
|
||||||
PATCH_OFFSET(ptr, autoVmin);
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,24 +49,15 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
R_THROW(ldr::ResultInvalidGpuDvfs());
|
R_THROW(ldr::ResultInvalidGpuDvfs());
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 vmin = C.marikoGpuVmin;
|
|
||||||
|
|
||||||
/* Automatic voltage. */
|
|
||||||
if (!C.marikoGpuVmin) {
|
if (!C.marikoGpuVmin) {
|
||||||
vmin = GetAutoVoltage();
|
R_SKIP();
|
||||||
PATCH_OFFSET(ptr, vmin);
|
|
||||||
PATCH_OFFSET(ptr + 3, vmin);
|
|
||||||
PATCH_OFFSET(ptr + 6, vmin);
|
|
||||||
PATCH_OFFSET(ptr + 9, vmin);
|
|
||||||
} else {
|
|
||||||
/* Manual voltage. */
|
|
||||||
PATCH_OFFSET(ptr, vmin);
|
|
||||||
PATCH_OFFSET(ptr + 3, vmin);
|
|
||||||
PATCH_OFFSET(ptr + 6, vmin);
|
|
||||||
PATCH_OFFSET(ptr + 9, vmin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PATCH_OFFSET(ptr + 12, vmin);
|
PATCH_OFFSET(ptr + 0, C.marikoGpuVmin);
|
||||||
|
PATCH_OFFSET(ptr + 3, C.marikoGpuVmin);
|
||||||
|
PATCH_OFFSET(ptr + 6, C.marikoGpuVmin);
|
||||||
|
PATCH_OFFSET(ptr + 9, C.marikoGpuVmin);
|
||||||
|
PATCH_OFFSET(ptr + 12, C.marikoGpuVmin);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,7 @@ private:
|
|||||||
size_t fontsize = 0;
|
size_t fontsize = 0;
|
||||||
bool showFPS = false;
|
bool showFPS = false;
|
||||||
uint64_t systemtickfrequency_impl = systemtickfrequency;
|
uint64_t systemtickfrequency_impl = systemtickfrequency;
|
||||||
|
|
||||||
// Pre-compiled render data structures
|
// Pre-compiled render data structures
|
||||||
struct RenderItem {
|
struct RenderItem {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -45,7 +45,7 @@ private:
|
|||||||
const char* volt_ptr;
|
const char* volt_ptr;
|
||||||
bool has_voltage;
|
bool has_voltage;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resolution tracking
|
// Resolution tracking
|
||||||
resolutionCalls m_resolutionRenderCalls[8] = {0};
|
resolutionCalls m_resolutionRenderCalls[8] = {0};
|
||||||
resolutionCalls m_resolutionViewportCalls[8] = {0};
|
resolutionCalls m_resolutionViewportCalls[8] = {0};
|
||||||
@@ -62,7 +62,7 @@ private:
|
|||||||
|
|
||||||
bool skipOnce = true;
|
bool skipOnce = true;
|
||||||
bool runOnce = true;
|
bool runOnce = true;
|
||||||
|
|
||||||
// Fixed spacing system - calculate actual widths at render time
|
// Fixed spacing system - calculate actual widths at render time
|
||||||
struct LayoutMetrics {
|
struct LayoutMetrics {
|
||||||
uint32_t label_data_gap = 8; // Fixed gap between label and data
|
uint32_t label_data_gap = 8; // Fixed gap between label and data
|
||||||
@@ -72,20 +72,20 @@ private:
|
|||||||
uint32_t side_margin = 3; // Margins on left and right
|
uint32_t side_margin = 3; // Margins on left and right
|
||||||
bool calculated = false;
|
bool calculated = false;
|
||||||
} layout;
|
} layout;
|
||||||
|
|
||||||
// Lookup table for difference symbols
|
// Lookup table for difference symbols
|
||||||
static constexpr const char* diffSymbols[4] = {"△", "@", "▽", "≠"};
|
static constexpr const char* diffSymbols[4] = {"△", "@", "▽", "≠"};
|
||||||
|
|
||||||
inline const char* getDifferenceSymbol(int32_t delta) {
|
inline const char* getDifferenceSymbol(int32_t delta) {
|
||||||
if (delta > 20000) return diffSymbols[0]; // △
|
if (delta > 20000) return diffSymbols[0]; // △
|
||||||
if (delta > -20000) return diffSymbols[1]; // @
|
if (delta > -20000) return diffSymbols[1]; // @
|
||||||
if (delta < -50000) return diffSymbols[3]; // ≠
|
if (delta < -50000) return diffSymbols[3]; // ≠
|
||||||
return diffSymbols[2]; // ▽
|
return diffSymbols[2]; // ▽
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateLayoutMetrics(tsl::gfx::Renderer *renderer) {
|
void calculateLayoutMetrics(tsl::gfx::Renderer *renderer) {
|
||||||
if (layout.calculated) return;
|
if (layout.calculated) return;
|
||||||
|
|
||||||
// Use font size to determine appropriate spacing
|
// Use font size to determine appropriate spacing
|
||||||
if (fontsize <= 16) {
|
if (fontsize <= 16) {
|
||||||
layout.label_data_gap = 6;
|
layout.label_data_gap = 6;
|
||||||
@@ -103,12 +103,16 @@ private:
|
|||||||
layout.volt_data_gap = 0;
|
layout.volt_data_gap = 0;
|
||||||
layout.item_spacing = 20;
|
layout.item_spacing = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
layout.calculated = true;
|
layout.calculated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MicroOverlay() {
|
MicroOverlay() {
|
||||||
|
CPU_temp_c[0] = '\0';
|
||||||
|
GPU_temp_c[0] = '\0';
|
||||||
|
RAM_temp_c[0] = '\0';
|
||||||
|
|
||||||
tsl::hlp::requestForeground(false);
|
tsl::hlp::requestForeground(false);
|
||||||
disableJumpTo = true;
|
disableJumpTo = true;
|
||||||
//tsl::initializeUltrahandSettings();
|
//tsl::initializeUltrahandSettings();
|
||||||
@@ -135,7 +139,7 @@ public:
|
|||||||
//alphabackground = 0x0;
|
//alphabackground = 0x0;
|
||||||
deactivateOriginalFooter = true;
|
deactivateOriginalFooter = true;
|
||||||
StartThreads();
|
StartThreads();
|
||||||
|
|
||||||
// Pre-allocate render items vector
|
// Pre-allocate render items vector
|
||||||
//renderItems.reserve(8);
|
//renderItems.reserve(8);
|
||||||
realVoltsPolling = settings.realVolts;
|
realVoltsPolling = settings.realVolts;
|
||||||
@@ -144,15 +148,15 @@ public:
|
|||||||
if (R_SUCCEEDED(psmCheck) && R_SUCCEEDED(i2cCheck)) {
|
if (R_SUCCEEDED(psmCheck) && R_SUCCEEDED(i2cCheck)) {
|
||||||
uint16_t data = 0;
|
uint16_t data = 0;
|
||||||
float tempA = 0.0;
|
float tempA = 0.0;
|
||||||
|
|
||||||
// Get initial power consumption
|
// Get initial power consumption
|
||||||
Max17050ReadReg(MAX17050_AvgCurrent, &data);
|
Max17050ReadReg(MAX17050_AvgCurrent, &data);
|
||||||
tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data;
|
tempA = (1.5625 / (max17050SenseResistor * max17050CGain)) * (s16)data;
|
||||||
PowerConsumption = tempA * batVoltageAvg / 1000000.0; // Rough initial estimate
|
PowerConsumption = tempA * batVoltageAvg / 1000000.0; // Rough initial estimate
|
||||||
|
|
||||||
// Get initial battery info
|
// Get initial battery info
|
||||||
psmGetBatteryChargeInfoFields(psmService, &_batteryChargeInfoFields);
|
psmGetBatteryChargeInfoFields(psmService, &_batteryChargeInfoFields);
|
||||||
|
|
||||||
// Get initial time estimate
|
// Get initial time estimate
|
||||||
if (tempA >= 0) {
|
if (tempA >= 0) {
|
||||||
batTimeEstimate = -1;
|
batTimeEstimate = -1;
|
||||||
@@ -171,18 +175,18 @@ public:
|
|||||||
batTimeEstimate = -1;
|
batTimeEstimate = -1;
|
||||||
_batteryChargeInfoFields = {0};
|
_batteryChargeInfoFields = {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now format the initial Battery_c string
|
// Now format the initial Battery_c string
|
||||||
char remainingBatteryLife[8];
|
char remainingBatteryLife[8];
|
||||||
const float drawW = (fabsf(PowerConsumption) < 0.01f) ? 0.0f : PowerConsumption;
|
const float drawW = (fabsf(PowerConsumption) < 0.01f) ? 0.0f : PowerConsumption;
|
||||||
|
|
||||||
if (batTimeEstimate >= 0 && !(drawW <= 0.01f && drawW >= -0.01f)) {
|
if (batTimeEstimate >= 0 && !(drawW <= 0.01f && drawW >= -0.01f)) {
|
||||||
snprintf(remainingBatteryLife, sizeof(remainingBatteryLife),
|
snprintf(remainingBatteryLife, sizeof(remainingBatteryLife),
|
||||||
"%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60);
|
"%d:%02d", batTimeEstimate / 60, batTimeEstimate % 60);
|
||||||
} else {
|
} else {
|
||||||
strcpy(remainingBatteryLife, "--:--");
|
strcpy(remainingBatteryLife, "--:--");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!settings.invertBatteryDisplay) {
|
if (!settings.invertBatteryDisplay) {
|
||||||
snprintf(Battery_c, sizeof(Battery_c),
|
snprintf(Battery_c, sizeof(Battery_c),
|
||||||
"%.2f W%.1f%% [%s]",
|
"%.2f W%.1f%% [%s]",
|
||||||
@@ -197,39 +201,39 @@ public:
|
|||||||
drawW);
|
drawW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~MicroOverlay() {
|
~MicroOverlay() {
|
||||||
CloseThreads();
|
CloseThreads();
|
||||||
fixForeground = true;
|
fixForeground = true;
|
||||||
FullMode = true;
|
FullMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast parsing and render item preparation
|
// Fast parsing and render item preparation
|
||||||
void prepareRenderItems() {
|
void prepareRenderItems() {
|
||||||
if (!renderDataDirty) return;
|
if (!renderDataDirty) return;
|
||||||
|
|
||||||
renderItems.clear();
|
renderItems.clear();
|
||||||
|
|
||||||
// Fast manual parsing of settings.show
|
// Fast manual parsing of settings.show
|
||||||
const std::string& show = settings.show;
|
const std::string& show = settings.show;
|
||||||
size_t start = 0, end = 0;
|
size_t start = 0, end = 0;
|
||||||
uint8_t seen_flags = 0;
|
uint8_t seen_flags = 0;
|
||||||
|
|
||||||
static size_t len;
|
static size_t len;
|
||||||
static uint32_t key3;
|
static uint32_t key3;
|
||||||
while (start < show.length()) {
|
while (start < show.length()) {
|
||||||
end = show.find('+', start);
|
end = show.find('+', start);
|
||||||
if (end == std::string::npos) end = show.length();
|
if (end == std::string::npos) end = show.length();
|
||||||
|
|
||||||
len = end - start;
|
len = end - start;
|
||||||
if (len >= 3) {
|
if (len >= 3) {
|
||||||
const char* key = &show[start];
|
const char* key = &show[start];
|
||||||
|
|
||||||
// Use first 3 chars for fast comparison
|
// Use first 3 chars for fast comparison
|
||||||
key3 = (key[0] << 16) | (key[1] << 8) | key[2];
|
key3 = (key[0] << 16) | (key[1] << 8) | key[2];
|
||||||
|
|
||||||
switch (key3) {
|
switch (key3) {
|
||||||
case 0x435055: // "CPU"
|
case 0x435055: // "CPU"
|
||||||
if (!(seen_flags & 1)) {
|
if (!(seen_flags & 1)) {
|
||||||
@@ -286,7 +290,7 @@ public:
|
|||||||
seen_flags |= 512;
|
seen_flags |= 512;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x445443: // "DTC"
|
case 0x445443: // "DTC"
|
||||||
if (!(seen_flags & 256) && settings.showDTC) {
|
if (!(seen_flags & 256) && settings.showDTC) {
|
||||||
renderItems.push_back({8, settings.useDTCSymbol ? "\uE007" : "DTC", DTC_c, nullptr, false});
|
renderItems.push_back({8, settings.useDTCSymbol ? "\uE007" : "DTC", DTC_c, nullptr, false});
|
||||||
seen_flags |= 256;
|
seen_flags |= 256;
|
||||||
@@ -296,38 +300,38 @@ public:
|
|||||||
}
|
}
|
||||||
start = end + 1;
|
start = end + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDataDirty = false;
|
renderDataDirty = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual tsl::elm::Element* createUI() override {
|
virtual tsl::elm::Element* createUI() override {
|
||||||
|
|
||||||
auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) {
|
auto* Status = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, u16 x, u16 y, u16 w, u16 h) {
|
||||||
cachedMargin = renderer->getTextDimensions("CPUGPURAMSOCBAT[]", false, fontsize).second;
|
cachedMargin = renderer->getTextDimensions("CPUGPURAMSOCBAT[]", false, fontsize).second;
|
||||||
if (!Initialized) {
|
if (!Initialized) {
|
||||||
//cachedMargin = renderer->drawString(" ", false, 0, 0, fontsize, renderer->a(0x0000)).first;
|
//cachedMargin = renderer->drawString(" ", false, 0, 0, fontsize, renderer->a(0x0000)).first;
|
||||||
|
|
||||||
catColorA = settings.catColor;
|
catColorA = settings.catColor;
|
||||||
textColorA = settings.textColor;
|
textColorA = settings.textColor;
|
||||||
base_y = settings.setPosBottom ?
|
base_y = settings.setPosBottom ?
|
||||||
tsl::cfg::FramebufferHeight - (fontsize + (fontsize / 4)) +1: 0;
|
tsl::cfg::FramebufferHeight - (fontsize + (fontsize / 4)) +1: 0;
|
||||||
Initialized = true;
|
Initialized = true;
|
||||||
renderDataDirty = true;
|
renderDataDirty = true;
|
||||||
layout.calculated = false; // Force recalculation
|
layout.calculated = false; // Force recalculation
|
||||||
tsl::hlp::requestForeground(false);
|
tsl::hlp::requestForeground(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//renderer->drawRect(0, 0, tsl::cfg::FramebufferWidth, cachedMargin + 4, a(settings.backgroundColor));
|
//renderer->drawRect(0, 0, tsl::cfg::FramebufferWidth, cachedMargin + 4, a(settings.backgroundColor));
|
||||||
renderer->drawRect(0, settings.setPosBottom ? base_y-1 : 0, tsl::cfg::FramebufferWidth, cachedMargin + 4, a(settings.backgroundColor));
|
renderer->drawRect(0, settings.setPosBottom ? base_y-1 : 0, tsl::cfg::FramebufferWidth, cachedMargin + 4, a(settings.backgroundColor));
|
||||||
|
|
||||||
// Prepare render items if settings changed
|
// Prepare render items if settings changed
|
||||||
prepareRenderItems();
|
prepareRenderItems();
|
||||||
calculateLayoutMetrics(renderer);
|
calculateLayoutMetrics(renderer);
|
||||||
|
|
||||||
// Separate battery from other items
|
// Separate battery from other items
|
||||||
std::vector<RenderItem> main_items;
|
std::vector<RenderItem> main_items;
|
||||||
//RenderItem* battery_item = nullptr;
|
//RenderItem* battery_item = nullptr;
|
||||||
|
|
||||||
for (auto& item : renderItems) {
|
for (auto& item : renderItems) {
|
||||||
//if (item.type == 6) { // BAT
|
//if (item.type == 6) { // BAT
|
||||||
// battery_item = &item;
|
// battery_item = &item;
|
||||||
@@ -347,7 +351,7 @@ public:
|
|||||||
main_items.push_back(item);
|
main_items.push_back(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate actual widths for all main items
|
// Calculate actual widths for all main items
|
||||||
struct ItemLayout {
|
struct ItemLayout {
|
||||||
uint32_t label_width;
|
uint32_t label_width;
|
||||||
@@ -355,7 +359,7 @@ public:
|
|||||||
uint32_t volt_width;
|
uint32_t volt_width;
|
||||||
uint32_t total_width;
|
uint32_t total_width;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<ItemLayout> item_layouts;
|
std::vector<ItemLayout> item_layouts;
|
||||||
uint32_t total_main_width = 0;
|
uint32_t total_main_width = 0;
|
||||||
|
|
||||||
@@ -364,81 +368,81 @@ public:
|
|||||||
static ItemLayout item_layout;
|
static ItemLayout item_layout;
|
||||||
for (const auto& item : main_items) {
|
for (const auto& item : main_items) {
|
||||||
item_layout = {};
|
item_layout = {};
|
||||||
|
|
||||||
// Calculate actual label width
|
// Calculate actual label width
|
||||||
//auto label_dim = renderer->drawString(item.label, false, 0, 0, fontsize, renderer->a(0x0000));
|
//auto label_dim = renderer->drawString(item.label, false, 0, 0, fontsize, renderer->a(0x0000));
|
||||||
//auto label_dim = renderer->getTextDimensions(item.label, fontsize);
|
//auto label_dim = renderer->getTextDimensions(item.label, fontsize);
|
||||||
item_layout.label_width = renderer->getTextDimensions(item.label, false, fontsize).first;
|
item_layout.label_width = renderer->getTextDimensions(item.label, false, fontsize).first;
|
||||||
|
|
||||||
// Calculate actual data width
|
// Calculate actual data width
|
||||||
//auto data_dim = renderer->drawString(item.data_ptr, false, 0, 0, fontsize, renderer->a(0x0000));
|
//auto data_dim = renderer->drawString(item.data_ptr, false, 0, 0, fontsize, renderer->a(0x0000));
|
||||||
//auto data_dim = renderer->getTextDimensions(item.data_ptr, fontsize);
|
//auto data_dim = renderer->getTextDimensions(item.data_ptr, fontsize);
|
||||||
item_layout.data_width = renderer->getTextDimensions(item.data_ptr, false, fontsize).first;
|
item_layout.data_width = renderer->getTextDimensions(item.data_ptr, false, fontsize).first;
|
||||||
|
|
||||||
// Calculate voltage width if present
|
// Calculate voltage width if present
|
||||||
if (item.has_voltage && item.volt_ptr) {
|
if (item.has_voltage && item.volt_ptr) {
|
||||||
//uto volt_dim = renderer->drawString(item.volt_ptr, false, 0, 0, fontsize, renderer->a(0x0000));
|
//uto volt_dim = renderer->drawString(item.volt_ptr, false, 0, 0, fontsize, renderer->a(0x0000));
|
||||||
//auto volt_dim = renderer->getTextDimensions(item.volt_ptr, fontsize);
|
//auto volt_dim = renderer->getTextDimensions(item.volt_ptr, fontsize);
|
||||||
item_layout.volt_width = renderer->getTextDimensions(item.volt_ptr, false, fontsize).first;
|
item_layout.volt_width = renderer->getTextDimensions(item.volt_ptr, false, fontsize).first;
|
||||||
|
|
||||||
// Total: label + gap + data + gap + "|" + gap + voltage
|
// Total: label + gap + data + gap + "|" + gap + voltage
|
||||||
//auto sep_width = renderer->drawString("", false, 0, 0, fontsize, renderer->a(0x0000));
|
//auto sep_width = renderer->drawString("", false, 0, 0, fontsize, renderer->a(0x0000));
|
||||||
item_layout.total_width = item_layout.label_width + layout.label_data_gap +
|
item_layout.total_width = item_layout.label_width + layout.label_data_gap +
|
||||||
item_layout.data_width + layout.volt_separator_gap +
|
item_layout.data_width + layout.volt_separator_gap +
|
||||||
sep_width + layout.volt_data_gap + item_layout.volt_width;
|
sep_width + layout.volt_data_gap + item_layout.volt_width;
|
||||||
} else {
|
} else {
|
||||||
// Total: label + gap + data
|
// Total: label + gap + data
|
||||||
item_layout.total_width = item_layout.label_width + layout.label_data_gap + item_layout.data_width;
|
item_layout.total_width = item_layout.label_width + layout.label_data_gap + item_layout.data_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
item_layouts.push_back(item_layout);
|
item_layouts.push_back(item_layout);
|
||||||
total_main_width += item_layout.total_width;
|
total_main_width += item_layout.total_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Determine if we have battery and handle it as the rightmost item
|
// Determine if we have battery and handle it as the rightmost item
|
||||||
std::vector<RenderItem> all_items_ordered;
|
std::vector<RenderItem> all_items_ordered;
|
||||||
std::vector<ItemLayout> all_layouts_ordered;
|
std::vector<ItemLayout> all_layouts_ordered;
|
||||||
|
|
||||||
// Add main items first
|
// Add main items first
|
||||||
for (size_t i = 0; i < main_items.size(); i++) {
|
for (size_t i = 0; i < main_items.size(); i++) {
|
||||||
all_items_ordered.push_back(main_items[i]);
|
all_items_ordered.push_back(main_items[i]);
|
||||||
all_layouts_ordered.push_back(item_layouts[i]);
|
all_layouts_ordered.push_back(item_layouts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add battery as the last item if present
|
// Add battery as the last item if present
|
||||||
//if (battery_item) {
|
//if (battery_item) {
|
||||||
// //auto bat_label_dim = renderer->drawString("BAT", false, 0, 0, fontsize, renderer->a(0x0000));
|
// //auto bat_label_dim = renderer->drawString("BAT", false, 0, 0, fontsize, renderer->a(0x0000));
|
||||||
// //auto bat_label_dim = renderer->getTextDimensions("BAT", fontsize);
|
// //auto bat_label_dim = renderer->getTextDimensions("BAT", fontsize);
|
||||||
// //auto bat_data_dim = renderer->drawString(battery_item->data_ptr, false, 0, 0, fontsize, renderer->a(0x0000));
|
// //auto bat_data_dim = renderer->drawString(battery_item->data_ptr, false, 0, 0, fontsize, renderer->a(0x0000));
|
||||||
// //auto bat_data_dim = renderer->getTextDimensions(battery_item->data_ptr, fontsize);
|
// //auto bat_data_dim = renderer->getTextDimensions(battery_item->data_ptr, fontsize);
|
||||||
//
|
//
|
||||||
// ItemLayout battery_layout = {};
|
// ItemLayout battery_layout = {};
|
||||||
// battery_layout.label_width = renderer->getTextDimensions("BAT", false, fontsize).first;
|
// battery_layout.label_width = renderer->getTextDimensions("BAT", false, fontsize).first;
|
||||||
// battery_layout.data_width = renderer->getTextDimensions(battery_item->data_ptr, false, fontsize).first;
|
// battery_layout.data_width = renderer->getTextDimensions(battery_item->data_ptr, false, fontsize).first;
|
||||||
// battery_layout.volt_width = 0;
|
// battery_layout.volt_width = 0;
|
||||||
// battery_layout.total_width = battery_layout.label_width + layout.label_data_gap + battery_layout.data_width;
|
// battery_layout.total_width = battery_layout.label_width + layout.label_data_gap + battery_layout.data_width;
|
||||||
//
|
//
|
||||||
// all_items_ordered.push_back(*battery_item);
|
// all_items_ordered.push_back(*battery_item);
|
||||||
// all_layouts_ordered.push_back(battery_layout);
|
// all_layouts_ordered.push_back(battery_layout);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
// Calculate total width of all items
|
// Calculate total width of all items
|
||||||
uint32_t total_all_width = 0;
|
uint32_t total_all_width = 0;
|
||||||
for (const auto& item_layout : all_layouts_ordered) {
|
for (const auto& item_layout : all_layouts_ordered) {
|
||||||
total_all_width += item_layout.total_width;
|
total_all_width += item_layout.total_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate available space for distribution
|
// Calculate available space for distribution
|
||||||
//uint32_t available_width = tsl::cfg::FramebufferWidth - (2 * layout.side_margin);
|
//uint32_t available_width = tsl::cfg::FramebufferWidth - (2 * layout.side_margin);
|
||||||
//uint32_t remaining_space = available_width - total_all_width;
|
//uint32_t remaining_space = available_width - total_all_width;
|
||||||
|
|
||||||
// Calculate positions based on alignment mode
|
// Calculate positions based on alignment mode
|
||||||
std::vector<uint32_t> item_positions;
|
std::vector<uint32_t> item_positions;
|
||||||
const size_t N = all_items_ordered.size();
|
const size_t N = all_items_ordered.size();
|
||||||
if (N == 0) return;
|
if (N == 0) return;
|
||||||
|
|
||||||
if (N == 1) {
|
if (N == 1) {
|
||||||
// Single item positioning based on alignment
|
// Single item positioning based on alignment
|
||||||
if (settings.alignTo == 2) { // RIGHT
|
if (settings.alignTo == 2) { // RIGHT
|
||||||
@@ -452,43 +456,43 @@ public:
|
|||||||
for (const auto& layout : all_layouts_ordered) {
|
for (const auto& layout : all_layouts_ordered) {
|
||||||
total_widths += layout.total_width;
|
total_widths += layout.total_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.alignTo == 0) { // LEFT alignment
|
if (settings.alignTo == 0) { // LEFT alignment
|
||||||
// All items except last positioned from left with small gaps
|
// All items except last positioned from left with small gaps
|
||||||
// Last item (battery if present) positioned at far right
|
// Last item (battery if present) positioned at far right
|
||||||
const uint32_t small_gap = layout.item_spacing;
|
const uint32_t small_gap = layout.item_spacing;
|
||||||
|
|
||||||
// Position items from left
|
// Position items from left
|
||||||
uint32_t current_x = layout.side_margin;
|
uint32_t current_x = layout.side_margin;
|
||||||
for (size_t i = 0; i < N - 1; ++i) {
|
for (size_t i = 0; i < N - 1; ++i) {
|
||||||
item_positions.push_back(current_x);
|
item_positions.push_back(current_x);
|
||||||
current_x += all_layouts_ordered[i].total_width + small_gap;
|
current_x += all_layouts_ordered[i].total_width + small_gap;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position last item at far right
|
// Position last item at far right
|
||||||
const uint32_t last_width = all_layouts_ordered[N-1].total_width;
|
const uint32_t last_width = all_layouts_ordered[N-1].total_width;
|
||||||
item_positions.push_back(tsl::cfg::FramebufferWidth - layout.side_margin - last_width);
|
item_positions.push_back(tsl::cfg::FramebufferWidth - layout.side_margin - last_width);
|
||||||
|
|
||||||
} else if (settings.alignTo == 2) { // RIGHT alignment
|
} else if (settings.alignTo == 2) { // RIGHT alignment
|
||||||
// First item at far left, remaining items packed at right
|
// First item at far left, remaining items packed at right
|
||||||
const uint32_t small_gap = layout.item_spacing;
|
const uint32_t small_gap = layout.item_spacing;
|
||||||
|
|
||||||
// Resize vector to hold all positions
|
// Resize vector to hold all positions
|
||||||
item_positions.resize(N);
|
item_positions.resize(N);
|
||||||
|
|
||||||
// Position first item at far left
|
// Position first item at far left
|
||||||
item_positions[0] = layout.side_margin;
|
item_positions[0] = layout.side_margin;
|
||||||
|
|
||||||
// Calculate total width of items 1 to N-1 plus gaps between them
|
// Calculate total width of items 1 to N-1 plus gaps between them
|
||||||
uint32_t right_group_width = 0;
|
uint32_t right_group_width = 0;
|
||||||
for (size_t i = 1; i < N; ++i) {
|
for (size_t i = 1; i < N; ++i) {
|
||||||
right_group_width += all_layouts_ordered[i].total_width;
|
right_group_width += all_layouts_ordered[i].total_width;
|
||||||
if (i < N - 1) right_group_width += small_gap; // Gap after each item except the last
|
if (i < N - 1) right_group_width += small_gap; // Gap after each item except the last
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start positioning from right margin minus total width of right group
|
// Start positioning from right margin minus total width of right group
|
||||||
uint32_t current_x = tsl::cfg::FramebufferWidth - layout.side_margin - right_group_width;
|
uint32_t current_x = tsl::cfg::FramebufferWidth - layout.side_margin - right_group_width;
|
||||||
|
|
||||||
// Position items 1 to N-1 sequentially from left to right within the right group
|
// Position items 1 to N-1 sequentially from left to right within the right group
|
||||||
for (size_t i = 1; i < N; ++i) {
|
for (size_t i = 1; i < N; ++i) {
|
||||||
item_positions[i] = current_x;
|
item_positions[i] = current_x;
|
||||||
@@ -497,10 +501,10 @@ public:
|
|||||||
} else { // CENTER alignment (default behavior)
|
} else { // CENTER alignment (default behavior)
|
||||||
// Total available width for spacing = framebuffer width minus total item widths minus margins
|
// Total available width for spacing = framebuffer width minus total item widths minus margins
|
||||||
const int32_t total_spacing = (int32_t)tsl::cfg::FramebufferWidth - (2 * (int32_t)layout.side_margin) - (int32_t)total_widths;
|
const int32_t total_spacing = (int32_t)tsl::cfg::FramebufferWidth - (2 * (int32_t)layout.side_margin) - (int32_t)total_widths;
|
||||||
|
|
||||||
// Number of gaps between items is N-1
|
// Number of gaps between items is N-1
|
||||||
const uint32_t gap = total_spacing > 0 ? (uint32_t)(total_spacing / (N - 1)) : 0;
|
const uint32_t gap = total_spacing > 0 ? (uint32_t)(total_spacing / (N - 1)) : 0;
|
||||||
|
|
||||||
// Position first item flush left
|
// Position first item flush left
|
||||||
item_positions.push_back(layout.side_margin);
|
item_positions.push_back(layout.side_margin);
|
||||||
static uint32_t prev_pos, prev_width;
|
static uint32_t prev_pos, prev_width;
|
||||||
@@ -510,11 +514,11 @@ public:
|
|||||||
prev_width = all_layouts_ordered[i - 1].total_width;
|
prev_width = all_layouts_ordered[i - 1].total_width;
|
||||||
item_positions.push_back(prev_pos + prev_width + gap);
|
item_positions.push_back(prev_pos + prev_width + gap);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fix any rounding error for center alignment
|
// Fix any rounding error for center alignment
|
||||||
const int32_t last_item_end = item_positions.back() + all_layouts_ordered.back().total_width;
|
const int32_t last_item_end = item_positions.back() + all_layouts_ordered.back().total_width;
|
||||||
const int32_t overflow = (int32_t)tsl::cfg::FramebufferWidth - layout.side_margin - last_item_end;
|
const int32_t overflow = (int32_t)tsl::cfg::FramebufferWidth - layout.side_margin - last_item_end;
|
||||||
|
|
||||||
if (overflow != 0) {
|
if (overflow != 0) {
|
||||||
for (size_t i = 1; i < item_positions.size(); ++i) {
|
for (size_t i = 1; i < item_positions.size(); ++i) {
|
||||||
item_positions[i] += overflow;
|
item_positions[i] += overflow;
|
||||||
@@ -532,11 +536,11 @@ public:
|
|||||||
const auto& item = all_items_ordered[i];
|
const auto& item = all_items_ordered[i];
|
||||||
const auto& item_layout = all_layouts_ordered[i];
|
const auto& item_layout = all_layouts_ordered[i];
|
||||||
current_x = item_positions[i];
|
current_x = item_positions[i];
|
||||||
|
|
||||||
// Draw label
|
// Draw label
|
||||||
renderer->drawString(item.label, false, current_x, base_y + cachedMargin, fontsize, catColorA);
|
renderer->drawString(item.label, false, current_x, base_y + cachedMargin, fontsize, catColorA);
|
||||||
current_x += item_layout.label_width + layout.label_data_gap;
|
current_x += item_layout.label_width + layout.label_data_gap;
|
||||||
|
|
||||||
// Draw data
|
// Draw data
|
||||||
//renderer->drawString(item.data_ptr, false, current_x, base_y + fontsize, fontsize, textColorA);
|
//renderer->drawString(item.data_ptr, false, current_x, base_y + fontsize, fontsize, textColorA);
|
||||||
|
|
||||||
@@ -552,22 +556,22 @@ public:
|
|||||||
const size_t cPos = dataStr.find("C", degreesPos);
|
const size_t cPos = dataStr.find("C", degreesPos);
|
||||||
if (cPos != std::string::npos) {
|
if (cPos != std::string::npos) {
|
||||||
const size_t tempEnd = cPos + 1;
|
const size_t tempEnd = cPos + 1;
|
||||||
|
|
||||||
const std::string preTempPart = dataStr.substr(0, tempStart);
|
const std::string preTempPart = dataStr.substr(0, tempStart);
|
||||||
const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart);
|
const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart);
|
||||||
const std::string postTempPart = dataStr.substr(tempEnd);
|
const std::string postTempPart = dataStr.substr(tempEnd);
|
||||||
|
|
||||||
const float temp = realCPU_Temp / 1000.0f;
|
const float temp = realCPU_Temp / 1000.0f;
|
||||||
const tsl::Color tempColor = tsl::GradientColor(temp);
|
const tsl::Color tempColor = tsl::GradientColor(temp);
|
||||||
|
|
||||||
uint32_t renderX = current_x;
|
uint32_t renderX = current_x;
|
||||||
if (!preTempPart.empty()) {
|
if (!preTempPart.empty()) {
|
||||||
renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first;
|
renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor));
|
||||||
|
|
||||||
if (!postTempPart.empty()) {
|
if (!postTempPart.empty()) {
|
||||||
renderX += renderer->getTextDimensions(tempPart, false, fontsize).first;
|
renderX += renderer->getTextDimensions(tempPart, false, fontsize).first;
|
||||||
renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
@@ -581,7 +585,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (item.type == 1) { // GPU
|
} else if (item.type == 1) { // GPU
|
||||||
std::string dataStr(item.data_ptr);
|
std::string dataStr(item.data_ptr);
|
||||||
const size_t degreesPos = dataStr.find("°");
|
const size_t degreesPos = dataStr.find("°");
|
||||||
@@ -592,22 +596,22 @@ public:
|
|||||||
const size_t cPos = dataStr.find("C", degreesPos);
|
const size_t cPos = dataStr.find("C", degreesPos);
|
||||||
if (cPos != std::string::npos) {
|
if (cPos != std::string::npos) {
|
||||||
const size_t tempEnd = cPos + 1;
|
const size_t tempEnd = cPos + 1;
|
||||||
|
|
||||||
const std::string preTempPart = dataStr.substr(0, tempStart);
|
const std::string preTempPart = dataStr.substr(0, tempStart);
|
||||||
const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart);
|
const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart);
|
||||||
const std::string postTempPart = dataStr.substr(tempEnd);
|
const std::string postTempPart = dataStr.substr(tempEnd);
|
||||||
|
|
||||||
const float temp = realGPU_Temp / 1000.0f;
|
const float temp = realGPU_Temp / 1000.0f;
|
||||||
const tsl::Color tempColor = tsl::GradientColor(temp);
|
const tsl::Color tempColor = tsl::GradientColor(temp);
|
||||||
|
|
||||||
uint32_t renderX = current_x;
|
uint32_t renderX = current_x;
|
||||||
if (!preTempPart.empty()) {
|
if (!preTempPart.empty()) {
|
||||||
renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first;
|
renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor));
|
||||||
|
|
||||||
if (!postTempPart.empty()) {
|
if (!postTempPart.empty()) {
|
||||||
renderX += renderer->getTextDimensions(tempPart, false, fontsize).first;
|
renderX += renderer->getTextDimensions(tempPart, false, fontsize).first;
|
||||||
renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
@@ -621,7 +625,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (item.type == 2) { // RAM
|
} else if (item.type == 2) { // RAM
|
||||||
std::string dataStr(item.data_ptr);
|
std::string dataStr(item.data_ptr);
|
||||||
const size_t degreesPos = dataStr.find("°");
|
const size_t degreesPos = dataStr.find("°");
|
||||||
@@ -632,22 +636,22 @@ public:
|
|||||||
const size_t cPos = dataStr.find("C", degreesPos);
|
const size_t cPos = dataStr.find("C", degreesPos);
|
||||||
if (cPos != std::string::npos) {
|
if (cPos != std::string::npos) {
|
||||||
const size_t tempEnd = cPos + 1;
|
const size_t tempEnd = cPos + 1;
|
||||||
|
|
||||||
const std::string preTempPart = dataStr.substr(0, tempStart);
|
const std::string preTempPart = dataStr.substr(0, tempStart);
|
||||||
const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart);
|
const std::string tempPart = dataStr.substr(tempStart, tempEnd - tempStart);
|
||||||
const std::string postTempPart = dataStr.substr(tempEnd);
|
const std::string postTempPart = dataStr.substr(tempEnd);
|
||||||
|
|
||||||
const float temp = realRAM_Temp / 1000.0f;
|
const float temp = realRAM_Temp / 1000.0f;
|
||||||
const tsl::Color tempColor = tsl::GradientColor(temp);
|
const tsl::Color tempColor = tsl::GradientColor(temp);
|
||||||
|
|
||||||
uint32_t renderX = current_x;
|
uint32_t renderX = current_x;
|
||||||
if (!preTempPart.empty()) {
|
if (!preTempPart.empty()) {
|
||||||
renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(preTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first;
|
renderX += renderer->getTextDimensions(preTempPart, false, fontsize).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor));
|
||||||
|
|
||||||
if (!postTempPart.empty()) {
|
if (!postTempPart.empty()) {
|
||||||
renderX += renderer->getTextDimensions(tempPart, false, fontsize).first;
|
renderX += renderer->getTextDimensions(tempPart, false, fontsize).first;
|
||||||
renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(postTempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
@@ -661,7 +665,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (item.type == 3) { // SOC temperature
|
} else if (item.type == 3) { // SOC temperature
|
||||||
// Parse SOC temperature: "XX°C (XX%)"
|
// Parse SOC temperature: "XX°C (XX%)"
|
||||||
std::string dataStr(item.data_ptr);
|
std::string dataStr(item.data_ptr);
|
||||||
@@ -670,18 +674,18 @@ public:
|
|||||||
const size_t cPos = dataStr.find("C", degreesPos);
|
const size_t cPos = dataStr.find("C", degreesPos);
|
||||||
if (cPos != std::string::npos) {
|
if (cPos != std::string::npos) {
|
||||||
const size_t tempEnd = cPos + 1; // Include the 'C'
|
const size_t tempEnd = cPos + 1; // Include the 'C'
|
||||||
|
|
||||||
// Extract temperature value and apply gradient
|
// Extract temperature value and apply gradient
|
||||||
const int temp = atoi(item.data_ptr);
|
const int temp = atoi(item.data_ptr);
|
||||||
const tsl::Color tempColor = tsl::GradientColor((float)temp);
|
const tsl::Color tempColor = tsl::GradientColor((float)temp);
|
||||||
|
|
||||||
// Split into temperature part and remaining part
|
// Split into temperature part and remaining part
|
||||||
const std::string tempPart = dataStr.substr(0, tempEnd);
|
const std::string tempPart = dataStr.substr(0, tempEnd);
|
||||||
const std::string restPart = dataStr.substr(tempEnd);
|
const std::string restPart = dataStr.substr(tempEnd);
|
||||||
|
|
||||||
// Render temperature with gradient color
|
// Render temperature with gradient color
|
||||||
renderer->drawString(tempPart, false, current_x, base_y + cachedMargin, fontsize, tempColor);
|
renderer->drawString(tempPart, false, current_x, base_y + cachedMargin, fontsize, tempColor);
|
||||||
|
|
||||||
// Render remaining text with normal color
|
// Render remaining text with normal color
|
||||||
if (!restPart.empty()) {
|
if (!restPart.empty()) {
|
||||||
const uint32_t tempPartWidth = renderer->getTextDimensions(tempPart, false, fontsize).first;
|
const uint32_t tempPartWidth = renderer->getTextDimensions(tempPart, false, fontsize).first;
|
||||||
@@ -695,14 +699,14 @@ public:
|
|||||||
// Fallback: render normally
|
// Fallback: render normally
|
||||||
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (item.type == 4) { // TMP multiple temperatures
|
} else if (item.type == 4) { // TMP multiple temperatures
|
||||||
// Parse TMP temperatures: "XX°C XX°C XX°C (XX%)"
|
// Parse TMP temperatures: "XX°C XX°C XX°C (XX%)"
|
||||||
std::string dataStr(item.data_ptr);
|
std::string dataStr(item.data_ptr);
|
||||||
uint32_t renderX = current_x;
|
uint32_t renderX = current_x;
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
bool parseSuccess = true;
|
bool parseSuccess = true;
|
||||||
|
|
||||||
// Parse up to 3 temperatures
|
// Parse up to 3 temperatures
|
||||||
for (int tempCount = 0; tempCount < 3 && parseSuccess && pos < dataStr.length(); tempCount++) {
|
for (int tempCount = 0; tempCount < 3 && parseSuccess && pos < dataStr.length(); tempCount++) {
|
||||||
// Skip any leading spaces
|
// Skip any leading spaces
|
||||||
@@ -711,47 +715,47 @@ public:
|
|||||||
renderX += renderer->getTextDimensions(" ", false, fontsize).first;
|
renderX += renderer->getTextDimensions(" ", false, fontsize).first;
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos >= dataStr.length()) break;
|
if (pos >= dataStr.length()) break;
|
||||||
|
|
||||||
// Find degrees symbol
|
// Find degrees symbol
|
||||||
const size_t degreesPos = dataStr.find("°", pos);
|
const size_t degreesPos = dataStr.find("°", pos);
|
||||||
if (degreesPos == std::string::npos) {
|
if (degreesPos == std::string::npos) {
|
||||||
parseSuccess = false;
|
parseSuccess = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find 'C' after degrees symbol
|
// Find 'C' after degrees symbol
|
||||||
const size_t cPos = dataStr.find("C", degreesPos);
|
const size_t cPos = dataStr.find("C", degreesPos);
|
||||||
if (cPos == std::string::npos) {
|
if (cPos == std::string::npos) {
|
||||||
parseSuccess = false;
|
parseSuccess = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t tempEnd = cPos + 1; // Include the 'C'
|
const size_t tempEnd = cPos + 1; // Include the 'C'
|
||||||
|
|
||||||
// Extract and render temperature with gradient
|
// Extract and render temperature with gradient
|
||||||
const std::string tempPart = dataStr.substr(pos, tempEnd - pos);
|
const std::string tempPart = dataStr.substr(pos, tempEnd - pos);
|
||||||
const int temp = atoi(tempPart.c_str());
|
const int temp = atoi(tempPart.c_str());
|
||||||
const tsl::Color tempColor = tsl::GradientColor((float)temp);
|
const tsl::Color tempColor = tsl::GradientColor((float)temp);
|
||||||
|
|
||||||
renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(tempPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, tempColor, a(settings.separatorColor));
|
||||||
renderX += renderer->getTextDimensions(tempPart, false, fontsize).first;
|
renderX += renderer->getTextDimensions(tempPart, false, fontsize).first;
|
||||||
|
|
||||||
pos = tempEnd;
|
pos = tempEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render any remaining text (like " (50%)")
|
// Render any remaining text (like " (50%)")
|
||||||
if (pos < dataStr.length()) {
|
if (pos < dataStr.length()) {
|
||||||
const std::string restPart = dataStr.substr(pos);
|
const std::string restPart = dataStr.substr(pos);
|
||||||
renderer->drawStringWithColoredSections(restPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(restPart, false, specialChars, renderX, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If parsing failed, fall back to normal rendering
|
// If parsing failed, fall back to normal rendering
|
||||||
if (!parseSuccess) {
|
if (!parseSuccess) {
|
||||||
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Normal rendering for all other item types
|
// Normal rendering for all other item types
|
||||||
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
@@ -761,7 +765,7 @@ public:
|
|||||||
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
renderer->drawStringWithColoredSections(item.data_ptr, false, specialChars, current_x, base_y + cachedMargin, fontsize, textColorA, a(settings.separatorColor));
|
||||||
}
|
}
|
||||||
current_x += item_layout.data_width;
|
current_x += item_layout.data_width;
|
||||||
|
|
||||||
// Draw voltage if present
|
// Draw voltage if present
|
||||||
if (item.has_voltage && item.volt_ptr) {
|
if (item.has_voltage && item.volt_ptr) {
|
||||||
current_x += layout.volt_separator_gap;
|
current_x += layout.volt_separator_gap;
|
||||||
@@ -773,7 +777,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("", "");
|
tsl::elm::HeaderOverlayFrame* rootFrame = new tsl::elm::HeaderOverlayFrame("", "");
|
||||||
rootFrame->setContent(Status);
|
rootFrame->setContent(Status);
|
||||||
return rootFrame;
|
return rootFrame;
|
||||||
@@ -827,7 +831,7 @@ public:
|
|||||||
|
|
||||||
// CPU usage calculations - optimized with fewer conditionals
|
// CPU usage calculations - optimized with fewer conditionals
|
||||||
const double inv_freq = 1.0 / systemtickfrequency_impl;
|
const double inv_freq = 1.0 / systemtickfrequency_impl;
|
||||||
|
|
||||||
// Capture systemtickfrequency_impl and inv_freq safely
|
// Capture systemtickfrequency_impl and inv_freq safely
|
||||||
const auto formatUsage = [this](char* buf, size_t size, uint64_t idletick, double inv_freq) {
|
const auto formatUsage = [this](char* buf, size_t size, uint64_t idletick, double inv_freq) {
|
||||||
if (idletick > systemtickfrequency_impl) {
|
if (idletick > systemtickfrequency_impl) {
|
||||||
@@ -836,60 +840,60 @@ public:
|
|||||||
snprintf(buf, size, "%.0f%%", (1.0 - (idletick * inv_freq)) * 100.0);
|
snprintf(buf, size, "%.0f%%", (1.0 - (idletick * inv_freq)) * 100.0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Atomically load idle ticks before using them
|
// Atomically load idle ticks before using them
|
||||||
const uint64_t idle0 = idletick0.load(std::memory_order_acquire);
|
const uint64_t idle0 = idletick0.load(std::memory_order_acquire);
|
||||||
const uint64_t idle1 = idletick1.load(std::memory_order_acquire);
|
const uint64_t idle1 = idletick1.load(std::memory_order_acquire);
|
||||||
const uint64_t idle2 = idletick2.load(std::memory_order_acquire);
|
const uint64_t idle2 = idletick2.load(std::memory_order_acquire);
|
||||||
const uint64_t idle3 = idletick3.load(std::memory_order_acquire);
|
const uint64_t idle3 = idletick3.load(std::memory_order_acquire);
|
||||||
|
|
||||||
formatUsage(CPU_Usage0, sizeof(CPU_Usage0), idle0, inv_freq);
|
formatUsage(CPU_Usage0, sizeof(CPU_Usage0), idle0, inv_freq);
|
||||||
formatUsage(CPU_Usage1, sizeof(CPU_Usage1), idle1, inv_freq);
|
formatUsage(CPU_Usage1, sizeof(CPU_Usage1), idle1, inv_freq);
|
||||||
formatUsage(CPU_Usage2, sizeof(CPU_Usage2), idle2, inv_freq);
|
formatUsage(CPU_Usage2, sizeof(CPU_Usage2), idle2, inv_freq);
|
||||||
formatUsage(CPU_Usage3, sizeof(CPU_Usage3), idle3, inv_freq);
|
formatUsage(CPU_Usage3, sizeof(CPU_Usage3), idle3, inv_freq);
|
||||||
|
|
||||||
mutexLock(&mutex_Misc);
|
mutexLock(&mutex_Misc);
|
||||||
|
|
||||||
// CPU frequency and voltage
|
// CPU frequency and voltage
|
||||||
const char* cpuDiff = "@";
|
const char* cpuDiff = "@";
|
||||||
if (realCPU_Hz) {
|
if (realCPU_Hz) {
|
||||||
const int32_t deltaCPU = (int32_t)(realCPU_Hz / 1000) - (CPU_Hz / 1000);
|
const int32_t deltaCPU = (int32_t)(realCPU_Hz / 1000) - (CPU_Hz / 1000);
|
||||||
cpuDiff = getDifferenceSymbol(deltaCPU);
|
cpuDiff = getDifferenceSymbol(deltaCPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t cpuFreq = settings.realFrequencies && realCPU_Hz ? realCPU_Hz : CPU_Hz;
|
const uint32_t cpuFreq = settings.realFrequencies && realCPU_Hz ? realCPU_Hz : CPU_Hz;
|
||||||
|
|
||||||
if (settings.showFullCPU) {
|
if (settings.showFullCPU) {
|
||||||
snprintf(CPU_compressed_c, sizeof(CPU_compressed_c),
|
snprintf(CPU_compressed_c, sizeof(CPU_compressed_c),
|
||||||
"[%s,%s,%s,%s]%s%u.%u",
|
"[%s,%s,%s,%s]%s%u.%u",
|
||||||
CPU_Usage0, CPU_Usage1, CPU_Usage2, CPU_Usage3,
|
CPU_Usage0, CPU_Usage1, CPU_Usage2, CPU_Usage3,
|
||||||
cpuDiff, cpuFreq / 1000000, (cpuFreq / 100000) % 10);
|
cpuDiff, cpuFreq / 1000000, (cpuFreq / 100000) % 10);
|
||||||
} else {
|
} else {
|
||||||
// Find max CPU usage across all cores
|
// Find max CPU usage across all cores
|
||||||
const auto extractUsage = [](const char* usage_str) -> double {
|
const auto extractUsage = [](const char* usage_str) -> double {
|
||||||
return strtod(usage_str, nullptr);
|
return strtod(usage_str, nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
const double usage0 = extractUsage(CPU_Usage0);
|
const double usage0 = extractUsage(CPU_Usage0);
|
||||||
const double usage1 = extractUsage(CPU_Usage1);
|
const double usage1 = extractUsage(CPU_Usage1);
|
||||||
const double usage2 = extractUsage(CPU_Usage2);
|
const double usage2 = extractUsage(CPU_Usage2);
|
||||||
const double usage3 = extractUsage(CPU_Usage3);
|
const double usage3 = extractUsage(CPU_Usage3);
|
||||||
|
|
||||||
const double maxUsage = std::max({usage0, usage1, usage2, usage3});
|
const double maxUsage = std::max({usage0, usage1, usage2, usage3});
|
||||||
|
|
||||||
snprintf(CPU_compressed_c, sizeof(CPU_compressed_c),
|
snprintf(CPU_compressed_c, sizeof(CPU_compressed_c),
|
||||||
"%.0f%%%s%u.%u",
|
"%.0f%%%s%u.%u",
|
||||||
maxUsage, cpuDiff, cpuFreq / 1000000, (cpuFreq / 100000) % 10);
|
maxUsage, cpuDiff, cpuFreq / 1000000, (cpuFreq / 100000) % 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.realTemps && realCPU_Temp != 0) {
|
if (settings.realTemps && realCPU_Temp != 0 && CPU_temp_c[0] != '\0') {
|
||||||
char temp_buffer[48];
|
char temp_buffer[48];
|
||||||
snprintf(temp_buffer, sizeof(temp_buffer), " %s", CPU_temp_c);
|
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);
|
strncat(CPU_compressed_c, temp_buffer, sizeof(CPU_compressed_c) - strlen(CPU_compressed_c) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (settings.realVolts) {
|
//if (settings.realVolts) {
|
||||||
// snprintf(CPU_volt_c, sizeof(CPU_volt_c), "%u.%u mV",
|
// snprintf(CPU_volt_c, sizeof(CPU_volt_c), "%u.%u mV",
|
||||||
// realCPU_mV/1000, (isMariko ? (realCPU_mV/100)%10 : (realCPU_mV/10)%100));
|
// realCPU_mV/1000, (isMariko ? (realCPU_mV/100)%10 : (realCPU_mV/10)%100));
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@@ -898,28 +902,28 @@ public:
|
|||||||
const uint32_t mv = realCPU_mV / 1000; // µV → mV
|
const uint32_t mv = realCPU_mV / 1000; // µV → mV
|
||||||
snprintf(CPU_volt_c, sizeof(CPU_volt_c), "%u mV", mv);
|
snprintf(CPU_volt_c, sizeof(CPU_volt_c), "%u mV", mv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// GPU frequency and voltage
|
// GPU frequency and voltage
|
||||||
const char* gpuDiff = "@";
|
const char* gpuDiff = "@";
|
||||||
if (realGPU_Hz) {
|
if (realGPU_Hz) {
|
||||||
const int32_t deltaGPU = (int32_t)(realGPU_Hz / 1000) - (GPU_Hz / 1000);
|
const int32_t deltaGPU = (int32_t)(realGPU_Hz / 1000) - (GPU_Hz / 1000);
|
||||||
gpuDiff = getDifferenceSymbol(deltaGPU);
|
gpuDiff = getDifferenceSymbol(deltaGPU);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t gpuFreq = settings.realFrequencies && realGPU_Hz ? realGPU_Hz : GPU_Hz;
|
const uint32_t gpuFreq = settings.realFrequencies && realGPU_Hz ? realGPU_Hz : GPU_Hz;
|
||||||
snprintf(GPU_Load_c, sizeof(GPU_Load_c),
|
snprintf(GPU_Load_c, sizeof(GPU_Load_c),
|
||||||
"%u%%%s%u.%u",
|
"%u%%%s%u.%u",
|
||||||
GPU_Load_u / 10,
|
GPU_Load_u / 10,
|
||||||
gpuDiff, gpuFreq / 1000000, (gpuFreq / 100000) % 10);
|
gpuDiff, gpuFreq / 1000000, (gpuFreq / 100000) % 10);
|
||||||
|
|
||||||
if (settings.realTemps && realGPU_Temp != 0) {
|
if (settings.realTemps && realGPU_Temp != 0 && GPU_temp_c[0] != '\0') {
|
||||||
char temp_buffer[48];
|
char temp_buffer[48];
|
||||||
snprintf(temp_buffer, sizeof(temp_buffer), " %s", GPU_temp_c);
|
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);
|
strncat(GPU_Load_c, temp_buffer, sizeof(GPU_Load_c) - strlen(GPU_Load_c) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (settings.realVolts) {
|
//if (settings.realVolts) {
|
||||||
// snprintf(GPU_volt_c, sizeof(GPU_volt_c), "%u.%u mV",
|
// snprintf(GPU_volt_c, sizeof(GPU_volt_c), "%u.%u mV",
|
||||||
// realGPU_mV/1000, (isMariko ? (realGPU_mV/100)%10 : (realGPU_mV/10)%100));
|
// realGPU_mV/1000, (isMariko ? (realGPU_mV/100)%10 : (realGPU_mV/10)%100));
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@@ -930,20 +934,20 @@ public:
|
|||||||
if (GPU_Hz_int == 0 && lastGPU_Hz_int != 0) {
|
if (GPU_Hz_int == 0 && lastGPU_Hz_int != 0) {
|
||||||
isRendering = false;
|
isRendering = false;
|
||||||
leventSignal(&renderingStopEvent);
|
leventSignal(&renderingStopEvent);
|
||||||
|
|
||||||
triggerExitNow = true;
|
triggerExitNow = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastGPU_Hz_int = GPU_Hz_int;
|
lastGPU_Hz_int = GPU_Hz_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ── GPU voltage ───────────────────────────── */
|
/* ── GPU voltage ───────────────────────────── */
|
||||||
if (settings.realVolts) {
|
if (settings.realVolts) {
|
||||||
const uint32_t mv = realGPU_mV / 1000;
|
const uint32_t mv = realGPU_mV / 1000;
|
||||||
snprintf(GPU_volt_c, sizeof(GPU_volt_c), "%u mV", mv);
|
snprintf(GPU_volt_c, sizeof(GPU_volt_c), "%u mV", mv);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RAM usage and frequency
|
// RAM usage and frequency
|
||||||
char MICRO_RAM_all_c[16];
|
char MICRO_RAM_all_c[16];
|
||||||
if (!settings.showpartLoad) {
|
if (!settings.showpartLoad) {
|
||||||
@@ -971,23 +975,23 @@ public:
|
|||||||
const int32_t deltaRAM = (int32_t)(realRAM_Hz / 1000) - (RAM_Hz / 1000);
|
const int32_t deltaRAM = (int32_t)(realRAM_Hz / 1000) - (RAM_Hz / 1000);
|
||||||
ramDiff = getDifferenceSymbol(deltaRAM);
|
ramDiff = getDifferenceSymbol(deltaRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t ramFreq = settings.realFrequencies && realRAM_Hz ? realRAM_Hz : RAM_Hz;
|
const uint32_t ramFreq = settings.realFrequencies && realRAM_Hz ? realRAM_Hz : RAM_Hz;
|
||||||
snprintf(RAM_var_compressed_c, sizeof(RAM_var_compressed_c),
|
snprintf(RAM_var_compressed_c, sizeof(RAM_var_compressed_c),
|
||||||
"%s%s%u.%u", MICRO_RAM_all_c, ramDiff,
|
"%s%s%u.%u", MICRO_RAM_all_c, ramDiff,
|
||||||
ramFreq / 1000000, (ramFreq / 100000) % 10);
|
ramFreq / 1000000, (ramFreq / 100000) % 10);
|
||||||
|
|
||||||
if (settings.realTemps && realRAM_Temp != 0) {
|
if (settings.realTemps && realRAM_Temp != 0 && RAM_temp_c[0] != '\0') {
|
||||||
char temp_buffer[48];
|
char temp_buffer[48];
|
||||||
snprintf(temp_buffer, sizeof(temp_buffer), " %s", RAM_temp_c);
|
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);
|
strncat(RAM_var_compressed_c, temp_buffer, sizeof(RAM_var_compressed_c) - strlen(RAM_var_compressed_c) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (settings.realVolts) {
|
//if (settings.realVolts) {
|
||||||
// uint32_t vdd2 = realRAM_mV / 10000;
|
// uint32_t vdd2 = realRAM_mV / 10000;
|
||||||
// uint32_t vddq = realRAM_mV % 10000;
|
// uint32_t vddq = realRAM_mV % 10000;
|
||||||
// if (isMariko) {
|
// if (isMariko) {
|
||||||
// snprintf(RAM_volt_c, sizeof(RAM_volt_c), "%u.%u%u.%u mV",
|
// snprintf(RAM_volt_c, sizeof(RAM_volt_c), "%u.%u%u.%u mV",
|
||||||
// vdd2/10, vdd2%10, vddq/10, vddq%10);
|
// vdd2/10, vdd2%10, vddq/10, vddq%10);
|
||||||
// } else {
|
// } else {
|
||||||
// snprintf(RAM_volt_c, sizeof(RAM_volt_c), "%u.%u mV", vdd2/10, vdd2%10);
|
// snprintf(RAM_volt_c, sizeof(RAM_volt_c), "%u.%u mV", vdd2/10, vdd2%10);
|
||||||
@@ -997,15 +1001,15 @@ public:
|
|||||||
/* ── RAM voltage ───────────────────────────── */
|
/* ── RAM voltage ───────────────────────────── */
|
||||||
if (settings.realVolts && (settings.showVDD2 || settings.showVDDQ)) {
|
if (settings.realVolts && (settings.showVDD2 || settings.showVDDQ)) {
|
||||||
/* realRAM_mV packs VDD2 | VDDQ in 10-µV units *
|
/* realRAM_mV packs VDD2 | VDDQ in 10-µV units *
|
||||||
* → split, convert to mV
|
* → split, convert to mV
|
||||||
*/
|
*/
|
||||||
const float mv_vdd2 = (realRAM_mV % 100000) / 10.0f; // VDD2
|
const float mv_vdd2 = (realRAM_mV % 100000) / 10.0f; // VDD2
|
||||||
const uint32_t mv_vddq = (realRAM_mV / 10000) / 10; // VDDQ
|
const uint32_t mv_vddq = (realRAM_mV / 10000) / 10; // VDDQ
|
||||||
|
|
||||||
// Build voltage string based on settings
|
// Build voltage string based on settings
|
||||||
RAM_volt_c[0] = '\0'; // Start with empty string
|
RAM_volt_c[0] = '\0'; // Start with empty string
|
||||||
char temp_buffer[16];
|
char temp_buffer[16];
|
||||||
|
|
||||||
if (settings.showVDD2) {
|
if (settings.showVDD2) {
|
||||||
if (settings.decimalVDD2) {
|
if (settings.decimalVDD2) {
|
||||||
snprintf(temp_buffer, sizeof(temp_buffer), "%.1f mV", mv_vdd2);
|
snprintf(temp_buffer, sizeof(temp_buffer), "%.1f mV", mv_vdd2);
|
||||||
@@ -1014,7 +1018,7 @@ public:
|
|||||||
}
|
}
|
||||||
strcat(RAM_volt_c, temp_buffer);
|
strcat(RAM_volt_c, temp_buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.showVDDQ && isMariko) {
|
if (settings.showVDDQ && isMariko) {
|
||||||
if (RAM_volt_c[0] != '\0') {
|
if (RAM_volt_c[0] != '\0') {
|
||||||
strcat(RAM_volt_c, "");
|
strcat(RAM_volt_c, "");
|
||||||
@@ -1025,7 +1029,7 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
RAM_volt_c[0] = '\0'; // Empty if voltages disabled
|
RAM_volt_c[0] = '\0'; // Empty if voltages disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Battery / power draw ───────────────────────────── */
|
/* ── Battery / power draw ───────────────────────────── */
|
||||||
char remainingBatteryLife[8];
|
char remainingBatteryLife[8];
|
||||||
|
|
||||||
@@ -1075,7 +1079,7 @@ public:
|
|||||||
"%d°C %d%%",
|
"%d°C %d%%",
|
||||||
(int)SOC_temperatureF, // SoC °C, no decimals
|
(int)SOC_temperatureF, // SoC °C, no decimals
|
||||||
duty); // fan %
|
duty); // fan %
|
||||||
|
|
||||||
/* Integer SOC, PCB and skin temperatures + duty *
|
/* Integer SOC, PCB and skin temperatures + duty *
|
||||||
* skin_temperaturemiliC is in milli-degrees C → divide by 1000 */
|
* skin_temperaturemiliC is in milli-degrees C → divide by 1000 */
|
||||||
snprintf(skin_temperature_c, sizeof skin_temperature_c,
|
snprintf(skin_temperature_c, sizeof skin_temperature_c,
|
||||||
@@ -1084,9 +1088,9 @@ public:
|
|||||||
(int)PCB_temperatureF, // PCB
|
(int)PCB_temperatureF, // PCB
|
||||||
(uint16_t)(skin_temperaturemiliC / 1000), // skin
|
(uint16_t)(skin_temperaturemiliC / 1000), // skin
|
||||||
duty);
|
duty);
|
||||||
|
|
||||||
//if (settings.realVolts) {
|
//if (settings.realVolts) {
|
||||||
// snprintf(SOC_volt_c, sizeof(SOC_volt_c), "%u.%u mV",
|
// snprintf(SOC_volt_c, sizeof(SOC_volt_c), "%u.%u mV",
|
||||||
// realSOC_mV/1000, (realSOC_mV/100)%10);
|
// realSOC_mV/1000, (realSOC_mV/100)%10);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
@@ -1097,18 +1101,30 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
SOC_volt_c[0] = '\0'; // Clear the buffer when disabled
|
SOC_volt_c[0] = '\0'; // Clear the buffer when disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.realTemps) {
|
if (settings.realTemps) {
|
||||||
if (realCPU_Temp != 0) {
|
if (realCPU_Temp != 0) {
|
||||||
snprintf(CPU_temp_c, sizeof(CPU_temp_c), " %.1f°C", realCPU_Temp / 1000.0f);
|
if (settings.realTempsDec) {
|
||||||
}
|
snprintf(CPU_temp_c, sizeof(CPU_temp_c), "%.1f°C", realCPU_Temp / 1000.0f);
|
||||||
if (realGPU_Temp != 0) {
|
} else {
|
||||||
snprintf(GPU_temp_c, sizeof(GPU_temp_c), " %.1f°C", realGPU_Temp / 1000.0f);
|
snprintf(CPU_temp_c, sizeof(CPU_temp_c), "%u°C", static_cast<u32>(realCPU_Temp / 1000.0));
|
||||||
}
|
}
|
||||||
if (realRAM_Temp != 0) {
|
}
|
||||||
snprintf(RAM_temp_c, sizeof(RAM_temp_c), " %.1f°C", realRAM_Temp / 1000.0f);
|
if (realGPU_Temp != 0) {
|
||||||
}
|
if (settings.realTempsDec) {
|
||||||
}
|
snprintf(GPU_temp_c, sizeof(GPU_temp_c), "%.1f°C", realGPU_Temp / 1000.0f);
|
||||||
|
} else {
|
||||||
|
snprintf(GPU_temp_c, sizeof(GPU_temp_c), "%u°C", static_cast<u32>(realGPU_Temp / 1000.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (realRAM_Temp != 0) {
|
||||||
|
if (settings.realTempsDec) {
|
||||||
|
snprintf(RAM_temp_c, sizeof(RAM_temp_c), "%.1f°C", realRAM_Temp / 1000.0f);
|
||||||
|
} else {
|
||||||
|
snprintf(RAM_temp_c, sizeof(RAM_temp_c), "%u°C", static_cast<u32>(realRAM_Temp / 1000.0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Resolution processing
|
// Resolution processing
|
||||||
//char RES_var_compressed_c[32] = "";
|
//char RES_var_compressed_c[32] = "";
|
||||||
@@ -1176,20 +1192,20 @@ public:
|
|||||||
m_resolutionOutput[out_iter].width = m_resolutionViewportCalls[x].width;
|
m_resolutionOutput[out_iter].width = m_resolutionViewportCalls[x].width;
|
||||||
m_resolutionOutput[out_iter].height = m_resolutionViewportCalls[x].height;
|
m_resolutionOutput[out_iter].height = m_resolutionViewportCalls[x].height;
|
||||||
m_resolutionOutput[out_iter].calls = m_resolutionViewportCalls[x].calls;
|
m_resolutionOutput[out_iter].calls = m_resolutionViewportCalls[x].calls;
|
||||||
out_iter++;
|
out_iter++;
|
||||||
}
|
}
|
||||||
found = false;
|
found = false;
|
||||||
if (out_iter == 8) break;
|
if (out_iter == 8) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qsort(m_resolutionOutput, 8, sizeof(resolutionCalls), compare);
|
qsort(m_resolutionOutput, 8, sizeof(resolutionCalls), compare);
|
||||||
|
|
||||||
// Anti-flicker swap logic
|
// Anti-flicker swap logic
|
||||||
static std::pair<uint16_t, uint16_t> old_res[2];
|
static std::pair<uint16_t, uint16_t> old_res[2];
|
||||||
|
|
||||||
// Only swap if BOTH resolutions exist (prevent swapping with empty slot)
|
// Only swap if BOTH resolutions exist (prevent swapping with empty slot)
|
||||||
if (m_resolutionOutput[0].width && m_resolutionOutput[1].width) {
|
if (m_resolutionOutput[0].width && m_resolutionOutput[1].width) {
|
||||||
if ((m_resolutionOutput[0].width == old_res[1].first && m_resolutionOutput[0].height == old_res[1].second) ||
|
if ((m_resolutionOutput[0].width == old_res[1].first && m_resolutionOutput[0].height == old_res[1].second) ||
|
||||||
(m_resolutionOutput[1].width == old_res[0].first && m_resolutionOutput[1].height == old_res[0].second)) {
|
(m_resolutionOutput[1].width == old_res[0].first && m_resolutionOutput[1].height == old_res[0].second)) {
|
||||||
const uint16_t swap_width = m_resolutionOutput[0].width;
|
const uint16_t swap_width = m_resolutionOutput[0].width;
|
||||||
const uint16_t swap_height = m_resolutionOutput[0].height;
|
const uint16_t swap_height = m_resolutionOutput[0].height;
|
||||||
@@ -1199,31 +1215,31 @@ public:
|
|||||||
m_resolutionOutput[1].height = swap_height;
|
m_resolutionOutput[1].height = swap_height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format resolution string
|
// Format resolution string
|
||||||
if (m_resolutionOutput[0].width) {
|
if (m_resolutionOutput[0].width) {
|
||||||
if (settings.showFullResolution) {
|
if (settings.showFullResolution) {
|
||||||
if (!m_resolutionOutput[1].width) {
|
if (!m_resolutionOutput[1].width) {
|
||||||
snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dx%d",
|
snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dx%d",
|
||||||
m_resolutionOutput[0].width, m_resolutionOutput[0].height);
|
m_resolutionOutput[0].width, m_resolutionOutput[0].height);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dx%d%dx%d",
|
snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dx%d%dx%d",
|
||||||
m_resolutionOutput[0].width, m_resolutionOutput[0].height,
|
m_resolutionOutput[0].width, m_resolutionOutput[0].height,
|
||||||
m_resolutionOutput[1].width, m_resolutionOutput[1].height);
|
m_resolutionOutput[1].width, m_resolutionOutput[1].height);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!m_resolutionOutput[1].width) {
|
if (!m_resolutionOutput[1].width) {
|
||||||
snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dp",
|
snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dp",
|
||||||
m_resolutionOutput[0].height);
|
m_resolutionOutput[0].height);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dp%dp",
|
snprintf(RES_var_compressed_c, sizeof(RES_var_compressed_c), "%dp%dp",
|
||||||
m_resolutionOutput[0].height, m_resolutionOutput[1].height);
|
m_resolutionOutput[0].height, m_resolutionOutput[1].height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always store current resolutions for next frame comparison
|
// Always store current resolutions for next frame comparison
|
||||||
old_res[0] = std::make_pair(m_resolutionOutput[0].width, m_resolutionOutput[0].height);
|
old_res[0] = std::make_pair(m_resolutionOutput[0].width, m_resolutionOutput[0].height);
|
||||||
old_res[1] = std::make_pair(m_resolutionOutput[1].width, m_resolutionOutput[1].height);
|
old_res[1] = std::make_pair(m_resolutionOutput[1].width, m_resolutionOutput[1].height);
|
||||||
@@ -1253,7 +1269,7 @@ public:
|
|||||||
mutexUnlock(&mutex_Misc);
|
mutexUnlock(&mutex_Misc);
|
||||||
|
|
||||||
//static bool skipOnce = true;
|
//static bool skipOnce = true;
|
||||||
|
|
||||||
if (!skipOnce) {
|
if (!skipOnce) {
|
||||||
//static bool runOnce = true;
|
//static bool runOnce = true;
|
||||||
if (runOnce) {
|
if (runOnce) {
|
||||||
@@ -1265,7 +1281,7 @@ public:
|
|||||||
skipOnce = false;
|
skipOnce = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override {
|
virtual bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight) override {
|
||||||
if (isKeyComboPressed(keysHeld, keysDown)) {
|
if (isKeyComboPressed(keysHeld, keysDown)) {
|
||||||
isRendering = false;
|
isRendering = false;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -643,9 +643,9 @@ protected:
|
|||||||
"Max Handheld Display",
|
"Max Handheld Display",
|
||||||
ValueRange(60, IsAula() ? 65 : 75, 1, " Hz", 1),
|
ValueRange(60, IsAula() ? 65 : 75, 1, " Hz", 1),
|
||||||
"Display Clock",
|
"Display Clock",
|
||||||
&displayThresholds,
|
&displayThresholds,
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1266,7 +1266,6 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::vector<NamedValue> mGpuVoltsVmin = {
|
std::vector<NamedValue> mGpuVoltsVmin = {
|
||||||
NamedValue("Auto", 0),
|
|
||||||
NamedValue("480mV", 480), NamedValue("485mV", 485), NamedValue("490mV", 490),
|
NamedValue("480mV", 480), NamedValue("485mV", 485), NamedValue("490mV", 490),
|
||||||
NamedValue("495mV", 495), NamedValue("500mV", 500), NamedValue("505mV", 505),
|
NamedValue("495mV", 495), NamedValue("500mV", 500), NamedValue("505mV", 505),
|
||||||
NamedValue("510mV", 510), NamedValue("515mV", 515), NamedValue("520mV", 520),
|
NamedValue("510mV", 510), NamedValue("515mV", 515), NamedValue("520mV", 520),
|
||||||
|
|||||||
Reference in New Issue
Block a user