rewrite everything
This commit is contained in:
23
Source/sys-clk/overlay/src/ipc.h
Normal file
23
Source/sys-clk/overlay/src/ipc.h
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <sysclk.h>
|
||||
#include <sysclk/client/ipc.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
81
Source/sys-clk/overlay/src/main.cpp
Normal file
81
Source/sys-clk/overlay/src/main.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define TESLA_INIT_IMPL
|
||||
#include <tesla.hpp>
|
||||
|
||||
#include "ui/gui/fatal_gui.h"
|
||||
#include "ui/gui/main_gui.h"
|
||||
#include "rgltr_services.h" // for extern Service g_rgltrSrv, etc.
|
||||
|
||||
class AppOverlay : public tsl::Overlay
|
||||
{
|
||||
public:
|
||||
AppOverlay() {}
|
||||
~AppOverlay() {}
|
||||
|
||||
//virtual void initServices() override {
|
||||
// rgltrInitialize();
|
||||
//}
|
||||
|
||||
virtual void exitServices() override {
|
||||
rgltrExit();
|
||||
sysclkIpcExit();
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<tsl::Gui> loadInitialGui() override
|
||||
{
|
||||
uint32_t apiVersion;
|
||||
smInitialize();
|
||||
|
||||
tsl::hlp::ScopeGuard smGuard([] { smExit(); });
|
||||
|
||||
if(!sysclkIpcRunning())
|
||||
{
|
||||
return initially<FatalGui>(
|
||||
"sys-clk is not running.\n\n"
|
||||
"\n"
|
||||
"Please make sure it is correctly\n\n"
|
||||
"installed and enabled.",
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
if(R_FAILED(sysclkIpcInitialize()) || R_FAILED(sysclkIpcGetAPIVersion(&apiVersion)))
|
||||
{
|
||||
return initially<FatalGui>(
|
||||
"Could not connect to sys-clk.\n\n"
|
||||
"\n"
|
||||
"Please make sure it is correctly\n\n"
|
||||
"installed and enabled.",
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
if(SYSCLK_IPC_API_VERSION != apiVersion)
|
||||
{
|
||||
return initially<FatalGui>(
|
||||
"Overlay not compatible with\n\n"
|
||||
"the running sys-clk version.\n\n"
|
||||
"\n"
|
||||
"Please make sure everything is\n\n"
|
||||
"installed and up to date.",
|
||||
""
|
||||
);
|
||||
}
|
||||
|
||||
return initially<MainGui>();
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return tsl::loop<AppOverlay>(argc, argv);
|
||||
}
|
||||
41
Source/sys-clk/overlay/src/pcv_types.h
Normal file
41
Source/sys-clk/overlay/src/pcv_types.h
Normal file
@@ -0,0 +1,41 @@
|
||||
typedef enum {
|
||||
PcvPowerDomain_Max77620_Sd0 = 0,
|
||||
PcvPowerDomain_Max77620_Sd1 = 1,
|
||||
PcvPowerDomain_Max77620_Sd2 = 2,
|
||||
PcvPowerDomain_Max77620_Sd3 = 3,
|
||||
PcvPowerDomain_Max77620_Ldo0 = 4,
|
||||
PcvPowerDomain_Max77620_Ldo1 = 5,
|
||||
PcvPowerDomain_Max77620_Ldo2 = 6,
|
||||
PcvPowerDomain_Max77620_Ldo3 = 7,
|
||||
PcvPowerDomain_Max77620_Ldo4 = 8,
|
||||
PcvPowerDomain_Max77620_Ldo5 = 9,
|
||||
PcvPowerDomain_Max77620_Ldo6 = 10,
|
||||
PcvPowerDomain_Max77620_Ldo7 = 11,
|
||||
PcvPowerDomain_Max77620_Ldo8 = 12,
|
||||
PcvPowerDomain_Max77621_Cpu = 13,
|
||||
PcvPowerDomain_Max77621_Gpu = 14,
|
||||
PcvPowerDomain_Max77812_Cpu = 15,
|
||||
PcvPowerDomain_Max77812_Gpu = 16,
|
||||
PcvPowerDomain_Max77812_Dram = 17,
|
||||
} PowerDomain;
|
||||
|
||||
typedef enum {
|
||||
PcvPowerDomainId_Max77620_Sd0 = 0x3A000080,
|
||||
PcvPowerDomainId_Max77620_Sd1 = 0x3A000081,
|
||||
PcvPowerDomainId_Max77620_Sd2 = 0x3A000082,
|
||||
PcvPowerDomainId_Max77620_Sd3 = 0x3A000083,
|
||||
PcvPowerDomainId_Max77620_Ldo0 = 0x3A0000A0,
|
||||
PcvPowerDomainId_Max77620_Ldo1 = 0x3A0000A1,
|
||||
PcvPowerDomainId_Max77620_Ldo2 = 0x3A0000A2,
|
||||
PcvPowerDomainId_Max77620_Ldo3 = 0x3A0000A3,
|
||||
PcvPowerDomainId_Max77620_Ldo4 = 0x3A0000A4,
|
||||
PcvPowerDomainId_Max77620_Ldo5 = 0x3A0000A5,
|
||||
PcvPowerDomainId_Max77620_Ldo6 = 0x3A0000A6,
|
||||
PcvPowerDomainId_Max77620_Ldo7 = 0x3A0000A7,
|
||||
PcvPowerDomainId_Max77620_Ldo8 = 0x3A0000A8,
|
||||
PcvPowerDomainId_Max77621_Cpu = 0x3A000003,
|
||||
PcvPowerDomainId_Max77621_Gpu = 0x3A000004,
|
||||
PcvPowerDomainId_Max77812_Cpu = 0x3A000003,
|
||||
PcvPowerDomainId_Max77812_Gpu = 0x3A000004,
|
||||
PcvPowerDomainId_Max77812_Dram = 0x3A000005,
|
||||
} PowerDomainId;
|
||||
19
Source/sys-clk/overlay/src/rgltr.h
Normal file
19
Source/sys-clk/overlay/src/rgltr.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include "pcv_types.h"
|
||||
|
||||
typedef struct {
|
||||
Service s;
|
||||
} RgltrSession;
|
||||
|
||||
Result rgltrInitialize(void);
|
||||
|
||||
void rgltrExit(void);
|
||||
|
||||
Service* rgltrGetServiceSession(void);
|
||||
|
||||
Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id);
|
||||
void rgltrCloseSession(RgltrSession* session);
|
||||
Result rgltrGetVoltage(RgltrSession* session, u32 *out_volt);
|
||||
Result rgltrGetPowerModuleNumLimit(u32 *out);
|
||||
Result rgltrGetVoltageEnabled(RgltrSession* session, u32 *out);
|
||||
43
Source/sys-clk/overlay/src/rgltr_services.cpp
Normal file
43
Source/sys-clk/overlay/src/rgltr_services.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
// rgltr_services.cpp (no changes needed here—just compile it once)
|
||||
#include <switch.h>
|
||||
#include "rgltr.h"
|
||||
#include "rgltr_services.h" // for extern Service g_rgltrSrv, etc.
|
||||
|
||||
// Global service handle
|
||||
Service g_rgltrSrv;
|
||||
|
||||
Result rgltrInitialize(void) {
|
||||
if (hosversionBefore(8, 0, 0)) {
|
||||
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||
}
|
||||
return smGetService(&g_rgltrSrv, "rgltr");
|
||||
}
|
||||
|
||||
void rgltrExit(void) {
|
||||
serviceClose(&g_rgltrSrv);
|
||||
}
|
||||
|
||||
Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id) {
|
||||
const u32 in = (u32)module_id;
|
||||
return serviceDispatchIn(
|
||||
&g_rgltrSrv,
|
||||
0,
|
||||
in,
|
||||
.out_num_objects = 1,
|
||||
.out_objects = &session_out->s
|
||||
);
|
||||
}
|
||||
|
||||
Result rgltrGetVoltage(RgltrSession* session, u32* out_volt) {
|
||||
// Service returns µV (microvolts) in a local u32:
|
||||
u32 temp = 0;
|
||||
Result rc = serviceDispatchOut(&session->s, 4, temp);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
*out_volt = temp;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void rgltrCloseSession(RgltrSession* session) {
|
||||
serviceClose(&session->s);
|
||||
}
|
||||
29
Source/sys-clk/overlay/src/rgltr_services.h
Normal file
29
Source/sys-clk/overlay/src/rgltr_services.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// rgltr_services.h
|
||||
// ========
|
||||
// Minimal header declarations for rgltr‐related functionality.
|
||||
// Any file that wants to call rgltrOpenSession(), rgltrGetVoltage(), etc. should
|
||||
// simply do `#include "infonx.h"` (NOT infonx.cpp).
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <switch.h> // for Service, Result, hosversionBefore(), smGetService(), serviceClose(), etc.
|
||||
#include "rgltr.h" // for RgltrSession, PowerDomainId, etc.
|
||||
|
||||
// Global service handle for "rgltr". Defined in infonx.cpp.
|
||||
extern Service g_rgltrSrv;
|
||||
|
||||
// Open/close the "rgltr" service. You must call rgltrInitialize() (once) before using
|
||||
// rgltrOpenSession() & friends. Call rgltrExit() when your app is shutting down.
|
||||
Result rgltrInitialize(void);
|
||||
void rgltrExit(void);
|
||||
|
||||
// Open a regulator session for the given PowerDomainId (e.g. CPU, GPU, DRAM).
|
||||
// On success, (*session_out).s will contain a valid Service handle.
|
||||
Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id);
|
||||
|
||||
// Query the current voltage (in microvolts, µV) from a previously opened session.
|
||||
// Writes the result into *out_volt.
|
||||
Result rgltrGetVoltage(RgltrSession* session, u32* out_volt);
|
||||
|
||||
// Close a previously opened regulator session.
|
||||
void rgltrCloseSession(RgltrSession* session);
|
||||
31
Source/sys-clk/overlay/src/ui/elements/base_frame.h
Normal file
31
Source/sys-clk/overlay/src/ui/elements/base_frame.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 <tesla.hpp>
|
||||
#include "../gui/base_gui.h"
|
||||
|
||||
class BaseFrame : public tsl::elm::HeaderOverlayFrame
|
||||
{
|
||||
public:
|
||||
BaseFrame(BaseGui* gui) : tsl::elm::HeaderOverlayFrame(234) {
|
||||
this->gui = gui;
|
||||
}
|
||||
|
||||
void draw(tsl::gfx::Renderer* renderer) override
|
||||
{
|
||||
tsl::elm::HeaderOverlayFrame::draw(renderer);
|
||||
this->gui->preDraw(renderer);
|
||||
}
|
||||
|
||||
protected:
|
||||
BaseGui* gui;
|
||||
};
|
||||
28
Source/sys-clk/overlay/src/ui/format.h
Normal file
28
Source/sys-clk/overlay/src/ui/format.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 <cstdio>
|
||||
|
||||
#define FREQ_DEFAULT_TEXT "Do not override"
|
||||
|
||||
static inline std::string formatListFreqMHz(std::uint32_t mhz)
|
||||
{
|
||||
if(mhz == 0)
|
||||
{
|
||||
return FREQ_DEFAULT_TEXT;
|
||||
}
|
||||
|
||||
char buf[10];
|
||||
return std::string(buf, snprintf(buf, sizeof(buf), "%u MHz", mhz));
|
||||
}
|
||||
|
||||
static inline std::string formatListFreqHz(std::uint32_t hz) { return formatListFreqMHz(hz / 1000000); }
|
||||
127
Source/sys-clk/overlay/src/ui/gui/app_profile_gui.cpp
Normal file
127
Source/sys-clk/overlay/src/ui/gui/app_profile_gui.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 "app_profile_gui.h"
|
||||
|
||||
#include "../format.h"
|
||||
#include "fatal_gui.h"
|
||||
|
||||
AppProfileGui::AppProfileGui(std::uint64_t applicationId, SysClkTitleProfileList* profileList)
|
||||
{
|
||||
this->applicationId = applicationId;
|
||||
this->profileList = profileList;
|
||||
}
|
||||
|
||||
AppProfileGui::~AppProfileGui()
|
||||
{
|
||||
delete this->profileList;
|
||||
}
|
||||
|
||||
void AppProfileGui::openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module)
|
||||
{
|
||||
std::uint32_t hzList[SYSCLK_FREQ_LIST_MAX];
|
||||
std::uint32_t hzCount;
|
||||
Result rc = sysclkIpcGetFreqList(module, &hzList[0], SYSCLK_FREQ_LIST_MAX, &hzCount);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcGetFreqList", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
tsl::changeTo<FreqChoiceGui>(this->profileList->mhzMap[profile][module] * 1000000, hzList, hzCount, module, [this, listItem, profile, module](std::uint32_t hz) {
|
||||
this->profileList->mhzMap[profile][module] = hz / 1000000;
|
||||
listItem->setValue(formatListFreqMHz(this->profileList->mhzMap[profile][module]));
|
||||
Result rc = sysclkIpcSetProfiles(this->applicationId, this->profileList);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcSetProfiles", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void AppProfileGui::addModuleListItem(SysClkProfile profile, SysClkModule module)
|
||||
{
|
||||
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(sysclkFormatModule(module, true));
|
||||
listItem->setValue(formatListFreqMHz(this->profileList->mhzMap[profile][module]));
|
||||
listItem->setClickListener([this, listItem, profile, module](u64 keys) {
|
||||
if((keys & HidNpadButton_A) == HidNpadButton_A)
|
||||
{
|
||||
this->openFreqChoiceGui(listItem, profile, module);
|
||||
return true;
|
||||
}
|
||||
else if((keys & HidNpadButton_Y) == HidNpadButton_Y)
|
||||
{
|
||||
// Reset to "Do not override" (0 MHz)
|
||||
this->profileList->mhzMap[profile][module] = 0;
|
||||
listItem->setValue(formatListFreqMHz(0));
|
||||
|
||||
// Save the updated profile
|
||||
Result rc = sysclkIpcSetProfiles(this->applicationId, this->profileList);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcSetProfiles", rc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this->listElement->addItem(listItem);
|
||||
}
|
||||
|
||||
void AppProfileGui::addProfileUI(SysClkProfile profile)
|
||||
{
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(sysclkFormatProfile(profile, true) + std::string(" ") + ult::DIVIDER_SYMBOL + " Reset"));
|
||||
this->addModuleListItem(profile, SysClkModule_CPU);
|
||||
this->addModuleListItem(profile, SysClkModule_GPU);
|
||||
this->addModuleListItem(profile, SysClkModule_MEM);
|
||||
}
|
||||
|
||||
void AppProfileGui::listUI()
|
||||
{
|
||||
this->addProfileUI(SysClkProfile_Docked);
|
||||
this->addProfileUI(SysClkProfile_Handheld);
|
||||
this->addProfileUI(SysClkProfile_HandheldCharging);
|
||||
this->addProfileUI(SysClkProfile_HandheldChargingOfficial);
|
||||
this->addProfileUI(SysClkProfile_HandheldChargingUSB);
|
||||
}
|
||||
|
||||
void AppProfileGui::changeTo(std::uint64_t applicationId)
|
||||
{
|
||||
SysClkTitleProfileList* profileList = new SysClkTitleProfileList;
|
||||
Result rc = sysclkIpcGetProfiles(applicationId, profileList);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
delete profileList;
|
||||
FatalGui::openWithResultCode("sysclkIpcGetProfiles", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
tsl::changeTo<AppProfileGui>(applicationId, profileList);
|
||||
}
|
||||
|
||||
void AppProfileGui::update()
|
||||
{
|
||||
BaseMenuGui::update();
|
||||
|
||||
if((this->context && this->applicationId != this->context->applicationId) && this->applicationId != SYSCLK_GLOBAL_PROFILE_TID)
|
||||
{
|
||||
tsl::changeTo<FatalGui>(
|
||||
"Application changed\n\n"
|
||||
"\n"
|
||||
"The running application changed\n\n"
|
||||
"while editing was going on.",
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
||||
34
Source/sys-clk/overlay/src/ui/gui/app_profile_gui.h
Normal file
34
Source/sys-clk/overlay/src/ui/gui/app_profile_gui.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 "../../ipc.h"
|
||||
#include "base_menu_gui.h"
|
||||
#include "freq_choice_gui.h"
|
||||
#define SYSCLK_GLOBAL_PROFILE_TID 0xA111111111111111
|
||||
|
||||
class AppProfileGui : public BaseMenuGui
|
||||
{
|
||||
protected:
|
||||
std::uint64_t applicationId;
|
||||
SysClkTitleProfileList* profileList;
|
||||
|
||||
void openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module);
|
||||
void addModuleListItem(SysClkProfile profile, SysClkModule module);
|
||||
void addProfileUI(SysClkProfile profile);
|
||||
|
||||
public:
|
||||
AppProfileGui(std::uint64_t applicationId, SysClkTitleProfileList* profileList);
|
||||
~AppProfileGui();
|
||||
void listUI() override;
|
||||
static void changeTo(std::uint64_t applicationId);
|
||||
void update() override;
|
||||
};
|
||||
56
Source/sys-clk/overlay/src/ui/gui/base_gui.cpp
Normal file
56
Source/sys-clk/overlay/src/ui/gui/base_gui.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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_gui.h"
|
||||
|
||||
#include "../elements/base_frame.h"
|
||||
#include "logo_rgba_bin.h"
|
||||
|
||||
|
||||
#define LOGO_WIDTH 110
|
||||
#define LOGO_HEIGHT 39
|
||||
#define LOGO_X 18
|
||||
#define LOGO_Y 21
|
||||
|
||||
#define LOGO_LABEL_X (LOGO_X + LOGO_WIDTH + 6)
|
||||
#define LOGO_LABEL_Y 50
|
||||
#define LOGO_LABEL_FONT_SIZE 28
|
||||
|
||||
#define VERSION_X (LOGO_LABEL_X + 110+8)
|
||||
#define VERSION_Y LOGO_LABEL_Y-4
|
||||
#define VERSION_FONT_SIZE 15
|
||||
|
||||
std::string getVersionString() {
|
||||
char buf[0x100] = ""; // 256 bytes — safe for any expected version string
|
||||
Result rc = sysclkIpcGetVersionString(buf, sizeof(buf));
|
||||
if (R_FAILED(rc) || buf[0] == '\0') {
|
||||
return "unknown";
|
||||
}
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
void BaseGui::preDraw(tsl::gfx::Renderer* renderer)
|
||||
{
|
||||
renderer->drawBitmap(LOGO_X, LOGO_Y, LOGO_WIDTH, LOGO_HEIGHT, logo_rgba_bin);
|
||||
renderer->drawString("overlay", false, LOGO_LABEL_X, LOGO_LABEL_Y, LOGO_LABEL_FONT_SIZE, renderer->a(TEXT_COLOR));
|
||||
renderer->drawString(TARGET_VERSION, false, VERSION_X, VERSION_Y, VERSION_FONT_SIZE, tsl::bannerVersionTextColor);
|
||||
}
|
||||
|
||||
tsl::elm::Element* BaseGui::createUI()
|
||||
{
|
||||
BaseFrame* rootFrame = new BaseFrame(this);
|
||||
rootFrame->setContent(this->baseUI());
|
||||
return rootFrame;
|
||||
}
|
||||
|
||||
void BaseGui::update()
|
||||
{
|
||||
this->refresh();
|
||||
}
|
||||
36
Source/sys-clk/overlay/src/ui/gui/base_gui.h
Normal file
36
Source/sys-clk/overlay/src/ui/gui/base_gui.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 <tesla.hpp>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../style.h"
|
||||
#include "../../ipc.h"
|
||||
|
||||
class BaseGui : public tsl::Gui
|
||||
{
|
||||
public:
|
||||
BaseGui() {}
|
||||
~BaseGui() {}
|
||||
virtual void preDraw(tsl::gfx::Renderer* renderer);
|
||||
void update() override;
|
||||
tsl::elm::Element* createUI() override;
|
||||
virtual tsl::elm::Element* baseUI() = 0;
|
||||
virtual void refresh() {}
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
extern std::string getVersionString();
|
||||
291
Source/sys-clk/overlay/src/ui/gui/base_menu_gui.cpp
Normal file
291
Source/sys-clk/overlay/src/ui/gui/base_menu_gui.cpp
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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() : tempColors{tsl::Color(0), tsl::Color(0), tsl::Color(0)}
|
||||
{
|
||||
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[10] = {
|
||||
"App ID", "Profile", "CPU", "GPU", "MEM", "SOC", "PCB", "Skin", "Now", "Avg"
|
||||
};
|
||||
|
||||
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("Official 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 = 129; // 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 = 149; // Direct assignment (129 + 20)
|
||||
|
||||
// === 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
|
||||
renderer->drawString(displayStrings[7], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM real
|
||||
|
||||
y = 169; // 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 = 191; // Direct assignment (169 + 22)
|
||||
|
||||
// === 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 = 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);
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// Optimized refresh - now does all the string formatting once per second
|
||||
void BaseMenuGui::refresh()
|
||||
{
|
||||
const u64 ticks = armGetSystemTick();
|
||||
// Use cached comparison - 1 billion nanoseconds
|
||||
if (armTicksToNs(ticks - this->lastContextUpdate) <= 1000000000UL) [[likely]] {
|
||||
return; // Early exit for most calls
|
||||
}
|
||||
|
||||
this->lastContextUpdate = ticks;
|
||||
|
||||
// Lazy context allocation
|
||||
if (!this->context) [[unlikely]] {
|
||||
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]] {
|
||||
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], "%u mV", cpuVoltageUv / 1000U);
|
||||
sprintf(displayStrings[9], "%u mV", gpuVoltageUv / 1000U);
|
||||
|
||||
// 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;
|
||||
}
|
||||
59
Source/sys-clk/overlay/src/ui/gui/base_menu_gui.h
Normal file
59
Source/sys-clk/overlay/src/ui/gui/base_menu_gui.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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"
|
||||
#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:
|
||||
bool g_hardwareModelCached = false;
|
||||
bool g_isMariko = false;
|
||||
|
||||
bool IsMariko() {
|
||||
if (!g_hardwareModelCached) {
|
||||
SetSysProductModel model = SetSysProductModel_Invalid;
|
||||
setsysGetProductModel(&model);
|
||||
g_isMariko = (model == SetSysProductModel_Iowa ||
|
||||
model == SetSysProductModel_Hoag ||
|
||||
model == SetSysProductModel_Calcio ||
|
||||
model == SetSysProductModel_Aula);
|
||||
g_hardwareModelCached = true;
|
||||
}
|
||||
return g_isMariko;
|
||||
}
|
||||
|
||||
bool IsErista() {
|
||||
return !IsMariko();
|
||||
}
|
||||
BaseMenuGui();
|
||||
~BaseMenuGui();
|
||||
void preDraw(tsl::gfx::Renderer* renderer) override;
|
||||
tsl::elm::List* listElement;
|
||||
tsl::elm::Element* baseUI() override;
|
||||
void refresh() override;
|
||||
virtual void listUI() = 0;
|
||||
|
||||
private:
|
||||
char displayStrings[17][32]; // Pre-formatted display strings
|
||||
tsl::Color tempColors[3]; // Pre-computed temperature colors
|
||||
};
|
||||
67
Source/sys-clk/overlay/src/ui/gui/fatal_gui.cpp
Normal file
67
Source/sys-clk/overlay/src/ui/gui/fatal_gui.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 "fatal_gui.h"
|
||||
|
||||
FatalGui::FatalGui(const std::string message, const std::string info)
|
||||
{
|
||||
this->message = message;
|
||||
this->info = info;
|
||||
}
|
||||
|
||||
void FatalGui::openWithResultCode(std::string tag, Result rc)
|
||||
{
|
||||
char rcStr[32];
|
||||
std::string info = tag;
|
||||
info.append(rcStr, snprintf(rcStr, sizeof(rcStr), "\n\n[0x%x] %04d-%04d", rc, R_MODULE(rc), R_DESCRIPTION(rc)));
|
||||
|
||||
tsl::changeTo<FatalGui>(
|
||||
"Could not connect to sys-clk.\n\n"
|
||||
"\n"
|
||||
"Please make sure everything is\n\n"
|
||||
"correctly installed and enabled.",
|
||||
info
|
||||
);
|
||||
}
|
||||
|
||||
tsl::elm::Element* FatalGui::baseUI()
|
||||
{
|
||||
tsl::elm::CustomDrawer* drawer = new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer* renderer, u16 x, u16 y, u16 w, u16 h) {
|
||||
renderer->drawString("\uE150", false, 40, 210, 40, TEXT_COLOR);
|
||||
renderer->drawString("Fatal error", false, 100, 210, 30, TEXT_COLOR);
|
||||
|
||||
std::uint32_t txtY = 255;
|
||||
if(!this->message.empty())
|
||||
{
|
||||
txtY += renderer->drawString(this->message.c_str(), false, 40, txtY, 23, TEXT_COLOR).second;
|
||||
txtY += 55;
|
||||
}
|
||||
|
||||
if(!this->info.empty())
|
||||
{
|
||||
renderer->drawString(this->info.c_str(), false, 40, txtY, 18, DESC_COLOR);
|
||||
}
|
||||
});
|
||||
|
||||
return drawer;
|
||||
}
|
||||
|
||||
bool FatalGui::handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight)
|
||||
{
|
||||
if((keysDown & HidNpadButton_A) == HidNpadButton_A || (keysDown & HidNpadButton_B) == HidNpadButton_B)
|
||||
{
|
||||
while(tsl::Overlay::get()->getCurrentGui() != nullptr) {
|
||||
tsl::goBack();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
29
Source/sys-clk/overlay/src/ui/gui/fatal_gui.h
Normal file
29
Source/sys-clk/overlay/src/ui/gui/fatal_gui.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 <list>
|
||||
|
||||
#include "base_gui.h"
|
||||
|
||||
class FatalGui : public BaseGui
|
||||
{
|
||||
protected:
|
||||
std::string message;
|
||||
std::string info;
|
||||
|
||||
public:
|
||||
FatalGui(const std::string message, const std::string info);
|
||||
~FatalGui() {}
|
||||
tsl::elm::Element* baseUI() override;
|
||||
bool handleInput(u64 keysDown, u64 keysHeld, const HidTouchState &touchPos, HidAnalogStickState joyStickPosLeft, HidAnalogStickState joyStickPosRight);
|
||||
static void openWithResultCode(std::string tag, Result rc);
|
||||
};
|
||||
67
Source/sys-clk/overlay/src/ui/gui/freq_choice_gui.cpp
Normal file
67
Source/sys-clk/overlay/src/ui/gui/freq_choice_gui.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 "freq_choice_gui.h"
|
||||
|
||||
#include "../format.h"
|
||||
#include "fatal_gui.h"
|
||||
|
||||
FreqChoiceGui::FreqChoiceGui(std::uint32_t selectedHz, std::uint32_t* hzList, std::uint32_t hzCount, SysClkModule module, FreqChoiceListener listener)
|
||||
{
|
||||
this->selectedHz = selectedHz;
|
||||
this->hzList = hzList;
|
||||
this->hzCount = hzCount;
|
||||
this->module = module; // Add this
|
||||
this->listener = listener;
|
||||
}
|
||||
|
||||
tsl::elm::ListItem* FreqChoiceGui::createFreqListItem(std::uint32_t hz, bool selected)
|
||||
{
|
||||
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(formatListFreqHz(hz), "", true);
|
||||
listItem->setValue(selected ? "\uE14B" : "");
|
||||
|
||||
listItem->setClickListener([this, hz](u64 keys) {
|
||||
if((keys & HidNpadButton_A) == HidNpadButton_A && this->listener)
|
||||
{
|
||||
if(this->listener(hz))
|
||||
{
|
||||
tsl::goBack();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return listItem;
|
||||
}
|
||||
|
||||
void FreqChoiceGui::listUI()
|
||||
{
|
||||
// Add CategoryHeader based on module
|
||||
std::string moduleName = sysclkFormatModule(this->module, true);
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader(moduleName));
|
||||
|
||||
this->listElement->addItem(this->createFreqListItem(0, this->selectedHz == 0));
|
||||
std::uint32_t hz;
|
||||
for(std::uint32_t i = 0; i < this->hzCount; i++) {
|
||||
hz = this->hzList[i];
|
||||
// Skip 204 MHz exactly
|
||||
if(moduleName == "Memory" && hz == 204000000) {
|
||||
continue;
|
||||
}
|
||||
// if(moduleName == "GPU") {
|
||||
// if(BaseGui::isMariko() && is)
|
||||
// continue;
|
||||
// }
|
||||
this->listElement->addItem(this->createFreqListItem(hz, (hz / 1000000) == (this->selectedHz / 1000000)));
|
||||
}
|
||||
this->listElement->jumpToItem("", "");
|
||||
}
|
||||
35
Source/sys-clk/overlay/src/ui/gui/freq_choice_gui.h
Normal file
35
Source/sys-clk/overlay/src/ui/gui/freq_choice_gui.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 <list>
|
||||
|
||||
#include "base_menu_gui.h"
|
||||
|
||||
using FreqChoiceListener = std::function<bool(std::uint32_t hz)>;
|
||||
|
||||
#define FREQ_DEFAULT_TEXT "Do not override"
|
||||
|
||||
class FreqChoiceGui : public BaseMenuGui
|
||||
{
|
||||
protected:
|
||||
std::uint32_t selectedHz;
|
||||
std::uint32_t* hzList;
|
||||
std::uint32_t hzCount;
|
||||
SysClkModule module; // Added
|
||||
FreqChoiceListener listener;
|
||||
tsl::elm::ListItem* createFreqListItem(std::uint32_t hz, bool selected);
|
||||
|
||||
public:
|
||||
FreqChoiceGui(std::uint32_t selectedHz, std::uint32_t* hzList, std::uint32_t hzCount, SysClkModule module, FreqChoiceListener listener);
|
||||
~FreqChoiceGui() {}
|
||||
void listUI() override;
|
||||
};
|
||||
108
Source/sys-clk/overlay/src/ui/gui/global_override_gui.cpp
Normal file
108
Source/sys-clk/overlay/src/ui/gui/global_override_gui.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 "global_override_gui.h"
|
||||
|
||||
#include "fatal_gui.h"
|
||||
#include "../format.h"
|
||||
|
||||
GlobalOverrideGui::GlobalOverrideGui()
|
||||
{
|
||||
for(std::uint16_t m = 0; m < SysClkModule_EnumMax; m++)
|
||||
{
|
||||
this->listItems[m] = nullptr;
|
||||
this->listHz[m] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalOverrideGui::openFreqChoiceGui(SysClkModule module)
|
||||
{
|
||||
std::uint32_t hzList[SYSCLK_FREQ_LIST_MAX];
|
||||
std::uint32_t hzCount;
|
||||
Result rc = sysclkIpcGetFreqList(module, &hzList[0], SYSCLK_FREQ_LIST_MAX, &hzCount);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcGetFreqList", rc);
|
||||
return;
|
||||
}
|
||||
tsl::changeTo<FreqChoiceGui>(this->context->overrideFreqs[module], hzList, hzCount, module, [this, module](std::uint32_t hz) {
|
||||
Result rc = sysclkIpcSetOverride(module, hz);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcSetOverride", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
this->lastContextUpdate = armGetSystemTick();
|
||||
this->context->overrideFreqs[module] = hz;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void GlobalOverrideGui::addModuleListItem(SysClkModule module)
|
||||
{
|
||||
tsl::elm::ListItem* listItem = new tsl::elm::ListItem(sysclkFormatModule(module, true));
|
||||
listItem->setValue(formatListFreqMHz(0));
|
||||
listItem->setClickListener([this, module](u64 keys) {
|
||||
if((keys & HidNpadButton_A) == HidNpadButton_A)
|
||||
{
|
||||
this->openFreqChoiceGui(module);
|
||||
return true;
|
||||
}
|
||||
else if((keys & HidNpadButton_Y) == HidNpadButton_Y)
|
||||
{
|
||||
// Reset override to "Do not override" (0 Hz)
|
||||
Result rc = sysclkIpcSetOverride(module, 0);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcSetOverride", rc);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update context and tracking variables
|
||||
this->lastContextUpdate = armGetSystemTick();
|
||||
this->context->overrideFreqs[module] = 0;
|
||||
this->listHz[module] = 0;
|
||||
|
||||
// Update display
|
||||
this->listItems[module]->setValue(formatListFreqHz(0));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
this->listElement->addItem(listItem);
|
||||
this->listItems[module] = listItem;
|
||||
}
|
||||
|
||||
void GlobalOverrideGui::listUI()
|
||||
{
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Temporary Overrides " + ult::DIVIDER_SYMBOL + " Reset"));
|
||||
this->addModuleListItem(SysClkModule_CPU);
|
||||
this->addModuleListItem(SysClkModule_GPU);
|
||||
this->addModuleListItem(SysClkModule_MEM);
|
||||
}
|
||||
|
||||
void GlobalOverrideGui::refresh()
|
||||
{
|
||||
BaseMenuGui::refresh();
|
||||
if(this->context)
|
||||
{
|
||||
for(std::uint16_t m = 0; m < SysClkModule_EnumMax; m++)
|
||||
{
|
||||
if(this->listItems[m] != nullptr && this->listHz[m] != this->context->overrideFreqs[m])
|
||||
{
|
||||
this->listItems[m]->setValue(formatListFreqHz(this->context->overrideFreqs[m]));
|
||||
this->listHz[m] = this->context->overrideFreqs[m];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
Source/sys-clk/overlay/src/ui/gui/global_override_gui.h
Normal file
31
Source/sys-clk/overlay/src/ui/gui/global_override_gui.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 "../../ipc.h"
|
||||
#include "base_menu_gui.h"
|
||||
#include "freq_choice_gui.h"
|
||||
|
||||
class GlobalOverrideGui : public BaseMenuGui
|
||||
{
|
||||
protected:
|
||||
tsl::elm::ListItem* listItems[SysClkModule_EnumMax];
|
||||
std::uint32_t listHz[SysClkModule_EnumMax];
|
||||
|
||||
void openFreqChoiceGui(SysClkModule module);
|
||||
void addModuleListItem(SysClkModule module);
|
||||
|
||||
public:
|
||||
GlobalOverrideGui();
|
||||
~GlobalOverrideGui() {}
|
||||
void listUI() override;
|
||||
void refresh() override;
|
||||
};
|
||||
93
Source/sys-clk/overlay/src/ui/gui/main_gui.cpp
Normal file
93
Source/sys-clk/overlay/src/ui/gui/main_gui.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 "main_gui.h"
|
||||
|
||||
#include "fatal_gui.h"
|
||||
#include "app_profile_gui.h"
|
||||
#include "global_override_gui.h"
|
||||
#include "misc_gui.h"
|
||||
|
||||
void MainGui::listUI()
|
||||
{
|
||||
this->enabledToggle = new tsl::elm::ToggleListItem("Enable", false);
|
||||
enabledToggle->setStateChangedListener([this](bool state) {
|
||||
Result rc = sysclkIpcSetEnabled(state);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcSetEnabled", rc);
|
||||
}
|
||||
|
||||
this->lastContextUpdate = armGetSystemTick();
|
||||
this->context->enabled = state;
|
||||
});
|
||||
this->listElement->addItem(this->enabledToggle);
|
||||
|
||||
tsl::elm::ListItem* appProfileItem = new tsl::elm::ListItem("Edit App Profile");
|
||||
appProfileItem->setClickListener([this](u64 keys) {
|
||||
if((keys & HidNpadButton_A) == HidNpadButton_A && this->context)
|
||||
{
|
||||
AppProfileGui::changeTo(this->context->applicationId);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
this->listElement->addItem(appProfileItem);
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Advanced"));
|
||||
|
||||
tsl::elm::ListItem* globalProfileItem = new tsl::elm::ListItem("Edit Global Profile");
|
||||
globalProfileItem->setClickListener([this](u64 keys) {
|
||||
if((keys & HidNpadButton_A) == HidNpadButton_A && this->context)
|
||||
{
|
||||
AppProfileGui::changeTo(SYSCLK_GLOBAL_PROFILE_TID);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
this->listElement->addItem(globalProfileItem);
|
||||
|
||||
tsl::elm::ListItem* globalOverrideItem = new tsl::elm::ListItem("Temporary Overrides");
|
||||
globalOverrideItem->setClickListener([this](u64 keys) {
|
||||
if((keys & HidNpadButton_A) == HidNpadButton_A)
|
||||
{
|
||||
tsl::changeTo<GlobalOverrideGui>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
this->listElement->addItem(globalOverrideItem);
|
||||
|
||||
//this->listElement->addItem(new tsl::elm::CategoryHeader("Misc"));
|
||||
|
||||
tsl::elm::ListItem* miscItem = new tsl::elm::ListItem("Settings");
|
||||
miscItem->setClickListener([this](u64 keys) {
|
||||
if((keys & HidNpadButton_A) == HidNpadButton_A && this->context)
|
||||
{
|
||||
tsl::changeTo<MiscGui>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
this->listElement->addItem(miscItem);
|
||||
}
|
||||
|
||||
void MainGui::refresh()
|
||||
{
|
||||
BaseMenuGui::refresh();
|
||||
//if(this->context)
|
||||
//{
|
||||
// this->enabledToggle->setState(this->context->enabled);
|
||||
//}
|
||||
}
|
||||
25
Source/sys-clk/overlay/src/ui/gui/main_gui.h
Normal file
25
Source/sys-clk/overlay/src/ui/gui/main_gui.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 "base_menu_gui.h"
|
||||
|
||||
class MainGui : public BaseMenuGui
|
||||
{
|
||||
protected:
|
||||
tsl::elm::ToggleListItem* enabledToggle;
|
||||
|
||||
public:
|
||||
MainGui() {}
|
||||
~MainGui() {}
|
||||
void listUI() override;
|
||||
void refresh() override;
|
||||
};
|
||||
444
Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp
Normal file
444
Source/sys-clk/overlay/src/ui/gui/misc_gui.cpp
Normal file
@@ -0,0 +1,444 @@
|
||||
#include "misc_gui.h"
|
||||
#include "fatal_gui.h"
|
||||
#include "../format.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
//#include <sstream>
|
||||
|
||||
MiscGui::MiscGui()
|
||||
{
|
||||
|
||||
// Load current config values
|
||||
configValues["uncapped_clocks"] = getConfigValue("uncapped_clocks");
|
||||
configValues["override_boost_mode"] = getConfigValue("override_boost_mode");
|
||||
configValues["auto_cpu_boost"] = getConfigValue("auto_cpu_boost");
|
||||
configValues["sync_reversenx"] = getConfigValue("sync_reversenx");
|
||||
// gpu_dvfs is handled separately as it's now a trackbar with integer values
|
||||
}
|
||||
|
||||
MiscGui::~MiscGui()
|
||||
{
|
||||
this->configToggles.clear();
|
||||
}
|
||||
|
||||
bool MiscGui::getConfigValue(const std::string& iniKey)
|
||||
{
|
||||
FILE* file = fopen("/config/sys-clk/config.ini", "r");
|
||||
if (!file) {
|
||||
// Return default values if file doesn't exist
|
||||
return (iniKey == "gpu_dvfs"); // gpu_dvfs defaults to true, others default to false
|
||||
}
|
||||
|
||||
char line[512];
|
||||
bool inValuesSection = false;
|
||||
|
||||
size_t len;
|
||||
while (fgets(line, sizeof(line), file)) {
|
||||
// Remove newline if present
|
||||
len = strlen(line);
|
||||
if (len > 0 && line[len - 1] == '\n') {
|
||||
line[len - 1] = '\0';
|
||||
}
|
||||
|
||||
// Trim whitespace
|
||||
char* start = line;
|
||||
while (*start == ' ' || *start == '\t') start++;
|
||||
char* end = start + strlen(start) - 1;
|
||||
while (end > start && (*end == ' ' || *end == '\t')) {
|
||||
*end = '\0';
|
||||
end--;
|
||||
}
|
||||
|
||||
// Check for [values] section
|
||||
if (strcmp(start, "[values]") == 0) {
|
||||
inValuesSection = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for new section
|
||||
if (strlen(start) > 0 && start[0] == '[') {
|
||||
inValuesSection = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse key=value in values section
|
||||
if (inValuesSection) {
|
||||
char* equalPos = strchr(start, '=');
|
||||
if (equalPos != nullptr) {
|
||||
*equalPos = '\0'; // Split the string
|
||||
char* key = start;
|
||||
char* value = equalPos + 1;
|
||||
|
||||
if(iniKey == "uncapped_clocks") {
|
||||
Result rc = sysclkIpcSetEnabled(value);
|
||||
}
|
||||
|
||||
// Trim key
|
||||
char* keyEnd = key + strlen(key) - 1;
|
||||
while (keyEnd > key && (*keyEnd == ' ' || *keyEnd == '\t')) {
|
||||
*keyEnd = '\0';
|
||||
keyEnd--;
|
||||
}
|
||||
|
||||
// Trim value
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
char* valueEnd = value + strlen(value) - 1;
|
||||
while (valueEnd > value && (*valueEnd == ' ' || *valueEnd == '\t')) {
|
||||
*valueEnd = '\0';
|
||||
valueEnd--;
|
||||
}
|
||||
|
||||
if (iniKey == key) {
|
||||
bool result = (strcmp(value, "1") == 0);
|
||||
fclose(file);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
||||
// Return default values if key not found
|
||||
return (iniKey == "gpu_dvfs"); // gpu_dvfs defaults to true, others default to false
|
||||
}
|
||||
|
||||
int MiscGui::getConfigIntValue(const std::string& iniKey, int defaultValue)
|
||||
{
|
||||
FILE* file = fopen("/config/sys-clk/config.ini", "r");
|
||||
if (!file) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
char line[512];
|
||||
bool inValuesSection = false;
|
||||
|
||||
size_t len;
|
||||
|
||||
while (fgets(line, sizeof(line), file)) {
|
||||
// Remove newline if present
|
||||
len = strlen(line);
|
||||
if (len > 0 && line[len - 1] == '\n') {
|
||||
line[len - 1] = '\0';
|
||||
}
|
||||
|
||||
// Trim whitespace
|
||||
char* start = line;
|
||||
while (*start == ' ' || *start == '\t') start++;
|
||||
char* end = start + strlen(start) - 1;
|
||||
while (end > start && (*end == ' ' || *end == '\t')) {
|
||||
*end = '\0';
|
||||
end--;
|
||||
}
|
||||
|
||||
// Check for [values] section
|
||||
if (strcmp(start, "[values]") == 0) {
|
||||
inValuesSection = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for new section
|
||||
if (strlen(start) > 0 && start[0] == '[') {
|
||||
inValuesSection = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse key=value in values section
|
||||
if (inValuesSection) {
|
||||
char* equalPos = strchr(start, '=');
|
||||
if (equalPos != nullptr) {
|
||||
*equalPos = '\0'; // Split the string
|
||||
char* key = start;
|
||||
char* value = equalPos + 1;
|
||||
|
||||
// Trim key
|
||||
char* keyEnd = key + strlen(key) - 1;
|
||||
while (keyEnd > key && (*keyEnd == ' ' || *keyEnd == '\t')) {
|
||||
*keyEnd = '\0';
|
||||
keyEnd--;
|
||||
}
|
||||
|
||||
// Trim value
|
||||
while (*value == ' ' || *value == '\t') value++;
|
||||
char* valueEnd = value + strlen(value) - 1;
|
||||
while (valueEnd > value && (*valueEnd == ' ' || *valueEnd == '\t')) {
|
||||
*valueEnd = '\0';
|
||||
valueEnd--;
|
||||
}
|
||||
|
||||
if (iniKey == key) {
|
||||
int result = atoi(value);
|
||||
fclose(file);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
SysClkIpcToggleUncappedClocks(SysClkModule_CPU, g_freq_table_hz[SysClkModule_CPU][result])
|
||||
|
||||
void MiscGui::setConfigValue(const std::string& iniKey, bool value)
|
||||
{
|
||||
if(iniKey == "uncapped_clocks") {
|
||||
Result rc = sysclkIpcSetEnabled(value);
|
||||
}
|
||||
// Read the entire file
|
||||
FILE* file = fopen("/config/sys-clk/config.ini", "r");
|
||||
std::vector<std::string> lines;
|
||||
|
||||
if (file) {
|
||||
char line[512];
|
||||
size_t len;
|
||||
while (fgets(line, sizeof(line), file)) {
|
||||
// Remove newline if present
|
||||
len = strlen(line);
|
||||
if (len > 0 && line[len - 1] == '\n') {
|
||||
line[len - 1] = '\0';
|
||||
}
|
||||
lines.push_back(std::string(line));
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// Find and update the value
|
||||
bool inValuesSection = false;
|
||||
bool keyFound = false;
|
||||
int valuesSectionIndex = -1;
|
||||
|
||||
std::string trimmedLine;
|
||||
size_t equalPos;
|
||||
std::string key;
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
trimmedLine = lines[i];
|
||||
trimmedLine.erase(0, trimmedLine.find_first_not_of(" \t"));
|
||||
trimmedLine.erase(trimmedLine.find_last_not_of(" \t") + 1);
|
||||
|
||||
if (trimmedLine == "[values]") {
|
||||
inValuesSection = true;
|
||||
valuesSectionIndex = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trimmedLine.length() > 0 && trimmedLine[0] == '[') {
|
||||
inValuesSection = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inValuesSection) {
|
||||
equalPos = trimmedLine.find('=');
|
||||
if (equalPos != std::string::npos) {
|
||||
key = trimmedLine.substr(0, equalPos);
|
||||
key.erase(0, key.find_first_not_of(" \t"));
|
||||
key.erase(key.find_last_not_of(" \t") + 1);
|
||||
|
||||
if (key == iniKey) {
|
||||
lines[i] = iniKey + "=" + (value ? "1" : "0");
|
||||
keyFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If key wasn't found, add it to the values section
|
||||
if (!keyFound) {
|
||||
if (valuesSectionIndex == -1) {
|
||||
// Add [values] section if it doesn't exist
|
||||
lines.push_back("[values]");
|
||||
lines.push_back(iniKey + "=" + (value ? "1" : "0"));
|
||||
} else {
|
||||
// Add to existing values section
|
||||
lines.insert(lines.begin() + valuesSectionIndex + 1, iniKey + "=" + (value ? "1" : "0"));
|
||||
}
|
||||
}
|
||||
|
||||
// Write the file back
|
||||
FILE* outFile = fopen("/config/sys-clk/config.ini", "w");
|
||||
if (outFile) {
|
||||
for (const auto& fileLine : lines) {
|
||||
fprintf(outFile, "%s\n", fileLine.c_str());
|
||||
}
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
|
||||
void MiscGui::setConfigIntValue(const std::string& iniKey, int value)
|
||||
{
|
||||
// Read the entire file
|
||||
FILE* file = fopen("/config/sys-clk/config.ini", "r");
|
||||
std::vector<std::string> lines;
|
||||
|
||||
if (file) {
|
||||
char line[512];
|
||||
size_t len;
|
||||
while (fgets(line, sizeof(line), file)) {
|
||||
// Remove newline if present
|
||||
len = strlen(line);
|
||||
if (len > 0 && line[len - 1] == '\n') {
|
||||
line[len - 1] = '\0';
|
||||
}
|
||||
lines.push_back(std::string(line));
|
||||
}
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// Find and update the value
|
||||
bool inValuesSection = false;
|
||||
bool keyFound = false;
|
||||
int valuesSectionIndex = -1;
|
||||
|
||||
std::string trimmedLine;
|
||||
size_t equalPos;
|
||||
std::string key;
|
||||
|
||||
for (size_t i = 0; i < lines.size(); i++) {
|
||||
trimmedLine = lines[i];
|
||||
trimmedLine.erase(0, trimmedLine.find_first_not_of(" \t"));
|
||||
trimmedLine.erase(trimmedLine.find_last_not_of(" \t") + 1);
|
||||
|
||||
if (trimmedLine == "[values]") {
|
||||
inValuesSection = true;
|
||||
valuesSectionIndex = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (trimmedLine.length() > 0 && trimmedLine[0] == '[') {
|
||||
inValuesSection = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (inValuesSection) {
|
||||
equalPos = trimmedLine.find('=');
|
||||
if (equalPos != std::string::npos) {
|
||||
key = trimmedLine.substr(0, equalPos);
|
||||
key.erase(0, key.find_first_not_of(" \t"));
|
||||
key.erase(key.find_last_not_of(" \t") + 1);
|
||||
|
||||
if (key == iniKey) {
|
||||
lines[i] = iniKey + "=" + std::to_string(value);
|
||||
keyFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If key wasn't found, add it to the values section
|
||||
if (!keyFound) {
|
||||
if (valuesSectionIndex == -1) {
|
||||
// Add [values] section if it doesn't exist
|
||||
lines.push_back("[values]");
|
||||
lines.push_back(iniKey + "=" + std::to_string(value));
|
||||
} else {
|
||||
// Add to existing values section
|
||||
lines.insert(lines.begin() + valuesSectionIndex + 1, iniKey + "=" + std::to_string(value));
|
||||
}
|
||||
}
|
||||
|
||||
// Write the file back
|
||||
FILE* outFile = fopen("/config/sys-clk/config.ini", "w");
|
||||
if (outFile) {
|
||||
for (const auto& fileLine : lines) {
|
||||
fprintf(outFile, "%s\n", fileLine.c_str());
|
||||
}
|
||||
fclose(outFile);
|
||||
}
|
||||
}
|
||||
|
||||
void MiscGui::addConfigToggle(const std::string& iniKey, const char* displayName) {
|
||||
tsl::elm::ToggleListItem* toggle = new tsl::elm::ToggleListItem(displayName, configValues[iniKey]);
|
||||
toggle->setStateChangedListener([this, iniKey](bool state) {
|
||||
configValues[iniKey] = state;
|
||||
setConfigValue(iniKey, state);
|
||||
this->lastContextUpdate = armGetSystemTick();
|
||||
});
|
||||
this->listElement->addItem(toggle);
|
||||
this->configToggles[iniKey] = toggle;
|
||||
}
|
||||
|
||||
void MiscGui::updateConfigToggles() {
|
||||
for (const auto& [key, toggle] : this->configToggles) {
|
||||
if (toggle != nullptr) {
|
||||
bool currentValue = getConfigValue(key);
|
||||
configValues[key] = currentValue;
|
||||
toggle->setState(currentValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MiscGui::listUI()
|
||||
{
|
||||
|
||||
this->listElement->addItem(new tsl::elm::CategoryHeader("Settings"));
|
||||
|
||||
this->enabledToggle = new tsl::elm::ToggleListItem("Enable", false);
|
||||
enabledToggle->setStateChangedListener([this](bool state) {
|
||||
Result rc = sysclkIpcSetEnabled(state);
|
||||
if(R_FAILED(rc))
|
||||
{
|
||||
FatalGui::openWithResultCode("sysclkIpcSetEnabled", rc);
|
||||
}
|
||||
|
||||
this->lastContextUpdate = armGetSystemTick();
|
||||
this->context->enabled = state;
|
||||
});
|
||||
this->listElement->addItem(this->enabledToggle);
|
||||
|
||||
// Add the 4 boolean config toggles using INI keys
|
||||
addConfigToggle("uncapped_clocks", "Uncapped Clocks");
|
||||
addConfigToggle("override_boost_mode", "Override Boost Mode");
|
||||
addConfigToggle("auto_cpu_boost", "Auto CPU Boost");
|
||||
addConfigToggle("reversenx_sync", "Sync ReverseNX");
|
||||
|
||||
// Add GPU DVFS as a NamedStepTrackBar with V2 style
|
||||
this->gpuDvfsTrackbar = new tsl::elm::NamedStepTrackBar("", {
|
||||
"Off",
|
||||
"Official Service Method",
|
||||
"Hijack Method"
|
||||
}, true, "GPU DVFS");
|
||||
|
||||
// Set initial value (default is 0 if not set)
|
||||
int currentDvfsValue = getConfigIntValue("gpu_dvfs", 1);
|
||||
// Ensure the value is within valid range (0-2)
|
||||
currentDvfsValue = std::max(0, std::min(2, currentDvfsValue));
|
||||
this->gpuDvfsTrackbar->setProgress(static_cast<u8>(currentDvfsValue));
|
||||
|
||||
// Set up the value change listener to update the INI file
|
||||
this->gpuDvfsTrackbar->setValueChangedListener([this](u8 value) {
|
||||
// Ensure value is within expected range
|
||||
const int intValue = static_cast<int>(std::min(static_cast<u8>(2), value));
|
||||
setConfigIntValue("gpu_dvfs", intValue);
|
||||
this->lastContextUpdate = armGetSystemTick();
|
||||
});
|
||||
|
||||
this->listElement->addItem(this->gpuDvfsTrackbar);
|
||||
}
|
||||
|
||||
void MiscGui::refresh() {
|
||||
BaseMenuGui::refresh();
|
||||
|
||||
// Update the enabled toggle state
|
||||
if(this->context)
|
||||
{
|
||||
this->enabledToggle->setState(this->context->enabled);
|
||||
}
|
||||
|
||||
// Update config values and toggle states every 60 frames (once per second at 60fps)
|
||||
if (this->context && ++frameCounter >= 60)
|
||||
{
|
||||
frameCounter = 0;
|
||||
updateConfigToggles();
|
||||
|
||||
// Update GPU DVFS trackbar
|
||||
if (this->gpuDvfsTrackbar != nullptr) {
|
||||
int currentDvfsValue = getConfigIntValue("gpu_dvfs", 1);
|
||||
// Ensure the value is within valid range (0-2)
|
||||
currentDvfsValue = std::max(0, std::min(2, currentDvfsValue));
|
||||
this->gpuDvfsTrackbar->setProgress(static_cast<u8>(currentDvfsValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
30
Source/sys-clk/overlay/src/ui/gui/misc_gui.h
Normal file
30
Source/sys-clk/overlay/src/ui/gui/misc_gui.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
#include "../../ipc.h"
|
||||
#include "base_menu_gui.h"
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
class MiscGui : public BaseMenuGui
|
||||
{
|
||||
public:
|
||||
MiscGui();
|
||||
~MiscGui();
|
||||
void listUI() override;
|
||||
void refresh() override;
|
||||
protected:
|
||||
|
||||
std::unordered_map<std::string, tsl::elm::ToggleListItem*> configToggles;
|
||||
std::unordered_map<std::string, bool> configValues;
|
||||
|
||||
void addConfigToggle(const std::string& iniKey, const char* displayName);
|
||||
void updateConfigToggles();
|
||||
bool getConfigValue(const std::string& iniKey);
|
||||
void setConfigValue(const std::string& iniKey, bool value);
|
||||
int getConfigIntValue(const std::string& iniKey, int defaultValue);
|
||||
void setConfigIntValue(const std::string& iniKey, int value);
|
||||
|
||||
tsl::elm::ToggleListItem* enabledToggle;
|
||||
tsl::elm::NamedStepTrackBar* gpuDvfsTrackbar; // Add this line
|
||||
|
||||
u8 frameCounter = 60;
|
||||
};
|
||||
20
Source/sys-clk/overlay/src/ui/style.h
Normal file
20
Source/sys-clk/overlay/src/ui/style.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* "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 <tesla.hpp>
|
||||
|
||||
#define TEXT_COLOR tsl::gfx::Renderer::a(0xFFFF)
|
||||
#define DESC_COLOR tsl::gfx::Renderer::a({ 0xC, 0xC, 0xC, 0xF })
|
||||
#define VALUE_COLOR tsl::gfx::Renderer::a({ 0x5, 0xC, 0xA, 0xF })
|
||||
#define SMALL_TEXT_SIZE 15
|
||||
#define LABEL_SPACING 7
|
||||
#define LABEL_FONT_SIZE 15
|
||||
Reference in New Issue
Block a user