From 2fd78d6c30540b2ceba913382cfd0447d853252e Mon Sep 17 00:00:00 2001 From: Lightos1 <124387232+Lightos1@users.noreply.github.com> Date: Sat, 17 Oct 2026 19:18:24 +0200 Subject: [PATCH] hoc-clk: make logging toggle config based --- Source/hoc-clk/common/include/hocclk/config.h | 14 +++- .../src/ui/gui/config_info_strings.cpp | 12 ++++ .../hoc-clk/overlay/src/ui/gui/misc_gui.cpp | 7 ++ .../hoc-clk/sysmodule/src/file/file_utils.cpp | 72 ++++++++++++------- .../hoc-clk/sysmodule/src/file/file_utils.hpp | 3 +- Source/hoc-clk/sysmodule/src/main.cpp | 3 +- 6 files changed, 82 insertions(+), 29 deletions(-) diff --git a/Source/hoc-clk/common/include/hocclk/config.h b/Source/hoc-clk/common/include/hocclk/config.h index b3c33af4..f72a18b6 100644 --- a/Source/hoc-clk/common/include/hocclk/config.h +++ b/Source/hoc-clk/common/include/hocclk/config.h @@ -81,6 +81,9 @@ typedef enum { HocClkConfigValue_Watchdog, + HocClkConfigValue_FileLogging, + HocClkConfigValue_UartLogging, + KipConfigValue_custRev, KipConfigValue_KipVersion, // KipConfigValue_mtcConf, @@ -341,6 +344,11 @@ static inline const char* hocclkFormatConfigValue(HocClkConfigValue val, bool pr case HocClkConfigValue_Watchdog: return pretty ? "Watchcat" : "watchdog"; // More dignified + + case HocClkConfigValue_FileLogging: + return pretty ? "File Logging" : "file_logging"; + case HocClkConfigValue_UartLogging: + return pretty ? "UART Logging" : "uart_logging"; // KIP config values case KipConfigValue_custRev: return pretty ? "Custom Revision" : "kip_cust_rev"; @@ -593,6 +601,8 @@ static inline uint64_t hocclkDefaultConfigValue(HocClkConfigValue val) case HocClkConfigValue_MemoryFrequencyMeasurementMode: case HocClkConfigValue_MarikoMiddleFreqs: case HocClkConfigValue_LiveGpuVoltage: + case HocClkConfigValue_FileLogging: + case HocClkConfigValue_UartLogging: return 0ULL; case HocClkConfigValue_RamDisplayUnit: return (uint64_t)RamDisplayUnit_MHz; @@ -654,6 +664,9 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case HocClkConfigValue_MarikoMiddleFreqs: case HocClkConfigValue_LiveGpuVoltage: case HocClkConfigValue_Watchdog: + case HocClkConfigValue_FileLogging: + case HocClkConfigValue_UartLogging: + case KipConfigValue_eristaCpuUnlock: return (input & 0x1) == input; case KipConfigValue_KipVersion: @@ -790,7 +803,6 @@ static inline uint64_t hocclkValidConfigValue(HocClkConfigValue val, uint64_t in case KipConfigValue_g_soc_volt_3266000: case KipConfigValue_g_soc_volt_3333000: case KipConfigValue_eristaCpuVmin: - case KipConfigValue_eristaCpuUnlock: case KipConfigValue_t6_tRTW_fine_tune: case KipConfigValue_t7_tWTR_fine_tune: case KipCrc32: diff --git a/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp b/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp index cecdd7ab..f799175e 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/config_info_strings.cpp @@ -560,6 +560,18 @@ std::vector ConfigInfoStrings(HocClkConfigValue val, bool isMariko, "Voltage applies globally across all frequencies.", "\"Reset\" restores default or RAM-stable minimum." }; + case HocClkConfigValue_FileLogging: + return { + "Write sysmodule logs to log.txt in the config folder.", + "Takes effect after a reboot.", + "Default: Off" + }; + case HocClkConfigValue_UartLogging: + return { + "Output sysmodule logs over UART.", + "Takes effect after a reboot.", + "Default: Off" + }; default: return {}; } diff --git a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp index 6fb5a89a..c8b4afab 100644 --- a/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/hoc-clk/overlay/src/ui/gui/misc_gui.cpp @@ -806,6 +806,13 @@ class GeneralSettingsSubMenuGui : public MiscGui { addConfigButton(HocClkConfigValue_PollingIntervalMs, "Polling Interval", ValueRange(50, 1000, 50, "ms", 1), "Polling Interval", &thresholdsDisabled, {}, {}, false); + tsl::elm::CustomDrawer *loggingSpacer = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *, s32, s32, s32, s32) {}); + loggingSpacer->setBoundaries(0, 0, tsl::cfg::FramebufferWidth, 12); + this->listElement->addItem(loggingSpacer); + this->listElement->addItem(new CompactCategoryHeader("Logging")); + addConfigToggle(HocClkConfigValue_FileLogging, nullptr); + addConfigToggle(HocClkConfigValue_UartLogging, nullptr); + tsl::elm::CustomDrawer *exSetWarning = new tsl::elm::CustomDrawer([](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { renderer->drawString("\uE150 Experimental Settings are incomplete ", false, x + 20, y + 30, 18, tsl::style::color::ColorText); renderer->drawString("and may not work correctly or at all!", false, x + 20, y + 50, 18, tsl::style::color::ColorText); diff --git a/Source/hoc-clk/sysmodule/src/file/file_utils.cpp b/Source/hoc-clk/sysmodule/src/file/file_utils.cpp index 9d049d7b..5aa9cce7 100644 --- a/Source/hoc-clk/sysmodule/src/file/file_utils.cpp +++ b/Source/hoc-clk/sysmodule/src/file/file_utils.cpp @@ -30,8 +30,12 @@ #include "../hos/apm_ext.h" #include "file_utils.hpp" +#include "config.hpp" #include #include +#include +#include +#include extern "C" void __libnx_init_time(void); @@ -45,19 +49,24 @@ namespace file::utils { std::atomic_bool g_has_initialized = false; bool g_log_enabled = false; bool g_uart_enabled = false; + bool g_flags_resolved = false; - bool FlagExists(const char *path) { - FILE *file = fopen(path, "r"); - if (file) { - fclose(file); - return true; + constexpr size_t MaxPendingLines = 64; + std::vector> g_pending_lines; + + void EmitLine(u64 secs, const char *buff, int len) { + if (g_uart_enabled) { + svcOutputDebugString(buff, len); } - return false; - } - void RefreshFlags() { - g_log_enabled = FlagExists(FILE_LOG_FLAG_PATH); - g_uart_enabled = FlagExists(FILE_UART_FLAG_PATH); + if (g_log_enabled) { + FILE *file = fopen(FILE_LOG_FILE_PATH, "a"); + + if (file) { + fprintf(file, "[%luls] %s", secs, buff); + fclose(file); + } + } } void InitializeThreadFunc(void *args) { @@ -66,6 +75,24 @@ namespace file::utils { } // namespace + void InitializeLogging() { + const bool logEnabled = config::GetConfigValue(HocClkConfigValue_FileLogging); + const bool uartEnabled = config::GetConfigValue(HocClkConfigValue_UartLogging); + + std::scoped_lock lock{ g_log_mutex }; + g_log_enabled = logEnabled; + g_uart_enabled = uartEnabled; + g_flags_resolved = true; + + if (g_log_enabled || g_uart_enabled) { + for (const auto &[secs, line] : g_pending_lines) { + EmitLine(secs, line.c_str(), (int)line.size()); + } + } + g_pending_lines.clear(); + g_pending_lines.shrink_to_fit(); + } + bool IsInitialized() { return g_has_initialized; } @@ -85,7 +112,7 @@ namespace file::utils { return; } - if (!g_log_enabled && !g_uart_enabled) { + if (g_flags_resolved && !g_log_enabled && !g_uart_enabled) { return; } @@ -106,22 +133,18 @@ namespace file::utils { buff[len++] = '\n'; buff[len] = '\0'; - // Debug UART log - if (g_uart_enabled) { - svcOutputDebugString(buff, len); - } + timespec now = {}; + clock_gettime(CLOCK_REALTIME, &now); + const u64 secs = now.tv_sec - bootTimeS; - if (g_log_enabled) { - FILE *file = fopen(FILE_LOG_FILE_PATH, "a"); - - if (file) { - timespec now = {}; - clock_gettime(CLOCK_REALTIME, &now); - - fprintf(file, "[%luls] %s", now.tv_sec - bootTimeS, buff); - fclose(file); + if (!g_flags_resolved) { + if (g_pending_lines.size() < MaxPendingLines) { + g_pending_lines.emplace_back(secs, std::string(buff, len)); } + return; } + + EmitLine(secs, buff, len); } void WriteContextToCsv(const HocClkContext *context) { @@ -212,7 +235,6 @@ namespace file::utils { } if (R_SUCCEEDED(rc)) { - RefreshFlags(); g_has_initialized = true; LogLine("=== hoc-clk " TARGET_VERSION " ==="); LogLine("by m4xw, natinusala, p-sam, Souldbminer, Lightos_ and Dominatorul"); diff --git a/Source/hoc-clk/sysmodule/src/file/file_utils.hpp b/Source/hoc-clk/sysmodule/src/file/file_utils.hpp index 1ffc5c27..340a6676 100644 --- a/Source/hoc-clk/sysmodule/src/file/file_utils.hpp +++ b/Source/hoc-clk/sysmodule/src/file/file_utils.hpp @@ -36,8 +36,6 @@ #define FILE_CONFIG_DIR "/config/" CONFIG_DIR #define FILE_CONTEXT_CSV_PATH FILE_CONFIG_DIR "/context.csv" -#define FILE_LOG_FLAG_PATH FILE_CONFIG_DIR "/log.flag" -#define FILE_UART_FLAG_PATH FILE_CONFIG_DIR "/uart.flag" #define FILE_LOG_FILE_PATH FILE_CONFIG_DIR "/log.txt" #define FILE_SETTINGS_PATH FILE_CONFIG_DIR "/settings.ini" #define FILE_KIP_DIR FILE_CONFIG_DIR "/kip" @@ -53,6 +51,7 @@ namespace file::utils { bool IsLogEnabled(); bool IsUartEnabled(); void InitializeAsync(); + void InitializeLogging(); void LogLine(const char *format, ...); void WriteContextToCsv(const HocClkContext *context); diff --git a/Source/hoc-clk/sysmodule/src/main.cpp b/Source/hoc-clk/sysmodule/src/main.cpp index 2a785506..5ddac8dd 100644 --- a/Source/hoc-clk/sysmodule/src/main.cpp +++ b/Source/hoc-clk/sysmodule/src/main.cpp @@ -126,7 +126,8 @@ int main(int argc, char **argv) { return 1; } file::config::Initialize(); - file::config::Refresh(); // Get config from file + file::config::Refresh(); + file::utils::InitializeLogging(); board::Initialize(); hos::InitializeProcessManagement();