From 8f6a5eee281bb265138757db7ef6518d496d20c6 Mon Sep 17 00:00:00 2001 From: souldbminersmwc Date: Tue, 31 Mar 2026 16:50:16 -0400 Subject: [PATCH] finish rewrite (for old version) --- Source/rewrite-hoc-clk/build.sh | 24 +- Source/rewrite-hoc-clk/common/include/crc32.h | 38 +- .../common/include/display_refresh_rate.h | 126 -- .../common/include/notification.h | 25 +- Source/rewrite-hoc-clk/common/src/crc32.cpp | 56 + .../common/src/display_refresh_rate.cpp | 733 ------- .../common/src/notification.cpp | 43 + .../sysmodule/src/board/board.cpp | 26 +- .../sysmodule/src/board/board_freq.cpp | 19 +- .../sysmodule/src/board/board_freq.hpp | 2 +- .../sysmodule/src/board/board_sensor.cpp | 4 +- .../sysmodule/src/board/board_sensor.hpp | 4 +- .../sysmodule/src/board/board_volt.cpp | 10 +- .../src/board/display_refresh_rate.cpp | 736 +++++++ .../src/board/display_refresh_rate.hpp | 127 ++ .../sysmodule/src/clock_manager.cpp | 1768 +++++------------ .../sysmodule/src/clock_manager.h | 260 --- .../sysmodule/src/clock_manager.hpp | 69 + .../rewrite-hoc-clk/sysmodule/src/config.cpp | 841 ++++---- .../sysmodule/src/{config.h => config.hpp} | 44 +- .../rewrite-hoc-clk/sysmodule/src/errors.cpp | 49 +- .../sysmodule/src/{errors.h => errors.hpp} | 28 +- .../sysmodule/src/file_utils.cpp | 305 ++- .../src/{file_utils.h => file_utils.hpp} | 30 +- .../sysmodule/src/governor.cpp | 349 ++++ .../sysmodule/src/governor.hpp | 27 + .../sysmodule/src/integrations.cpp | 202 +- .../src/{integrations.h => integrations.hpp} | 65 +- .../sysmodule/src/ipc_service.cpp | 574 +++--- .../sysmodule/src/ipc_service.h | 66 - .../{process_management.h => ipc_service.hpp} | 23 +- Source/rewrite-hoc-clk/sysmodule/src/kip.cpp | 255 +++ Source/rewrite-hoc-clk/sysmodule/src/kip.h | 450 ----- Source/rewrite-hoc-clk/sysmodule/src/kip.hpp | 467 +++++ Source/rewrite-hoc-clk/sysmodule/src/main.cpp | 43 +- .../sysmodule/src/process_management.cpp | 4 +- Source/sys-clk/sysmodule/src/board.cpp | 2 +- 37 files changed, 3740 insertions(+), 4154 deletions(-) delete mode 100644 Source/rewrite-hoc-clk/common/include/display_refresh_rate.h create mode 100644 Source/rewrite-hoc-clk/common/src/crc32.cpp delete mode 100644 Source/rewrite-hoc-clk/common/src/display_refresh_rate.cpp create mode 100644 Source/rewrite-hoc-clk/common/src/notification.cpp create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/board/display_refresh_rate.cpp create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/board/display_refresh_rate.hpp delete mode 100644 Source/rewrite-hoc-clk/sysmodule/src/clock_manager.h create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/clock_manager.hpp rename Source/rewrite-hoc-clk/sysmodule/src/{config.h => config.hpp} (64%) rename Source/rewrite-hoc-clk/sysmodule/src/{errors.h => errors.hpp} (82%) rename Source/rewrite-hoc-clk/sysmodule/src/{file_utils.h => file_utils.hpp} (81%) create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/governor.cpp create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/governor.hpp rename Source/rewrite-hoc-clk/sysmodule/src/{integrations.h => integrations.hpp} (64%) delete mode 100644 Source/rewrite-hoc-clk/sysmodule/src/ipc_service.h rename Source/rewrite-hoc-clk/sysmodule/src/{process_management.h => ipc_service.hpp} (81%) create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/kip.cpp delete mode 100644 Source/rewrite-hoc-clk/sysmodule/src/kip.h create mode 100644 Source/rewrite-hoc-clk/sysmodule/src/kip.hpp diff --git a/Source/rewrite-hoc-clk/build.sh b/Source/rewrite-hoc-clk/build.sh index fbd37070..be77b3e4 100644 --- a/Source/rewrite-hoc-clk/build.sh +++ b/Source/rewrite-hoc-clk/build.sh @@ -24,19 +24,19 @@ cp -vf "$ROOT_DIR/sysmodule/out/horizon-oc.nsp" "$DIST_DIR/atmosphere/contents/$ >"$DIST_DIR/atmosphere/contents/$TITLE_ID/flags/boot2.flag" cp -vf "$ROOT_DIR/sysmodule/toolbox.json" "$DIST_DIR/atmosphere/contents/$TITLE_ID/toolbox.json" -echo "*** overlay ***" -pushd "$ROOT_DIR/overlay" -make -j$CORES -popd > /dev/null +# echo "*** overlay ***" +# pushd "$ROOT_DIR/overlay" +# make -j$CORES +# popd > /dev/null -mkdir -p "$DIST_DIR/switch/.overlays" -cp -vf "$ROOT_DIR/overlay/out/horizon-oc-overlay.ovl" "$DIST_DIR/switch/.overlays/horizon-oc-overlay.ovl" +# mkdir -p "$DIST_DIR/switch/.overlays" +# cp -vf "$ROOT_DIR/overlay/out/horizon-oc-overlay.ovl" "$DIST_DIR/switch/.overlays/horizon-oc-overlay.ovl" -echo "*** assets ***" -mkdir -p "$DIST_DIR/config/horizon-oc" -cp -vf "$ROOT_DIR/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template" -cp -vf "$ROOT_DIR/../../README.md" "$DIST_DIR/README.md" +# echo "*** assets ***" +# mkdir -p "$DIST_DIR/config/horizon-oc" +# cp -vf "$ROOT_DIR/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template" +# cp -vf "$ROOT_DIR/../../README.md" "$DIST_DIR/README.md" -echo "*** lang ***" +# echo "*** lang ***" -cp -r "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/" +# cp -r "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/" diff --git a/Source/rewrite-hoc-clk/common/include/crc32.h b/Source/rewrite-hoc-clk/common/include/crc32.h index 67539c7d..f4c5e2f5 100644 --- a/Source/rewrite-hoc-clk/common/include/crc32.h +++ b/Source/rewrite-hoc-clk/common/include/crc32.h @@ -18,39 +18,7 @@ #pragma once #include #include - -uint32_t crc32(const uint8_t *data, size_t length) { - uint32_t crc = 0xFFFFFFFF; - - for (size_t i = 0; i < length; i++) { - crc ^= data[i]; - for (int j = 0; j < 8; j++) { - crc = (crc >> 1) ^ (0xEDB88320 & -(crc & 1)); - } - } - return ~crc; +namespace crc32 { + uint32_t crc32(const uint8_t *data, size_t length); + uint32_t checksum_file(const char *filename); } - -uint32_t checksum_file(const char *filename) { - FILE *file = fopen(filename, "rb"); - if (!file) { - perror("[crc32] Error opening file"); - return 0; - } - - uint8_t buffer[1024]; - uint32_t crc = 0xFFFFFFFF; - size_t bytes_read; - - while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) { - for (size_t i = 0; i < bytes_read; i++) { - crc ^= buffer[i]; - for (int j = 0; j < 8; j++) { - crc = (crc >> 1) ^ (0xEDB88320 & -(crc & 1)); - } - } - } - - fclose(file); - return ~crc; -} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/common/include/display_refresh_rate.h b/Source/rewrite-hoc-clk/common/include/display_refresh_rate.h deleted file mode 100644 index add49b3a..00000000 --- a/Source/rewrite-hoc-clk/common/include/display_refresh_rate.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) Souldbminer, based on reasearch by MasaGratoR and Cooler3D - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#pragma once - -#include -#include -#include - -typedef struct { - uint16_t hFrontPorch; - uint8_t hSyncWidth; - uint8_t hBackPorch; - uint8_t vFrontPorch; - uint8_t vSyncWidth; - uint8_t vBackPorch; - uint8_t VIC; - uint32_t pixelClock_kHz; -} DockedTimings; - -typedef struct { - uint8_t hSyncWidth; - uint16_t hFrontPorch; - uint8_t hBackPorch; - uint8_t vSyncWidth; - uint16_t vFrontPorch; - uint8_t vBackPorch; - uint32_t pixelClock_kHz; -} HandheldTimings; - -typedef struct { - uint8_t min; - uint8_t max; -} MinMaxRefreshRate; - -typedef struct { - uint32_t unk0; - uint32_t hActive; - uint32_t vActive; - uint32_t hSyncWidth; - uint32_t vSyncWidth; - uint32_t hFrontPorch; - uint32_t vFrontPorch; - uint32_t hBackPorch; - uint32_t vBackPorch; - uint32_t pclkKHz; - uint32_t bitsPerPixel; - uint32_t vmode; - uint32_t sync; - uint32_t unk1; - uint32_t reserved; -} NvdcMode2; - -typedef struct { - NvdcMode2 modes[201]; - uint32_t num_modes; -} NvdcModeDB2; - -typedef struct { - unsigned int PLLD_DIVM: 8; - unsigned int reserved_1: 3; - unsigned int PLLD_DIVN: 8; - unsigned int reserved_2: 1; - unsigned int PLLD_DIVP: 3; - unsigned int CSI_CLK_SRC: 1; - unsigned int reserved_3: 1; - unsigned int PLL_D: 1; - unsigned int reserved_4: 1; - unsigned int PLLD_LOCK: 1; - unsigned int reserved_5: 1; - unsigned int PLLD_REF_DIS: 1; - unsigned int PLLD_ENABLE: 1; - unsigned int PLLD_BYPASS: 1; -} PLLD_BASE; - -typedef struct { - signed int PLLD_SDM_DIN: 16; - unsigned int PLLD_EN_SDM: 1; - unsigned int PLLD_LOCK_OVERRIDE: 1; - unsigned int PLLD_EN_LCKDET: 1; - unsigned int PLLD_FREQLOCK: 1; - unsigned int PLLD_IDDQ: 1; - unsigned int PLLD_ENABLE_CLK: 1; - unsigned int PLLD_KVCO: 1; - unsigned int PLLD_KCP: 2; - unsigned int PLLD_PTS: 2; - unsigned int PLLD_LDPULSE_ADJ: 3; - unsigned int reserved: 2; -} PLLD_MISC; - -typedef struct { - uint64_t clkVirtAddr; - uint64_t dsiVirtAddr; - bool isDocked; - bool isLite; - bool isRetroSUPER; - bool isPossiblySpoofedRetro; - bool dontForce60InDocked; - bool matchLowestDocked; - bool displaySync; - bool displaySyncOutOfFocus60; - bool displaySyncDocked; - bool displaySyncDockedOutOfFocus60; -} DisplayRefreshConfig; -bool DisplayRefresh_Initialize(const DisplayRefreshConfig* config); -void DisplayRefresh_SetDockedState(bool isDocked); -bool DisplayRefresh_SetRate(uint32_t new_refreshRate); -bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal); -uint8_t DisplayRefresh_GetDockedHighestAllowed(void); -void DisplayRefresh_CorrectOledGamma(uint32_t refresh_rate); -void DisplayRefresh_SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p); -void DisplayRefresh_Shutdown(void); diff --git a/Source/rewrite-hoc-clk/common/include/notification.h b/Source/rewrite-hoc-clk/common/include/notification.h index a6389b6f..3f1b1558 100644 --- a/Source/rewrite-hoc-clk/common/include/notification.h +++ b/Source/rewrite-hoc-clk/common/include/notification.h @@ -20,25 +20,6 @@ #include #include #include - -static void writeNotification(const std::string& message) { - static const char* flagPath = "sdmc:/config/ultrahand/flags/NOTIFICATIONS.flag"; - - FILE* flagFile = fopen(flagPath, "r"); - if (!flagFile) { - return; - } - fclose(flagFile); - - std::string filename = "Horizon OC -" + std::to_string(std::time(nullptr)) + ".notify"; - std::string fullPath = "sdmc:/config/ultrahand/notifications/" + filename; - - FILE* file = fopen(fullPath.c_str(), "w"); - if (file) { - fprintf(file, "{\n"); - fprintf(file, " \"text\": \"%s\",\n", message.c_str()); - fprintf(file, " \"fontSize\": 28\n"); - fprintf(file, "}\n"); - fclose(file); - } - } +namespace notification { + void writeNotification(const std::string& message); +} diff --git a/Source/rewrite-hoc-clk/common/src/crc32.cpp b/Source/rewrite-hoc-clk/common/src/crc32.cpp new file mode 100644 index 00000000..608817d8 --- /dev/null +++ b/Source/rewrite-hoc-clk/common/src/crc32.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include + +namespace crc32 { + uint32_t crc32(const uint8_t *data, size_t length) { + uint32_t crc = 0xFFFFFFFF; + + for (size_t i = 0; i < length; i++) { + crc ^= data[i]; + for (int j = 0; j < 8; j++) { + crc = (crc >> 1) ^ (0xEDB88320 & -(crc & 1)); + } + } + return ~crc; + } + + uint32_t checksum_file(const char *filename) { + FILE *file = fopen(filename, "rb"); + if (!file) { + perror("[crc32] Error opening file"); + return 0; + } + + uint8_t buffer[1024]; + uint32_t crc = 0xFFFFFFFF; + size_t bytes_read; + + while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0) { + for (size_t i = 0; i < bytes_read; i++) { + crc ^= buffer[i]; + for (int j = 0; j < 8; j++) { + crc = (crc >> 1) ^ (0xEDB88320 & -(crc & 1)); + } + } + } + + fclose(file); + return ~crc; + } +} diff --git a/Source/rewrite-hoc-clk/common/src/display_refresh_rate.cpp b/Source/rewrite-hoc-clk/common/src/display_refresh_rate.cpp deleted file mode 100644 index 65936751..00000000 --- a/Source/rewrite-hoc-clk/common/src/display_refresh_rate.cpp +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Copyright (c) Souldbminer, based on reasearch by MasaGratoR and Cooler3D - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -#include "display_refresh_rate.h" -#include -#include -#include -#include -#define DSI_CLOCK_HZ 234000000llu -#define NVDISP_GET_MODE2 0x803C021B -#define NVDISP_SET_MODE2 0x403C021C -#define NVDISP_VALIDATE_MODE2 0xC03C021D -#define NVDISP_GET_MODE_DB2 0xEF20021E -#define NVDISP_GET_PANEL_DATA 0xC01C0226 - -#define MAX_REFRESH_RATE 72 - -static DisplayRefreshConfig g_config = {0}; -static bool g_initialized = false; - -static uint8_t g_dockedHighestRefreshRate = 60; -static uint8_t g_dockedLinkRate = 10; -static bool g_wasRetroSuperTurnedOff = false; -static uint32_t g_lastVActive = 1080; -static bool g_canChangeRefreshRateDocked = false; -static uint8_t g_lastVActiveSet = 0; - -static const uint8_t g_dockedRefreshRates[] = {40, 45, 50, 55, 60, 70, 72, 75, 80, 90, 95, 100, 110, 120, 130, 140, 144, 150, 160, 165, 170, 180, 190, 200, 210, 220, 230, 240}; -// Calculate with this tool: - -// https://tomverbeure.github.io/video_timings_calculator?horiz_pixels=1920&vert_pixels=1080&refresh_rate=240&margins=false&interlaced=false&bpc=8&color_fmt=rgb444&video_opt=false&custom_hblank=80&custom_vblank=6 - -/* -typedef struct { - uint16_t hFrontPorch; - uint8_t hSyncWidth; - uint8_t hBackPorch; - uint8_t vFrontPorch; - uint8_t vSyncWidth; - uint8_t vBackPorch; - uint8_t VIC; - uint32_t pixelClock_kHz; -} DockedTimings; -*/ -static const DockedTimings g_dockedTimings1080p[] = { - {8, 32, 40, 7, 8, 6, 0, 88080}, // 40Hz - {8, 32, 40, 9, 8, 6, 0, 99270}, // 45Hz - {528, 44, 148, 4, 5, 36, 31, 148500}, // 50Hz - {8, 32, 40, 15, 8, 6, 0, 121990}, // 55Hz - {88, 44, 148, 4, 5, 36, 16, 148500}, // 60Hz - {8, 32, 40, 22, 8, 6, 0, 156240}, // 70Hz - {8, 32, 40, 23, 8, 6, 0, 160848}, // 72Hz - {8, 32, 40, 25, 8, 6, 0, 167850}, // 75Hz - {8, 32, 40, 28, 8, 6, 0, 179520}, // 80Hz - {8, 32, 40, 33, 8, 6, 0, 202860}, // 90Hz - {8, 32, 40, 36, 8, 6, 0, 214700}, // 95Hz - {528, 44, 148, 4, 5, 36, 64, 297000}, // 100Hz - {8, 32, 40, 44, 8, 6, 0, 250360}, // 110Hz - {88, 44, 148, 4, 5, 36, 63, 297000}, // 120Hz - {8, 32, 40, 55, 8, 6, 0, 298750}, //130Hz CVT-RBv2 - {8, 32, 40, 61, 8, 6, 0, 323400}, //140Hz CVT-RBv2 - {8, 32, 40, 63, 8, 6, 0, 333216}, //144Hz CVT-RBv2 - {8, 32, 40, 67, 8, 6, 0, 348300}, //150Hz CVT-RBv2 - {8, 32, 40, 72, 8, 6, 0, 373120}, //160Hz CVT-RBv2 - {8, 32, 40, 75, 8, 6, 0, 385770}, //165Hz CVT-RBv2 - {8, 32, 40, 78, 8, 6, 0, 398480}, //170Hz CVT-RBv2 - {8, 32, 40, 84, 8, 6, 0, 424080}, //180Hz CVT-RBv2 - {8, 32, 40, 90, 8, 6, 0, 449920}, //190Hz CVT-RBv2 - {8, 32, 40, 96, 8, 6, 0, 476000}, //200Hz CVT-RBv2 - {8, 32, 40, 102, 8, 6, 0, 502320}, //210Hz CVT-RBv2 - {8, 32, 40, 108, 8, 6, 0, 528880}, //220Hz CVT-RBv2 - {8, 32, 40, 114, 8, 6, 0, 555680}, //230Hz CVT-RBv2 - {8, 32, 40, 121, 8, 6, 0, 583200}, //240Hz CVT-RBv2 - // technically you can go to 476hz, but in practice, why would you? -}; - -// These timings *should* work but are untested -static const HandheldTimings g_handheldTimingsRETRO[] = { - {72, 136, 72, 1, 660, 9, 78000}, // 40Hz - {72, 136, 72, 1, 612, 9, 77982}, // 41Hz - {72, 136, 72, 1, 567, 9, 77994}, // 42Hz - {72, 136, 72, 1, 524, 9, 78002}, // 43Hz - {72, 136, 72, 1, 483, 9, 78012}, // 44Hz - {72, 136, 72, 1, 443, 9, 77985}, // 45Hz - {72, 136, 72, 1, 406, 9, 78016}, // 46Hz - {72, 136, 72, 1, 370, 9, 78020}, // 47Hz - {72, 136, 72, 1, 335, 9, 78000}, // 48Hz - {72, 136, 72, 1, 302, 9, 78008}, // 49Hz - {72, 136, 72, 1, 270, 9, 78000}, // 50Hz - {72, 136, 72, 1, 239, 9, 77979}, // 51Hz - {72, 136, 72, 1, 210, 9, 78000}, // 52Hz - {72, 136, 72, 1, 182, 9, 78016}, // 53Hz - {72, 136, 72, 1, 154, 9, 77976}, // 54Hz - {72, 136, 72, 1, 128, 9, 77990}, // 55Hz - {72, 136, 72, 1, 103, 9, 78008}, // 56Hz - {72, 136, 72, 1, 78, 9, 77976}, // 57Hz - {72, 136, 72, 1, 55, 9, 78010}, // 58Hz - {72, 136, 72, 1, 32, 9, 77998}, // 59Hz - {72, 136, 72, 1, 10, 9, 78000}, // 60Hz -}; - -static const MinMaxRefreshRate g_handheldModeRefreshRate = {40, 80}; - -static uint8_t _getDockedRefreshRateIterator(uint32_t refreshRate) { - for (size_t i = 0; i < sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]); i++) { - if (g_dockedRefreshRates[i] == refreshRate) return i; - } - return 0xFF; -} - -static void _changeOledElvssSettings(const uint32_t* offsets, const uint32_t* value, uint32_t size, uint32_t start) { - if (!g_config.dsiVirtAddr || !value || !size) return; - - volatile uint32_t* dsi = (uint32_t*)g_config.dsiVirtAddr; - - #define DSI_VIDEO_MODE_CONTROL 0x4E - #define DSI_WR_DATA 0xA - #define DSI_TRIGGER 0x13 - #define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15 - #define MIPI_DSI_DCS_LONG_WRITE 0x39 - #define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0 - #define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 - - dsi[DSI_VIDEO_MODE_CONTROL] = true; - svcSleepThread(20000000); - - dsi[DSI_WR_DATA] = MIPI_DSI_DCS_LONG_WRITE | (5 << 8); - dsi[DSI_WR_DATA] = 0x5A5A5AE2; - dsi[DSI_WR_DATA] = 0x5A; - dsi[DSI_TRIGGER] = 0; - - for (size_t i = start; i < size; i++) { - dsi[DSI_WR_DATA] = ((MIPI_DCS_PRIV_SM_SET_REG_OFFSET | ((offsets[i] % 0x100) << 8)) << 8) | MIPI_DSI_DCS_SHORT_WRITE_PARAM; - dsi[DSI_TRIGGER] = 0; - dsi[DSI_WR_DATA] = ((MIPI_DCS_PRIV_SM_SET_ELVSS | (value[i] << 8)) << 8) | MIPI_DSI_DCS_SHORT_WRITE_PARAM; - dsi[DSI_TRIGGER] = 0; - } - - dsi[DSI_WR_DATA] = MIPI_DSI_DCS_LONG_WRITE | (5 << 8); - dsi[DSI_WR_DATA] = 0xA55A5AE2; - dsi[DSI_WR_DATA] = 0xA5; - dsi[DSI_TRIGGER] = 0; - - dsi[DSI_VIDEO_MODE_CONTROL] = false; - svcSleepThread(20000000); -} -void DisplayRefresh_SetDockedState(bool isDocked) { - g_config.isDocked = isDocked; -} - -bool DisplayRefresh_Initialize(const DisplayRefreshConfig* config) { - if (!config) return false; - - g_config = *config; - g_initialized = true; - return true; -} - -void DisplayRefresh_CorrectOledGamma(uint32_t refresh_rate) { - static uint32_t last_refresh_rate = 60; - static int counter = 0; - - if (g_config.isDocked || refresh_rate < 45 || refresh_rate > 60) { - last_refresh_rate = 60; - return; - } - - if (counter != 9) { - counter++; - return; - } - counter = 0; - - uint32_t offsets[] = {0x1A, 0x24, 0x25}; - uint32_t values[] = {2, 0, 0x83}; - - if (refresh_rate == 60) { - if (last_refresh_rate == 60) return; - } else if (refresh_rate == 45) { - if (last_refresh_rate == 45) return; - uint32_t vals[] = {4, 1, 0}; - memcpy(values, vals, sizeof(vals)); - } else if (refresh_rate == 50) { - if (last_refresh_rate == 50) return; - uint32_t vals[] = {3, 1, 0}; - memcpy(values, vals, sizeof(vals)); - } else if (refresh_rate == 55) { - if (last_refresh_rate == 55) return; - uint32_t vals[] = {3, 1, 0}; - memcpy(values, vals, sizeof(vals)); - } else { - return; - } - - for (int i = 0; i < 5; i++) { - _changeOledElvssSettings(offsets, values, 3, 0); - } - last_refresh_rate = refresh_rate; -} - -void DisplayRefresh_SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p) { - // Function kept for API compatibility but does nothing - (void)refreshRates; - (void)is720p; -} - -uint8_t DisplayRefresh_GetDockedHighestAllowed(void) { - return (g_dockedHighestRefreshRate > 60) ? g_dockedHighestRefreshRate : 60; -} - -static void _getDockedHighestRefreshRate(uint32_t fd_in) { - uint8_t highestRefreshRate = 60; - uint32_t fd = fd_in; - - if(!fd) nvOpen(&fd, "/dev/nvdisp-disp1"); - NvdcModeDB2 db2 = {0}; - int rc = nvIoctl(fd, NVDISP_GET_MODE_DB2, &db2); - - if (rc == 0) { - for (size_t i = 0; i < db2.num_modes; i++) { - if (db2.modes[i].hActive < 1920 || db2.modes[i].vActive < 1080) - continue; - - uint32_t v_total = db2.modes[i].vActive + db2.modes[i].vSyncWidth + db2.modes[i].vFrontPorch + db2.modes[i].vBackPorch; - uint32_t h_total = db2.modes[i].hActive + db2.modes[i].hSyncWidth + db2.modes[i].hFrontPorch + db2.modes[i].hBackPorch; - double refreshRate = round((double)(db2.modes[i].pclkKHz * 1000) / (double)(v_total * h_total)); - - if (highestRefreshRate < (uint8_t)refreshRate) - highestRefreshRate = (uint8_t)refreshRate; - } - } else { - g_dockedHighestRefreshRate = 60; - } - - const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]); - if (highestRefreshRate > g_dockedRefreshRates[numRates - 1]) - highestRefreshRate = g_dockedRefreshRates[numRates - 1]; - - NvdcMode2 display_b = {0}; - rc = nvIoctl(fd, NVDISP_GET_MODE2, &display_b); - - struct dpaux_read_0x100 { - uint32_t cmd; - uint32_t addr; - uint32_t size; - struct { - unsigned char link_rate; - unsigned int lane_count: 5; - unsigned int unk1: 2; - unsigned int isFramingEnhanced: 1; - unsigned char downspread; - unsigned char training_pattern; - unsigned char lane_pattern[4]; - unsigned char unk2[8]; - } set; - } dpaux = {6, 0x100, 0x10}; - - rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux); - if (rc == 0) { - g_dockedLinkRate = dpaux.set.link_rate; - // if (display_b.hActive == 1920 && display_b.vActive == 1080 && highestRefreshRate > 75 && dpaux.set.link_rate < 20 && ) - // highestRefreshRate = 75; - } - - if (!fd_in) nvClose(fd); - g_dockedHighestRefreshRate = highestRefreshRate; -} - -static bool _setPLLDHandheldRefreshRate(uint32_t new_refreshRate) { - if (!g_config.clkVirtAddr) return false; - - uint32_t fd = 0; - if (nvOpen(&fd, "/dev/nvdisp-disp0")) { - return false; - } - - struct dpaux_read { - uint32_t cmd; - uint32_t addr; - uint32_t size; - struct { - unsigned int rev_minor : 4; - unsigned int rev_major : 4; - unsigned char link_rate; - unsigned int lane_count: 5; - unsigned int unk1: 2; - unsigned int isFramingEnhanced: 1; - unsigned char unk2[13]; - } DPCD; - } dpaux = {6, 0, 0x10}; - - int rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux); - nvClose(fd); - if (rc != 0x75c) return false; - - PLLD_BASE base = {0}; - PLLD_MISC misc = {0}; - memcpy(&base, (void*)(g_config.clkVirtAddr + 0xD0), 4); - memcpy(&misc, (void*)(g_config.clkVirtAddr + 0xDC), 4); - - uint32_t value = ((base.PLLD_DIVN / base.PLLD_DIVM) * 10) / 4; - if (value == 0 || value == 80) return false; - - if (new_refreshRate > g_handheldModeRefreshRate.max) { - new_refreshRate = g_handheldModeRefreshRate.max; - } else if (new_refreshRate < g_handheldModeRefreshRate.min) { - bool skip = false; - for (size_t i = 2; i <= 4; i++) { - if (new_refreshRate * i == 60) { - skip = true; - new_refreshRate = 60; - break; - } - } - if (!skip) { - for (size_t i = 2; i <= 4; i++) { - if (((new_refreshRate * i) >= g_handheldModeRefreshRate.min) && ((new_refreshRate * i) <= g_handheldModeRefreshRate.max)) { - skip = true; - new_refreshRate *= i; - break; - } - } - } - if (!skip) new_refreshRate = 60; - } - - uint32_t pixelClock = (9375 * ((4096 * ((2 * base.PLLD_DIVN) + 1)) + misc.PLLD_SDM_DIN)) / (8 * base.PLLD_DIVM); - uint16_t refreshRateNow = pixelClock / (DSI_CLOCK_HZ / 60); - - if (refreshRateNow == new_refreshRate) { - return true; - } - - uint8_t base_refreshRate = new_refreshRate - (new_refreshRate % 5); - base.PLLD_DIVN = (4 * base_refreshRate) / 10; - base.PLLD_DIVM = 1; - - uint64_t expected_pixel_clock = (DSI_CLOCK_HZ * new_refreshRate) / 60; - misc.PLLD_SDM_DIN = ((8 * base.PLLD_DIVM * expected_pixel_clock) / 9375) - (4096 * ((2 * base.PLLD_DIVN) + 1)); - - memcpy((void*)(g_config.clkVirtAddr + 0xD0), &base, 4); - memcpy((void*)(g_config.clkVirtAddr + 0xDC), &misc, 4); - return true; -} - -static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) { - if (g_config.isLite || !g_canChangeRefreshRateDocked) - return false; - - uint32_t fd = 0; - if (nvOpen(&fd, "/dev/nvdisp-disp1")) { - return false; - } - - NvdcMode2 display_b = {0}; - int rc = nvIoctl(fd, NVDISP_GET_MODE2, &display_b); - if (rc != 0) { - nvClose(fd); - return false; - } - - if (!display_b.pclkKHz) { - nvClose(fd); - return false; - } - - if (!((display_b.vActive == 480 && display_b.hActive == 720) || - (display_b.vActive == 720 && display_b.hActive == 1280) || - (display_b.vActive == 1080 && display_b.hActive == 1920))) { - nvClose(fd); - return false; - } - - if (display_b.vActive != g_lastVActiveSet) { - g_lastVActiveSet = display_b.vActive; - } - - uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch; - uint32_t v_total = display_b.vActive + display_b.vFrontPorch + display_b.vSyncWidth + display_b.vBackPorch; - uint32_t refreshRateNow = ((display_b.pclkKHz) * 1000 + 999) / (h_total * v_total); - - int8_t itr = -1; - const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]); - - // Find closest matching refresh rate - if ((new_refreshRate <= 60) && ((60 % new_refreshRate) == 0)) { - itr = _getDockedRefreshRateIterator(60); - } - - if (itr == -1) { - for (size_t i = 0; i < numRates; i++) { - uint8_t val = g_dockedRefreshRates[i]; - if ((val % new_refreshRate) == 0) { - itr = i; - break; - } - } - } - - if (itr == -1) { - if (!g_config.matchLowestDocked) { - itr = _getDockedRefreshRateIterator(60); - } else { - for (size_t i = 0; i < numRates; i++) { - if (new_refreshRate < g_dockedRefreshRates[i]) { - itr = i; - break; - } - } - } - } - - if (itr == -1) itr = _getDockedRefreshRateIterator(60); - - // Clamp to highest allowed refresh rate - if (g_dockedRefreshRates[itr] > g_dockedHighestRefreshRate) { - for (int8_t i = itr; i >= 0; i--) { - if (g_dockedRefreshRates[i] <= g_dockedHighestRefreshRate) { - itr = i; - break; - } - } - } - - if (refreshRateNow == g_dockedRefreshRates[itr]) { - nvClose(fd); - return true; - } - - if (itr >= 0 && itr < (int8_t)numRates) { - if (display_b.vActive == 720) { - uint32_t clock = ((h_total * v_total) * g_dockedRefreshRates[itr]) / 1000; - display_b.pclkKHz = clock; - } else { - display_b.hFrontPorch = g_dockedTimings1080p[itr].hFrontPorch; - display_b.hSyncWidth = g_dockedTimings1080p[itr].hSyncWidth; - display_b.hBackPorch = g_dockedTimings1080p[itr].hBackPorch; - display_b.vFrontPorch = g_dockedTimings1080p[itr].vFrontPorch; - display_b.vSyncWidth = g_dockedTimings1080p[itr].vSyncWidth; - display_b.vBackPorch = g_dockedTimings1080p[itr].vBackPorch; - display_b.pclkKHz = g_dockedTimings1080p[itr].pixelClock_kHz; - display_b.vmode = (g_dockedRefreshRates[itr] >= 100 ? 0x400000 : 0x200000); - display_b.unk1 = (g_dockedRefreshRates[itr] >= 100 ? 0x80 : 0); - display_b.sync = 3; - display_b.bitsPerPixel = 24; - } - - rc = nvIoctl(fd, NVDISP_VALIDATE_MODE2, &display_b); - if (rc == 0) { - rc = nvIoctl(fd, NVDISP_SET_MODE2, &display_b); - } - } - - nvClose(fd); - return true; -} - -static bool _setNvDispHandheldRefreshRate(uint32_t new_refreshRate) { - if (!g_config.isRetroSUPER) return false; - - if (!g_config.displaySync) { - g_wasRetroSuperTurnedOff = false; - } else if (g_wasRetroSuperTurnedOff) { - svcSleepThread(2000000000); - g_wasRetroSuperTurnedOff = false; - } - - svcSleepThread(1000000000); - - uint32_t fd = 0; - if (nvOpen(&fd, "/dev/nvdisp-disp0")) { - return false; - } - - NvdcMode2 display_b = {0}; - int rc = nvIoctl(fd, NVDISP_GET_MODE2, &display_b); - if (rc != 0) { - nvClose(fd); - return false; - } - - if (!display_b.pclkKHz) { - nvClose(fd); - return false; - } - - if ((display_b.vActive == 1280 && display_b.hActive == 720) == false) { - nvClose(fd); - return false; - } - - uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch; - uint32_t v_total = display_b.vActive + display_b.vFrontPorch + display_b.vSyncWidth + display_b.vBackPorch; - uint32_t refreshRateNow = ((display_b.pclkKHz) * 1000 + 999) / (h_total * v_total); - - if (new_refreshRate > g_handheldModeRefreshRate.max) { - new_refreshRate = g_handheldModeRefreshRate.max; - } else if (new_refreshRate < g_handheldModeRefreshRate.min) { - bool skip = false; - for (size_t i = 2; i <= 4; i++) { - if (new_refreshRate * i == 60) { - skip = true; - new_refreshRate = 60; - break; - } - } - if (!skip) { - for (size_t i = 2; i <= (sizeof(g_handheldTimingsRETRO) / sizeof(g_handheldTimingsRETRO[0])); i++) { - if (((new_refreshRate * i) >= g_handheldModeRefreshRate.min) && ((new_refreshRate * i) <= g_handheldModeRefreshRate.max)) { - skip = true; - new_refreshRate *= i; - break; - } - } - } - if (!skip) new_refreshRate = 60; - } - - if (new_refreshRate == refreshRateNow) { - nvClose(fd); - return true; - } - - uint32_t itr = (new_refreshRate - 40) / 5; - display_b.hFrontPorch = g_handheldTimingsRETRO[itr].hFrontPorch; - display_b.hSyncWidth = g_handheldTimingsRETRO[itr].hSyncWidth; - display_b.hBackPorch = g_handheldTimingsRETRO[itr].hBackPorch; - display_b.vFrontPorch = g_handheldTimingsRETRO[itr].vFrontPorch; - display_b.vSyncWidth = g_handheldTimingsRETRO[itr].vSyncWidth; - display_b.vBackPorch = g_handheldTimingsRETRO[itr].vBackPorch; - display_b.pclkKHz = g_handheldTimingsRETRO[itr].pixelClock_kHz; - - rc = nvIoctl(fd, NVDISP_VALIDATE_MODE2, &display_b); - if (rc == 0) { - for (size_t i = 0; i < 5; i++) { - nvIoctl(fd, NVDISP_SET_MODE2, &display_b); - } - } - - nvClose(fd); - return true; -} - -bool DisplayRefresh_SetRate(uint32_t new_refreshRate) { - if (!new_refreshRate || !g_initialized) return false; - - uint32_t fd = 0; - - if (g_config.isRetroSUPER && !g_config.isDocked) { - return _setNvDispHandheldRefreshRate(new_refreshRate); - } - - else if ((!g_config.isRetroSUPER && g_config.isLite) || R_FAILED(nvOpen(&fd, "/dev/nvdisp-disp1"))) { - if (_setPLLDHandheldRefreshRate(new_refreshRate) == false) - return false; - } - else { - struct dpaux_read { - uint32_t cmd; - uint32_t addr; - uint32_t size; - struct { - unsigned int rev_minor : 4; - unsigned int rev_major : 4; - unsigned char link_rate; - unsigned int lane_count: 5; - unsigned int unk1: 2; - unsigned int isFramingEnhanced: 1; - unsigned char unk2[13]; - } DPCD; - } dpaux = {6, 0, 0x10}; - - int rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux); - nvClose(fd); - - if (rc != 0) { - if (!g_config.isRetroSUPER) { - return _setPLLDHandheldRefreshRate(new_refreshRate); - } else { - return _setNvDispHandheldRefreshRate(new_refreshRate); - } - } else { - if(g_config.isDocked) - return _setNvDispDockedRefreshRate(new_refreshRate); - else - return true; - } - } - return false; -} - -bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal) { - if (!out_refreshRate || !g_initialized || !g_config.clkVirtAddr) return false; - static uint32_t value = 60; - - if (g_config.isRetroSUPER && !g_config.isDocked) { - uint32_t fd = 0; - PLLD_BASE temp = {0}; - PLLD_MISC misc = {0}; - memcpy(&temp, (void*)(g_config.clkVirtAddr + 0xD0), 4); - memcpy(&misc, (void*)(g_config.clkVirtAddr + 0xDC), 4); - - value = ((temp.PLLD_DIVN / temp.PLLD_DIVM) * 10) / 4; - - if (value != 0 && value != 80) { - if (!nvOpen(&fd, "/dev/nvdisp-disp0")) { - NvdcMode2 display_b = {0}; - if (nvIoctl(fd, NVDISP_GET_MODE2, &display_b) == 0) { - uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch; - uint32_t v_total = display_b.vActive + display_b.vFrontPorch + display_b.vSyncWidth + display_b.vBackPorch; - uint32_t pixelClock = display_b.pclkKHz * 1000 + 999; - value = pixelClock / (h_total * v_total); - } - nvClose(fd); - } else { - return false; - } - } else { - g_wasRetroSuperTurnedOff = true; - } - } - else if ((!g_config.isPossiblySpoofedRetro) || (g_config.isPossiblySpoofedRetro && !g_config.isRetroSUPER)) { - PLLD_BASE temp = {0}; - PLLD_MISC misc = {0}; - memcpy(&temp, (void*)(g_config.clkVirtAddr + 0xD0), 4); - memcpy(&misc, (void*)(g_config.clkVirtAddr + 0xDC), 4); - - value = ((temp.PLLD_DIVN / temp.PLLD_DIVM) * 10) / 4; - - if (value == 0 || value == 80) { - // Docked mode - if (g_config.isLite) return false; - - g_config.isDocked = true; - - if (!g_canChangeRefreshRateDocked) { - uint32_t fd = 0; - if (!nvOpen(&fd, "/dev/nvdisp-disp1")) { - struct dpaux_read_0x100 { - uint32_t cmd; - uint32_t addr; - uint32_t size; - struct { - unsigned char link_rate; - unsigned int lane_count: 5; - unsigned int unk1: 2; - unsigned int isFramingEnhanced: 1; - unsigned char downspread; - unsigned char training_pattern; - unsigned char lane_pattern[4]; - unsigned char unk2[8]; - } set; - } dpaux = {6, 0x100, 0x10}; - - int rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux); - nvClose(fd); - - if (rc == 0) { - _getDockedHighestRefreshRate(0); - g_canChangeRefreshRateDocked = true; - } else { - svcSleepThread(1000000000); - return false; - } - } else { - return false; - } - } - if(internal) { - *out_refreshRate = value; - return true; - } - uint32_t fd = 0; - if (!nvOpen(&fd, "/dev/nvdisp-disp1")) { - NvdcMode2 display_b = {0}; - if (nvIoctl(fd, NVDISP_GET_MODE2, &display_b) == 0) { - if (!display_b.pclkKHz) { - nvClose(fd); - return false; - } - - if (g_lastVActive != display_b.vActive) { - g_lastVActive = display_b.vActive; - _getDockedHighestRefreshRate(fd); - } - - uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch; - uint32_t v_total = display_b.vActive + display_b.vFrontPorch + display_b.vSyncWidth + display_b.vBackPorch; - uint32_t pixelClock = display_b.pclkKHz * 1000 + 999; - value = pixelClock / (h_total * v_total); - } else { - value = 60; - } - nvClose(fd); - } else { - value = 60; - } - } - else if (!g_config.isRetroSUPER) { - // Handheld mode - g_config.isDocked = false; - g_canChangeRefreshRateDocked = false; - - uint32_t pixelClock = (9375 * ((4096 * ((2 * temp.PLLD_DIVN) + 1)) + misc.PLLD_SDM_DIN)) / (8 * temp.PLLD_DIVM); - value = pixelClock / (DSI_CLOCK_HZ / 60); - } - else { - return false; - } - } - - *out_refreshRate = value; - return true; -} - -void DisplayRefresh_Shutdown(void) { - g_initialized = false; - memset(&g_config, 0, sizeof(g_config)); -} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/common/src/notification.cpp b/Source/rewrite-hoc-clk/common/src/notification.cpp new file mode 100644 index 00000000..76f2f341 --- /dev/null +++ b/Source/rewrite-hoc-clk/common/src/notification.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) ppkantorski (bord2death) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +#include "notification.h" + +namespace notification { + void writeNotification(const std::string& message) { + static const char* flagPath = "sdmc:/config/ultrahand/flags/NOTIFICATIONS.flag"; + + FILE* flagFile = fopen(flagPath, "r"); + if (!flagFile) { + return; + } + fclose(flagFile); + + std::string filename = "Horizon OC -" + std::to_string(std::time(nullptr)) + ".notify"; + std::string fullPath = "sdmc:/config/ultrahand/notifications/" + filename; + + FILE* file = fopen(fullPath.c_str(), "w"); + if (file) { + fprintf(file, "{\n"); + fprintf(file, " \"text\": \"%s\",\n", message.c_str()); + fprintf(file, " \"fontSize\": 28\n"); + fprintf(file, "}\n"); + fclose(file); + } + } +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/board.cpp b/Source/rewrite-hoc-clk/sysmodule/src/board/board.cpp index 3dbd1a97..350c5abc 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/board/board.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/board.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include "display_refresh_rate.hpp" #include #include @@ -141,18 +141,16 @@ namespace board { StartMiscThread(pwmCheck, &iCon); - if (gConsoleType != HorizonOCConsoleType_Hoag) { - u64 clkVirtAddr, dsiVirtAddr, outsize; + u64 clkVirtAddr, dsiVirtAddr, outsize; - rc = svcQueryMemoryMapping(&clkVirtAddr, &outsize, 0x60006000, 0x1000); - ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (clk)"); + rc = svcQueryMemoryMapping(&clkVirtAddr, &outsize, 0x60006000, 0x1000); + ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (clk)"); - rc = svcQueryMemoryMapping(&dsiVirtAddr, &outsize, 0x54300000, 0x40000); - ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (dsi)"); + rc = svcQueryMemoryMapping(&dsiVirtAddr, &outsize, 0x54300000, 0x40000); + ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (dsi)"); - DisplayRefreshConfig cfg = {.clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr}; - DisplayRefresh_Initialize(&cfg); - } + display::DisplayRefreshConfig cfg = {.clkVirtAddr = clkVirtAddr, .dsiVirtAddr = dsiVirtAddr}; + display::Initialize(&cfg); CacheDfllData(); } @@ -185,9 +183,7 @@ namespace board { pmdmntExit(); nvExit(); - if (gConsoleType != HorizonOCConsoleType_Hoag) { - DisplayRefresh_Shutdown(); - } + display::Shutdown(); } SysClkSocType GetSocType() { @@ -209,7 +205,7 @@ namespace board { svcCallSecureMonitor(&args); if (args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed - writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!"); + notification::writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!"); return false; } @@ -219,7 +215,7 @@ namespace board { /* TODO: Put this into a different file. */ void SetDisplayRefreshDockedState(bool docked) { if (GetConsoleType() != HorizonOCConsoleType_Hoag) { - DisplayRefresh_SetDockedState(docked); + display::SetDockedState(docked); } } diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/board_freq.cpp b/Source/rewrite-hoc-clk/sysmodule/src/board/board_freq.cpp index d56c81fd..1e7ac409 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/board/board_freq.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/board_freq.cpp @@ -27,10 +27,10 @@ #include #include #include -#include +#include "display_refresh_rate.hpp" #include "board.hpp" #include "board_name.hpp" -#include "../errors.h" +#include "../errors.hpp" namespace board { @@ -70,8 +70,8 @@ namespace board { bool usesGovenor = module > SysClkModule_MEM; - if (module == HorizonOCModule_Display && HorizonOCConsoleType() != HorizonOCConsoleType_Hoag) { - DisplayRefresh_SetRate(hz); + if (module == HorizonOCModule_Display) { + display::SetRate(hz); return; } @@ -103,11 +103,8 @@ namespace board { } u32 GetDisplayRate(u32 hz) { - if (GetConsoleType() != HorizonOCConsoleType_Hoag) { - DisplayRefresh_GetRate(&hz, false); - return hz; - } - return 60; + display::GetRate(&hz, false); + return hz; } u32 GetHz(SysClkModule module) { @@ -186,7 +183,7 @@ namespace board { u32 GetHighestDockedDisplayRate() { if (GetConsoleType() != HorizonOCConsoleType_Hoag) { - return DisplayRefresh_GetDockedHighestAllowed(); + return display::GetDockedHighestAllowed(); } return 60; @@ -226,7 +223,7 @@ namespace board { void ResetToStockDisplay() { if (GetConsoleType() != HorizonOCConsoleType_Hoag) { - DisplayRefresh_SetRate(60); + display::SetRate(60); } } diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/board_freq.hpp b/Source/rewrite-hoc-clk/sysmodule/src/board/board_freq.hpp index 5ed8b624..6d47456b 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/board/board_freq.hpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/board_freq.hpp @@ -28,7 +28,7 @@ #include #include #include -#include "../errors.h" +#include "../errors.hpp" namespace board { diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/board_sensor.cpp b/Source/rewrite-hoc-clk/sysmodule/src/board/board_sensor.cpp index df5ad87b..5fe3a211 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/board/board_sensor.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/board_sensor.cpp @@ -34,7 +34,7 @@ namespace board { - u32 GetTemperatureMilli(SysClkThermalSensor sensor) { + s32 GetTemperatureMilli(SysClkThermalSensor sensor) { s32 millis = 0; BatteryChargeInfo info; @@ -60,7 +60,7 @@ namespace board { return std::max(0, millis); } - u32 GetPowerMw(SysClkPowerSensor sensor) { + s32 GetPowerMw(SysClkPowerSensor sensor) { switch (sensor) { case SysClkPowerSensor_Now: return max17050PowerNow(); diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/board_sensor.hpp b/Source/rewrite-hoc-clk/sysmodule/src/board/board_sensor.hpp index ec95e1ac..36c5ba46 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/board/board_sensor.hpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/board_sensor.hpp @@ -30,7 +30,7 @@ namespace board { - u32 GetTemperatureMilli(SysClkThermalSensor sensor); - u32 GetPowerMw(SysClkPowerSensor sensor); + s32 GetTemperatureMilli(SysClkThermalSensor sensor); + s32 GetPowerMw(SysClkPowerSensor sensor); } diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/board_volt.cpp b/Source/rewrite-hoc-clk/sysmodule/src/board/board_volt.cpp index e9be3112..3408b1fb 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/board/board_volt.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/board_volt.cpp @@ -34,7 +34,7 @@ #include "board.hpp" #include "board_freq.hpp" #include "board_volt.hpp" -#include "../file_utils.h" +#include "../file_utils.hpp" namespace board { @@ -336,7 +336,7 @@ namespace board { Handle handle = GetPcvHandle(); if (handle == INVALID_HANDLE) { - FileUtils::LogLine("[dvfs] Invalid handle!"); + fileUtils::LogLine("[dvfs] Invalid handle!"); return; } @@ -355,7 +355,7 @@ namespace board { if (R_FAILED(resultProcessMemory) || !address) { svcCloseHandle(handle); - FileUtils::LogLine("[dvfs] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory)); + fileUtils::LogLine("[dvfs] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory)); handle = INVALID_HANDLE; return; } @@ -415,7 +415,7 @@ namespace board { Handle handle = GetPcvHandle(); if (handle == INVALID_HANDLE) { - FileUtils::LogLine("Invalid handle!"); + fileUtils::LogLine("Invalid handle!"); return; } @@ -426,7 +426,7 @@ namespace board { } svcCloseHandle(handle); - FileUtils::LogLine("[dvfs] voltage set to %u mV", vmin); + fileUtils::LogLine("[dvfs] voltage set to %u mV", vmin); } u32 GetMinimumGpuVmin(u32 freqMhz, u32 bracket) { diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/display_refresh_rate.cpp b/Source/rewrite-hoc-clk/sysmodule/src/board/display_refresh_rate.cpp new file mode 100644 index 00000000..6aa4a9c6 --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/display_refresh_rate.cpp @@ -0,0 +1,736 @@ +/* + * Copyright (c) Souldbminer, based on reasearch by MasaGratoR and Cooler3D + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#include "display_refresh_rate.hpp" +#include +#include +#include +#include + +namespace display { + #define DSI_CLOCK_HZ 234000000llu + #define NVDISP_GET_MODE2 0x803C021B + #define NVDISP_SET_MODE2 0x403C021C + #define NVDISP_VALIDATE_MODE2 0xC03C021D + #define NVDISP_GET_MODE_DB2 0xEF20021E + #define NVDISP_GET_PANEL_DATA 0xC01C0226 + + #define MAX_REFRESH_RATE 72 + + static DisplayRefreshConfig g_config = {0}; + static bool g_initialized = false; + + static uint8_t g_dockedHighestRefreshRate = 60; + static uint8_t g_dockedLinkRate = 10; + static bool g_wasRetroSuperTurnedOff = false; + static uint32_t g_lastVActive = 1080; + static bool g_canChangeRefreshRateDocked = false; + static uint8_t g_lastVActiveSet = 0; + + static const uint8_t g_dockedRefreshRates[] = {40, 45, 50, 55, 60, 70, 72, 75, 80, 90, 95, 100, 110, 120, 130, 140, 144, 150, 160, 165, 170, 180, 190, 200, 210, 220, 230, 240}; + // Calculate with this tool: + + // https://tomverbeure.github.io/video_timings_calculator?horiz_pixels=1920&vert_pixels=1080&refresh_rate=240&margins=false&interlaced=false&bpc=8&color_fmt=rgb444&video_opt=false&custom_hblank=80&custom_vblank=6 + + /* + typedef struct { + uint16_t hFrontPorch; + uint8_t hSyncWidth; + uint8_t hBackPorch; + uint8_t vFrontPorch; + uint8_t vSyncWidth; + uint8_t vBackPorch; + uint8_t VIC; + uint32_t pixelClock_kHz; + } DockedTimings; + */ + static const DockedTimings g_dockedTimings1080p[] = { + {8, 32, 40, 7, 8, 6, 0, 88080}, // 40Hz + {8, 32, 40, 9, 8, 6, 0, 99270}, // 45Hz + {528, 44, 148, 4, 5, 36, 31, 148500}, // 50Hz + {8, 32, 40, 15, 8, 6, 0, 121990}, // 55Hz + {88, 44, 148, 4, 5, 36, 16, 148500}, // 60Hz + {8, 32, 40, 22, 8, 6, 0, 156240}, // 70Hz + {8, 32, 40, 23, 8, 6, 0, 160848}, // 72Hz + {8, 32, 40, 25, 8, 6, 0, 167850}, // 75Hz + {8, 32, 40, 28, 8, 6, 0, 179520}, // 80Hz + {8, 32, 40, 33, 8, 6, 0, 202860}, // 90Hz + {8, 32, 40, 36, 8, 6, 0, 214700}, // 95Hz + {528, 44, 148, 4, 5, 36, 64, 297000}, // 100Hz + {8, 32, 40, 44, 8, 6, 0, 250360}, // 110Hz + {88, 44, 148, 4, 5, 36, 63, 297000}, // 120Hz + {8, 32, 40, 55, 8, 6, 0, 298750}, //130Hz CVT-RBv2 + {8, 32, 40, 61, 8, 6, 0, 323400}, //140Hz CVT-RBv2 + {8, 32, 40, 63, 8, 6, 0, 333216}, //144Hz CVT-RBv2 + {8, 32, 40, 67, 8, 6, 0, 348300}, //150Hz CVT-RBv2 + {8, 32, 40, 72, 8, 6, 0, 373120}, //160Hz CVT-RBv2 + {8, 32, 40, 75, 8, 6, 0, 385770}, //165Hz CVT-RBv2 + {8, 32, 40, 78, 8, 6, 0, 398480}, //170Hz CVT-RBv2 + {8, 32, 40, 84, 8, 6, 0, 424080}, //180Hz CVT-RBv2 + {8, 32, 40, 90, 8, 6, 0, 449920}, //190Hz CVT-RBv2 + {8, 32, 40, 96, 8, 6, 0, 476000}, //200Hz CVT-RBv2 + {8, 32, 40, 102, 8, 6, 0, 502320}, //210Hz CVT-RBv2 + {8, 32, 40, 108, 8, 6, 0, 528880}, //220Hz CVT-RBv2 + {8, 32, 40, 114, 8, 6, 0, 555680}, //230Hz CVT-RBv2 + {8, 32, 40, 121, 8, 6, 0, 583200}, //240Hz CVT-RBv2 + // technically you can go to 476hz, but in practice, why would you? + }; + + // These timings *should* work but are untested + static const HandheldTimings g_handheldTimingsRETRO[] = { + {72, 136, 72, 1, 660, 9, 78000}, // 40Hz + {72, 136, 72, 1, 612, 9, 77982}, // 41Hz + {72, 136, 72, 1, 567, 9, 77994}, // 42Hz + {72, 136, 72, 1, 524, 9, 78002}, // 43Hz + {72, 136, 72, 1, 483, 9, 78012}, // 44Hz + {72, 136, 72, 1, 443, 9, 77985}, // 45Hz + {72, 136, 72, 1, 406, 9, 78016}, // 46Hz + {72, 136, 72, 1, 370, 9, 78020}, // 47Hz + {72, 136, 72, 1, 335, 9, 78000}, // 48Hz + {72, 136, 72, 1, 302, 9, 78008}, // 49Hz + {72, 136, 72, 1, 270, 9, 78000}, // 50Hz + {72, 136, 72, 1, 239, 9, 77979}, // 51Hz + {72, 136, 72, 1, 210, 9, 78000}, // 52Hz + {72, 136, 72, 1, 182, 9, 78016}, // 53Hz + {72, 136, 72, 1, 154, 9, 77976}, // 54Hz + {72, 136, 72, 1, 128, 9, 77990}, // 55Hz + {72, 136, 72, 1, 103, 9, 78008}, // 56Hz + {72, 136, 72, 1, 78, 9, 77976}, // 57Hz + {72, 136, 72, 1, 55, 9, 78010}, // 58Hz + {72, 136, 72, 1, 32, 9, 77998}, // 59Hz + {72, 136, 72, 1, 10, 9, 78000}, // 60Hz + }; + + static const MinMaxRefreshRate g_handheldModeRefreshRate = {40, 80}; + + static uint8_t _getDockedRefreshRateIterator(uint32_t refreshRate) { + for (size_t i = 0; i < sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]); i++) { + if (g_dockedRefreshRates[i] == refreshRate) return i; + } + return 0xFF; + } + + static void _changeOledElvssSettings(const uint32_t* offsets, const uint32_t* value, uint32_t size, uint32_t start) { + if (!g_config.dsiVirtAddr || !value || !size) return; + + volatile uint32_t* dsi = (uint32_t*)g_config.dsiVirtAddr; + + #define DSI_VIDEO_MODE_CONTROL 0x4E + #define DSI_WR_DATA 0xA + #define DSI_TRIGGER 0x13 + #define MIPI_DSI_DCS_SHORT_WRITE_PARAM 0x15 + #define MIPI_DSI_DCS_LONG_WRITE 0x39 + #define MIPI_DCS_PRIV_SM_SET_REG_OFFSET 0xB0 + #define MIPI_DCS_PRIV_SM_SET_ELVSS 0xB1 + + dsi[DSI_VIDEO_MODE_CONTROL] = true; + svcSleepThread(20000000); + + dsi[DSI_WR_DATA] = MIPI_DSI_DCS_LONG_WRITE | (5 << 8); + dsi[DSI_WR_DATA] = 0x5A5A5AE2; + dsi[DSI_WR_DATA] = 0x5A; + dsi[DSI_TRIGGER] = 0; + + for (size_t i = start; i < size; i++) { + dsi[DSI_WR_DATA] = ((MIPI_DCS_PRIV_SM_SET_REG_OFFSET | ((offsets[i] % 0x100) << 8)) << 8) | MIPI_DSI_DCS_SHORT_WRITE_PARAM; + dsi[DSI_TRIGGER] = 0; + dsi[DSI_WR_DATA] = ((MIPI_DCS_PRIV_SM_SET_ELVSS | (value[i] << 8)) << 8) | MIPI_DSI_DCS_SHORT_WRITE_PARAM; + dsi[DSI_TRIGGER] = 0; + } + + dsi[DSI_WR_DATA] = MIPI_DSI_DCS_LONG_WRITE | (5 << 8); + dsi[DSI_WR_DATA] = 0xA55A5AE2; + dsi[DSI_WR_DATA] = 0xA5; + dsi[DSI_TRIGGER] = 0; + + dsi[DSI_VIDEO_MODE_CONTROL] = false; + svcSleepThread(20000000); + } + void SetDockedState(bool isDocked) { + g_config.isDocked = isDocked; + } + + bool Initialize(const DisplayRefreshConfig* config) { + if (!config) return false; + + g_config = *config; + g_initialized = true; + return true; + } + + void CorrectOledGamma(uint32_t refresh_rate) { + static uint32_t last_refresh_rate = 60; + static int counter = 0; + + if (g_config.isDocked || refresh_rate < 45 || refresh_rate > 60) { + last_refresh_rate = 60; + return; + } + + if (counter != 9) { + counter++; + return; + } + counter = 0; + + uint32_t offsets[] = {0x1A, 0x24, 0x25}; + uint32_t values[] = {2, 0, 0x83}; + + if (refresh_rate == 60) { + if (last_refresh_rate == 60) return; + } else if (refresh_rate == 45) { + if (last_refresh_rate == 45) return; + uint32_t vals[] = {4, 1, 0}; + memcpy(values, vals, sizeof(vals)); + } else if (refresh_rate == 50) { + if (last_refresh_rate == 50) return; + uint32_t vals[] = {3, 1, 0}; + memcpy(values, vals, sizeof(vals)); + } else if (refresh_rate == 55) { + if (last_refresh_rate == 55) return; + uint32_t vals[] = {3, 1, 0}; + memcpy(values, vals, sizeof(vals)); + } else { + return; + } + + for (int i = 0; i < 5; i++) { + _changeOledElvssSettings(offsets, values, 3, 0); + } + last_refresh_rate = refresh_rate; + } + + void SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p) { + // Function kept for API compatibility but does nothing + (void)refreshRates; + (void)is720p; + } + + uint8_t GetDockedHighestAllowed(void) { + return (g_dockedHighestRefreshRate > 60) ? g_dockedHighestRefreshRate : 60; + } + + static void _getDockedHighestRefreshRate(uint32_t fd_in) { + uint8_t highestRefreshRate = 60; + uint32_t fd = fd_in; + + if(!fd) nvOpen(&fd, "/dev/nvdisp-disp1"); + NvdcModeDB2 db2 = {0}; + int rc = nvIoctl(fd, NVDISP_GET_MODE_DB2, &db2); + + if (rc == 0) { + for (size_t i = 0; i < db2.num_modes; i++) { + if (db2.modes[i].hActive < 1920 || db2.modes[i].vActive < 1080) + continue; + + uint32_t v_total = db2.modes[i].vActive + db2.modes[i].vSyncWidth + db2.modes[i].vFrontPorch + db2.modes[i].vBackPorch; + uint32_t h_total = db2.modes[i].hActive + db2.modes[i].hSyncWidth + db2.modes[i].hFrontPorch + db2.modes[i].hBackPorch; + double refreshRate = round((double)(db2.modes[i].pclkKHz * 1000) / (double)(v_total * h_total)); + + if (highestRefreshRate < (uint8_t)refreshRate) + highestRefreshRate = (uint8_t)refreshRate; + } + } else { + g_dockedHighestRefreshRate = 60; + } + + const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]); + if (highestRefreshRate > g_dockedRefreshRates[numRates - 1]) + highestRefreshRate = g_dockedRefreshRates[numRates - 1]; + + NvdcMode2 display_b = {0}; + rc = nvIoctl(fd, NVDISP_GET_MODE2, &display_b); + + struct dpaux_read_0x100 { + uint32_t cmd; + uint32_t addr; + uint32_t size; + struct { + unsigned char link_rate; + unsigned int lane_count: 5; + unsigned int unk1: 2; + unsigned int isFramingEnhanced: 1; + unsigned char downspread; + unsigned char training_pattern; + unsigned char lane_pattern[4]; + unsigned char unk2[8]; + } set; + } dpaux = {6, 0x100, 0x10}; + + rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux); + if (rc == 0) { + g_dockedLinkRate = dpaux.set.link_rate; + // if (display_b.hActive == 1920 && display_b.vActive == 1080 && highestRefreshRate > 75 && dpaux.set.link_rate < 20 && ) + // highestRefreshRate = 75; + } + + if (!fd_in) nvClose(fd); + g_dockedHighestRefreshRate = highestRefreshRate; + } + + static bool _setPLLDHandheldRefreshRate(uint32_t new_refreshRate) { + if (!g_config.clkVirtAddr) return false; + + uint32_t fd = 0; + if (nvOpen(&fd, "/dev/nvdisp-disp0")) { + return false; + } + + struct dpaux_read { + uint32_t cmd; + uint32_t addr; + uint32_t size; + struct { + unsigned int rev_minor : 4; + unsigned int rev_major : 4; + unsigned char link_rate; + unsigned int lane_count: 5; + unsigned int unk1: 2; + unsigned int isFramingEnhanced: 1; + unsigned char unk2[13]; + } DPCD; + } dpaux = {6, 0, 0x10}; + + int rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux); + nvClose(fd); + if (rc != 0x75c) return false; + + PLLD_BASE base = {0}; + PLLD_MISC misc = {0}; + memcpy(&base, (void*)(g_config.clkVirtAddr + 0xD0), 4); + memcpy(&misc, (void*)(g_config.clkVirtAddr + 0xDC), 4); + + uint32_t value = ((base.PLLD_DIVN / base.PLLD_DIVM) * 10) / 4; + if (value == 0 || value == 80) return false; + + if (new_refreshRate > g_handheldModeRefreshRate.max) { + new_refreshRate = g_handheldModeRefreshRate.max; + } else if (new_refreshRate < g_handheldModeRefreshRate.min) { + bool skip = false; + for (size_t i = 2; i <= 4; i++) { + if (new_refreshRate * i == 60) { + skip = true; + new_refreshRate = 60; + break; + } + } + if (!skip) { + for (size_t i = 2; i <= 4; i++) { + if (((new_refreshRate * i) >= g_handheldModeRefreshRate.min) && ((new_refreshRate * i) <= g_handheldModeRefreshRate.max)) { + skip = true; + new_refreshRate *= i; + break; + } + } + } + if (!skip) new_refreshRate = 60; + } + + uint32_t pixelClock = (9375 * ((4096 * ((2 * base.PLLD_DIVN) + 1)) + misc.PLLD_SDM_DIN)) / (8 * base.PLLD_DIVM); + uint16_t refreshRateNow = pixelClock / (DSI_CLOCK_HZ / 60); + + if (refreshRateNow == new_refreshRate) { + return true; + } + + uint8_t base_refreshRate = new_refreshRate - (new_refreshRate % 5); + base.PLLD_DIVN = (4 * base_refreshRate) / 10; + base.PLLD_DIVM = 1; + + uint64_t expected_pixel_clock = (DSI_CLOCK_HZ * new_refreshRate) / 60; + misc.PLLD_SDM_DIN = ((8 * base.PLLD_DIVM * expected_pixel_clock) / 9375) - (4096 * ((2 * base.PLLD_DIVN) + 1)); + + memcpy((void*)(g_config.clkVirtAddr + 0xD0), &base, 4); + memcpy((void*)(g_config.clkVirtAddr + 0xDC), &misc, 4); + return true; + } + + static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) { + if (g_config.isLite || !g_canChangeRefreshRateDocked) + return false; + + uint32_t fd = 0; + if (nvOpen(&fd, "/dev/nvdisp-disp1")) { + return false; + } + + NvdcMode2 display_b = {0}; + int rc = nvIoctl(fd, NVDISP_GET_MODE2, &display_b); + if (rc != 0) { + nvClose(fd); + return false; + } + + if (!display_b.pclkKHz) { + nvClose(fd); + return false; + } + + if (!((display_b.vActive == 480 && display_b.hActive == 720) || + (display_b.vActive == 720 && display_b.hActive == 1280) || + (display_b.vActive == 1080 && display_b.hActive == 1920))) { + nvClose(fd); + return false; + } + + if (display_b.vActive != g_lastVActiveSet) { + g_lastVActiveSet = display_b.vActive; + } + + uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch; + uint32_t v_total = display_b.vActive + display_b.vFrontPorch + display_b.vSyncWidth + display_b.vBackPorch; + uint32_t refreshRateNow = ((display_b.pclkKHz) * 1000 + 999) / (h_total * v_total); + + int8_t itr = -1; + const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]); + + // Find closest matching refresh rate + if ((new_refreshRate <= 60) && ((60 % new_refreshRate) == 0)) { + itr = _getDockedRefreshRateIterator(60); + } + + if (itr == -1) { + for (size_t i = 0; i < numRates; i++) { + uint8_t val = g_dockedRefreshRates[i]; + if ((val % new_refreshRate) == 0) { + itr = i; + break; + } + } + } + + if (itr == -1) { + if (!g_config.matchLowestDocked) { + itr = _getDockedRefreshRateIterator(60); + } else { + for (size_t i = 0; i < numRates; i++) { + if (new_refreshRate < g_dockedRefreshRates[i]) { + itr = i; + break; + } + } + } + } + + if (itr == -1) itr = _getDockedRefreshRateIterator(60); + + // Clamp to highest allowed refresh rate + if (g_dockedRefreshRates[itr] > g_dockedHighestRefreshRate) { + for (int8_t i = itr; i >= 0; i--) { + if (g_dockedRefreshRates[i] <= g_dockedHighestRefreshRate) { + itr = i; + break; + } + } + } + + if (refreshRateNow == g_dockedRefreshRates[itr]) { + nvClose(fd); + return true; + } + + if (itr >= 0 && itr < (int8_t)numRates) { + if (display_b.vActive == 720) { + uint32_t clock = ((h_total * v_total) * g_dockedRefreshRates[itr]) / 1000; + display_b.pclkKHz = clock; + } else { + display_b.hFrontPorch = g_dockedTimings1080p[itr].hFrontPorch; + display_b.hSyncWidth = g_dockedTimings1080p[itr].hSyncWidth; + display_b.hBackPorch = g_dockedTimings1080p[itr].hBackPorch; + display_b.vFrontPorch = g_dockedTimings1080p[itr].vFrontPorch; + display_b.vSyncWidth = g_dockedTimings1080p[itr].vSyncWidth; + display_b.vBackPorch = g_dockedTimings1080p[itr].vBackPorch; + display_b.pclkKHz = g_dockedTimings1080p[itr].pixelClock_kHz; + display_b.vmode = (g_dockedRefreshRates[itr] >= 100 ? 0x400000 : 0x200000); + display_b.unk1 = (g_dockedRefreshRates[itr] >= 100 ? 0x80 : 0); + display_b.sync = 3; + display_b.bitsPerPixel = 24; + } + + rc = nvIoctl(fd, NVDISP_VALIDATE_MODE2, &display_b); + if (rc == 0) { + rc = nvIoctl(fd, NVDISP_SET_MODE2, &display_b); + } + } + + nvClose(fd); + return true; + } + + static bool _setNvDispHandheldRefreshRate(uint32_t new_refreshRate) { + if (!g_config.isRetroSUPER) return false; + + if (!g_config.displaySync) { + g_wasRetroSuperTurnedOff = false; + } else if (g_wasRetroSuperTurnedOff) { + svcSleepThread(2000000000); + g_wasRetroSuperTurnedOff = false; + } + + svcSleepThread(1000000000); + + uint32_t fd = 0; + if (nvOpen(&fd, "/dev/nvdisp-disp0")) { + return false; + } + + NvdcMode2 display_b = {0}; + int rc = nvIoctl(fd, NVDISP_GET_MODE2, &display_b); + if (rc != 0) { + nvClose(fd); + return false; + } + + if (!display_b.pclkKHz) { + nvClose(fd); + return false; + } + + if ((display_b.vActive == 1280 && display_b.hActive == 720) == false) { + nvClose(fd); + return false; + } + + uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch; + uint32_t v_total = display_b.vActive + display_b.vFrontPorch + display_b.vSyncWidth + display_b.vBackPorch; + uint32_t refreshRateNow = ((display_b.pclkKHz) * 1000 + 999) / (h_total * v_total); + + if (new_refreshRate > g_handheldModeRefreshRate.max) { + new_refreshRate = g_handheldModeRefreshRate.max; + } else if (new_refreshRate < g_handheldModeRefreshRate.min) { + bool skip = false; + for (size_t i = 2; i <= 4; i++) { + if (new_refreshRate * i == 60) { + skip = true; + new_refreshRate = 60; + break; + } + } + if (!skip) { + for (size_t i = 2; i <= (sizeof(g_handheldTimingsRETRO) / sizeof(g_handheldTimingsRETRO[0])); i++) { + if (((new_refreshRate * i) >= g_handheldModeRefreshRate.min) && ((new_refreshRate * i) <= g_handheldModeRefreshRate.max)) { + skip = true; + new_refreshRate *= i; + break; + } + } + } + if (!skip) new_refreshRate = 60; + } + + if (new_refreshRate == refreshRateNow) { + nvClose(fd); + return true; + } + + uint32_t itr = (new_refreshRate - 40) / 5; + display_b.hFrontPorch = g_handheldTimingsRETRO[itr].hFrontPorch; + display_b.hSyncWidth = g_handheldTimingsRETRO[itr].hSyncWidth; + display_b.hBackPorch = g_handheldTimingsRETRO[itr].hBackPorch; + display_b.vFrontPorch = g_handheldTimingsRETRO[itr].vFrontPorch; + display_b.vSyncWidth = g_handheldTimingsRETRO[itr].vSyncWidth; + display_b.vBackPorch = g_handheldTimingsRETRO[itr].vBackPorch; + display_b.pclkKHz = g_handheldTimingsRETRO[itr].pixelClock_kHz; + + rc = nvIoctl(fd, NVDISP_VALIDATE_MODE2, &display_b); + if (rc == 0) { + for (size_t i = 0; i < 5; i++) { + nvIoctl(fd, NVDISP_SET_MODE2, &display_b); + } + } + + nvClose(fd); + return true; + } + + bool SetRate(uint32_t new_refreshRate) { + if (!new_refreshRate || !g_initialized) return false; + + uint32_t fd = 0; + + if (g_config.isRetroSUPER && !g_config.isDocked) { + return _setNvDispHandheldRefreshRate(new_refreshRate); + } + + else if ((!g_config.isRetroSUPER && g_config.isLite) || R_FAILED(nvOpen(&fd, "/dev/nvdisp-disp1"))) { + if (_setPLLDHandheldRefreshRate(new_refreshRate) == false) + return false; + } + else { + struct dpaux_read { + uint32_t cmd; + uint32_t addr; + uint32_t size; + struct { + unsigned int rev_minor : 4; + unsigned int rev_major : 4; + unsigned char link_rate; + unsigned int lane_count: 5; + unsigned int unk1: 2; + unsigned int isFramingEnhanced: 1; + unsigned char unk2[13]; + } DPCD; + } dpaux = {6, 0, 0x10}; + + int rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux); + nvClose(fd); + + if (rc != 0) { + if (!g_config.isRetroSUPER) { + return _setPLLDHandheldRefreshRate(new_refreshRate); + } else { + return _setNvDispHandheldRefreshRate(new_refreshRate); + } + } else { + if(g_config.isDocked) + return _setNvDispDockedRefreshRate(new_refreshRate); + else + return true; + } + } + return false; + } + + bool GetRate(uint32_t* out_refreshRate, bool internal) { + if (!out_refreshRate || !g_initialized || !g_config.clkVirtAddr) return false; + static uint32_t value = 60; + + if (g_config.isRetroSUPER && !g_config.isDocked) { + uint32_t fd = 0; + PLLD_BASE temp = {0}; + PLLD_MISC misc = {0}; + memcpy(&temp, (void*)(g_config.clkVirtAddr + 0xD0), 4); + memcpy(&misc, (void*)(g_config.clkVirtAddr + 0xDC), 4); + + value = ((temp.PLLD_DIVN / temp.PLLD_DIVM) * 10) / 4; + + if (value != 0 && value != 80) { + if (!nvOpen(&fd, "/dev/nvdisp-disp0")) { + NvdcMode2 display_b = {0}; + if (nvIoctl(fd, NVDISP_GET_MODE2, &display_b) == 0) { + uint64_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch; + uint64_t v_total = display_b.vActive + display_b.vFrontPorch + display_b.vSyncWidth + display_b.vBackPorch; + uint64_t pixelClock = display_b.pclkKHz * 1000 + 999; + value = (u32)(pixelClock / (h_total * v_total)); + } + nvClose(fd); + } else { + return false; + } + } else { + g_wasRetroSuperTurnedOff = true; + } + } + else if ((!g_config.isPossiblySpoofedRetro) || (g_config.isPossiblySpoofedRetro && !g_config.isRetroSUPER)) { + PLLD_BASE temp = {0}; + PLLD_MISC misc = {0}; + memcpy(&temp, (void*)(g_config.clkVirtAddr + 0xD0), 4); + memcpy(&misc, (void*)(g_config.clkVirtAddr + 0xDC), 4); + + value = ((temp.PLLD_DIVN / temp.PLLD_DIVM) * 10) / 4; + + if (value == 0 || value == 80) { + // Docked mode + if (g_config.isLite) return false; + + g_config.isDocked = true; + + if (!g_canChangeRefreshRateDocked) { + uint32_t fd = 0; + if (!nvOpen(&fd, "/dev/nvdisp-disp1")) { + struct dpaux_read_0x100 { + uint32_t cmd; + uint32_t addr; + uint32_t size; + struct { + unsigned char link_rate; + unsigned int lane_count: 5; + unsigned int unk1: 2; + unsigned int isFramingEnhanced: 1; + unsigned char downspread; + unsigned char training_pattern; + unsigned char lane_pattern[4]; + unsigned char unk2[8]; + } set; + } dpaux = {6, 0x100, 0x10}; + + int rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux); + nvClose(fd); + + if (rc == 0) { + _getDockedHighestRefreshRate(0); + g_canChangeRefreshRateDocked = true; + } else { + svcSleepThread(1000000000); + return false; + } + } else { + return false; + } + } + if(internal) { + *out_refreshRate = value; + return true; + } + uint32_t fd = 0; + if (!nvOpen(&fd, "/dev/nvdisp-disp1")) { + NvdcMode2 display_b = {0}; + if (nvIoctl(fd, NVDISP_GET_MODE2, &display_b) == 0) { + if (!display_b.pclkKHz) { + nvClose(fd); + return false; + } + + if (g_lastVActive != display_b.vActive) { + g_lastVActive = display_b.vActive; + _getDockedHighestRefreshRate(fd); + } + + uint64_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch; + uint64_t v_total = display_b.vActive + display_b.vFrontPorch + display_b.vSyncWidth + display_b.vBackPorch; + uint64_t pixelClock = display_b.pclkKHz * 1000 + 999; + value = (u32)(pixelClock / (h_total * v_total)); + } else { + value = 60; + } + nvClose(fd); + } else { + value = 60; + } + } + else if (!g_config.isRetroSUPER) { + // Handheld mode + g_config.isDocked = false; + g_canChangeRefreshRateDocked = false; + + uint32_t pixelClock = (9375ULL * ((4096 * ((2 * temp.PLLD_DIVN) + 1)) + misc.PLLD_SDM_DIN)) / (8 * temp.PLLD_DIVM); + value = pixelClock / (DSI_CLOCK_HZ / 60); + } + else { + return false; + } + } + + *out_refreshRate = value; + return true; + } + + void Shutdown(void) { + g_initialized = false; + memset(&g_config, 0, sizeof(g_config)); + } +} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/board/display_refresh_rate.hpp b/Source/rewrite-hoc-clk/sysmodule/src/board/display_refresh_rate.hpp new file mode 100644 index 00000000..32e91272 --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/board/display_refresh_rate.hpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) Souldbminer, based on reasearch by MasaGratoR and Cooler3D + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include +#include +#include +namespace display { + typedef struct { + uint16_t hFrontPorch; + uint8_t hSyncWidth; + uint8_t hBackPorch; + uint8_t vFrontPorch; + uint8_t vSyncWidth; + uint8_t vBackPorch; + uint8_t VIC; + uint32_t pixelClock_kHz; + } DockedTimings; + + typedef struct { + uint8_t hSyncWidth; + uint16_t hFrontPorch; + uint8_t hBackPorch; + uint8_t vSyncWidth; + uint16_t vFrontPorch; + uint8_t vBackPorch; + uint32_t pixelClock_kHz; + } HandheldTimings; + + typedef struct { + uint8_t min; + uint8_t max; + } MinMaxRefreshRate; + + typedef struct { + uint32_t unk0; + uint32_t hActive; + uint32_t vActive; + uint32_t hSyncWidth; + uint32_t vSyncWidth; + uint32_t hFrontPorch; + uint32_t vFrontPorch; + uint32_t hBackPorch; + uint32_t vBackPorch; + uint32_t pclkKHz; + uint32_t bitsPerPixel; + uint32_t vmode; + uint32_t sync; + uint32_t unk1; + uint32_t reserved; + } NvdcMode2; + + typedef struct { + NvdcMode2 modes[201]; + uint32_t num_modes; + } NvdcModeDB2; + + typedef struct { + unsigned int PLLD_DIVM: 8; + unsigned int reserved_1: 3; + unsigned int PLLD_DIVN: 8; + unsigned int reserved_2: 1; + unsigned int PLLD_DIVP: 3; + unsigned int CSI_CLK_SRC: 1; + unsigned int reserved_3: 1; + unsigned int PLL_D: 1; + unsigned int reserved_4: 1; + unsigned int PLLD_LOCK: 1; + unsigned int reserved_5: 1; + unsigned int PLLD_REF_DIS: 1; + unsigned int PLLD_ENABLE: 1; + unsigned int PLLD_BYPASS: 1; + } PLLD_BASE; + + typedef struct { + signed int PLLD_SDM_DIN: 16; + unsigned int PLLD_EN_SDM: 1; + unsigned int PLLD_LOCK_OVERRIDE: 1; + unsigned int PLLD_EN_LCKDET: 1; + unsigned int PLLD_FREQLOCK: 1; + unsigned int PLLD_IDDQ: 1; + unsigned int PLLD_ENABLE_CLK: 1; + unsigned int PLLD_KVCO: 1; + unsigned int PLLD_KCP: 2; + unsigned int PLLD_PTS: 2; + unsigned int PLLD_LDPULSE_ADJ: 3; + unsigned int reserved: 2; + } PLLD_MISC; + + typedef struct { + uint64_t clkVirtAddr; + uint64_t dsiVirtAddr; + bool isDocked; + bool isLite; + bool isRetroSUPER; + bool isPossiblySpoofedRetro; + bool dontForce60InDocked; + bool matchLowestDocked; + bool displaySync; + bool displaySyncOutOfFocus60; + bool displaySyncDocked; + bool displaySyncDockedOutOfFocus60; + } DisplayRefreshConfig; + bool Initialize(const DisplayRefreshConfig* config); + void SetDockedState(bool isDocked); + bool SetRate(uint32_t new_refreshRate); + bool GetRate(uint32_t* out_refreshRate, bool internal); + uint8_t GetDockedHighestAllowed(void); + void CorrectOledGamma(uint32_t refresh_rate); + void SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p); + void Shutdown(void); +} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.cpp b/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.cpp index 4a9b4e50..5093c44a 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.cpp @@ -24,1290 +24,618 @@ * -------------------------------------------------------------------------- */ - -#include "clock_manager.h" +#include "clock_manager.hpp" #include -#include "file_utils.h" +#include "file_utils.hpp" #include "board/board.hpp" #include "process_management.hpp" -#include "errors.h" -#include "ipc_service.h" -#include "kip.h" +#include "errors.hpp" +#include "ipc_service.hpp" +#include "kip.hpp" #include -#include "notification.h" -#include -#include +#include "board/display_refresh_rate.hpp" #include #include +#include "config.hpp" +#include "integrations.hpp" +#include +#include "kip.hpp" +#include "governor.hpp" #define HOSPPC_HAS_BOOST (hosversionAtLeast(7,0,0)) -// governor constants -#define POLL_NS 5'000'000 // 5 ms – governor poll rate -#define DOWN_HOLD_TICKS 10 // 50 ms – how long to in POLL_NS to hold while ramping down -#define STEP_UTIL 900 // multiplier for step calculations +namespace clockManager { -bool isGpuGovernorEnabled = false; -bool isCpuGovernorEnabled = false; -bool lastGpuGovernorState = false; -bool lastCpuGovernorState = false; -bool lastVrrGovernorState = false; -bool hasChanged = true; -ClockManager *ClockManager::instance = NULL; -Thread cpuGovernorTHREAD; -Thread gpuGovernorTHREAD; -Thread vrrTHREAD; -u32 initialConfigValues[SysClkConfigValue_EnumMax]; // initial config. used for safety checks -bool kipAvailable = false; -bool isCpuGovernorInBoostMode = false; -bool isVRREnabled = false; -ClockManager *ClockManager::GetInstance() -{ - return instance; -} + bool gRunning = false; + LockableMutex gContextMutex; + SysClkContext gContext = {}; + FreqTable gFreqTable[SysClkModule_EnumMax]; + std::uint64_t gLastTempLogNs = 0; + std::uint64_t gLastFreqLogNs = 0; + std::uint64_t gLastPowerLogNs = 0; + std::uint64_t gLastCsvWriteNs = 0; -void ClockManager::Exit() -{ - if (instance) + bool IsAssignableHz(SysClkModule module, std::uint32_t hz) { - delete instance; - } -} - -void ClockManager::Initialize() -{ - if (!instance) - { - instance = new ClockManager(); - } -} - -ClockManager::ClockManager() -{ - this->config = Config::CreateDefault(); - this->context = new SysClkContext; - this->context->applicationId = 0; - this->context->profile = SysClkProfile_Handheld; - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - this->context->freqs[module] = 0; - this->context->realFreqs[module] = 0; - this->context->overrideFreqs[module] = 0; - this->RefreshFreqTableRow((SysClkModule)module); + switch (module) { + case SysClkModule_CPU: + return hz >= 500000000; + case SysClkModule_MEM: + return hz >= 665600000; + default: + return true; + } } - this->running = false; - this->lastTempLogNs = 0; - this->lastCsvWriteNs = 0; - - this->sysDockIntegration = new SysDockIntegration; - this->saltyNXIntegration = new SaltyNXIntegration; - - memset(&initialConfigValues, 0, sizeof(initialConfigValues)); - this->GetKipData(); - - threadCreate( - &cpuGovernorTHREAD, - ClockManager::CpuGovernorThread, - this, - NULL, - 0x2000, - 0x3F, - -2 - ); - - threadCreate( - &gpuGovernorTHREAD, - ClockManager::GovernorThread, - this, - NULL, - 0x2000, - 0x3F, - -2 - ); - - threadCreate( - &vrrTHREAD, - ClockManager::VRRThread, - this, - NULL, - 0x2000, - 0x3F, - -2 - ); - - board::FuseData *fuse = board::GetFuseData(); - - this->context->speedos[0] = fuse->cpuSpeedo; - this->context->speedos[1] = fuse->gpuSpeedo; - this->context->speedos[2] = fuse->socSpeedo; - this->context->iddq[0] = fuse->cpuIDDQ; - this->context->iddq[1] = fuse->gpuIDDQ; - this->context->iddq[2] = fuse->socIDDQ; - this->context->waferX = fuse->waferX; - this->context->waferY = fuse->waferY; - - this->context->dramID = board::GetDramID(); - this->context->isDram8GB = board::IsDram8GB(); - board::SetGpuSchedulingMode((GpuSchedulingMode)this->config->GetConfigValue(HorizonOCConfigValue_GPUScheduling), (GpuSchedulingOverrideMethod)this->config->GetConfigValue(HorizonOCConfigValue_GPUSchedulingMethod)); - this->context->gpuSchedulingMode = (GpuSchedulingMode)this->config->GetConfigValue(HorizonOCConfigValue_GPUScheduling); - - this->context->isSysDockInstalled = this->sysDockIntegration->getCurrentSysDockState(); - this->context->isSaltyNXInstalled = this->saltyNXIntegration->getCurrentSaltyNXState(); - if(this->context->isSaltyNXInstalled) { - this->saltyNXIntegration->LoadSaltyNX(); - } - - this->context->isUsingRetroSuper = board::IsUsingRetroSuperDisplay(); - - threadStart(&cpuGovernorTHREAD); - threadStart(&gpuGovernorTHREAD); - threadStart(&vrrTHREAD); -} - -ClockManager::~ClockManager() -{ - threadClose(&cpuGovernorTHREAD); - threadClose(&gpuGovernorTHREAD); - threadClose(&vrrTHREAD); - - delete this->sysDockIntegration; - delete this->saltyNXIntegration; - delete this->config; - delete this->context; -} - -SysClkContext ClockManager::GetCurrentContext() -{ - std::scoped_lock lock{this->contextMutex}; - return *this->context; -} - -Config *ClockManager::GetConfig() -{ - return this->config; -} - -void ClockManager::SetRunning(bool running) -{ - this->running = running; -} - -bool ClockManager::Running() -{ - return this->running; -} - -void ClockManager::GetFreqList(SysClkModule module, std::uint32_t *list, std::uint32_t maxCount, std::uint32_t *outCount) -{ - ASSERT_ENUM_VALID(SysClkModule, module); - - *outCount = std::min(maxCount, this->freqTable[module].count); - memcpy(list, &this->freqTable[module].list[0], *outCount * sizeof(this->freqTable[0].list[0])); -} - -bool ClockManager::IsAssignableHz(SysClkModule module, std::uint32_t hz) -{ - switch (module) + std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile) { - case SysClkModule_CPU: - return hz >= 500000000; - case SysClkModule_MEM: - return hz >= 665600000; - default: - return true; - } -} - -std::uint32_t ClockManager::GetMaxAllowedHz(SysClkModule module, SysClkProfile profile) -{ - if (this->config->GetConfigValue(HocClkConfigValue_UncappedClocks)) - { - return ~0; // Integer limit, uncapped clocks ON - } - else - { - if (module == SysClkModule_GPU) - { - if (profile < SysClkProfile_HandheldCharging) - { - switch (board::GetSocType()) { + if (config::GetConfigValue(HocClkConfigValue_UncappedClocks)) { + return ~0; // Integer limit, uncapped clocks ON + } else { + if (module == SysClkModule_GPU) { + if (profile < SysClkProfile_HandheldCharging) { + switch (board::GetSocType()) { case SysClkSocType_Erista: return 460800000; case SysClkSocType_Mariko: - switch(this->config->GetConfigValue(KipConfigValue_marikoGpuUV)) { - case 0: - return 614400000; - case 1: - return 691200000; - case 2: - return 768000000; - default: - return 614400000; + switch (config::GetConfigValue(KipConfigValue_marikoGpuUV)) { + case 0: + return 614400000; + case 1: + return 691200000; + case 2: + return 768000000; + default: + return 614400000; } default: return 460800000; - } - } - else if (profile <= SysClkProfile_HandheldChargingUSB) - { - switch(board::GetSocType()) { + } + } else if (profile <= SysClkProfile_HandheldChargingUSB) { + switch (board::GetSocType()) { case SysClkSocType_Erista: return 768000000; case SysClkSocType_Mariko: - switch(this->config->GetConfigValue(KipConfigValue_marikoGpuUV)) { - case 0: - return 844800000; - case 1: - return 921600000; - case 2: - return 998400000; - default: - return 844800000; + switch (config::GetConfigValue(KipConfigValue_marikoGpuUV)) { + case 0: + return 844800000; + case 1: + return 921600000; + case 2: + return 998400000; + default: + return 844800000; } default: return 768000000; + } } - } - } else if(module == SysClkModule_CPU) { - if(profile < SysClkProfile_HandheldCharging && board::GetSocType() == SysClkSocType_Erista) { - return 1581000000; - } else { - return ~0; - } - } - } - return 0; -} - -std::uint32_t ClockManager::GetNearestHz(SysClkModule module, std::uint32_t inHz, std::uint32_t maxHz) -{ - std::uint32_t *freqs = &this->freqTable[module].list[0]; - size_t count = this->freqTable[module].count - 1; - - size_t i = 0; - while (i < count) - { - if (maxHz > 0 && freqs[i] >= maxHz) - { - break; - } - - if (inHz <= ((std::uint64_t)freqs[i] + freqs[i + 1]) / 2) - { - break; - } - - i++; - } - - return freqs[i]; -} - -bool ClockManager::ConfigIntervalTimeout(SysClkConfigValue intervalMsConfigValue, std::uint64_t ns, std::uint64_t *lastLogNs) -{ - std::uint64_t logInterval = this->GetConfig()->GetConfigValue(intervalMsConfigValue) * 1000000ULL; - bool shouldLog = logInterval && ((ns - *lastLogNs) > logInterval); - - if (shouldLog) - { - *lastLogNs = ns; - } - - return shouldLog; -} - -void ClockManager::RefreshFreqTableRow(SysClkModule module) -{ - std::scoped_lock lock{this->contextMutex}; - - std::uint32_t freqs[SYSCLK_FREQ_LIST_MAX]; - std::uint32_t count; - - FileUtils::LogLine("[mgr] %s freq list refresh", board::GetModuleName(module, true)); - board::GetFreqList(module, &freqs[0], SYSCLK_FREQ_LIST_MAX, &count); - - std::uint32_t *hz = &this->freqTable[module].list[0]; - this->freqTable[module].count = 0; - for (std::uint32_t i = 0; i < count; i++) - { - if (!this->IsAssignableHz(module, freqs[i])) - { - continue; - } - - *hz = freqs[i]; - FileUtils::LogLine("[mgr] %02u - %u - %u.%u MHz", this->freqTable[module].count, *hz, *hz / 1000000, *hz / 100000 - *hz / 1000000 * 10); - - this->freqTable[module].count++; - hz++; - } - - FileUtils::LogLine("[mgr] count = %u", this->freqTable[module].count); -} - -u32 ClockManager::SchedutilTargetHz(u32 util, u32 tableMaxHz) { - u64 hz = (u64)tableMaxHz * util / STEP_UTIL; - return (u32)(std::min(hz, static_cast(tableMaxHz))); -} - -u32 ClockManager::TableIndexForHz(const FreqTable& table, u32 targetHz) { // must pass in a freqTable as tables are different for cpu/gpu - for (u32 i = 0; i < table.count; i++) - if (table.list[i] >= targetHz) - return i; - return table.count - 1; -} - -u32 ClockManager::ResolveTargetHz(ClockManager* mgr, SysClkModule module) { - u32 hz = mgr->context->overrideFreqs[module]; - if (!hz) - hz = mgr->config->GetAutoClockHz( - mgr->context->applicationId, module, - mgr->context->profile, false); - if (!hz) - hz = mgr->config->GetAutoClockHz( - GLOBAL_PROFILE_ID, module, - mgr->context->profile, false); - return hz; -} - -void ClockManager::CpuGovernorThread(void* arg) { - ClockManager* mgr = static_cast(arg); - - u32 downHoldRemaining = 0; - u32 lastHz = 0; - u32 minHz = 612; - u32 tick = 0; - for (;;) { - if (!mgr->running || !isCpuGovernorEnabled) { - downHoldRemaining = 0; - lastHz = 0; - svcSleepThread(POLL_NS); - continue; - } - - u32 mode = 0; - Result rc = apmExtGetCurrentPerformanceConfiguration(&mode); - - if (R_SUCCEEDED(rc) && apmExtIsBoostMode(mode)) { - isCpuGovernorInBoostMode = true; - downHoldRemaining = 0; - lastHz = 0; - continue; // TODO: figure out a way to get boost clock easily and set it instead of just skipping the governor - } else if(!apmExtIsBoostMode(mode)) { - isCpuGovernorInBoostMode = false; - } - - auto& table = mgr->freqTable[SysClkModule_CPU]; - - if (table.count == 0) - continue; - - std::scoped_lock lock{mgr->contextMutex}; - - u32 cpuLoad = board::GetPartLoad(HocClkPartLoad_CPUMax); - - u32 tableMaxHz = table.list[table.count - 1]; - u32 desiredHz = ClockManager::SchedutilTargetHz(cpuLoad, tableMaxHz); - u32 targetHz = ClockManager::ResolveTargetHz(mgr, SysClkModule_CPU); - u32 maxHz = mgr->GetMaxAllowedHz(SysClkModule_CPU, mgr->context->profile); - - if (targetHz && desiredHz > targetHz) - desiredHz = targetHz; - - if (maxHz && desiredHz > maxHz) - desiredHz = maxHz; - - u32 newHz = table.list[ClockManager::TableIndexForHz(table, desiredHz)]; - - // ramp up fast, go down slow - bool goingDown = (lastHz != 0) && (newHz < lastHz); - - if (!goingDown) - downHoldRemaining = 0; - else if (downHoldRemaining == 0) - downHoldRemaining = DOWN_HOLD_TICKS; - - if (downHoldRemaining > 0) - downHoldRemaining--; - - if(++tick > 50) { - minHz = mgr->config->GetConfigValue(HorizonOCConfigValue_CpuGovernorMinimumFreq); - tick = 0; - } - - if(newHz < minHz) - newHz = minHz; - - if ((!goingDown || (downHoldRemaining == 0)) && mgr->IsAssignableHz(SysClkModule_CPU, newHz)) { - board::SetHz(SysClkModule_CPU, newHz); - mgr->context->freqs[SysClkModule_CPU] = newHz; - lastHz = newHz; - } - - svcSleepThread(POLL_NS); - } -} - -void ClockManager::GovernorThread(void* arg) { - ClockManager* mgr = static_cast(arg); - - u32 downHoldRemaining = 0; - u32 lastHz = 0; - - for (;;) { - if (!mgr->running || !isGpuGovernorEnabled) { - downHoldRemaining = 0; - lastHz = 0; - svcSleepThread(POLL_NS); - continue; - } - - auto& table = mgr->freqTable[SysClkModule_GPU]; - if (table.count == 0) - continue; - - std::scoped_lock lock{mgr->contextMutex}; - - u32 gpuLoad = board::GetPartLoad(HocClkPartLoad_GPU); - u32 tableMaxHz = table.list[table.count - 1]; - u32 desiredHz = ClockManager::SchedutilTargetHz(gpuLoad, tableMaxHz); - u32 targetHz = ClockManager::ResolveTargetHz(mgr, SysClkModule_GPU); - u32 maxHz = mgr->GetMaxAllowedHz(SysClkModule_GPU, mgr->context->profile); - - if (targetHz && desiredHz > targetHz) - desiredHz = targetHz; - - if (maxHz && desiredHz > maxHz) - desiredHz = maxHz; - - u32 newHz = table.list[ClockManager::TableIndexForHz(table, desiredHz)]; - bool goingDown = (lastHz != 0) && (newHz < lastHz); - - if (!goingDown) - downHoldRemaining = 0; - else if (downHoldRemaining == 0) - downHoldRemaining = DOWN_HOLD_TICKS; - - if (downHoldRemaining > 0) - downHoldRemaining--; - - if ((!goingDown || (downHoldRemaining == 0)) && mgr->IsAssignableHz(SysClkModule_GPU, newHz)) { - board::SetHz(SysClkModule_GPU, newHz); - mgr->context->freqs[SysClkModule_GPU] = newHz; - lastHz = newHz; - } - - svcSleepThread(POLL_NS); - } -} - -void ClockManager::VRRThread(void* arg) { - ClockManager* mgr = static_cast(arg); - u8 tick = 0; - for (;;) { - if (!mgr->running || mgr->context->profile == SysClkProfile_Docked || !isVRREnabled) { - svcSleepThread(POLL_NS); - continue; - } - - std::scoped_lock lock{mgr->contextMutex}; - - u8 fps; - - if(mgr->context->isSaltyNXInstalled) { - fps = mgr->saltyNXIntegration->GetFPS(); - } else { - svcSleepThread(~0ULL); // effectively disable the thread if SaltyNX isn't installed, as there's no point in it running - continue; - } - - - if(fps == 254) { - svcSleepThread(POLL_NS); - continue; - } - // if(appletGetFocusState() != AppletFocusState_InFocus) { - // board::ResetToStockDisplay(); - // continue; - // } - - u32 targetHz = mgr->context->overrideFreqs[HorizonOCModule_Display]; - if (!targetHz) - { - targetHz = mgr->config->GetAutoClockHz(mgr->context->applicationId, HorizonOCModule_Display, mgr->context->profile, false); - if(!targetHz) - targetHz = mgr->config->GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Display, mgr->context->profile, false); - } - - u8 maxDisplay; - if(targetHz) { - maxDisplay = targetHz; - } else { - maxDisplay = 60; // don't assume display stuff! - } - - u8 minDisplay = board::GetConsoleType() == HorizonOCConsoleType_Aula ? 45 : 40; - if(maxDisplay == minDisplay) - continue; - - if(fps >= minDisplay && fps <= maxDisplay) { - board::SetHz(HorizonOCModule_Display, fps); - mgr->context->freqs[HorizonOCModule_Display] = fps; - mgr->context->realFreqs[HorizonOCModule_Display] = fps; - } else { - for(u32 i = 0; i < 10; i++) { - u32 compareHz = fps * i; - if(compareHz >= minDisplay && compareHz <= maxDisplay) { - board::SetHz(HorizonOCModule_Display, compareHz); - mgr->context->freqs[HorizonOCModule_Display] = compareHz; - mgr->context->realFreqs[HorizonOCModule_Display] = compareHz; - break; + } else if (module == SysClkModule_CPU) { + if (profile < SysClkProfile_HandheldCharging && board::GetSocType() == SysClkSocType_Erista) { + return 1581000000; + } else { + return ~0; } } } - - - if(++tick > 50) { - board::SetHz(HorizonOCModule_Display, maxDisplay); - tick = 0; - svcSleepThread(50'000'000); - } - - svcSleepThread(POLL_NS); - } -} - -void ClockManager::HandleSafetyFeatures() { - if(this->config->GetConfigValue(HocClkConfigValue_HandheldTDP) && (this->context->profile != SysClkProfile_Docked)) { // Enable while charging as non-PD charger can cause lack of power - if (board::GetConsoleType() == HorizonOCConsoleType_Hoag) { - if (board::GetPowerMw(SysClkPowerSensor_Avg) < - this->config->GetConfigValue(HocClkConfigValue_LiteTDPLimit)) { - ResetToStockClocks(); - return; - } - } else { - if(board::GetPowerMw(SysClkPowerSensor_Avg) < - this->config->GetConfigValue(HocClkConfigValue_HandheldTDPLimit)) { - ResetToStockClocks(); - return; - } - } + return 0; } - if(((tmp451TempSoc() / 1000) > (int)this->config->GetConfigValue(HocClkConfigValue_ThermalThrottleThreshold)) && this->config->GetConfigValue(HocClkConfigValue_ThermalThrottle)) { - ResetToStockClocks(); - return; - } -} - -void ClockManager::HandleMiscFeatures() { - if(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)) { - I2c_Bq24193_SetFastChargeCurrentLimit(this->config->GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)); - } -} - -void ClockManager::HandleGovernor(uint32_t targetHz) { - u32 tempTargetHz = this->context->overrideFreqs[HorizonOCModule_Governor]; - if (!tempTargetHz) + std::uint32_t GetNearestHz(SysClkModule module, std::uint32_t inHz, std::uint32_t maxHz) { - tempTargetHz = this->config->GetAutoClockHz(this->context->applicationId, HorizonOCModule_Governor, this->context->profile, true); - if (!tempTargetHz) - tempTargetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Governor, this->context->profile, true); + std::uint32_t *freqs = &gFreqTable[module].list[0]; + size_t count = gFreqTable[module].count - 1; + + size_t i = 0; + while (i < count) { + if (maxHz > 0 && freqs[i] >= maxHz) { + break; + } + if (inHz <= ((std::uint64_t)freqs[i] + freqs[i + 1]) / 2) { + break; + } + i++; + } + + return freqs[i]; } - auto resolve = [](u8 app, u8 temp) -> u8 { - if (temp == ComponentGovernor_Disabled) return ComponentGovernor_Disabled; - if (temp != ComponentGovernor_DoNotOverride) return temp; - return app; - }; - - u8 effectiveCpu = resolve(GovernorStateCpu(targetHz), GovernorStateCpu(tempTargetHz)); - u8 effectiveGpu = resolve(GovernorStateGpu(targetHz), GovernorStateGpu(tempTargetHz)); - u8 effectiveVrr = resolve(GovernorStateVrr(targetHz), GovernorStateVrr(tempTargetHz)); - - bool newCpuGovernorState = (effectiveCpu == ComponentGovernor_Enabled); - bool newGpuGovernorState = (effectiveGpu == ComponentGovernor_Enabled); - bool newVrrGovernorState = (effectiveVrr == ComponentGovernor_Enabled); - - isCpuGovernorEnabled = newCpuGovernorState; - isGpuGovernorEnabled = newGpuGovernorState; - isVRREnabled = newVrrGovernorState; - - if(newCpuGovernorState == false && lastCpuGovernorState == true) { - svcSleepThread(100'000'000); // thread syncing. probably a cleaner way to do this but hey, it works! + void ResetToStockClocks() + { board::ResetToStockCpu(); - } - if(newGpuGovernorState == false && lastGpuGovernorState == true) { - svcSleepThread(100'000'000); + if (config::GetConfigValue(HorizonOCConfigValue_LiveCpuUv)) { + if (board::GetSocType() == SysClkSocType_Erista) + board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); + else + board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf))); + } + board::ResetToStockGpu(); } - if (newVrrGovernorState == false && lastVrrGovernorState == true) { - svcSleepThread(100'000'000); - board::ResetToStockDisplay(); - } - if(newCpuGovernorState != lastCpuGovernorState || newGpuGovernorState != lastGpuGovernorState || newVrrGovernorState != lastVrrGovernorState) { - FileUtils::LogLine("[mgr] Governor state changed: CPU %s, GPU %s, VRR %s", newCpuGovernorState ? "enabled" : "disabled", newGpuGovernorState ? "enabled" : "disabled", newVrrGovernorState ? "enabled" : "disabled"); - lastCpuGovernorState = newCpuGovernorState; - lastGpuGovernorState = newGpuGovernorState; - lastVrrGovernorState = newVrrGovernorState; - } -} -void ClockManager::DVFSBeforeSet(u32 targetHz) { - s32 dvfsOffset = this->config->GetConfigValue(HorizonOCConfigValue_DVFSOffset); - u32 vmin = board::GetMinimumGpuVmin(targetHz / 1000000, board::GetGpuSpeedoBracket()) + dvfsOffset; + bool ConfigIntervalTimeout(SysClkConfigValue intervalMsConfigValue, std::uint64_t ns, std::uint64_t *lastLogNs) + { + std::uint64_t logInterval = config::GetConfigValue(intervalMsConfigValue) * 1000000ULL; + bool shouldLog = logInterval && ((ns - *lastLogNs) > logInterval); - board::PcvHijackGpuVolts(vmin); + if (shouldLog) { + *lastLogNs = ns; + } - /* Update the voltage. */ - if (I2c_BuckConverter_GetMvOut(&I2c_Mariko_GPU) < vmin) { - I2c_BuckConverter_SetMvOut(&I2c_Mariko_GPU, vmin); + return shouldLog; } - this->context->voltages[HocClkVoltage_GPU] = vmin * 1000; -} + void RefreshFreqTableRow(SysClkModule module) + { + std::scoped_lock lock{gContextMutex}; -void ClockManager::DVFSAfterSet(u32 targetHz) { - s32 dvfsOffset = this->config->GetConfigValue(HorizonOCConfigValue_DVFSOffset); - dvfsOffset = std::max(dvfsOffset, -80); - u32 vmin = board::GetMinimumGpuVmin(targetHz / 1000000, board::GetGpuSpeedoBracket()); + std::uint32_t freqs[SYSCLK_FREQ_LIST_MAX]; + std::uint32_t count; - if (vmin) { - vmin += dvfsOffset; + fileUtils::LogLine("[mgr] %s freq list refresh", board::GetModuleName(module, true)); + board::GetFreqList(module, &freqs[0], SYSCLK_FREQ_LIST_MAX, &count); + + std::uint32_t *hz = &gFreqTable[module].list[0]; + gFreqTable[module].count = 0; + for (std::uint32_t i = 0; i < count; i++) { + if (!IsAssignableHz(module, freqs[i])) { + continue; + } + + *hz = freqs[i]; + fileUtils::LogLine("[mgr] %02u - %u - %u.%u MHz", gFreqTable[module].count, *hz, *hz / 1000000, *hz / 100000 - *hz / 1000000 * 10); + + gFreqTable[module].count++; + hz++; + } + + fileUtils::LogLine("[mgr] count = %u", gFreqTable[module].count); } - u32 maxHz = this->GetMaxAllowedHz(SysClkModule_GPU, this->context->profile); - u32 nearestHz = this->GetNearestHz(SysClkModule_GPU, targetHz, maxHz); - board::PcvHijackGpuVolts(vmin); - - if (targetHz) { - board::SetHz(SysClkModule_GPU, ~0); - board::SetHz(SysClkModule_GPU, nearestHz); - } else { - board::SetHz(SysClkModule_GPU, ~0); - board::ResetToStockGpu(); - } -} - -void ClockManager::HandleCpuUv() { - if(board::GetSocType() == SysClkSocType_Erista) - board::SetDfllTunings(this->config->GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); - else - board::SetDfllTunings(this->config->GetConfigValue(KipConfigValue_marikoCpuUVLow), this->config->GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(this->config->GetConfigValue(KipConfigValue_tableConf))); -} - -void ClockManager::DVFSReset() { - if (board::GetSocType() == SysClkSocType_Mariko && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) { - board::PcvHijackGpuVolts(0); - - u32 targetHz = this->context->overrideFreqs[SysClkModule_GPU]; - if (!targetHz) { - targetHz = this->config->GetAutoClockHz(this->context->applicationId, SysClkModule_GPU, this->context->profile, false); - if(!targetHz) { - targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_GPU, this->context->profile, false); + void HandleSafetyFeatures() + { + if (config::GetConfigValue(HocClkConfigValue_HandheldTDP) && (gContext.profile != SysClkProfile_Docked)) { + if (board::GetConsoleType() == HorizonOCConsoleType_Hoag) { + if (board::GetPowerMw(SysClkPowerSensor_Avg) < -(int)config::GetConfigValue(HocClkConfigValue_LiteTDPLimit)) { + ResetToStockClocks(); + return; + } + } else { + if (board::GetPowerMw(SysClkPowerSensor_Avg) < -(int)config::GetConfigValue(HocClkConfigValue_HandheldTDPLimit)) { + ResetToStockClocks(); + return; + } } } - u32 maxHz = this->GetMaxAllowedHz(SysClkModule_GPU, this->context->profile); - u32 nearestHz = this->GetNearestHz(SysClkModule_GPU, targetHz, maxHz); - board::SetHz(SysClkModule_GPU, ~0); - if(targetHz) { + if (((tmp451TempSoc() / 1000) > (int)config::GetConfigValue(HocClkConfigValue_ThermalThrottleThreshold)) && config::GetConfigValue(HocClkConfigValue_ThermalThrottle)) { + ResetToStockClocks(); + return; + } + } + + void HandleMiscFeatures() + { + if (config::GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)) { + I2c_Bq24193_SetFastChargeCurrentLimit(config::GetConfigValue(HorizonOCConfigValue_BatteryChargeCurrent)); + } + } + + void DVFSBeforeSet(u32 targetHz) + { + s32 dvfsOffset = config::GetConfigValue(HorizonOCConfigValue_DVFSOffset); + u32 vmin = board::GetMinimumGpuVmin(targetHz / 1000000, board::GetGpuSpeedoBracket()) + dvfsOffset; + + board::PcvHijackGpuVolts(vmin); + + /* Update the voltage. */ + if (I2c_BuckConverter_GetMvOut(&I2c_Mariko_GPU) < vmin) { + I2c_BuckConverter_SetMvOut(&I2c_Mariko_GPU, vmin); + } + + gContext.voltages[HocClkVoltage_GPU] = vmin * 1000; + } + + void DVFSAfterSet(u32 targetHz) + { + s32 dvfsOffset = config::GetConfigValue(HorizonOCConfigValue_DVFSOffset); + dvfsOffset = std::max(dvfsOffset, -80); + u32 vmin = board::GetMinimumGpuVmin(targetHz / 1000000, board::GetGpuSpeedoBracket()); + + if (vmin) { + vmin += dvfsOffset; + } + + u32 maxHz = GetMaxAllowedHz(SysClkModule_GPU, gContext.profile); + u32 nearestHz = GetNearestHz(SysClkModule_GPU, targetHz, maxHz); + board::PcvHijackGpuVolts(vmin); + + if (targetHz) { + board::SetHz(SysClkModule_GPU, ~0); board::SetHz(SysClkModule_GPU, nearestHz); } else { - board::ResetToStockGpu(); - } - } -} - -void ClockManager::HandleFreqReset(SysClkModule module, bool isBoost) { - switch (module) - { - case SysClkModule_CPU: - if(!(isBoost || (this->config->GetConfigValue(HocClkConfigValue_OverwriteBoostMode) && isBoost))) - board::ResetToStockCpu(); - if(this->config->GetConfigValue(HorizonOCConfigValue_LiveCpuUv)) { - if(board::GetSocType() == SysClkSocType_Erista) - board::SetDfllTunings(this->config->GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); - else - board::SetDfllTunings(this->config->GetConfigValue(KipConfigValue_marikoCpuUVLow), this->config->GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(this->config->GetConfigValue(KipConfigValue_tableConf))); - } - - break; - case SysClkModule_GPU: - board::ResetToStockGpu(); - break; - case SysClkModule_MEM: - board::ResetToStockMem(); - DVFSReset(); - break; - case HorizonOCModule_Display: - if(this->config->GetConfigValue(HorizonOCConfigValue_OverwriteRefreshRate)) { - board::ResetToStockDisplay(); - } - break; - default: - break; - } - -} - -void ClockManager::SetClocks(bool isBoost) { - std::uint32_t targetHz = 0; - std::uint32_t maxHz = 0; - std::uint32_t nearestHz = 0; - - if(isBoost && !this->config->GetConfigValue(HocClkConfigValue_OverwriteBoostMode)) { - u32 boostFreq = board::GetHz(SysClkModule_CPU); - if (boostFreq / 1000000 > 1785) { - board::SetHz(SysClkModule_CPU, boostFreq); - } - return; // Return if we are't overwriting boost mode - } - - bool returnRaw = false; // Return a value scaled to MHz instead of raw value - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - u32 oldHz = board::GetHz((SysClkModule)module); // Get Old hz (used primarily for DVFS Logic) - - if(module > SysClkModule_MEM) - returnRaw = true; - else - returnRaw = false; - targetHz = this->context->overrideFreqs[module]; - if (!targetHz) - { - targetHz = this->config->GetAutoClockHz(this->context->applicationId, (SysClkModule)module, this->context->profile, returnRaw); - if(!targetHz) - targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, (SysClkModule)module, this->context->profile, returnRaw); - } - - if(module == HorizonOCModule_Governor) { - HandleGovernor(targetHz); - } - - bool noCPU = isCpuGovernorEnabled; - bool noGPU = isGpuGovernorEnabled; - bool noDisp = isVRREnabled; - if(noDisp && module == HorizonOCModule_Display) - continue; - - if(module == HorizonOCModule_Display && this->config->GetConfigValue(HorizonOCConfigValue_OverwriteRefreshRate) && !noDisp) { - if(targetHz) { - board::SetHz(HorizonOCModule_Display, targetHz); - this->context->freqs[HorizonOCModule_Display] = targetHz; - this->context->realFreqs[HorizonOCModule_Display] = targetHz; - } else { - HandleFreqReset(HorizonOCModule_Display, isBoost); - } - - } - - // Skip GPU and CPU if governors handle them - if(module > SysClkModule_MEM) { - continue; - } - - - if(noCPU && module == SysClkModule_CPU) - continue; - if(noGPU && module == SysClkModule_GPU) - continue; - - if (targetHz) - { - maxHz = this->GetMaxAllowedHz((SysClkModule)module, this->context->profile); - nearestHz = this->GetNearestHz((SysClkModule)module, targetHz, maxHz); - - if (nearestHz != this->context->freqs[module]) { - FileUtils::LogLine( - "[mgr] %s clock set : %u.%u MHz (target = %u.%u MHz)", - board::GetModuleName((SysClkModule)module, true), - nearestHz / 1000000, nearestHz / 100000 - nearestHz / 1000000 * 10, - targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10 - ); - - if(module == SysClkModule_MEM && board::GetSocType() == SysClkSocType_Mariko && targetHz > oldHz && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) { - DVFSBeforeSet(targetHz); - } - - board::SetHz((SysClkModule)module, nearestHz); - this->context->freqs[module] = nearestHz; - - if(module == SysClkModule_CPU && (this->config->GetConfigValue(HorizonOCConfigValue_LiveCpuUv))) { - HandleCpuUv(); - } - - if(module == SysClkModule_MEM && board::GetSocType() == SysClkSocType_Mariko && targetHz < oldHz && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) { - DVFSAfterSet(targetHz); - } - } - } else { - HandleFreqReset((SysClkModule)module, isBoost); - } - } - -} - -void ClockManager::Tick() -{ - std::scoped_lock lock{this->contextMutex}; - std::uint32_t mode = 0; - Result rc = apmExtGetCurrentPerformanceConfiguration(&mode); - ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration"); - - bool isBoost = apmExtIsBoostMode(mode); - - HandleSafetyFeatures(); - - if (this->RefreshContext() || this->config->Refresh()) - { - HandleMiscFeatures(); - SetClocks(isBoost); - } -} - -void ClockManager::ResetToStockClocks() { - board::ResetToStockCpu(); - if(this->config->GetConfigValue(HorizonOCConfigValue_LiveCpuUv)) - { - if(board::GetSocType() == SysClkSocType_Erista) - board::SetDfllTunings(this->config->GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); - else - board::SetDfllTunings(this->config->GetConfigValue(KipConfigValue_marikoCpuUVLow), this->config->GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(this->config->GetConfigValue(KipConfigValue_tableConf))); - } - - board::ResetToStockGpu(); -} - -void ClockManager::WaitForNextTick() -{ - if(!(board::GetHz(SysClkModule_MEM) < 665000000)) - svcSleepThread(this->GetConfig()->GetConfigValue(SysClkConfigValue_PollingIntervalMs) * 1000000ULL); - else - svcSleepThread(5000 * 1000000ULL); // 5 seconds in sleep mode -} - -bool ClockManager::RefreshContext() -{ - bool hasChanged = false; - - std::uint32_t mode = 0; - Result rc = apmExtGetCurrentPerformanceConfiguration(&mode); - ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration"); - - std::uint64_t applicationId = processManagement::GetCurrentApplicationId(); - if (applicationId != this->context->applicationId) - { - FileUtils::LogLine("[mgr] TitleID change: %016lX", applicationId); - this->context->applicationId = applicationId; - hasChanged = true; - } - - SysClkProfile profile = board::GetProfile(); - if (profile != this->context->profile) - { - FileUtils::LogLine("[mgr] Profile change: %s", board::GetProfileName(profile, true)); - this->context->profile = profile; - hasChanged = true; - } - - // restore clocks to stock values on app or profile change - if (hasChanged) - { - board::ResetToStock(); - if (board::GetSocType() == SysClkSocType_Mariko && this->config->GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) { - board::PcvHijackGpuVolts(0); board::SetHz(SysClkModule_GPU, ~0); board::ResetToStockGpu(); } - this->WaitForNextTick(); } - std::uint32_t hz = 0; - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) + void HandleCpuUv() { - hz = board::GetHz((SysClkModule)module); - if (hz != 0 && hz != this->context->freqs[module]) - { - FileUtils::LogLine("[mgr] %s clock change: %u.%u MHz", board::GetModuleName((SysClkModule)module, true), hz / 1000000, hz / 100000 - hz / 1000000 * 10); - this->context->freqs[module] = hz; - hasChanged = true; - } + if (board::GetSocType() == SysClkSocType_Erista) + board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); + else + board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf))); + } - hz = this->GetConfig()->GetOverrideHz((SysClkModule)module); - if (hz != this->context->overrideFreqs[module]) - { - if (hz) - { - FileUtils::LogLine("[mgr] %s override change: %u.%u MHz", board::GetModuleName((SysClkModule)module, true), hz / 1000000, hz / 100000 - hz / 1000000 * 10); + void DVFSReset() + { + if (board::GetSocType() == SysClkSocType_Mariko && config::GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) { + board::PcvHijackGpuVolts(0); + + u32 targetHz = gContext.overrideFreqs[SysClkModule_GPU]; + if (!targetHz) { + targetHz = config::GetAutoClockHz(gContext.applicationId, SysClkModule_GPU, gContext.profile, false); + if (!targetHz) { + targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, SysClkModule_GPU, gContext.profile, false); + } } - this->context->overrideFreqs[module] = hz; - hasChanged = true; - } - } + u32 maxHz = GetMaxAllowedHz(SysClkModule_GPU, gContext.profile); + u32 nearestHz = GetNearestHz(SysClkModule_GPU, targetHz, maxHz); - std::uint64_t ns = armTicksToNs(armGetSystemTick()); - - // temperatures do not and should not force a refresh, hasChanged untouched - std::uint32_t millis = 0; - bool shouldLogTemp = this->ConfigIntervalTimeout(SysClkConfigValue_TempLogIntervalMs, ns, &this->lastTempLogNs); - for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) - { - millis = board::GetTemperatureMilli((SysClkThermalSensor)sensor); - if (shouldLogTemp) - { - FileUtils::LogLine("[mgr] %s temp: %u.%u °C", board::GetThermalSensorName((SysClkThermalSensor)sensor, true), millis / 1000, (millis - millis / 1000 * 1000) / 100); - } - this->context->temps[sensor] = millis; - } - - // power stats do not and should not force a refresh, hasChanged untouched - std::int32_t mw = 0; - bool shouldLogPower = this->ConfigIntervalTimeout(SysClkConfigValue_PowerLogIntervalMs, ns, &this->lastPowerLogNs); - for (unsigned int sensor = 0; sensor < SysClkPowerSensor_EnumMax; sensor++) - { - mw = board::GetPowerMw((SysClkPowerSensor)sensor); - if (shouldLogPower) - { - FileUtils::LogLine("[mgr] Power %s: %d mW", board::GetPowerSensorName((SysClkPowerSensor)sensor, false), mw); - } - this->context->power[sensor] = mw; - } - - // real freqs do not and should not force a refresh, hasChanged untouched - std::uint32_t realHz = 0; - bool shouldLogFreq = this->ConfigIntervalTimeout(SysClkConfigValue_FreqLogIntervalMs, ns, &this->lastFreqLogNs); - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - realHz = board::GetRealHz((SysClkModule)module); - if (shouldLogFreq) - { - FileUtils::LogLine("[mgr] %s real freq: %u.%u MHz", board::GetModuleName((SysClkModule)module, true), realHz / 1000000, realHz / 100000 - realHz / 1000000 * 10); - } - this->context->realFreqs[module] = realHz; - } - - // ram load do not and should not force a refresh, hasChanged untouched - for (unsigned int loadSource = 0; loadSource < SysClkPartLoad_EnumMax; loadSource++) - { - this->context->partLoad[loadSource] = board::GetPartLoad((SysClkPartLoad)loadSource); - } - - for (unsigned int voltageSource = 0; voltageSource < HocClkVoltage_EnumMax; voltageSource++) - { - this->context->voltages[voltageSource] = board::GetVoltage((HocClkVoltage)voltageSource); - } - - if (this->ConfigIntervalTimeout(SysClkConfigValue_CsvWriteIntervalMs, ns, &this->lastCsvWriteNs)) - { - FileUtils::WriteContextToCsv(this->context); - } - - // this->context->maxDisplayFreq = board::GetHighestDockedDisplayRate(); - u32 targetHz = this->context->overrideFreqs[HorizonOCModule_Display]; - if (!targetHz) - { - targetHz = this->config->GetAutoClockHz(this->context->applicationId, HorizonOCModule_Display, this->context->profile, true); - if(!targetHz) - targetHz = this->config->GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Display, this->context->profile, true); - } - - if(targetHz && this->context->realFreqs[HorizonOCModule_Display] > targetHz && this->context->profile != SysClkProfile_Docked) { - this->context->realFreqs[HorizonOCModule_Display] = targetHz; // clean up display real freqs, should probably be moved to the real freqs loop? - hasChanged = true; - } - - if(board::GetConsoleType() != HorizonOCConsoleType_Hoag) - board::SetDisplayRefreshDockedState(this->context->profile == SysClkProfile_Docked); - if(this->context->isSaltyNXInstalled) - this->context->fps = saltyNXIntegration->GetFPS(); - else - this->context->fps = 254; // N/A - - if(this->context->isSaltyNXInstalled) - this->context->resolutionHeight = saltyNXIntegration->GetResolutionHeight(); - else - this->context->resolutionHeight = 0; // N/A - - return hasChanged; -} - -void ClockManager::SetKipData() { - // TODO: figure out if this REALLY causes issues (i doubt it) - // if(board::GetSocType() == SysClkSocType_Mariko) { - // if(R_FAILED(I2c_BuckConverter_SetMvOut(&I2c_Mariko_DRAM_VDDQ, this->config->GetConfigValue(KipConfigValue_marikoEmcVddqVolt) / 1000))) { - // FileUtils::LogLine("[clock_manager] Failed set i2c vddq"); - // writeNotification("Horizon OC\nFailed to write I2C\nwhile setting vddq"); - // } - // } - CustomizeTable table; - FILE* fp; - fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r"); - - if (fp == NULL) { - writeNotification("Horizon OC\nKip opening failed"); - kipAvailable = false; - return; - } else { - kipAvailable = true; - fclose(fp); - } - - if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) { - FileUtils::LogLine("[clock_manager] Failed to read KIP file"); - writeNotification("Horizon OC\nKip read failed"); - return; - } - - CUST_WRITE_FIELD_BATCH(&table, custRev, this->config->GetConfigValue(KipConfigValue_custRev)); - // CUST_WRITE_FIELD_BATCH(&table, mtcConf, this->config->GetConfigValue(KipConfigValue_mtcConf)); - CUST_WRITE_FIELD_BATCH(&table, hpMode, this->config->GetConfigValue(KipConfigValue_hpMode)); - - CUST_WRITE_FIELD_BATCH(&table, commonEmcMemVolt, this->config->GetConfigValue(KipConfigValue_commonEmcMemVolt)); - CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock)); - CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock1, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock1)); - CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock2, this->config->GetConfigValue(KipConfigValue_eristaEmcMaxClock2)); - CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock)); - CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, this->config->GetConfigValue(KipConfigValue_marikoEmcVddqVolt)); - CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, this->config->GetConfigValue(KipConfigValue_emcDvbShift)); - - CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, this->config->GetConfigValue(KipConfigValue_t1_tRCD)); - CUST_WRITE_FIELD_BATCH(&table, t2_tRP, this->config->GetConfigValue(KipConfigValue_t2_tRP)); - CUST_WRITE_FIELD_BATCH(&table, t3_tRAS, this->config->GetConfigValue(KipConfigValue_t3_tRAS)); - CUST_WRITE_FIELD_BATCH(&table, t4_tRRD, this->config->GetConfigValue(KipConfigValue_t4_tRRD)); - CUST_WRITE_FIELD_BATCH(&table, t5_tRFC, this->config->GetConfigValue(KipConfigValue_t5_tRFC)); - CUST_WRITE_FIELD_BATCH(&table, t6_tRTW, this->config->GetConfigValue(KipConfigValue_t6_tRTW)); - CUST_WRITE_FIELD_BATCH(&table, t7_tWTR, this->config->GetConfigValue(KipConfigValue_t7_tWTR)); - CUST_WRITE_FIELD_BATCH(&table, t8_tREFI, this->config->GetConfigValue(KipConfigValue_t8_tREFI)); - CUST_WRITE_FIELD_BATCH(&table, mem_burst_read_latency, this->config->GetConfigValue(KipConfigValue_mem_burst_read_latency)); - CUST_WRITE_FIELD_BATCH(&table, mem_burst_write_latency, this->config->GetConfigValue(KipConfigValue_mem_burst_write_latency)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuUV, this->config->GetConfigValue(KipConfigValue_eristaCpuUV)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuVmin, this->config->GetConfigValue(KipConfigValue_eristaCpuVmin)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuMaxVolt, this->config->GetConfigValue(KipConfigValue_eristaCpuMaxVolt)); - CUST_WRITE_FIELD_BATCH(&table, eristaCpuUnlock, this->config->GetConfigValue(KipConfigValue_eristaCpuUnlock)); - - CUST_WRITE_FIELD_BATCH(&table, marikoCpuUVLow, this->config->GetConfigValue(KipConfigValue_marikoCpuUVLow)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuUVHigh, this->config->GetConfigValue(KipConfigValue_marikoCpuUVHigh)); - CUST_WRITE_FIELD_BATCH(&table, tableConf, this->config->GetConfigValue(KipConfigValue_tableConf)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuLowVmin, this->config->GetConfigValue(KipConfigValue_marikoCpuLowVmin)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuHighVmin, this->config->GetConfigValue(KipConfigValue_marikoCpuHighVmin)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuMaxVolt, this->config->GetConfigValue(KipConfigValue_marikoCpuMaxVolt)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuMaxClock, this->config->GetConfigValue(KipConfigValue_marikoCpuMaxClock)); - - CUST_WRITE_FIELD_BATCH(&table, eristaCpuBoostClock, this->config->GetConfigValue(KipConfigValue_eristaCpuBoostClock)); - CUST_WRITE_FIELD_BATCH(&table, marikoCpuBoostClock, this->config->GetConfigValue(KipConfigValue_marikoCpuBoostClock)); - - CUST_WRITE_FIELD_BATCH(&table, eristaGpuUV, this->config->GetConfigValue(KipConfigValue_eristaGpuUV)); - CUST_WRITE_FIELD_BATCH(&table, eristaGpuVmin, this->config->GetConfigValue(KipConfigValue_eristaGpuVmin)); - - CUST_WRITE_FIELD_BATCH(&table, marikoGpuUV, this->config->GetConfigValue(KipConfigValue_marikoGpuUV)); - CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmin, this->config->GetConfigValue(KipConfigValue_marikoGpuVmin)); - CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmax, this->config->GetConfigValue(KipConfigValue_marikoGpuVmax)); - - CUST_WRITE_FIELD_BATCH(&table, commonGpuVoltOffset, this->config->GetConfigValue(KipConfigValue_commonGpuVoltOffset)); - CUST_WRITE_FIELD_BATCH(&table, gpuSpeedo, this->config->GetConfigValue(KipConfigValue_gpuSpeedo)); - - for (int i = 0; i < 24; i++) { - table.marikoGpuVoltArray[i] = this->config->GetConfigValue((SysClkConfigValue)(KipConfigValue_g_volt_76800 + i)); - } - - for (int i = 0; i < 27; i++) { - table.eristaGpuVoltArray[i] = this->config->GetConfigValue((SysClkConfigValue)(KipConfigValue_g_volt_e_76800 + i)); - } - - CUST_WRITE_FIELD_BATCH(&table, t6_tRTW_fine_tune, this->config->GetConfigValue(KipConfigValue_t6_tRTW_fine_tune)); - CUST_WRITE_FIELD_BATCH(&table, t7_tWTR_fine_tune, this->config->GetConfigValue(KipConfigValue_t7_tWTR_fine_tune)); - - if (!cust_write_table("sdmc:/atmosphere/kips/hoc.kip", &table)) { - FileUtils::LogLine("[clock_manager] Failed to write KIP file"); - writeNotification("Horizon OC\nKip write failed"); - } - - SysClkConfigValueList configValues; - this->config->GetConfigValues(&configValues); - - configValues.values[KipCrc32] = (u64)checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum - - if (this->config->SetConfigValues(&configValues, false)) { - FileUtils::LogLine("[clock_manager] Successfully loaded KIP data into config"); - } else { - FileUtils::LogLine("[clock_manager] Warning: Failed to set config values from KIP"); - writeNotification("Horizon OC\nKip config set failed"); - } -} - -// I know this is very hacky, but the config system in the sysmodule doesn't really support writing - -void ClockManager::GetKipData() { - FILE* fp; - if(this->config->Refresh()) { - - fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r"); - - if (fp == NULL) { - writeNotification("Horizon OC\nKip opening failed"); - kipAvailable = false; - return; - } else { - kipAvailable = true; - fclose(fp); - } - - - - SysClkConfigValueList configValues; - this->config->GetConfigValues(&configValues); - - CustomizeTable table; - - if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) { - FileUtils::LogLine("[clock_manager] Failed to read KIP file for GetKipData"); - writeNotification("Horizon OC\nKip read failed"); - return; - } - - if((u64)checksum_file("sdmc:/atmosphere/kips/hoc.kip") != this->config->GetConfigValue(KipCrc32) && !this->config->GetConfigValue(HocClkConfigValue_IsFirstLoad)) { - SetKipData(); - writeNotification("Horizon OC\nKIP has been updated"); - writeNotification("Horizon OC\nPlease reboot your console"); - writeNotification("Horizon OC\nto complete the update"); - return; - } - if(this->config->GetConfigValue(HocClkConfigValue_IsFirstLoad) == true) { - configValues.values[HocClkConfigValue_IsFirstLoad] = (u64)false; - writeNotification("Horizon OC has been installed"); - } - static bool writeBootConfigValues = true; - - configValues.values[KipCrc32] = (u64)checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum - - - if(writeBootConfigValues) { - writeBootConfigValues = false; - - // initialConfigValues[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table); - initialConfigValues[KipConfigValue_hpMode] = cust_get_hp_mode(&table); - - initialConfigValues[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table); - initialConfigValues[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table); - initialConfigValues[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table); - initialConfigValues[KipConfigValue_eristaEmcMaxClock2] = cust_get_erista_emc_max2(&table); - initialConfigValues[KipConfigValue_marikoEmcMaxClock] = cust_get_mariko_emc_max(&table); - initialConfigValues[KipConfigValue_marikoEmcVddqVolt] = cust_get_mariko_emc_vddq(&table); - initialConfigValues[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table); - - initialConfigValues[KipConfigValue_t1_tRCD] = cust_get_tRCD(&table); - initialConfigValues[KipConfigValue_t2_tRP] = cust_get_tRP(&table); - initialConfigValues[KipConfigValue_t3_tRAS] = cust_get_tRAS(&table); - initialConfigValues[KipConfigValue_t4_tRRD] = cust_get_tRRD(&table); - initialConfigValues[KipConfigValue_t5_tRFC] = cust_get_tRFC(&table); - initialConfigValues[KipConfigValue_t6_tRTW] = cust_get_tRTW(&table); - initialConfigValues[KipConfigValue_t7_tWTR] = cust_get_tWTR(&table); - initialConfigValues[KipConfigValue_t8_tREFI] = cust_get_tREFI(&table); - initialConfigValues[KipConfigValue_mem_burst_read_latency] = cust_get_burst_read_lat(&table); - initialConfigValues[KipConfigValue_mem_burst_write_latency] = cust_get_burst_write_lat(&table); - - initialConfigValues[KipConfigValue_eristaCpuUV] = cust_get_erista_cpu_uv(&table); - initialConfigValues[KipConfigValue_eristaCpuVmin] = cust_get_eristaCpuVmin(&table); - initialConfigValues[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table); - initialConfigValues[KipConfigValue_eristaCpuUnlock] = cust_get_eristaCpuUnlock(&table); - - initialConfigValues[KipConfigValue_marikoCpuUVLow] = cust_get_mariko_cpu_uv_low(&table); - initialConfigValues[KipConfigValue_marikoCpuUVHigh] = cust_get_mariko_cpu_uv_high(&table); - initialConfigValues[KipConfigValue_tableConf] = cust_get_table_conf(&table); - initialConfigValues[KipConfigValue_marikoCpuLowVmin] = cust_get_mariko_cpu_low_vmin(&table); - initialConfigValues[KipConfigValue_marikoCpuHighVmin] = cust_get_mariko_cpu_high_vmin(&table); - initialConfigValues[KipConfigValue_marikoCpuMaxVolt] = cust_get_mariko_cpu_max_volt(&table); - initialConfigValues[KipConfigValue_marikoCpuMaxClock] = cust_get_marikoCpuMaxClock(&table); - initialConfigValues[KipConfigValue_eristaCpuBoostClock] = cust_get_erista_cpu_boost(&table); - initialConfigValues[KipConfigValue_marikoCpuBoostClock] = cust_get_mariko_cpu_boost(&table); - - initialConfigValues[KipConfigValue_eristaGpuUV] = cust_get_erista_gpu_uv(&table); - initialConfigValues[KipConfigValue_eristaGpuVmin] = cust_get_erista_gpu_vmin(&table); - initialConfigValues[KipConfigValue_marikoGpuUV] = cust_get_mariko_gpu_uv(&table); - initialConfigValues[KipConfigValue_marikoGpuVmin] = cust_get_mariko_gpu_vmin(&table); - initialConfigValues[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table); - initialConfigValues[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table); - initialConfigValues[KipConfigValue_gpuSpeedo] = cust_get_gpu_speedo(&table); - initialConfigValues[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table); - initialConfigValues[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table); - } - - // configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table); - configValues.values[KipConfigValue_hpMode] = cust_get_hp_mode(&table); - - configValues.values[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table); - configValues.values[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table); - configValues.values[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table); - configValues.values[KipConfigValue_eristaEmcMaxClock2] = cust_get_erista_emc_max2(&table); - configValues.values[KipConfigValue_marikoEmcMaxClock] = cust_get_mariko_emc_max(&table); - configValues.values[KipConfigValue_marikoEmcVddqVolt] = cust_get_mariko_emc_vddq(&table); - configValues.values[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table); - - configValues.values[KipConfigValue_t1_tRCD] = cust_get_tRCD(&table); - configValues.values[KipConfigValue_t2_tRP] = cust_get_tRP(&table); - configValues.values[KipConfigValue_t3_tRAS] = cust_get_tRAS(&table); - configValues.values[KipConfigValue_t4_tRRD] = cust_get_tRRD(&table); - configValues.values[KipConfigValue_t5_tRFC] = cust_get_tRFC(&table); - configValues.values[KipConfigValue_t6_tRTW] = cust_get_tRTW(&table); - configValues.values[KipConfigValue_t7_tWTR] = cust_get_tWTR(&table); - configValues.values[KipConfigValue_t8_tREFI] = cust_get_tREFI(&table); - configValues.values[KipConfigValue_mem_burst_read_latency] = cust_get_burst_read_lat(&table); - configValues.values[KipConfigValue_mem_burst_write_latency] = cust_get_burst_write_lat(&table); - - configValues.values[KipConfigValue_eristaCpuUV] = cust_get_erista_cpu_uv(&table); - configValues.values[KipConfigValue_eristaCpuVmin] = cust_get_eristaCpuVmin(&table); - configValues.values[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table); - configValues.values[KipConfigValue_eristaCpuUnlock] = cust_get_eristaCpuUnlock(&table); - - - configValues.values[KipConfigValue_marikoCpuUVLow] = cust_get_mariko_cpu_uv_low(&table); - configValues.values[KipConfigValue_marikoCpuUVHigh] = cust_get_mariko_cpu_uv_high(&table); - configValues.values[KipConfigValue_tableConf] = cust_get_table_conf(&table); - configValues.values[KipConfigValue_marikoCpuLowVmin] = cust_get_mariko_cpu_low_vmin(&table); - configValues.values[KipConfigValue_marikoCpuHighVmin] = cust_get_mariko_cpu_high_vmin(&table); - configValues.values[KipConfigValue_marikoCpuMaxVolt] = cust_get_mariko_cpu_max_volt(&table); - configValues.values[KipConfigValue_marikoCpuMaxClock] = cust_get_marikoCpuMaxClock(&table); - configValues.values[KipConfigValue_eristaCpuBoostClock] = cust_get_erista_cpu_boost(&table); - configValues.values[KipConfigValue_marikoCpuBoostClock] = cust_get_mariko_cpu_boost(&table); - - configValues.values[KipConfigValue_eristaGpuUV] = cust_get_erista_gpu_uv(&table); - configValues.values[KipConfigValue_eristaGpuVmin] = cust_get_erista_gpu_vmin(&table); - configValues.values[KipConfigValue_marikoGpuUV] = cust_get_mariko_gpu_uv(&table); - configValues.values[KipConfigValue_marikoGpuVmin] = cust_get_mariko_gpu_vmin(&table); - configValues.values[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table); - configValues.values[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table); - configValues.values[KipConfigValue_gpuSpeedo] = board::GetFuseData()->gpuSpeedo; // cust_get_gpu_speedo(&table); - - for (int i = 0; i < 24; i++) { - configValues.values[KipConfigValue_g_volt_76800 + i] = cust_get_mariko_gpu_volt(&table, i); - initialConfigValues[KipConfigValue_g_volt_76800 + i] = cust_get_mariko_gpu_volt(&table, i); - } - - for (int i = 0; i < 27; i++) { - configValues.values[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_volt(&table, i); - initialConfigValues[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_volt(&table, i); - } - - configValues.values[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table); - configValues.values[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table); - - // if(cust_get_cust_rev(&table) == KIP_CUST_REV) - // return; - - if (sizeof(SysClkConfigValueList) <= sizeof(configValues)) { - if (this->config->SetConfigValues(&configValues, false)) { - FileUtils::LogLine("[clock_manager] Successfully loaded KIP data into config"); + board::SetHz(SysClkModule_GPU, ~0); + if (targetHz) { + board::SetHz(SysClkModule_GPU, nearestHz); } else { - FileUtils::LogLine("[clock_manager] Warning: Failed to set config values from KIP"); - writeNotification("Horizon OC\nKip config set failed"); + board::ResetToStockGpu(); } - } else { - FileUtils::LogLine("[clock_manager] Error: Config value list buffer size mismatch"); - writeNotification("Horizon OC\nConfig Buffer Mismatch"); } - } else { - FileUtils::LogLine("[clock_manager] Config refresh error in GetKipData!"); - writeNotification("Horizon OC\nConfig refresh failed"); } -} + + void HandleFreqReset(SysClkModule module, bool isBoost) + { + switch (module) { + case SysClkModule_CPU: + if (!(isBoost || (config::GetConfigValue(HocClkConfigValue_OverwriteBoostMode) && isBoost))) + board::ResetToStockCpu(); + if (config::GetConfigValue(HorizonOCConfigValue_LiveCpuUv)) { + if (board::GetSocType() == SysClkSocType_Erista) + board::SetDfllTunings(config::GetConfigValue(KipConfigValue_eristaCpuUV), 0, 1581000000); + else + board::SetDfllTunings(config::GetConfigValue(KipConfigValue_marikoCpuUVLow), config::GetConfigValue(KipConfigValue_marikoCpuUVHigh), board::CalculateTbreak(config::GetConfigValue(KipConfigValue_tableConf))); + } + break; + case SysClkModule_GPU: + board::ResetToStockGpu(); + break; + case SysClkModule_MEM: + board::ResetToStockMem(); + DVFSReset(); + break; + case HorizonOCModule_Display: + if (config::GetConfigValue(HorizonOCConfigValue_OverwriteRefreshRate)) { + board::ResetToStockDisplay(); + } + break; + default: + break; + } + } + + void SetClocks(bool isBoost) + { + std::uint32_t targetHz = 0; + std::uint32_t maxHz = 0; + std::uint32_t nearestHz = 0; + + if (isBoost && !config::GetConfigValue(HocClkConfigValue_OverwriteBoostMode)) { + u32 boostFreq = board::GetHz(SysClkModule_CPU); + if (boostFreq / 1000000 > 1785) { + board::SetHz(SysClkModule_CPU, boostFreq); + } + return; // Return if we aren't overwriting boost mode + } + + bool returnRaw = false; // Return a value scaled to MHz instead of raw value + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + u32 oldHz = board::GetHz((SysClkModule)module); // Get Old hz (used primarily for DVFS Logic) + + if (module > SysClkModule_MEM) + returnRaw = true; + else + returnRaw = false; + targetHz = gContext.overrideFreqs[module]; + if (!targetHz) { + targetHz = config::GetAutoClockHz(gContext.applicationId, (SysClkModule)module, gContext.profile, returnRaw); + if (!targetHz) + targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, (SysClkModule)module, gContext.profile, returnRaw); + } + + if (module == HorizonOCModule_Governor) { + governor::HandleGovernor(targetHz); + } + + bool noCPU = governor::isCpuGovernorEnabled; + bool noGPU = governor::isGpuGovernorEnabled; + bool noDisp = governor::isVRREnabled; + if (noDisp && module == HorizonOCModule_Display) + continue; + + if (module == HorizonOCModule_Display && config::GetConfigValue(HorizonOCConfigValue_OverwriteRefreshRate) && !noDisp) { + if (targetHz) { + board::SetHz(HorizonOCModule_Display, targetHz); + gContext.freqs[HorizonOCModule_Display] = targetHz; + gContext.realFreqs[HorizonOCModule_Display] = targetHz; + } else { + HandleFreqReset(HorizonOCModule_Display, isBoost); + } + } + + // Skip GPU and CPU if governors handle them + if (module > SysClkModule_MEM) { + continue; + } + + if (noCPU && module == SysClkModule_CPU) + continue; + if (noGPU && module == SysClkModule_GPU) + continue; + + if (targetHz) { + maxHz = GetMaxAllowedHz((SysClkModule)module, gContext.profile); + nearestHz = GetNearestHz((SysClkModule)module, targetHz, maxHz); + + if (nearestHz != gContext.freqs[module]) { + fileUtils::LogLine( + "[mgr] %s clock set : %u.%u MHz (target = %u.%u MHz)", + board::GetModuleName((SysClkModule)module, true), + nearestHz / 1000000, nearestHz / 100000 - nearestHz / 1000000 * 10, + targetHz / 1000000, targetHz / 100000 - targetHz / 1000000 * 10 + ); + + if (module == SysClkModule_MEM && board::GetSocType() == SysClkSocType_Mariko && targetHz > oldHz && config::GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) { + DVFSBeforeSet(targetHz); + } + + board::SetHz((SysClkModule)module, nearestHz); + gContext.freqs[module] = nearestHz; + + if (module == SysClkModule_CPU && config::GetConfigValue(HorizonOCConfigValue_LiveCpuUv)) { + HandleCpuUv(); + } + + if (module == SysClkModule_MEM && board::GetSocType() == SysClkSocType_Mariko && targetHz < oldHz && config::GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) { + DVFSAfterSet(targetHz); + } + } + } else { + HandleFreqReset((SysClkModule)module, isBoost); + } + } + } + + bool RefreshContext() + { + bool hasChanged = false; + + std::uint32_t mode = 0; + Result rc = apmExtGetCurrentPerformanceConfiguration(&mode); + ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration"); + + std::uint64_t applicationId = processManagement::GetCurrentApplicationId(); + if (applicationId != gContext.applicationId) { + fileUtils::LogLine("[mgr] TitleID change: %016lX", applicationId); + gContext.applicationId = applicationId; + hasChanged = true; + } + + SysClkProfile profile = board::GetProfile(); + if (profile != gContext.profile) { + fileUtils::LogLine("[mgr] Profile change: %s", board::GetProfileName(profile, true)); + gContext.profile = profile; + hasChanged = true; + } + + // restore clocks to stock values on app or profile change + if (hasChanged) { + board::ResetToStock(); + if (board::GetSocType() == SysClkSocType_Mariko && config::GetConfigValue(HorizonOCConfigValue_DVFSMode) == DVFSMode_Hijack) { + board::PcvHijackGpuVolts(0); + board::SetHz(SysClkModule_GPU, ~0); + board::ResetToStockGpu(); + } + WaitForNextTick(); + } + + std::uint32_t hz = 0; + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + hz = board::GetHz((SysClkModule)module); + if (hz != 0 && hz != gContext.freqs[module]) { + fileUtils::LogLine("[mgr] %s clock change: %u.%u MHz", board::GetModuleName((SysClkModule)module, true), hz / 1000000, hz / 100000 - hz / 1000000 * 10); + gContext.freqs[module] = hz; + hasChanged = true; + } + + hz = config::GetOverrideHz((SysClkModule)module); + if (hz != gContext.overrideFreqs[module]) { + if (hz) { + fileUtils::LogLine("[mgr] %s override change: %u.%u MHz", board::GetModuleName((SysClkModule)module, true), hz / 1000000, hz / 100000 - hz / 1000000 * 10); + } + gContext.overrideFreqs[module] = hz; + hasChanged = true; + } + } + + std::uint64_t ns = armTicksToNs(armGetSystemTick()); + + // temperatures do not and should not force a refresh, hasChanged untouched + std::uint32_t millis = 0; + bool shouldLogTemp = ConfigIntervalTimeout(SysClkConfigValue_TempLogIntervalMs, ns, &gLastTempLogNs); + for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) { + millis = board::GetTemperatureMilli((SysClkThermalSensor)sensor); + if (shouldLogTemp) { + fileUtils::LogLine("[mgr] %s temp: %u.%u °C", board::GetThermalSensorName((SysClkThermalSensor)sensor, true), millis / 1000, (millis - millis / 1000 * 1000) / 100); + } + gContext.temps[sensor] = millis; + } + + // power stats do not and should not force a refresh, hasChanged untouched + std::int32_t mw = 0; + bool shouldLogPower = ConfigIntervalTimeout(SysClkConfigValue_PowerLogIntervalMs, ns, &gLastPowerLogNs); + for (unsigned int sensor = 0; sensor < SysClkPowerSensor_EnumMax; sensor++) { + mw = board::GetPowerMw((SysClkPowerSensor)sensor); + if (shouldLogPower) { + fileUtils::LogLine("[mgr] Power %s: %d mW", board::GetPowerSensorName((SysClkPowerSensor)sensor, false), mw); + } + gContext.power[sensor] = mw; + } + + // real freqs do not and should not force a refresh, hasChanged untouched + std::uint32_t realHz = 0; + bool shouldLogFreq = ConfigIntervalTimeout(SysClkConfigValue_FreqLogIntervalMs, ns, &gLastFreqLogNs); + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + realHz = board::GetRealHz((SysClkModule)module); + if (shouldLogFreq) { + fileUtils::LogLine("[mgr] %s real freq: %u.%u MHz", board::GetModuleName((SysClkModule)module, true), realHz / 1000000, realHz / 100000 - realHz / 1000000 * 10); + } + gContext.realFreqs[module] = realHz; + } + + // ram load do not and should not force a refresh, hasChanged untouched + for (unsigned int loadSource = 0; loadSource < SysClkPartLoad_EnumMax; loadSource++) { + gContext.partLoad[loadSource] = board::GetPartLoad((SysClkPartLoad)loadSource); + } + + for (unsigned int voltageSource = 0; voltageSource < HocClkVoltage_EnumMax; voltageSource++) { + gContext.voltages[voltageSource] = board::GetVoltage((HocClkVoltage)voltageSource); + } + + if (ConfigIntervalTimeout(SysClkConfigValue_CsvWriteIntervalMs, ns, &gLastCsvWriteNs)) { + fileUtils::WriteContextToCsv(&gContext); + } + + // this->context->maxDisplayFreq = board::GetHighestDockedDisplayRate(); + u32 targetHz = gContext.overrideFreqs[HorizonOCModule_Display]; + if (!targetHz) { + targetHz = config::GetAutoClockHz(gContext.applicationId, HorizonOCModule_Display, gContext.profile, true); + if (!targetHz) + targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Display, gContext.profile, true); + } + + if (board::GetConsoleType() != HorizonOCConsoleType_Hoag) + board::SetDisplayRefreshDockedState(gContext.profile == SysClkProfile_Docked); + + if (gContext.isSaltyNXInstalled) + gContext.fps = integrations::GetSaltyNXFPS(); + else + gContext.fps = 254; // N/A + + if (gContext.isSaltyNXInstalled) + gContext.resolutionHeight = integrations::GetSaltyNXResolutionHeight(); + else + gContext.resolutionHeight = 0; // N/A + + return hasChanged; + } + + void Initialize() + { + config::Initialize(); + + gContext = {}; + gContext.applicationId = 0; + gContext.profile = SysClkProfile_Handheld; + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + gContext.freqs[module] = 0; + gContext.realFreqs[module] = 0; + gContext.overrideFreqs[module] = 0; + RefreshFreqTableRow((SysClkModule)module); + } + + gRunning = false; + gLastTempLogNs = 0; + gLastCsvWriteNs = 0; + + kip::GetKipData(); + + board::FuseData *fuse = board::GetFuseData(); + + gContext.speedos[0] = fuse->cpuSpeedo; + gContext.speedos[1] = fuse->gpuSpeedo; + gContext.speedos[2] = fuse->socSpeedo; + gContext.iddq[0] = fuse->cpuIDDQ; + gContext.iddq[1] = fuse->gpuIDDQ; + gContext.iddq[2] = fuse->socIDDQ; + gContext.waferX = fuse->waferX; + gContext.waferY = fuse->waferY; + + gContext.dramID = board::GetDramID(); + gContext.isDram8GB = board::IsDram8GB(); + board::SetGpuSchedulingMode((GpuSchedulingMode)config::GetConfigValue(HorizonOCConfigValue_GPUScheduling), (GpuSchedulingOverrideMethod)config::GetConfigValue(HorizonOCConfigValue_GPUSchedulingMethod)); + gContext.gpuSchedulingMode = (GpuSchedulingMode)config::GetConfigValue(HorizonOCConfigValue_GPUScheduling); + + gContext.isSysDockInstalled = integrations::GetSysDockState(); + gContext.isSaltyNXInstalled = integrations::GetSaltyNXState(); + if (gContext.isSaltyNXInstalled) { + integrations::LoadSaltyNX(); + } + + gContext.isUsingRetroSuper = board::IsUsingRetroSuperDisplay(); + governor::startThreads(); + } + + void Exit() + { + governor::exitThreads(); + config::Exit(); + } + + SysClkContext GetCurrentContext() + { + std::scoped_lock lock{gContextMutex}; + return gContext; + } + + void SetRunning(bool running) + { + gRunning = running; + } + + bool Running() + { + return gRunning; + } + + void GetFreqList(SysClkModule module, std::uint32_t *list, std::uint32_t maxCount, std::uint32_t *outCount) + { + ASSERT_ENUM_VALID(SysClkModule, module); + + *outCount = std::min(maxCount, gFreqTable[module].count); + memcpy(list, &gFreqTable[module].list[0], *outCount * sizeof(gFreqTable[0].list[0])); + } + + void Tick() + { + std::scoped_lock lock{gContextMutex}; + std::uint32_t mode = 0; + Result rc = apmExtGetCurrentPerformanceConfiguration(&mode); + ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration"); + + bool isBoost = apmExtIsBoostMode(mode); + + HandleSafetyFeatures(); + + if (RefreshContext() || config::Refresh()) { + HandleMiscFeatures(); + SetClocks(isBoost); + } + } + + void WaitForNextTick() + { + if (!(board::GetHz(SysClkModule_MEM) < 665000000)) + svcSleepThread(config::GetConfigValue(SysClkConfigValue_PollingIntervalMs) * 1000000ULL); + else + svcSleepThread(5000 * 1000000ULL); // 5 seconds in sleep mode + } +} // namespace clockManager diff --git a/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.h b/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.h deleted file mode 100644 index 9e195931..00000000 --- a/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.h +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -/* -------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * , , - * 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 -#include -#include -#include "config.h" -#include -#include "integrations.h" - -class SysDockIntegration; -class SaltyNXIntegration; -class ClockManager -{ - public: - /** - * Get instance - * @return Pointer to a ClockManager instance - */ - static ClockManager* GetInstance(); - static void Initialize(); - static void Exit(); - ClockManager(); - virtual ~ClockManager(); - - /** - * Get context object - * @return Context instance - */ - SysClkContext GetCurrentContext(); - - /** - * Get config object - * @return Pointer to a config instance - */ - Config* GetConfig(); - - /** - * Set clock manager running - * @param running Is running or not? - */ - void SetRunning(bool running); - - /** - * Is clock manager running - * @return running or not? - */ - bool Running(); - - /** - * Get frequency list from clkrst - * - * @param module Module to get frequency list for - * @param list List of frequencies - * @param maxCount How many entries to expect in list. Usually 32 - * @param outCount How many entries were retrived - */ - void GetFreqList(SysClkModule module, std::uint32_t* list, std::uint32_t maxCount, std::uint32_t* outCount); - - /** - * Handles safety features - * - */ - void HandleSafetyFeatures(); - - /** - * Handles misc features (currently only battery charge current). - * - */ - void HandleMiscFeatures(); - - /** - * Handles governor state resolution and applies CPU/GPU governor transitions. - * - * @param targetHz Governor override value for the current profile. - */ - void HandleGovernor(uint32_t targetHz); - - /** - * Handles DVFS logic before the frequency set - * - * @param targetHz Governor override value for the current profile. - */ - void DVFSBeforeSet(u32 targetHz); - - /** - * Handles DVFS logic after the frequency set - * - * @param targetHz Governor override value for the current profile. - */ - void DVFSAfterSet(u32 targetHz); - - /** - * Reset the GPU vMin - * - */ - void DVFSReset(); - - /** - * Handles the Live CPU UV Feature - * - */ - void HandleCpuUv(); - - /** - * Handles frequency resets - * - * @param module The module to reset frequency for - * @param isBoost Is in boost mode - */ - void HandleFreqReset(SysClkModule module, bool isBoost); - - /** - * Sets clocks - * - * @param isBoost Is in boost mode - */ - void SetClocks(bool isBoost); - - /** - * Main function, runs every 5s in sleep mode, and a user specified amount when awake - * - */ - void Tick(); - - /** - * Reset CPU/GPU to stock values - * - */ - void ResetToStockClocks(); - - /** - * Wait for the next tick event - * - */ - void WaitForNextTick(); - - /** - * Set the data in the KIP - * - */ - void SetKipData(); - - /** - * Get the data from the KIP - * - */ - void GetKipData(); - - /** - * Runs the CPU Governor - * - * @param arg Cast to ClockManager* for context - */ - static void CpuGovernorThread(void* arg); - - /** - * Runs the GPU Governor - * - * @param arg Cast to ClockManager* for context - */ - static void GovernorThread(void* arg); - - /** - * Runs the VRR Algorithm - * - * @param arg Cast to ClockManager* for context - */ - static void VRRThread(void* arg); - - /** - * Frequency table - * - */ - struct FreqTable { - std::uint32_t count; - std::uint32_t list[SYSCLK_FREQ_LIST_MAX]; - } freqTable[SysClkModule_EnumMax]; - - /** - * Gets the current GPU speedo bracket - * - * @param speedo GPU Speedo - */ - int GetSpeedoBracket (int speedo); - - /** - * Gets the required vMin for a ram frequency for a speedo - * - * @param freq RAM Freq in MHz - * @param speedo GPU Speedo - */ - unsigned int GetGpuVoltage (unsigned int freq, int speedo); - - /** - * Gets the required vMin for a ram frequency for a speedo - * - * @param util Utilization in percentile - * @param tableMaxHz Table Max Hz - */ - static u32 SchedutilTargetHz(u32 util, u32 tableMaxHz); - - /** - * Gets the required vMin for a ram frequency for a speedo - * - * @param table FreqTable for module - * @param targetHz Hz to search for - */ - static u32 TableIndexForHz(const FreqTable& table, u32 targetHz); - - /** - * Gets the required vMin for a ram frequency for a speedo - * - * @param mgr ClockManager instance (runs in a thread so must be passed) - * @param module Module for which to resolve target Hz - */ - static u32 ResolveTargetHz(ClockManager* mgr, SysClkModule module); - - protected: - bool IsAssignableHz(SysClkModule module, std::uint32_t hz); - inline std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile); - std::uint32_t GetNearestHz(SysClkModule module, std::uint32_t inHz, std::uint32_t maxHz); - bool ConfigIntervalTimeout(SysClkConfigValue intervalMsConfigValue, std::uint64_t ns, std::uint64_t* lastLogNs); - void RefreshFreqTableRow(SysClkModule module); - bool RefreshContext(); - static ClockManager *instance; - std::atomic_bool running; - LockableMutex contextMutex; - Config* config; - SysClkContext* context; - std::uint64_t lastTempLogNs; - std::uint64_t lastFreqLogNs; - std::uint64_t lastPowerLogNs; - std::uint64_t lastCsvWriteNs; - SysDockIntegration *sysDockIntegration; - SaltyNXIntegration *saltyNXIntegration; -}; \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.hpp b/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.hpp new file mode 100644 index 00000000..cd4ee1b5 --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/clock_manager.hpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/* -------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * , , + * 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 +#include +#include + +namespace clockManager { + + struct FreqTable { + std::uint32_t count; + std::uint32_t list[SYSCLK_FREQ_LIST_MAX]; + }; + + + extern bool hasChanged; + + // instance variables + extern bool gRunning; + extern LockableMutex gContextMutex; + extern SysClkContext gContext; + extern FreqTable gFreqTable[SysClkModule_EnumMax]; + extern std::uint64_t gLastTempLogNs; + extern std::uint64_t gLastFreqLogNs; + extern std::uint64_t gLastPowerLogNs; + extern std::uint64_t gLastCsvWriteNs; + + + void Initialize(); + void Exit(); + + SysClkContext GetCurrentContext(); + + void SetRunning(bool running); + bool Running(); + + std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile); + bool IsAssignableHz(SysClkModule module, std::uint32_t hz); + + void GetFreqList(SysClkModule module, std::uint32_t* list, std::uint32_t maxCount, std::uint32_t* outCount); + + void Tick(); + void WaitForNextTick(); +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/config.cpp b/Source/rewrite-hoc-clk/sysmodule/src/config.cpp index 31090152..00bff981 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/config.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/config.cpp @@ -24,497 +24,454 @@ * -------------------------------------------------------------------------- */ - -#include "config.h" +#include "config.hpp" #include #include #include #include #include #include -#include "errors.h" -#include "file_utils.h" +#include +#include +#include +#include +#include +#include +#include +#include "board/board.hpp" +#include "errors.hpp" +#include "file_utils.hpp" -Config::Config(std::string path) -{ - this->path = path; - this->loaded = false; - this->profileMHzMap = std::map, std::uint32_t>(); - this->profileCountMap = std::map(); - this->mtime = 0; - this->enabled = false; - for(unsigned int i = 0; i < SysClkModule_EnumMax; i++) - { - this->overrideFreqs[i] = 0; - } +namespace config { - for(unsigned int i = 0; i < SysClkConfigValue_EnumMax; i++) - { - this->configValues[i] = sysclkDefaultConfigValue((SysClkConfigValue)i); - } -} + uint64_t configValues[SysClkConfigValue_EnumMax]; -Config::~Config() -{ - std::scoped_lock lock{this->configMutex}; - this->Close(); -} + namespace { -Config* Config::CreateDefault() -{ - return new Config(FILE_CONFIG_DIR "/config.ini"); -} + bool gLoaded = false; + std::string gPath; + time_t gMtime = 0; + std::atomic_bool gEnabled{false}; + std::uint32_t gOverrideFreqs[SysClkModule_EnumMax]; + std::map, std::uint32_t> gProfileMHzMap; + std::map gProfileCountMap; + LockableMutex gConfigMutex; + LockableMutex gOverrideMutex; -void Config::Load() -{ - FileUtils::LogLine("[cfg] Reading %s", this->path.c_str()); - - this->Close(); - this->mtime = this->CheckModificationTime(); - if(!this->mtime) - { - FileUtils::LogLine("[cfg] Error finding file"); - } - else if (!ini_browse(&BrowseIniFunc, this, this->path.c_str())) - { - FileUtils::LogLine("[cfg] Error loading file"); - } - - this->loaded = true; -} - -void Config::Close() -{ - this->loaded = false; - this->profileMHzMap.clear(); - this->profileCountMap.clear(); - - for(unsigned int i = 0; i < SysClkConfigValue_EnumMax; i++) - { - this->configValues[i] = sysclkDefaultConfigValue((SysClkConfigValue)i); - } -} - -bool Config::Refresh() -{ - std::scoped_lock lock{this->configMutex}; - if (!this->loaded || this->mtime != this->CheckModificationTime()) - { - this->Load(); - return true; - } - return false; -} - -bool Config::HasProfilesLoaded() -{ - std::scoped_lock lock{this->configMutex}; - return this->loaded; -} - -time_t Config::CheckModificationTime() -{ - time_t mtime = 0; - struct stat st; - if (stat(this->path.c_str(), &st) == 0) - { - mtime = st.st_mtime; - } - - return mtime; -} - -std::uint32_t Config::FindClockMHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile) -{ - if (this->loaded) - { - std::map, std::uint32_t>::const_iterator it = this->profileMHzMap.find(std::make_tuple(tid, profile, module)); - if (it != this->profileMHzMap.end()) - { - return it->second; + time_t CheckModificationTime() { + time_t mtime = 0; + struct stat st; + if (stat(gPath.c_str(), &st) == 0) { + mtime = st.st_mtime; + } + return mtime; } - } - return 0; -} + std::uint32_t FindClockMHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile) { + if (gLoaded) { + auto it = gProfileMHzMap.find(std::make_tuple(tid, profile, module)); + if (it != gProfileMHzMap.end()) { + return it->second; + } + } + return 0; + } -std::uint32_t Config::FindClockHzFromProfiles(std::uint64_t tid, SysClkModule module, std::initializer_list profiles, u32 mhzMultiplier) -{ - std::uint32_t mhz = 0; + std::uint32_t FindClockHzFromProfiles(std::uint64_t tid, SysClkModule module, std::initializer_list profiles, u32 mhzMultiplier = 1000000) { + std::uint32_t mhz = 0; - if (this->loaded) - { - for(auto profile: profiles) - { - mhz = FindClockMHz(tid, module, profile); + if (gLoaded) { + for (auto profile: profiles) { + mhz = FindClockMHz(tid, module, profile); + if (mhz) { + break; + } + } + } - if(mhz) - { - break; + return std::max((std::uint32_t)0, mhz * mhzMultiplier); + } + + int BrowseIniFunc(const char* section, const char* key, const char* value, void* userdata) { + (void)userdata; + std::uint64_t input; + if (!strcmp(section, CONFIG_VAL_SECTION)) { + for (unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++) { + if (!strcmp(key, sysclkFormatConfigValue((SysClkConfigValue)kval, false))) { + input = strtoul(value, NULL, 0); + if (!sysclkValidConfigValue((SysClkConfigValue)kval, input)) { + input = sysclkDefaultConfigValue((SysClkConfigValue)kval); + fileUtils::LogLine("[cfg] Invalid value for key '%s' in section '%s': using default %d", key, section, input); + } + configValues[kval] = input; + return 1; + } + } + + fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized config value", key, section); + return 1; + } + + std::uint64_t tid = strtoul(section, NULL, 16); + + if (!tid || strlen(section) != 16) { + fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Invalid TitleID", key, section); + return 1; + } + + SysClkProfile parsedProfile = SysClkProfile_EnumMax; + SysClkModule parsedModule = SysClkModule_EnumMax; + + for (unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++) { + const char* profileCode = board::GetProfileName((SysClkProfile)profile, false); + size_t profileCodeLen = strlen(profileCode); + + if (!strncmp(key, profileCode, profileCodeLen) && key[profileCodeLen] == '_') { + const char* subkey = key + profileCodeLen + 1; + + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + const char* moduleCode = board::GetModuleName((SysClkModule)module, false); + size_t moduleCodeLen = strlen(moduleCode); + if (!strncmp(subkey, moduleCode, moduleCodeLen) && subkey[moduleCodeLen] == '\0') { + parsedProfile = (SysClkProfile)profile; + parsedModule = (SysClkModule)module; + } + } + } + } + + if (parsedModule == SysClkModule_EnumMax || parsedProfile == SysClkProfile_EnumMax) { + fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized key", key, section); + return 1; + } + + std::uint32_t mhz = strtoul(value, NULL, 10); + if (!mhz) { + fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Invalid value", key, section); + return 1; + } + + gProfileMHzMap[std::make_tuple(tid, parsedProfile, parsedModule)] = mhz; + auto it = gProfileCountMap.find(tid); + if (it == gProfileCountMap.end()) { + gProfileCountMap[tid] = 1; + } else { + it->second++; + } + + return 1; + } + + void Close() { + gLoaded = false; + gProfileMHzMap.clear(); + gProfileCountMap.clear(); + for (unsigned int i = 0; i < SysClkConfigValue_EnumMax; i++) { + configValues[i] = sysclkDefaultConfigValue((SysClkConfigValue)i); } } - } - return std::max((std::uint32_t)0, mhz * mhzMultiplier); -} + void Load() { + fileUtils::LogLine("[cfg] Reading %s", gPath.c_str()); -std::uint32_t Config::GetAutoClockHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile, bool returnRaw) -{ - std::scoped_lock lock{this->configMutex}; - switch(profile) - { - case SysClkProfile_Handheld: - return FindClockHzFromProfiles(tid, module, {SysClkProfile_Handheld}, returnRaw ? 1 : 1000000); - case SysClkProfile_HandheldCharging: - case SysClkProfile_HandheldChargingUSB: - return FindClockHzFromProfiles(tid, module, {SysClkProfile_HandheldChargingUSB, SysClkProfile_HandheldCharging, SysClkProfile_Handheld}, returnRaw ? 1 : 1000000); - case SysClkProfile_HandheldChargingOfficial: - return FindClockHzFromProfiles(tid, module, {SysClkProfile_HandheldChargingOfficial, SysClkProfile_HandheldCharging, SysClkProfile_Handheld}, returnRaw ? 1 : 1000000); - case SysClkProfile_Docked: - return FindClockHzFromProfiles(tid, module, {SysClkProfile_Docked}, returnRaw ? 1 : 1000000); - default: - ERROR_THROW("Unhandled SysClkProfile: %u", profile); - } - - return 0; -} - -void Config::GetProfiles(std::uint64_t tid, SysClkTitleProfileList* out_profiles) -{ - std::scoped_lock lock{this->configMutex}; - - for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++) - { - for(unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - out_profiles->mhzMap[profile][module] = FindClockMHz(tid, (SysClkModule)module, (SysClkProfile)profile); - } - } -} - -bool Config::SetProfiles(std::uint64_t tid, SysClkTitleProfileList* profiles, bool immediate) -{ - std::scoped_lock lock{this->configMutex}; - uint8_t numProfiles = 0; - - char section[17] = {0}; - snprintf(section, sizeof(section), "%016lX", tid); - - std::vector keys; - std::vector values; - keys.reserve(SysClkProfile_EnumMax * SysClkModule_EnumMax); - values.reserve(SysClkProfile_EnumMax * SysClkModule_EnumMax); - - std::uint32_t* mhz = &profiles->mhz[0]; - - for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++) - { - for(unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - if(*mhz) - { - numProfiles++; - - std::string key = std::string(board::GetProfileName((SysClkProfile)profile, false)) + - "_" + - board::GetModuleName((SysClkModule)module, false); - std::string value = std::to_string(*mhz); - - keys.push_back(key); - values.push_back(value); + Close(); + gMtime = CheckModificationTime(); + if (!gMtime) { + fileUtils::LogLine("[cfg] Error finding file"); + } else if (!ini_browse(&BrowseIniFunc, nullptr, gPath.c_str())) { + fileUtils::LogLine("[cfg] Error loading file"); } - mhz++; + + gLoaded = true; + } + + } + + void Initialize() { + gPath = FILE_CONFIG_DIR "/config.ini"; + gLoaded = false; + gProfileMHzMap.clear(); + gProfileCountMap.clear(); + gMtime = 0; + gEnabled = false; + for (unsigned int i = 0; i < SysClkModule_EnumMax; i++) { + gOverrideFreqs[i] = 0; + } + for (unsigned int i = 0; i < SysClkConfigValue_EnumMax; i++) { + configValues[i] = sysclkDefaultConfigValue((SysClkConfigValue)i); } } - std::vector keyPointers; - std::vector valuePointers; - keyPointers.reserve(keys.size() + 1); - valuePointers.reserve(values.size() + 1); - - for(size_t i = 0; i < keys.size(); i++) { - keyPointers.push_back(keys[i].c_str()); - valuePointers.push_back(values[i].c_str()); + void Exit() { + std::scoped_lock lock{gConfigMutex}; + Close(); } - keyPointers.push_back(NULL); - valuePointers.push_back(NULL); - if(!ini_putsection(section, keyPointers.data(), valuePointers.data(), this->path.c_str())) - { + bool Refresh() { + std::scoped_lock lock{gConfigMutex}; + if (!gLoaded || gMtime != CheckModificationTime()) { + Load(); + return true; + } return false; } - if(immediate) - { - mhz = &profiles->mhz[0]; - this->profileCountMap[tid] = numProfiles; - for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++) - { - for(unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - if(*mhz) - { - this->profileMHzMap[std::make_tuple(tid, (SysClkProfile)profile, (SysClkModule)module)] = *mhz; - } - else - { - this->profileMHzMap.erase(std::make_tuple(tid, (SysClkProfile)profile, (SysClkModule)module)); + bool HasProfilesLoaded() { + std::scoped_lock lock{gConfigMutex}; + return gLoaded; + } + + std::uint32_t GetAutoClockHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile, bool returnRaw) { + std::scoped_lock lock{gConfigMutex}; + switch (profile) { + case SysClkProfile_Handheld: + return FindClockHzFromProfiles(tid, module, {SysClkProfile_Handheld}, returnRaw ? 1 : 1000000); + case SysClkProfile_HandheldCharging: + case SysClkProfile_HandheldChargingUSB: + return FindClockHzFromProfiles(tid, module, {SysClkProfile_HandheldChargingUSB, SysClkProfile_HandheldCharging, SysClkProfile_Handheld}, returnRaw ? 1 : 1000000); + case SysClkProfile_HandheldChargingOfficial: + return FindClockHzFromProfiles(tid, module, {SysClkProfile_HandheldChargingOfficial, SysClkProfile_HandheldCharging, SysClkProfile_Handheld}, returnRaw ? 1 : 1000000); + case SysClkProfile_Docked: + return FindClockHzFromProfiles(tid, module, {SysClkProfile_Docked}, returnRaw ? 1 : 1000000); + default: + ERROR_THROW("Unhandled SysClkProfile: %u", profile); + } + return 0; + } + + void GetProfiles(std::uint64_t tid, SysClkTitleProfileList* out_profiles) { + std::scoped_lock lock{gConfigMutex}; + for (unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++) { + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + out_profiles->mhzMap[profile][module] = FindClockMHz(tid, (SysClkModule)module, (SysClkProfile)profile); + } + } + } + + bool SetProfiles(std::uint64_t tid, SysClkTitleProfileList* profiles, bool immediate) { + std::scoped_lock lock{gConfigMutex}; + uint8_t numProfiles = 0; + + char section[17] = {0}; + snprintf(section, sizeof(section), "%016lX", tid); + + std::vector keys; + std::vector values; + keys.reserve(SysClkProfile_EnumMax * SysClkModule_EnumMax); + values.reserve(SysClkProfile_EnumMax * SysClkModule_EnumMax); + + std::uint32_t* mhz = &profiles->mhz[0]; + + for (unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++) { + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + if (*mhz) { + numProfiles++; + + std::string key = std::string(board::GetProfileName((SysClkProfile)profile, false)) + + "_" + + board::GetModuleName((SysClkModule)module, false); + std::string value = std::to_string(*mhz); + + keys.push_back(key); + values.push_back(value); } mhz++; } } - } - return true; -} + std::vector keyPointers; + std::vector valuePointers; + keyPointers.reserve(keys.size() + 1); + valuePointers.reserve(values.size() + 1); -std::uint8_t Config::GetProfileCount(std::uint64_t tid) -{ - std::map::iterator it = this->profileCountMap.find(tid); - if (it == this->profileCountMap.end()) - { - return 0; - } + for (size_t i = 0; i < keys.size(); i++) { + keyPointers.push_back(keys[i].c_str()); + valuePointers.push_back(values[i].c_str()); + } + keyPointers.push_back(NULL); + valuePointers.push_back(NULL); - return it->second; -} - -int Config::BrowseIniFunc(const char* section, const char* key, const char* value, void* userdata) -{ - Config* config = (Config*)userdata; - std::uint64_t input; - if(!strcmp(section, CONFIG_VAL_SECTION)) - { - for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++) - { - if(!strcmp(key, sysclkFormatConfigValue((SysClkConfigValue)kval, false))) - { - input = strtoul(value, NULL, 0); - if(!sysclkValidConfigValue((SysClkConfigValue)kval, input)) - { - input = sysclkDefaultConfigValue((SysClkConfigValue)kval); - FileUtils::LogLine("[cfg] Invalid value for key '%s' in section '%s': using default %d", key, section, input); - } - config->configValues[kval] = input; - return 1; - } + if (!ini_putsection(section, keyPointers.data(), valuePointers.data(), gPath.c_str())) { + return false; } - FileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized config value", key, section); - return 1; - } - - std::uint64_t tid = strtoul(section, NULL, 16); - - if(!tid || strlen(section) != 16) - { - FileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Invalid TitleID", key, section); - return 1; - } - - SysClkProfile parsedProfile = SysClkProfile_EnumMax; - SysClkModule parsedModule = SysClkModule_EnumMax; - - for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++) - { - const char* profileCode = board::GetProfileName((SysClkProfile)profile, false); - size_t profileCodeLen = strlen(profileCode); - - if(!strncmp(key, profileCode, profileCodeLen) && key[profileCodeLen] == '_') - { - const char* subkey = key + profileCodeLen + 1; - - for(unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - const char* moduleCode = board::GetModuleName((SysClkModule)module, false); - size_t moduleCodeLen = strlen(moduleCode); - if(!strncmp(subkey, moduleCode, moduleCodeLen) && subkey[moduleCodeLen] == '\0') - { - parsedProfile = (SysClkProfile)profile; - parsedModule = (SysClkModule)module; + if (immediate) { + mhz = &profiles->mhz[0]; + gProfileCountMap[tid] = numProfiles; + for (unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++) { + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + if (*mhz) { + gProfileMHzMap[std::make_tuple(tid, (SysClkProfile)profile, (SysClkModule)module)] = *mhz; + } else { + gProfileMHzMap.erase(std::make_tuple(tid, (SysClkProfile)profile, (SysClkModule)module)); + } + mhz++; } } } + + return true; } - if(parsedModule == SysClkModule_EnumMax || parsedProfile == SysClkProfile_EnumMax) - { - FileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized key", key, section); - return 1; - } - - std::uint32_t mhz = strtoul(value, NULL, 10); - if(!mhz) - { - FileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Invalid value", key, section); - return 1; - } - - config->profileMHzMap[std::make_tuple(tid, parsedProfile, parsedModule)] = mhz; - std::map::iterator it = config->profileCountMap.find(tid); - if (it == config->profileCountMap.end()) - { - config->profileCountMap[tid] = 1; - } - else - { - it->second++; - } - - return 1; -} - -void Config::SetEnabled(bool enabled) -{ - this->enabled = enabled; -} - -bool Config::Enabled() -{ - return this->enabled; -} - -void Config::SetOverrideHz(SysClkModule module, std::uint32_t hz) -{ - ASSERT_ENUM_VALID(SysClkModule, module); - - std::scoped_lock lock{this->overrideMutex}; - - this->overrideFreqs[module] = hz; -} - -std::uint32_t Config::GetOverrideHz(SysClkModule module) -{ - ASSERT_ENUM_VALID(SysClkModule, module); - - std::scoped_lock lock{this->overrideMutex}; - - return this->overrideFreqs[module]; -} - -std::uint64_t Config::GetConfigValue(SysClkConfigValue kval) -{ - ASSERT_ENUM_VALID(SysClkConfigValue, kval); - - std::scoped_lock lock{this->configMutex}; - - return this->configValues[kval]; -} - -const char* Config::GetConfigValueName(SysClkConfigValue kval, bool pretty) -{ - ASSERT_ENUM_VALID(SysClkConfigValue, kval); - - const char* result = sysclkFormatConfigValue(kval, pretty); - - return result; -} - -void Config::GetConfigValues(SysClkConfigValueList* out_configValues) -{ - std::scoped_lock lock{this->configMutex}; - - for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++) - { - out_configValues->values[kval] = this->configValues[kval]; - } -} - -bool Config::SetConfigValues(SysClkConfigValueList* configValues, bool immediate) -{ - std::scoped_lock lock{this->configMutex}; - - std::vector iniKeys; - std::vector iniValues; - - iniKeys.reserve(SysClkConfigValue_EnumMax + 1); - iniValues.reserve(SysClkConfigValue_EnumMax); - - for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++) - { - if(!sysclkValidConfigValue((SysClkConfigValue)kval, configValues->values[kval]) || - configValues->values[kval] == sysclkDefaultConfigValue((SysClkConfigValue)kval)) - { - continue; + std::uint8_t GetProfileCount(std::uint64_t tid) { + auto it = gProfileCountMap.find(tid); + if (it == gProfileCountMap.end()) { + return 0; } - - iniValues.push_back(std::to_string(configValues->values[kval])); - iniKeys.push_back(sysclkFormatConfigValue((SysClkConfigValue)kval, false)); + return it->second; } - // Null terminate - iniKeys.push_back(NULL); - - // Build pointer array for ini function - std::vector valuePointers; - valuePointers.reserve(iniValues.size() + 1); - for(const auto& val : iniValues) { - valuePointers.push_back(val.c_str()); - } - valuePointers.push_back(NULL); - - if(!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), this->path.c_str())) - { - return false; + void SetEnabled(bool enabled) { + gEnabled = enabled; } - // Only actually apply changes in memory after a successful save - if(immediate) - { - for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++) - { - if(sysclkValidConfigValue((SysClkConfigValue)kval, configValues->values[kval])) - { - this->configValues[kval] = configValues->values[kval]; - } - else - { - this->configValues[kval] = sysclkDefaultConfigValue((SysClkConfigValue)kval); - } + bool Enabled() { + return gEnabled; + } + + void SetOverrideHz(SysClkModule module, std::uint32_t hz) { + ASSERT_ENUM_VALID(SysClkModule, module); + std::scoped_lock lock{gOverrideMutex}; + gOverrideFreqs[module] = hz; + } + + std::uint32_t GetOverrideHz(SysClkModule module) { + ASSERT_ENUM_VALID(SysClkModule, module); + std::scoped_lock lock{gOverrideMutex}; + return gOverrideFreqs[module]; + } + + std::uint64_t GetConfigValue(SysClkConfigValue kval) { + ASSERT_ENUM_VALID(SysClkConfigValue, kval); + std::scoped_lock lock{gConfigMutex}; + return configValues[kval]; + } + + const char* GetConfigValueName(SysClkConfigValue kval, bool pretty) { + ASSERT_ENUM_VALID(SysClkConfigValue, kval); + return sysclkFormatConfigValue(kval, pretty); + } + + void GetConfigValues(SysClkConfigValueList* out_configValues) { + std::scoped_lock lock{gConfigMutex}; + for (unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++) { + out_configValues->values[kval] = configValues[kval]; } } - return true; + bool SetConfigValues(SysClkConfigValueList* configValues, bool immediate) { + std::scoped_lock lock{gConfigMutex}; + + std::vector iniKeys; + std::vector iniValues; + iniKeys.reserve(SysClkConfigValue_EnumMax + 1); + iniValues.reserve(SysClkConfigValue_EnumMax); + + for (unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++) { + if (!sysclkValidConfigValue((SysClkConfigValue)kval, configValues->values[kval]) || + configValues->values[kval] == sysclkDefaultConfigValue((SysClkConfigValue)kval)) { + continue; + } + iniValues.push_back(std::to_string(configValues->values[kval])); + iniKeys.push_back(sysclkFormatConfigValue((SysClkConfigValue)kval, false)); + } + + iniKeys.push_back(NULL); + + std::vector valuePointers; + valuePointers.reserve(iniValues.size() + 1); + for (const auto& val : iniValues) { + valuePointers.push_back(val.c_str()); + } + valuePointers.push_back(NULL); + + if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) { + return false; + } + + if (immediate) { + for (unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++) { + if (sysclkValidConfigValue((SysClkConfigValue)kval, configValues->values[kval])) { + config::configValues[kval] = configValues->values[kval]; + } else { + config::configValues[kval] = sysclkDefaultConfigValue((SysClkConfigValue)kval); + } + } + } + + return true; + } + + bool ResetConfigValue(SysClkConfigValue kval) { + if (!SYSCLK_ENUM_VALID(SysClkConfigValue, kval)) { + fileUtils::LogLine("[cfg] Invalid SysClkConfigValue: %u", kval); + return false; + } + + std::scoped_lock lock{gConfigMutex}; + + std::uint64_t defaultValue = sysclkDefaultConfigValue(kval); + + std::vector iniKeys; + std::vector iniValues; + iniKeys.reserve(2); + iniValues.reserve(1); + + iniKeys.push_back(sysclkFormatConfigValue(kval, false)); + iniValues.push_back(""); + iniKeys.push_back(NULL); + + std::vector valuePointers; + valuePointers.reserve(iniValues.size() + 1); + for (const auto& val : iniValues) { + valuePointers.push_back(val.c_str()); + } + valuePointers.push_back(NULL); + + if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) { + fileUtils::LogLine("[cfg] Failed to reset config value %u in INI", kval); + return false; + } + + configValues[kval] = defaultValue; + fileUtils::LogLine("[cfg] Reset config value %u to default: %llu", kval, defaultValue); + + return true; + } + + bool SetConfigValue(SysClkConfigValue kval, std::uint64_t value, bool immediate) { + if (!SYSCLK_ENUM_VALID(SysClkConfigValue, kval)) { + return false; + } + if (!sysclkValidConfigValue(kval, value)) { + return false; + } + + std::scoped_lock lock{gConfigMutex}; + + std::vector iniKeys; + std::vector iniValues; + iniKeys.reserve(2); + iniValues.reserve(1); + + iniKeys.push_back(sysclkFormatConfigValue(kval, false)); + iniValues.push_back(std::to_string(value)); + iniKeys.push_back(NULL); + + std::vector valuePointers; + valuePointers.reserve(2); + valuePointers.push_back(iniValues[0].c_str()); + valuePointers.push_back(NULL); + + if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) { + return false; + } + + if (immediate) { + configValues[kval] = value; + } + + return true; + } + } - -bool Config::ResetConfigValue(SysClkConfigValue kval) -{ - if (!SYSCLK_ENUM_VALID(SysClkConfigValue, kval)) { - FileUtils::LogLine("[cfg] Invalid SysClkConfigValue: %u", kval); - return false; - } - - std::scoped_lock lock{this->configMutex}; - - std::uint64_t defaultValue = sysclkDefaultConfigValue(kval); - - std::vector iniKeys; - std::vector iniValues; - - iniKeys.reserve(2); - iniValues.reserve(1); - - const char* keyStr = sysclkFormatConfigValue(kval, false); - - iniKeys.push_back(keyStr); - iniValues.push_back(""); - - iniKeys.push_back(NULL); - - std::vector valuePointers; - valuePointers.reserve(iniValues.size() + 1); - for (const auto& val : iniValues) { - valuePointers.push_back(val.c_str()); - } - valuePointers.push_back(NULL); - - if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), this->path.c_str())) { - FileUtils::LogLine("[cfg] Failed to reset config value %u in INI", kval); - return false; - } - - this->configValues[kval] = defaultValue; - FileUtils::LogLine("[cfg] Reset config value %u to default: %llu", kval, defaultValue); - - return true; -} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/config.h b/Source/rewrite-hoc-clk/sysmodule/src/config.hpp similarity index 64% rename from Source/rewrite-hoc-clk/sysmodule/src/config.h rename to Source/rewrite-hoc-clk/sysmodule/src/config.hpp index 28ded8f5..80a68ee1 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/config.h +++ b/Source/rewrite-hoc-clk/sysmodule/src/config.hpp @@ -24,31 +24,19 @@ * -------------------------------------------------------------------------- */ - #pragma once -#include -#include -#include -#include -#include -#include + +#include #include -#include -#include -#include "board/board.hpp" #define CONFIG_VAL_SECTION "values" -class Config -{ - public: - Config(std::string path); - virtual ~Config(); +namespace config { - static Config* CreateDefault(); + void Initialize(); + void Exit(); bool Refresh(); - bool HasProfilesLoaded(); std::uint8_t GetProfileCount(std::uint64_t tid); @@ -66,26 +54,8 @@ class Config void GetConfigValues(SysClkConfigValueList* out_configValues); bool SetConfigValues(SysClkConfigValueList* configValues, bool immediate); bool ResetConfigValue(SysClkConfigValue kval); - bool SetInternalValues(bool immediate); bool SetConfigValue(SysClkConfigValue kval, std::uint64_t value, bool immediate = true); - uint64_t configValues[SysClkConfigValue_EnumMax]; - protected: - void Load(); - void Close(); - bool kipOverride[SysClkConfigValue_EnumMax]; - time_t CheckModificationTime(); - std::uint32_t FindClockMHz(std::uint64_t tid, SysClkModule module, SysClkProfile profile); - std::uint32_t FindClockHzFromProfiles(std::uint64_t tid, SysClkModule module, std::initializer_list profiles, u32 mhzMultiplier = 1000000); - static int BrowseIniFunc(const char* section, const char* key, const char* value, void* userdata); + extern uint64_t configValues[SysClkConfigValue_EnumMax]; - std::map, std::uint32_t> profileMHzMap; - std::map profileCountMap; - bool loaded; - std::string path; - time_t mtime; - LockableMutex configMutex; - LockableMutex overrideMutex; - std::atomic_bool enabled; - std::uint32_t overrideFreqs[SysClkModule_EnumMax]; -}; +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/errors.cpp b/Source/rewrite-hoc-clk/sysmodule/src/errors.cpp index b7949432..ed077b59 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/errors.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/errors.cpp @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -24,31 +24,34 @@ * -------------------------------------------------------------------------- */ - -#include "errors.h" +#include "errors.hpp" +#include "file_utils.hpp" #include #include -#include "file_utils.h" -void Errors::ThrowException(const char* format, ...) -{ - va_list args; - va_start(args, format); - const char* msg = Errors::FormatMessage(format, args); - va_end(args); - FileUtils::LogLine(format, args); - throw std::runtime_error(msg); -} -const char* Errors::FormatMessage(const char* format, va_list args) -{ - size_t len = vsnprintf(NULL, 0, format, args) * sizeof(char); - char* buf = (char*)malloc(len + 1); - if (buf == NULL) - { - return format; +namespace errors { + + namespace { + + const char* FormatMessage(const char* format, va_list args) { + size_t len = vsnprintf(NULL, 0, format, args) * sizeof(char); + char* buf = (char*)malloc(len + 1); + if (buf == NULL) { + return format; + } + vsnprintf(buf, len + 1, format, args); + return buf; + } + } - vsnprintf(buf, len + 1, format, args); + void ThrowException(const char* format, ...) { + va_list args; + va_start(args, format); + const char* msg = FormatMessage(format, args); + va_end(args); + fileUtils::LogLine(format, args); + throw std::runtime_error(msg); + } - return buf; } diff --git a/Source/rewrite-hoc-clk/sysmodule/src/errors.h b/Source/rewrite-hoc-clk/sysmodule/src/errors.hpp similarity index 82% rename from Source/rewrite-hoc-clk/sysmodule/src/errors.h rename to Source/rewrite-hoc-clk/sysmodule/src/errors.hpp index f7575cf1..c73a4e81 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/errors.h +++ b/Source/rewrite-hoc-clk/sysmodule/src/errors.hpp @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -24,29 +24,25 @@ * -------------------------------------------------------------------------- */ - #pragma once #include #include -#define ERROR_THROW(format, ...) Errors::ThrowException(format "\n in %s:%u", ##__VA_ARGS__, __FILE__, __LINE__) +#define ERROR_THROW(format, ...) errors::ThrowException(format "\n in %s:%u", ##__VA_ARGS__, __FILE__, __LINE__) #define ERROR_RESULT_THROW(rc, format, ...) ERROR_THROW(format "\n RC: [0x%x] %04d-%04d", ##__VA_ARGS__, rc, R_MODULE(rc), R_DESCRIPTION(rc)) -#define ASSERT_RESULT_OK(rc, format, ...) \ - if (R_FAILED(rc)) \ - { \ +#define ASSERT_RESULT_OK(rc, format, ...) \ + if (R_FAILED(rc)) \ + { \ ERROR_RESULT_THROW(rc, "ASSERT_RESULT_OK: " format, ##__VA_ARGS__); \ } -#define ASSERT_ENUM_VALID(n, v) \ - if(!SYSCLK_ENUM_VALID(n, v)) { \ +#define ASSERT_ENUM_VALID(n, v) \ + if (!SYSCLK_ENUM_VALID(n, v)) { \ ERROR_THROW("No such %s: %u", #n, v); \ } -class Errors -{ - public: - static void ThrowException(const char* format, ...); +namespace errors { - protected: - static const char* FormatMessage(const char* format, va_list args); -}; + void ThrowException(const char* format, ...); + +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/file_utils.cpp b/Source/rewrite-hoc-clk/sysmodule/src/file_utils.cpp index a99494e8..80eb133b 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/file_utils.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/file_utils.cpp @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -24,194 +24,177 @@ * -------------------------------------------------------------------------- */ - -#include "file_utils.h" +#include "file_utils.hpp" #include -static LockableMutex g_log_mutex; -static LockableMutex g_csv_mutex; -static std::atomic_bool g_has_initialized = false; -static bool g_log_enabled = false; -static std::uint64_t g_last_flag_check = 0; - extern "C" void __libnx_init_time(void); -static void _FileUtils_InitializeThreadFunc(void* args) -{ - FileUtils::Initialize(); -} +namespace fileUtils { -bool FileUtils::IsInitialized() -{ - return g_has_initialized; -} + namespace { -void FileUtils::LogLine(const char* format, ...) -{ - std::scoped_lock lock{g_log_mutex}; + LockableMutex g_log_mutex; + LockableMutex g_csv_mutex; + std::atomic_bool g_has_initialized = false; + bool g_log_enabled = false; + std::uint64_t g_last_flag_check = 0; - va_list args; - va_start(args, format); - if (g_has_initialized) - { - FileUtils::RefreshFlags(false); + void RefreshFlags(bool force) { + std::uint64_t now = armTicksToNs(armGetSystemTick()); + if (!force && (now - g_last_flag_check) < FILE_FLAG_CHECK_INTERVAL_NS) { + return; + } - if(g_log_enabled) - { - FILE* file = fopen(FILE_LOG_FILE_PATH, "a"); - - if (file) - { - struct timespec now; - clock_gettime(CLOCK_REALTIME, &now); - struct tm* nowTm = localtime(&now.tv_sec); - - fprintf(file, "[%04d-%02d-%02d %02d:%02d:%02d.%03ld] ", nowTm->tm_year+1900, nowTm->tm_mon+1, nowTm->tm_mday, nowTm->tm_hour, nowTm->tm_min, nowTm->tm_sec, now.tv_nsec / 1000000UL); - vfprintf(file, format, args); - fprintf(file, "\n"); + FILE* file = fopen(FILE_LOG_FLAG_PATH, "r"); + if (file) { + g_log_enabled = true; fclose(file); + } else { + g_log_enabled = false; + } + + g_last_flag_check = now; + } + + void InitializeThreadFunc(void* args) { + Initialize(); + } + + } + + bool IsInitialized() { + return g_has_initialized; + } + + bool IsLogEnabled() { + return g_log_enabled; + } + + void LogLine(const char* format, ...) { + std::scoped_lock lock{g_log_mutex}; + + va_list args; + va_start(args, format); + if (g_has_initialized) { + RefreshFlags(false); + + if (g_log_enabled) { + FILE* file = fopen(FILE_LOG_FILE_PATH, "a"); + + if (file) { + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + struct tm* nowTm = localtime(&now.tv_sec); + + fprintf(file, "[%04d-%02d-%02d %02d:%02d:%02d.%03ld] ", nowTm->tm_year+1900, nowTm->tm_mon+1, nowTm->tm_mday, nowTm->tm_hour, nowTm->tm_min, nowTm->tm_sec, now.tv_nsec / 1000000UL); + vfprintf(file, format, args); + fprintf(file, "\n"); + fclose(file); + } } } + va_end(args); } - va_end(args); -} -void FileUtils::WriteContextToCsv(const SysClkContext* context) -{ - std::scoped_lock lock{g_csv_mutex}; + void WriteContextToCsv(const SysClkContext* context) { + std::scoped_lock lock{g_csv_mutex}; - FILE* file = fopen(FILE_CONTEXT_CSV_PATH, "a"); + FILE* file = fopen(FILE_CONTEXT_CSV_PATH, "a"); - if (file) - { - // Print header - if(!ftell(file)) - { - fprintf(file, "timestamp,profile,app_tid"); + if (file) { + // Print header + if (!ftell(file)) { + fprintf(file, "timestamp,profile,app_tid"); - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - fprintf(file, ",%s_hz", sysclkFormatModule((SysClkModule)module, false)); + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + fprintf(file, ",%s_hz", sysclkFormatModule((SysClkModule)module, false)); + } + + for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) { + fprintf(file, ",%s_milliC", sysclkFormatThermalSensor((SysClkThermalSensor)sensor, false)); + } + + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + fprintf(file, ",%s_real_hz", sysclkFormatModule((SysClkModule)module, false)); + } + + for (unsigned int sensor = 0; sensor < SysClkPowerSensor_EnumMax; sensor++) { + fprintf(file, ",%s_mw", sysclkFormatPowerSensor((SysClkPowerSensor)sensor, false)); + } + + fprintf(file, "\n"); } - for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) - { - fprintf(file, ",%s_milliC", sysclkFormatThermalSensor((SysClkThermalSensor)sensor, false)); + struct timespec now; + clock_gettime(CLOCK_REALTIME, &now); + + fprintf(file, "%ld%03ld,%s,%016lx", now.tv_sec, now.tv_nsec / 1000000UL, sysclkFormatProfile(context->profile, false), context->applicationId); + + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + fprintf(file, ",%d", context->freqs[module]); } - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - fprintf(file, ",%s_real_hz", sysclkFormatModule((SysClkModule)module, false)); + for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) { + fprintf(file, ",%d", context->temps[sensor]); } - for (unsigned int sensor = 0; sensor < SysClkPowerSensor_EnumMax; sensor++) - { - fprintf(file, ",%s_mw", sysclkFormatPowerSensor((SysClkPowerSensor)sensor, false)); + for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) { + fprintf(file, ",%d", context->realFreqs[module]); + } + + for (unsigned int sensor = 0; sensor < SysClkPowerSensor_EnumMax; sensor++) { + fprintf(file, ",%d", context->power[sensor]); } fprintf(file, "\n"); + fclose(file); } - - struct timespec now; - clock_gettime(CLOCK_REALTIME, &now); - - fprintf(file, "%ld%03ld,%s,%016lx", now.tv_sec, now.tv_nsec / 1000000UL, sysclkFormatProfile(context->profile, false), context->applicationId); - - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - fprintf(file, ",%d", context->freqs[module]); - } - - for (unsigned int sensor = 0; sensor < SysClkThermalSensor_EnumMax; sensor++) - { - fprintf(file, ",%d", context->temps[sensor]); - } - - for (unsigned int module = 0; module < SysClkModule_EnumMax; module++) - { - fprintf(file, ",%d", context->realFreqs[module]); - } - - for (unsigned int sensor = 0; sensor < SysClkPowerSensor_EnumMax; sensor++) - { - fprintf(file, ",%d", context->power[sensor]); - } - - fprintf(file, "\n"); - fclose(file); - } -} - -void FileUtils::RefreshFlags(bool force) -{ - std::uint64_t now = armTicksToNs(armGetSystemTick()); - if(!force && (now - g_last_flag_check) < FILE_FLAG_CHECK_INTERVAL_NS) - { - return; } - FILE* file = fopen(FILE_LOG_FLAG_PATH, "r"); - if (file) - { - g_log_enabled = true; - fclose(file); - } else { + void InitializeAsync() { + Thread initThread = {0}; + threadCreate(&initThread, InitializeThreadFunc, NULL, NULL, 0x4000, 0x15, 0); + threadStart(&initThread); + } + + Result Initialize() { + Result rc = 0; + + if (R_SUCCEEDED(rc)) { + rc = timeInitialize(); + } + + __libnx_init_time(); + timeExit(); + + if (R_SUCCEEDED(rc)) { + rc = fsInitialize(); + } + + if (R_SUCCEEDED(rc)) { + rc = fsdevMountSdmc(); + } + + if (R_SUCCEEDED(rc)) { + RefreshFlags(true); + g_has_initialized = true; + LogLine("=== hoc-clk " TARGET_VERSION " ==="); + LogLine("by m4xw, natinusala, p-sam, Souldbminer and Lightos_"); + } + + return rc; + } + + void Exit() { + if (!g_has_initialized) { + return; + } + + g_has_initialized = false; g_log_enabled = false; + + fsdevUnmountAll(); + fsExit(); } - g_last_flag_check = now; -} - -void FileUtils::InitializeAsync() -{ - Thread initThread = {0}; - threadCreate(&initThread, _FileUtils_InitializeThreadFunc, NULL, NULL, 0x4000, 0x15, 0); - threadStart(&initThread); -} - -Result FileUtils::Initialize() -{ - Result rc = 0; - - if (R_SUCCEEDED(rc)) - { - rc = timeInitialize(); - } - - __libnx_init_time(); - timeExit(); - - if (R_SUCCEEDED(rc)) - { - rc = fsInitialize(); - } - - if (R_SUCCEEDED(rc)) - { - rc = fsdevMountSdmc(); - } - - if (R_SUCCEEDED(rc)) - { - FileUtils::RefreshFlags(true); - g_has_initialized = true; - FileUtils::LogLine("=== hoc-clk " TARGET_VERSION " ==="); - FileUtils::LogLine("by m4xw, natinusala, p-sam, Souldbminer and Lightos_"); - } - - return rc; -} - -void FileUtils::Exit() -{ - if (!g_has_initialized) - { - return; - } - - g_has_initialized = false; - g_log_enabled = false; - - fsdevUnmountAll(); - fsExit(); } diff --git a/Source/rewrite-hoc-clk/sysmodule/src/file_utils.h b/Source/rewrite-hoc-clk/sysmodule/src/file_utils.hpp similarity index 81% rename from Source/rewrite-hoc-clk/sysmodule/src/file_utils.h rename to Source/rewrite-hoc-clk/sysmodule/src/file_utils.hpp index 993420de..3289126b 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/file_utils.h +++ b/Source/rewrite-hoc-clk/sysmodule/src/file_utils.hpp @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -24,8 +24,8 @@ * -------------------------------------------------------------------------- */ - #pragma once + #include #include #include @@ -40,16 +40,14 @@ #define FILE_LOG_FLAG_PATH FILE_CONFIG_DIR "/log.flag" #define FILE_LOG_FILE_PATH FILE_CONFIG_DIR "/log.txt" -class FileUtils -{ - public: - static void Exit(); - static Result Initialize(); - static bool IsInitialized(); - static bool IsLogEnabled(); - static void InitializeAsync(); - static void LogLine(const char* format, ...); - static void WriteContextToCsv(const SysClkContext* context); - protected: - static void RefreshFlags(bool force); -}; +namespace fileUtils { + + void Exit(); + Result Initialize(); + bool IsInitialized(); + bool IsLogEnabled(); + void InitializeAsync(); + void LogLine(const char* format, ...); + void WriteContextToCsv(const SysClkContext* context); + +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/governor.cpp b/Source/rewrite-hoc-clk/sysmodule/src/governor.cpp new file mode 100644 index 00000000..90a170b2 --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/governor.cpp @@ -0,0 +1,349 @@ +#include "governor.hpp" + +namespace governor { + + #define POLL_NS 5'000'000 // 5 ms – governor poll rate + #define DOWN_HOLD_TICKS 10 // 50 ms – how long to in POLL_NS to hold while ramping down + #define STEP_UTIL 900 // multiplier for step calculations + + bool isGpuGovernorEnabled = false; + bool isCpuGovernorEnabled = false; + bool lastGpuGovernorState = false; + bool lastCpuGovernorState = false; + bool lastVrrGovernorState = false; + bool hasChanged = true; + bool isCpuGovernorInBoostMode = false; + bool isVRREnabled = false; + + // thread handles + Thread cpuGovernorTHREAD; + Thread gpuGovernorTHREAD; + Thread vrrTHREAD; + + void HandleGovernor(uint32_t targetHz) + { + u32 tempTargetHz = clockManager::gContext.overrideFreqs[HorizonOCModule_Governor]; + if (!tempTargetHz) { + tempTargetHz = config::GetAutoClockHz(clockManager::gContext.applicationId, HorizonOCModule_Governor, clockManager::gContext.profile, true); + if (!tempTargetHz) + tempTargetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Governor, clockManager::gContext.profile, true); + } + + auto resolve = [](u8 app, u8 temp) -> u8 { + if (temp == ComponentGovernor_Disabled) return ComponentGovernor_Disabled; + if (temp != ComponentGovernor_DoNotOverride) return temp; + return app; + }; + + u8 effectiveCpu = resolve(GovernorStateCpu(targetHz), GovernorStateCpu(tempTargetHz)); + u8 effectiveGpu = resolve(GovernorStateGpu(targetHz), GovernorStateGpu(tempTargetHz)); + u8 effectiveVrr = resolve(GovernorStateVrr(targetHz), GovernorStateVrr(tempTargetHz)); + + bool newCpuGovernorState = (effectiveCpu == ComponentGovernor_Enabled); + bool newGpuGovernorState = (effectiveGpu == ComponentGovernor_Enabled); + bool newVrrGovernorState = (effectiveVrr == ComponentGovernor_Enabled); + + isCpuGovernorEnabled = newCpuGovernorState; + isGpuGovernorEnabled = newGpuGovernorState; + isVRREnabled = newVrrGovernorState; + + if (newCpuGovernorState == false && lastCpuGovernorState == true) { + svcSleepThread(100'000'000); // thread syncing. probably a cleaner way to do this but hey, it works! + board::ResetToStockCpu(); + } + if (newGpuGovernorState == false && lastGpuGovernorState == true) { + svcSleepThread(100'000'000); + board::ResetToStockGpu(); + } + if (newVrrGovernorState == false && lastVrrGovernorState == true) { + svcSleepThread(100'000'000); + board::ResetToStockDisplay(); + } + if (newCpuGovernorState != lastCpuGovernorState || newGpuGovernorState != lastGpuGovernorState || newVrrGovernorState != lastVrrGovernorState) { + fileUtils::LogLine("[mgr] Governor state changed: CPU %s, GPU %s, VRR %s", newCpuGovernorState ? "enabled" : "disabled", newGpuGovernorState ? "enabled" : "disabled", newVrrGovernorState ? "enabled" : "disabled"); + lastCpuGovernorState = newCpuGovernorState; + lastGpuGovernorState = newGpuGovernorState; + lastVrrGovernorState = newVrrGovernorState; + } + } + + u32 SchedutilTargetHz(u32 util, u32 tableMaxHz) + { + u64 hz = (u64)tableMaxHz * util / STEP_UTIL; + return (u32)(std::min(hz, static_cast(tableMaxHz))); + } + + u32 TableIndexForHz(const clockManager::FreqTable& table, u32 targetHz) + { + for (u32 i = 0; i < table.count; i++) + if (table.list[i] >= targetHz) + return i; + return table.count - 1; + } + + u32 ResolveTargetHz(SysClkModule module) + { + u32 hz = clockManager::gContext.overrideFreqs[module]; + if (!hz) + hz = config::GetAutoClockHz( + clockManager::gContext.applicationId, module, + clockManager::gContext.profile, false); + if (!hz) + hz = config::GetAutoClockHz( + GLOBAL_PROFILE_ID, module, + clockManager::gContext.profile, false); + return hz; + } + + void CpuGovernorThread(void* arg) + { + (void)arg; + + u32 downHoldRemaining = 0; + u32 lastHz = 0; + u32 minHz = 612; + u32 tick = 0; + for (;;) { + if (!clockManager::gRunning || !isCpuGovernorEnabled) { + downHoldRemaining = 0; + lastHz = 0; + svcSleepThread(POLL_NS); + continue; + } + + u32 mode = 0; + Result rc = apmExtGetCurrentPerformanceConfiguration(&mode); + + if (R_SUCCEEDED(rc) && apmExtIsBoostMode(mode)) { + isCpuGovernorInBoostMode = true; + downHoldRemaining = 0; + lastHz = 0; + continue; // TODO: figure out a way to get boost clock easily and set it instead of just skipping the governor + } else if (!apmExtIsBoostMode(mode)) { + isCpuGovernorInBoostMode = false; + } + + auto& table = clockManager::gFreqTable[SysClkModule_CPU]; + + if (table.count == 0) + continue; + + std::scoped_lock lock{clockManager::gContextMutex}; + + u32 cpuLoad = board::GetPartLoad(HocClkPartLoad_CPUMax); + + u32 tableMaxHz = table.list[table.count - 1]; + u32 desiredHz = SchedutilTargetHz(cpuLoad, tableMaxHz); + u32 targetHz = ResolveTargetHz(SysClkModule_CPU); + u32 maxHz = clockManager::GetMaxAllowedHz(SysClkModule_CPU, clockManager::gContext.profile); + + if (targetHz && desiredHz > targetHz) + desiredHz = targetHz; + + if (maxHz && desiredHz > maxHz) + desiredHz = maxHz; + + u32 newHz = table.list[TableIndexForHz(table, desiredHz)]; + + // ramp up fast, go down slow + bool goingDown = (lastHz != 0) && (newHz < lastHz); + + if (!goingDown) + downHoldRemaining = 0; + else if (downHoldRemaining == 0) + downHoldRemaining = DOWN_HOLD_TICKS; + + if (downHoldRemaining > 0) + downHoldRemaining--; + + if (++tick > 50) { + minHz = config::GetConfigValue(HorizonOCConfigValue_CpuGovernorMinimumFreq); + tick = 0; + } + + if (newHz < minHz) + newHz = minHz; + + if ((!goingDown || (downHoldRemaining == 0)) && clockManager::IsAssignableHz(SysClkModule_CPU, newHz)) { + board::SetHz(SysClkModule_CPU, newHz); + clockManager::gContext.freqs[SysClkModule_CPU] = newHz; + lastHz = newHz; + } + + svcSleepThread(POLL_NS); + } + } + + void GovernorThread(void* arg) + { + (void)arg; + + u32 downHoldRemaining = 0; + u32 lastHz = 0; + + for (;;) { + if (!clockManager::gRunning || !isGpuGovernorEnabled) { + downHoldRemaining = 0; + lastHz = 0; + svcSleepThread(POLL_NS); + continue; + } + + auto& table = clockManager::gFreqTable[SysClkModule_GPU]; + if (table.count == 0) + continue; + + std::scoped_lock lock{clockManager::gContextMutex}; + + u32 gpuLoad = board::GetPartLoad(HocClkPartLoad_GPU); + u32 tableMaxHz = table.list[table.count - 1]; + u32 desiredHz = SchedutilTargetHz(gpuLoad, tableMaxHz); + u32 targetHz = ResolveTargetHz(SysClkModule_GPU); + u32 maxHz = clockManager::GetMaxAllowedHz(SysClkModule_GPU, clockManager::gContext.profile); + + if (targetHz && desiredHz > targetHz) + desiredHz = targetHz; + + if (maxHz && desiredHz > maxHz) + desiredHz = maxHz; + + u32 newHz = table.list[TableIndexForHz(table, desiredHz)]; + bool goingDown = (lastHz != 0) && (newHz < lastHz); + + if (!goingDown) + downHoldRemaining = 0; + else if (downHoldRemaining == 0) + downHoldRemaining = DOWN_HOLD_TICKS; + + if (downHoldRemaining > 0) + downHoldRemaining--; + + if ((!goingDown || (downHoldRemaining == 0)) && clockManager::IsAssignableHz(SysClkModule_GPU, newHz)) { + board::SetHz(SysClkModule_GPU, newHz); + clockManager::gContext.freqs[SysClkModule_GPU] = newHz; + lastHz = newHz; + } + + svcSleepThread(POLL_NS); + } + } + + void VRRThread(void* arg) + { + (void)arg; + + u8 tick = 0; + for (;;) { + if (!clockManager::gRunning || clockManager::gContext.profile == SysClkProfile_Docked || !isVRREnabled) { + svcSleepThread(POLL_NS); + continue; + } + + std::scoped_lock lock{clockManager::gContextMutex}; + + u8 fps; + + if (clockManager::gContext.isSaltyNXInstalled) { + fps = integrations::GetSaltyNXFPS(); + } else { + svcSleepThread(~0ULL); // effectively disable the thread if SaltyNX isn't installed, as there's no point in it running + continue; + } + + if (fps == 254) { + svcSleepThread(POLL_NS); + continue; + } + // if(appletGetFocusState() != AppletFocusState_InFocus) { + // board::ResetToStockDisplay(); + // continue; + // } + + u32 targetHz = clockManager::gContext.overrideFreqs[HorizonOCModule_Display]; + if (!targetHz) { + targetHz = config::GetAutoClockHz(clockManager::gContext.applicationId, HorizonOCModule_Display, clockManager::gContext.profile, false); + if (!targetHz) + targetHz = config::GetAutoClockHz(GLOBAL_PROFILE_ID, HorizonOCModule_Display, clockManager::gContext.profile, false); + } + + u8 maxDisplay; + if (targetHz) { + maxDisplay = targetHz; + } else { + maxDisplay = 60; // don't assume display stuff! + } + + u8 minDisplay = board::GetConsoleType() == HorizonOCConsoleType_Aula ? 45 : 40; + if (maxDisplay == minDisplay) + continue; + + if (fps >= minDisplay && fps <= maxDisplay) { + board::SetHz(HorizonOCModule_Display, fps); + clockManager::gContext.freqs[HorizonOCModule_Display] = fps; + clockManager::gContext.realFreqs[HorizonOCModule_Display] = fps; + } else { + for (u32 i = 0; i < 10; i++) { + u32 compareHz = fps * i; + if (compareHz >= minDisplay && compareHz <= maxDisplay) { + board::SetHz(HorizonOCModule_Display, compareHz); + clockManager::gContext.freqs[HorizonOCModule_Display] = compareHz; + clockManager::gContext.realFreqs[HorizonOCModule_Display] = compareHz; + break; + } + } + } + + if (++tick > 50) { + board::SetHz(HorizonOCModule_Display, maxDisplay); + tick = 0; + svcSleepThread(50'000'000); + } + + svcSleepThread(POLL_NS); + } + } + + + void startThreads() { + + threadCreate( + &cpuGovernorTHREAD, + CpuGovernorThread, + nullptr, + NULL, + 0x2000, + 0x3F, + -2 + ); + + threadCreate( + &gpuGovernorTHREAD, + GovernorThread, + nullptr, + NULL, + 0x2000, + 0x3F, + -2 + ); + + threadCreate( + &vrrTHREAD, + VRRThread, + nullptr, + NULL, + 0x2000, + 0x3F, + -2 + ); + + threadStart(&cpuGovernorTHREAD); + threadStart(&gpuGovernorTHREAD); + threadStart(&vrrTHREAD); + } + + void exitThreads() { + threadClose(&cpuGovernorTHREAD); + threadClose(&gpuGovernorTHREAD); + threadClose(&vrrTHREAD); + } +} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/governor.hpp b/Source/rewrite-hoc-clk/sysmodule/src/governor.hpp new file mode 100644 index 00000000..352adc4b --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/governor.hpp @@ -0,0 +1,27 @@ +#include +#include +#include "board/board.hpp" +#include "clock_manager.hpp" +#include +#include "file_utils.hpp" +#include "board/board.hpp" +#include "errors.hpp" +#include "config.hpp" +#include "integrations.hpp" +#include + +namespace governor { + extern bool isCpuGovernorInBoostMode; + extern bool isVRREnabled; + extern bool isGpuGovernorEnabled; + extern bool isCpuGovernorEnabled; + extern bool lastGpuGovernorState; + extern bool lastCpuGovernorState; + extern bool lastVrrGovernorState; + void startThreads(); + void exitThreads(); + void HandleGovernor(uint32_t targetHz); + void CpuGovernorThread(void* arg); + void GovernorThread(void* arg); + void VRRThread(void* arg); +} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/integrations.cpp b/Source/rewrite-hoc-clk/sysmodule/src/integrations.cpp index d088c5e8..b1c603cb 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/integrations.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/integrations.cpp @@ -15,123 +15,137 @@ * */ +/* -------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * , , + * 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 "integrations.h" +#include "integrations.hpp" #include #include #include "process_management.hpp" -SysDockIntegration::SysDockIntegration() { -} +namespace integrations { -bool SysDockIntegration::getCurrentSysDockState() { - struct stat st = {0}; - return stat("sdmc:/atmosphere/contents/42000000000000A0/flags/boot2.flag", &st) == 0; -} + namespace { -SaltyNXIntegration::SaltyNXIntegration() { -} + NxFpsSharedBlock* gNxFps = nullptr; + SharedMemory gSharedMemory = {}; + bool gSharedMemoryUsed = false; + Handle gRemoteSharedMemory = 1; + u64 gPrevTid = 0; -void SaltyNXIntegration::LoadSaltyNX() { - if (!CheckPort()) - return; - LoadSharedMemory(); -} + bool CheckSaltyNXPort() { + Handle saltysd; -bool SaltyNXIntegration::getCurrentSaltyNXState() { - struct stat st = {0}; - return stat("sdmc:/atmosphere/contents/0000000000534C56/flags/boot2.flag", &st) == 0; -} + for (int i = 0; i < 67; i++) { + if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) { + svcCloseHandle(saltysd); + break; + } + if (i == 66) return false; + svcSleepThread(1'000'000); + } -bool SaltyNXIntegration::CheckPort() { - Handle saltysd; + for (int i = 0; i < 67; i++) { + if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) { + svcCloseHandle(saltysd); + return true; + } + svcSleepThread(1'000'000); + } - for (int i = 0; i < 67; i++) { - if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) { - svcCloseHandle(saltysd); - break; + return false; } - if (i == 66) return false; - svcSleepThread(1'000'000); + + void SearchSharedMemoryBlock(uintptr_t base) { + ptrdiff_t search_offset = 0; + while (search_offset < 0x1000) { + gNxFps = (NxFpsSharedBlock*)(base + search_offset); + if (gNxFps->MAGIC == 0x465053) + return; + search_offset += 4; + } + gNxFps = nullptr; + } + + void LoadSharedMemory() { + if (SaltySD_Connect()) + return; + SaltySD_GetSharedMemoryHandle(&gRemoteSharedMemory); + SaltySD_Term(); + shmemLoadRemote(&gSharedMemory, gRemoteSharedMemory, 0x1000, Perm_Rw); + if (!shmemMap(&gSharedMemory)) + gSharedMemoryUsed = true; + } + } - for (int i = 0; i < 67; i++) { - if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) { - svcCloseHandle(saltysd); - return true; - } - svcSleepThread(1'000'000); + bool GetSysDockState() { + struct stat st = {0}; + return stat("sdmc:/atmosphere/contents/42000000000000A0/flags/boot2.flag", &st) == 0; } - return false; -} + bool GetSaltyNXState() { + struct stat st = {0}; + return stat("sdmc:/atmosphere/contents/0000000000534C56/flags/boot2.flag", &st) == 0; + } -void SaltyNXIntegration::LoadSharedMemory() { - if (SaltySD_Connect()) - return; - SaltySD_GetSharedMemoryHandle(&remoteSharedMemory); - SaltySD_Term(); - shmemLoadRemote(&_sharedmemory, remoteSharedMemory, 0x1000, Perm_Rw); - if (!shmemMap(&_sharedmemory)) - SharedMemoryUsed = true; -} - -void SaltyNXIntegration::searchSharedMemoryBlock(uintptr_t base) { - ptrdiff_t search_offset = 0; - while (search_offset < 0x1000) { - NxFps = (NxFpsSharedBlock*)(base + search_offset); - if (NxFps->MAGIC == 0x465053) + void LoadSaltyNX() { + if (!CheckSaltyNXPort()) return; - search_offset += 4; - } - NxFps = 0; -} - -u64 prevTid = 0; - -u8 SaltyNXIntegration::GetFPS() { - if (!SharedMemoryUsed) - return 254; - - u64 tid = processManagement::GetCurrentApplicationId(); - if (tid == 0) - return 254; - - if (prevTid != tid) { - NxFps = 0; - prevTid = tid; + LoadSharedMemory(); } - if (!NxFps) { - uintptr_t base = (uintptr_t)shmemGetAddr(&_sharedmemory); - searchSharedMemoryBlock(base); + u8 GetSaltyNXFPS() { + if (!gSharedMemoryUsed) + return 254; + + u64 tid = processManagement::GetCurrentApplicationId(); + if (tid == 0) + return 254; + + if (gPrevTid != tid) { + gNxFps = nullptr; + gPrevTid = tid; + } + + if (!gNxFps) { + uintptr_t base = (uintptr_t)shmemGetAddr(&gSharedMemory); + SearchSharedMemoryBlock(base); + } + + return gNxFps ? gNxFps->FPS : 254; } - return NxFps ? NxFps->FPS : 254; -} + u16 GetSaltyNXResolutionHeight() { + if (!gSharedMemoryUsed) + return 0; -u16 SaltyNXIntegration::GetResolutionHeight() { - if (!SharedMemoryUsed) + u64 tid = processManagement::GetCurrentApplicationId(); + if (tid == 0) + return 0; + + if (gPrevTid != tid) { + gNxFps = nullptr; + gPrevTid = tid; + } + + if (!gNxFps) { + uintptr_t base = (uintptr_t)shmemGetAddr(&gSharedMemory); + SearchSharedMemoryBlock(base); + } + + if (gNxFps) { + gNxFps->renderCalls[0].calls = 0xFFFF; + svcSleepThread(10*1000); + return gNxFps->renderCalls[0].height == 0 ? gNxFps->viewportCalls[0].height : gNxFps->renderCalls[0].height; + } return 0; - - u64 tid = processManagement::GetCurrentApplicationId(); - if (tid == 0) - return 0; - - if (prevTid != tid) { - NxFps = 0; - prevTid = tid; } - if (!NxFps) { - uintptr_t base = (uintptr_t)shmemGetAddr(&_sharedmemory); - searchSharedMemoryBlock(base); - } - if(NxFps) { - NxFps->renderCalls[0].calls = 0xFFFF; - svcSleepThread(10*1000); - - return NxFps->renderCalls[0].height == 0 ? NxFps->viewportCalls[0].height : NxFps->renderCalls[0].height; - } - return 0; -} \ No newline at end of file +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/integrations.h b/Source/rewrite-hoc-clk/sysmodule/src/integrations.hpp similarity index 64% rename from Source/rewrite-hoc-clk/sysmodule/src/integrations.h rename to Source/rewrite-hoc-clk/sysmodule/src/integrations.hpp index 466e2f7d..daf9fa25 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/integrations.h +++ b/Source/rewrite-hoc-clk/sysmodule/src/integrations.hpp @@ -12,37 +12,24 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * + */ + +/* -------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * , , + * 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 -#include -#include -#include -#include -#include + #include -#include "errors.h" -#include "file_utils.h" +#include -#include "clock_manager.h" - -class SysDockIntegration { -public: - SysDockIntegration(); - - bool getCurrentSysDockState(); -}; - -class SaltyNXIntegration { -public: - struct resolutionCalls { - uint16_t width; - uint16_t height; - uint16_t calls; - }; +namespace integrations { struct NxFpsSharedBlock { uint32_t MAGIC; @@ -60,15 +47,18 @@ public: uint8_t ActiveBuffers; uint8_t SetActiveBuffers; union { - struct { + struct { bool handheld: 1; bool docked: 1; unsigned int reserved: 6; } NX_PACKED ds; uint8_t general; } displaySync; - resolutionCalls renderCalls[8]; - resolutionCalls viewportCalls[8]; + struct resolutionCalls { + uint16_t width; + uint16_t height; + uint16_t calls; + } renderCalls[8], viewportCalls[8]; bool forceOriginalRefreshRate; bool dontForce60InDocked; bool forceSuspend; @@ -78,17 +68,10 @@ public: uint64_t frameNumber; } NX_PACKED; - NxFpsSharedBlock* NxFps = 0; - SharedMemory _sharedmemory = {}; - bool SharedMemoryUsed = false; - Handle remoteSharedMemory = 1; - SaltyNXIntegration(); + bool GetSysDockState(); + bool GetSaltyNXState(); void LoadSaltyNX(); - bool getCurrentSaltyNXState(); + u8 GetSaltyNXFPS(); + u16 GetSaltyNXResolutionHeight(); - bool CheckPort(); - void LoadSharedMemory(); - void searchSharedMemoryBlock(uintptr_t base); - u8 GetFPS(); - u16 GetResolutionHeight(); -}; \ No newline at end of file +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.cpp b/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.cpp index 4dea5685..fe678b05 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.cpp @@ -24,351 +24,271 @@ * -------------------------------------------------------------------------- */ - -#include "ipc_service.h" +#include "ipc_service.hpp" #include #include -#include "file_utils.h" -#include "errors.h" -#include "clock_manager.h" -IpcService::IpcService(ClockManager* clockMgr) -{ - std::int32_t priority; - Result rc = svcGetThreadPriority(&priority, CUR_THREAD_HANDLE); - ASSERT_RESULT_OK(rc, "svcGetThreadPriority"); - rc = ipcServerInit(&this->server, SYSCLK_IPC_SERVICE_NAME, 42); - ASSERT_RESULT_OK(rc, "ipcServerInit"); - rc = threadCreate(&this->thread, &IpcService::ProcessThreadFunc, this, NULL, 0x2000, priority, -2); - ASSERT_RESULT_OK(rc, "threadCreate"); +#include +#include "file_utils.hpp" +#include "errors.hpp" +#include "clock_manager.hpp" +#include "config.hpp" +#include "kip.hpp" +namespace ipcService { - this->running = false; - this->clockMgr = clockMgr; + namespace { -} + bool gRunning = false; + Thread gThread; + LockableMutex gThreadMutex; + IpcServer gServer; -void IpcService::SetRunning(bool running) -{ - std::scoped_lock lock{this->threadMutex}; - if(this->running == running) - { - return; - } + Result GetApiVersion(u32* out_version) { + *out_version = SYSCLK_IPC_API_VERSION; + return 0; + } - this->running = running; - - if(running) - { - Result rc = threadStart(&this->thread); - ASSERT_RESULT_OK(rc, "threadStart"); - } - else - { - svcCancelSynchronization(this->thread.handle); - threadWaitForExit(&this->thread); - } -} - -IpcService::~IpcService() -{ - this->SetRunning(false); - Result rc = threadClose(&this->thread); - ASSERT_RESULT_OK(rc, "threadClose"); - rc = ipcServerExit(&this->server); - ASSERT_RESULT_OK(rc, "ipcServerExit"); -} - -void IpcService::ProcessThreadFunc(void* arg) -{ - Result rc; - IpcService* ipcSrv = (IpcService*)arg; - while(true) - { - rc = ipcServerProcess(&ipcSrv->server, &IpcService::ServiceHandlerFunc, arg); - if(R_FAILED(rc)) - { - if(rc == KERNELRESULT(Cancelled)) - { - return; + Result GetVersionString(char* out_buf, size_t bufSize) { + if (bufSize) { + strncpy(out_buf, TARGET_VERSION, bufSize-1); } - if(rc != KERNELRESULT(ConnectionClosed)) - { - FileUtils::LogLine("[ipc] ipcServerProcess: [0x%x] %04d-%04d", rc, R_MODULE(rc), R_DESCRIPTION(rc)); + return 0; + } + + Result GetCurrentContext(SysClkContext* out_ctx) { + *out_ctx = clockManager::GetCurrentContext(); + return 0; + } + + Result ExitHandler() { + clockManager::SetRunning(false); + return 0; + } + + Result GetProfileCount(std::uint64_t* tid, std::uint8_t* out_count) { + if (!config::HasProfilesLoaded()) { + return SYSCLK_ERROR(ConfigNotLoaded); + } + *out_count = config::GetProfileCount(*tid); + return 0; + } + + Result GetProfiles(std::uint64_t* tid, SysClkTitleProfileList* out_profiles) { + if (!config::HasProfilesLoaded()) { + return SYSCLK_ERROR(ConfigNotLoaded); + } + config::GetProfiles(*tid, out_profiles); + return 0; + } + + Result SetProfiles(SysClkIpc_SetProfiles_Args* args) { + if (!config::HasProfilesLoaded()) { + return SYSCLK_ERROR(ConfigNotLoaded); + } + SysClkTitleProfileList profiles = args->profiles; + if (!config::SetProfiles(args->tid, &profiles, true)) { + return SYSCLK_ERROR(ConfigSaveFailed); + } + return 0; + } + + Result SetEnabled(std::uint8_t* enabled) { + config::SetEnabled(*enabled); + return 0; + } + + Result SetOverride(SysClkIpc_SetOverride_Args* args) { + if (!SYSCLK_ENUM_VALID(SysClkModule, args->module)) { + return SYSCLK_ERROR(Generic); + } + config::SetOverrideHz(args->module, args->hz); + return 0; + } + + Result GetConfigValuesHandler(SysClkConfigValueList* out_configValues) { + if (!config::HasProfilesLoaded()) { + return SYSCLK_ERROR(ConfigNotLoaded); + } + config::GetConfigValues(out_configValues); + return 0; + } + + Result SetConfigValuesHandler(SysClkConfigValueList* configValues) { + if (!config::HasProfilesLoaded()) { + return SYSCLK_ERROR(ConfigNotLoaded); + } + SysClkConfigValueList copy = *configValues; + if (!config::SetConfigValues(©, true)) { + return SYSCLK_ERROR(ConfigSaveFailed); + } + return 0; + } + + Result GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t* out_list, std::size_t size, std::uint32_t* out_count) { + if (!SYSCLK_ENUM_VALID(SysClkModule, args->module)) { + return SYSCLK_ERROR(Generic); + } + if (args->maxCount != size/sizeof(*out_list)) { + return SYSCLK_ERROR(Generic); + } + clockManager::GetFreqList(args->module, out_list, args->maxCount, out_count); + return 0; + } + + Result ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8* out_data, size_t* out_dataSize) { + (void)arg; + switch (r->data.cmdId) { + case SysClkIpcCmd_GetApiVersion: + *out_dataSize = sizeof(u32); + return GetApiVersion((u32*)out_data); + + case SysClkIpcCmd_GetVersionString: + if (r->hipc.meta.num_recv_buffers >= 1) { + return GetVersionString( + (char*)hipcGetBufferAddress(r->hipc.data.recv_buffers), + hipcGetBufferSize(r->hipc.data.recv_buffers) + ); + } + break; + + case SysClkIpcCmd_GetCurrentContext: + if (r->data.size >= sizeof(std::uint64_t) && r->hipc.meta.num_recv_buffers >= 1) { + size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers); + if (bufSize >= sizeof(SysClkContext)) { + return GetCurrentContext((SysClkContext*)hipcGetBufferAddress(r->hipc.data.recv_buffers)); + } + } + break; + + case SysClkIpcCmd_Exit: + return ExitHandler(); + + case SysClkIpcCmd_GetProfileCount: + if (r->data.size >= sizeof(std::uint64_t)) { + *out_dataSize = sizeof(std::uint8_t); + return GetProfileCount((std::uint64_t*)r->data.ptr, (std::uint8_t*)out_data); + } + break; + + case SysClkIpcCmd_GetProfiles: + if (r->data.size >= sizeof(std::uint64_t) && r->hipc.meta.num_recv_buffers >= 1) { + size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers); + if (bufSize >= sizeof(SysClkTitleProfileList)) { + return GetProfiles((std::uint64_t*)r->data.ptr, (SysClkTitleProfileList*)hipcGetBufferAddress(r->hipc.data.recv_buffers)); + } + } + break; + + case SysClkIpcCmd_SetProfiles: + if (r->data.size >= sizeof(SysClkIpc_SetProfiles_Args)) { + return SetProfiles((SysClkIpc_SetProfiles_Args*)r->data.ptr); + } + break; + + case SysClkIpcCmd_SetEnabled: + if (r->data.size >= sizeof(std::uint8_t)) { + return SetEnabled((std::uint8_t*)r->data.ptr); + } + break; + + case SysClkIpcCmd_SetOverride: + if (r->data.size >= sizeof(SysClkIpc_SetOverride_Args)) { + return SetOverride((SysClkIpc_SetOverride_Args*)r->data.ptr); + } + break; + + case SysClkIpcCmd_GetConfigValues: + if (r->hipc.meta.num_recv_buffers >= 1) { + size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers); + if (bufSize >= sizeof(SysClkConfigValueList)) { + return GetConfigValuesHandler((SysClkConfigValueList*)hipcGetBufferAddress(r->hipc.data.recv_buffers)); + } + } + break; + + case SysClkIpcCmd_SetConfigValues: + if (r->hipc.meta.num_send_buffers >= 1) { + size_t bufSize = hipcGetBufferSize(r->hipc.data.send_buffers); + if (bufSize >= sizeof(SysClkConfigValueList)) { + return SetConfigValuesHandler((SysClkConfigValueList*)hipcGetBufferAddress(r->hipc.data.send_buffers)); + } + } + break; + + case SysClkIpcCmd_GetFreqList: + if (r->data.size >= sizeof(SysClkIpc_GetFreqList_Args) && r->hipc.meta.num_recv_buffers >= 1) { + *out_dataSize = sizeof(std::uint32_t); + return GetFreqList( + (SysClkIpc_GetFreqList_Args*)r->data.ptr, + (std::uint32_t*)hipcGetBufferAddress(r->hipc.data.recv_buffers), + hipcGetBufferSize(r->hipc.data.recv_buffers), + (std::uint32_t*)out_data + ); + } + break; + + case HocClkIpcCmd_SetKipData: + if (r->data.size >= 0) { + kip::SetKipData(); + return 0; + } + break; + } + + return SYSCLK_ERROR(Generic); + } + + void ProcessThreadFunc(void* arg) { + (void)arg; + Result rc; + while (true) { + rc = ipcServerProcess(&gServer, &ServiceHandlerFunc, nullptr); + if (R_FAILED(rc)) { + if (rc == KERNELRESULT(Cancelled)) { + return; + } + if (rc != KERNELRESULT(ConnectionClosed)) { + fileUtils::LogLine("[ipc] ipcServerProcess: [0x%x] %04d-%04d", rc, R_MODULE(rc), R_DESCRIPTION(rc)); + } + } } } - } -} -Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8* out_data, size_t* out_dataSize) -{ - IpcService* ipcSrv = (IpcService*)arg; - - switch(r->data.cmdId) - { - case SysClkIpcCmd_GetApiVersion: - *out_dataSize = sizeof(u32); - return ipcSrv->GetApiVersion((u32*)out_data); - - case SysClkIpcCmd_GetVersionString: - if(r->hipc.meta.num_recv_buffers >= 1) - { - return ipcSrv->GetVersionString( - (char*)hipcGetBufferAddress(r->hipc.data.recv_buffers), - hipcGetBufferSize(r->hipc.data.recv_buffers) - ); - } - break; - - case SysClkIpcCmd_GetCurrentContext: - if(r->data.size >= sizeof(std::uint64_t) && r->hipc.meta.num_recv_buffers >= 1) - { - size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers); - if(bufSize >= sizeof(SysClkContext)) - { - return ipcSrv->GetCurrentContext((SysClkContext*)hipcGetBufferAddress(r->hipc.data.recv_buffers)); - } - } - break; - case SysClkIpcCmd_Exit: - return ipcSrv->Exit(); - - case SysClkIpcCmd_GetProfileCount: - if(r->data.size >= sizeof(std::uint64_t)) - { - *out_dataSize = sizeof(std::uint8_t); - return ipcSrv->GetProfileCount((std::uint64_t*)r->data.ptr, (std::uint8_t*)out_data); - } - break; - - case SysClkIpcCmd_GetProfiles: - if(r->data.size >= sizeof(std::uint64_t) && r->hipc.meta.num_recv_buffers >= 1) - { - size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers); - if(bufSize >= sizeof(SysClkTitleProfileList)) - { - return ipcSrv->GetProfiles((std::uint64_t*)r->data.ptr, (SysClkTitleProfileList*)hipcGetBufferAddress(r->hipc.data.recv_buffers)); - } - } - break; - - case SysClkIpcCmd_SetProfiles: - if(r->data.size >= sizeof(SysClkIpc_SetProfiles_Args)) - { - return ipcSrv->SetProfiles((SysClkIpc_SetProfiles_Args*)r->data.ptr); - } - break; - - case SysClkIpcCmd_SetEnabled: - if(r->data.size >= sizeof(std::uint8_t)) - { - return ipcSrv->SetEnabled((std::uint8_t*)r->data.ptr); - } - break; - - case SysClkIpcCmd_SetOverride: - if(r->data.size >= sizeof(SysClkIpc_SetOverride_Args)) - { - return ipcSrv->SetOverride((SysClkIpc_SetOverride_Args*)r->data.ptr); - } - break; - - case SysClkIpcCmd_GetConfigValues: - if(r->hipc.meta.num_recv_buffers >= 1) - { - size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers); - if(bufSize >= sizeof(SysClkConfigValueList)) - { - return ipcSrv->GetConfigValues((SysClkConfigValueList*)hipcGetBufferAddress(r->hipc.data.recv_buffers)); - } - } - break; - - case SysClkIpcCmd_SetConfigValues: - if(r->hipc.meta.num_send_buffers >= 1) - { - size_t bufSize = hipcGetBufferSize(r->hipc.data.send_buffers); - if(bufSize >= sizeof(SysClkConfigValueList)) - { - return ipcSrv->SetConfigValues((SysClkConfigValueList*)hipcGetBufferAddress(r->hipc.data.send_buffers)); - } - } - break; - case SysClkIpcCmd_GetFreqList: - if(r->data.size >= sizeof(SysClkIpc_GetFreqList_Args) && r->hipc.meta.num_recv_buffers >= 1) - { - *out_dataSize = sizeof(std::uint32_t); - return ipcSrv->GetFreqList( - (SysClkIpc_GetFreqList_Args*)r->data.ptr, - (std::uint32_t*)hipcGetBufferAddress(r->hipc.data.recv_buffers), - hipcGetBufferSize(r->hipc.data.recv_buffers), - (std::uint32_t*)out_data - ); - } - break; - case HocClkIpcCmd_SetKipData: - if (r->data.size >= 0) { - return ipcSrv->SetKipData(); - } - break; } - return SYSCLK_ERROR(Generic); -} - -Result IpcService::GetApiVersion(u32* out_version) -{ - *out_version = SYSCLK_IPC_API_VERSION; - - return 0; -} - -Result IpcService::GetVersionString(char* out_buf, size_t bufSize) -{ - if(bufSize) - { - strncpy(out_buf, TARGET_VERSION, bufSize-1); + void Initialize() { + std::int32_t priority; + Result rc = svcGetThreadPriority(&priority, CUR_THREAD_HANDLE); + ASSERT_RESULT_OK(rc, "svcGetThreadPriority"); + rc = ipcServerInit(&gServer, SYSCLK_IPC_SERVICE_NAME, 42); + ASSERT_RESULT_OK(rc, "ipcServerInit"); + rc = threadCreate(&gThread, &ProcessThreadFunc, nullptr, NULL, 0x2000, priority, -2); + ASSERT_RESULT_OK(rc, "threadCreate"); + gRunning = false; } - return 0; -} - -Result IpcService::GetCurrentContext(SysClkContext* out_ctx) -{ - *out_ctx = this->clockMgr->GetCurrentContext(); - - return 0; -} - -Result IpcService::Exit() -{ - this->clockMgr->SetRunning(false); - - return 0; -} - -Result IpcService::GetProfileCount(std::uint64_t* tid, std::uint8_t* out_count) -{ - Config* config = this->clockMgr->GetConfig(); - if(!config->HasProfilesLoaded()) - { - return SYSCLK_ERROR(ConfigNotLoaded); + void Exit() { + SetRunning(false); + Result rc = threadClose(&gThread); + ASSERT_RESULT_OK(rc, "threadClose"); + rc = ipcServerExit(&gServer); + ASSERT_RESULT_OK(rc, "ipcServerExit"); } - *out_count = config->GetProfileCount(*tid); + void SetRunning(bool running) { + std::scoped_lock lock{gThreadMutex}; + if (gRunning == running) { + return; + } - return 0; -} + gRunning = running; -Result IpcService::GetProfiles(std::uint64_t* tid, SysClkTitleProfileList* out_profiles) -{ - Config* config = this->clockMgr->GetConfig(); - if(!config->HasProfilesLoaded()) - { - return SYSCLK_ERROR(ConfigNotLoaded); + if (running) { + Result rc = threadStart(&gThread); + ASSERT_RESULT_OK(rc, "threadStart"); + } else { + svcCancelSynchronization(gThread.handle); + threadWaitForExit(&gThread); + } } - config->GetProfiles(*tid, out_profiles); - - return 0; } - -Result IpcService::SetProfiles(SysClkIpc_SetProfiles_Args* args) -{ - Config* config = this->clockMgr->GetConfig(); - if(!config->HasProfilesLoaded()) - { - return SYSCLK_ERROR(ConfigNotLoaded); - } - - SysClkTitleProfileList profiles = args->profiles; - - if(!config->SetProfiles(args->tid, &profiles, true)) - { - return SYSCLK_ERROR(ConfigSaveFailed); - } - - return 0; -} - -Result IpcService::SetEnabled(std::uint8_t* enabled) -{ - Config* config = this->clockMgr->GetConfig(); - config->SetEnabled(*enabled); - - return 0; -} - -Result IpcService::SetOverride(SysClkIpc_SetOverride_Args* args) -{ - SysClkModule module = args->module; - std::uint32_t hz = args->hz; - - if(!SYSCLK_ENUM_VALID(SysClkModule, args->module)) - { - return SYSCLK_ERROR(Generic); - } - - Config* config = this->clockMgr->GetConfig(); - config->SetOverrideHz(module, hz); - - return 0; -} - -Result IpcService::GetConfigValues(SysClkConfigValueList* out_configValues) -{ - Config* config = this->clockMgr->GetConfig(); - if(!config->HasProfilesLoaded()) - { - return SYSCLK_ERROR(ConfigNotLoaded); - } - - config->GetConfigValues(out_configValues); - - return 0; -} - -Result IpcService::SetConfigValues(SysClkConfigValueList* configValues) -{ - Config* config = this->clockMgr->GetConfig(); - if(!config->HasProfilesLoaded()) - { - return SYSCLK_ERROR(ConfigNotLoaded); - } - - SysClkConfigValueList configValuesCopy = *configValues; - - if(!config->SetConfigValues(&configValuesCopy, true)) - { - return SYSCLK_ERROR(ConfigSaveFailed); - } - - return 0; -} - -Result IpcService::GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t* out_list, std::size_t size, std::uint32_t* out_count) -{ - if(!SYSCLK_ENUM_VALID(SysClkModule, args->module)) - { - return SYSCLK_ERROR(Generic); - } - - if(args->maxCount != size/sizeof(*out_list)) - { - return SYSCLK_ERROR(Generic); - } - - this->clockMgr->GetFreqList(args->module, out_list, args->maxCount, out_count); - - return 0; -} - -Result IpcService::SetKipData() { - this->clockMgr->SetKipData(); - - return 0; -} - -Result IpcService::GetKipData() { - this->clockMgr->GetKipData(); - - return 0; -} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.h b/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.h deleted file mode 100644 index cded785c..00000000 --- a/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -/* -------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * , , - * 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 -#include -#include -#include "clock_manager.h" - -class IpcService -{ - public: - - IpcService(ClockManager* clockMgr); - virtual ~IpcService(); - void SetRunning(bool running); - static void ProcessThreadFunc(void* arg); - static Result ServiceHandlerFunc(void* arg, const IpcServerRequest* r, std::uint8_t* out_data, size_t* out_dataSize); - - Result GetApiVersion(u32* out_version); - Result GetVersionString(char* out_buf, size_t bufSize); - Result GetCurrentContext(SysClkContext* out_ctx); - Result Exit(); - Result GetProfileCount(std::uint64_t* tid, std::uint8_t* out_count); - Result GetProfiles(std::uint64_t* tid, SysClkTitleProfileList* out_profiles); - Result SetProfiles(SysClkIpc_SetProfiles_Args* args); - Result SetEnabled(std::uint8_t* enabled); - Result SetOverride(SysClkIpc_SetOverride_Args* args); - Result GetConfigValues(SysClkConfigValueList* out_configValues); - Result SetConfigValues(SysClkConfigValueList* configValues); - Result GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t* out_list, std::size_t size, std::uint32_t* out_count); - Result SetKipData(); - Result GetKipData(); - bool running; - Thread thread; - LockableMutex threadMutex; - IpcServer server; - ClockManager* clockMgr; - protected: - -}; diff --git a/Source/rewrite-hoc-clk/sysmodule/src/process_management.h b/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.hpp similarity index 81% rename from Source/rewrite-hoc-clk/sysmodule/src/process_management.h rename to Source/rewrite-hoc-clk/sysmodule/src/ipc_service.hpp index 65abe792..421e4dc9 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/process_management.h +++ b/Source/rewrite-hoc-clk/sysmodule/src/ipc_service.hpp @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -24,18 +24,15 @@ * -------------------------------------------------------------------------- */ - #pragma once + +#include #include -#include -#define PROCESS_MANAGEMENT_QLAUNCH_TID 0x0100000000001000ULL +namespace ipcService { -class ProcessManagement -{ - public: - static void Initialize(); - static void WaitForQLaunch(); - static std::uint64_t GetCurrentApplicationId(); - static void Exit(); -}; + void Initialize(); + void Exit(); + void SetRunning(bool running); + +} diff --git a/Source/rewrite-hoc-clk/sysmodule/src/kip.cpp b/Source/rewrite-hoc-clk/sysmodule/src/kip.cpp new file mode 100644 index 00000000..ad15eebd --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/kip.cpp @@ -0,0 +1,255 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/* -------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * , , + * 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 "kip.hpp" +#include "board/board.hpp" + +namespace kip { + + bool kipAvailable = false; + + void SetKipData() + { + // TODO: figure out if this REALLY causes issues (i doubt it) + // if(board::GetSocType() == SysClkSocType_Mariko) { + // if(R_FAILED(I2c_BuckConverter_SetMvOut(&I2c_Mariko_DRAM_VDDQ, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt) / 1000))) { + // fileUtils::LogLine("[clock_manager] Failed set i2c vddq"); + // notification::writeNotification("Horizon OC\nFailed to write I2C\nwhile setting vddq"); + // } + // } + CustomizeTable table; + FILE* fp; + fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r"); + + if (fp == NULL) { + notification::writeNotification("Horizon OC\nKip opening failed"); + kipAvailable = false; + return; + } else { + kipAvailable = true; + fclose(fp); + } + + if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) { + fileUtils::LogLine("[clock_manager] Failed to read KIP file"); + notification::writeNotification("Horizon OC\nKip read failed"); + return; + } + + CUST_WRITE_FIELD_BATCH(&table, custRev, config::GetConfigValue(KipConfigValue_custRev)); + // CUST_WRITE_FIELD_BATCH(&table, mtcConf, config::GetConfigValue(KipConfigValue_mtcConf)); + CUST_WRITE_FIELD_BATCH(&table, hpMode, config::GetConfigValue(KipConfigValue_hpMode)); + + CUST_WRITE_FIELD_BATCH(&table, commonEmcMemVolt, config::GetConfigValue(KipConfigValue_commonEmcMemVolt)); + CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock)); + CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock1, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock1)); + CUST_WRITE_FIELD_BATCH(&table, eristaEmcMaxClock2, config::GetConfigValue(KipConfigValue_eristaEmcMaxClock2)); + CUST_WRITE_FIELD_BATCH(&table, marikoEmcMaxClock, config::GetConfigValue(KipConfigValue_marikoEmcMaxClock)); + CUST_WRITE_FIELD_BATCH(&table, marikoEmcVddqVolt, config::GetConfigValue(KipConfigValue_marikoEmcVddqVolt)); + CUST_WRITE_FIELD_BATCH(&table, emcDvbShift, config::GetConfigValue(KipConfigValue_emcDvbShift)); + + CUST_WRITE_FIELD_BATCH(&table, t1_tRCD, config::GetConfigValue(KipConfigValue_t1_tRCD)); + CUST_WRITE_FIELD_BATCH(&table, t2_tRP, config::GetConfigValue(KipConfigValue_t2_tRP)); + CUST_WRITE_FIELD_BATCH(&table, t3_tRAS, config::GetConfigValue(KipConfigValue_t3_tRAS)); + CUST_WRITE_FIELD_BATCH(&table, t4_tRRD, config::GetConfigValue(KipConfigValue_t4_tRRD)); + CUST_WRITE_FIELD_BATCH(&table, t5_tRFC, config::GetConfigValue(KipConfigValue_t5_tRFC)); + CUST_WRITE_FIELD_BATCH(&table, t6_tRTW, config::GetConfigValue(KipConfigValue_t6_tRTW)); + CUST_WRITE_FIELD_BATCH(&table, t7_tWTR, config::GetConfigValue(KipConfigValue_t7_tWTR)); + CUST_WRITE_FIELD_BATCH(&table, t8_tREFI, config::GetConfigValue(KipConfigValue_t8_tREFI)); + CUST_WRITE_FIELD_BATCH(&table, mem_burst_read_latency, config::GetConfigValue(KipConfigValue_mem_burst_read_latency)); + CUST_WRITE_FIELD_BATCH(&table, mem_burst_write_latency, config::GetConfigValue(KipConfigValue_mem_burst_write_latency)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuUV, config::GetConfigValue(KipConfigValue_eristaCpuUV)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuVmin, config::GetConfigValue(KipConfigValue_eristaCpuVmin)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuMaxVolt, config::GetConfigValue(KipConfigValue_eristaCpuMaxVolt)); + CUST_WRITE_FIELD_BATCH(&table, eristaCpuUnlock, config::GetConfigValue(KipConfigValue_eristaCpuUnlock)); + + CUST_WRITE_FIELD_BATCH(&table, marikoCpuUVLow, config::GetConfigValue(KipConfigValue_marikoCpuUVLow)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuUVHigh, config::GetConfigValue(KipConfigValue_marikoCpuUVHigh)); + CUST_WRITE_FIELD_BATCH(&table, tableConf, config::GetConfigValue(KipConfigValue_tableConf)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuLowVmin, config::GetConfigValue(KipConfigValue_marikoCpuLowVmin)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuHighVmin, config::GetConfigValue(KipConfigValue_marikoCpuHighVmin)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuMaxVolt, config::GetConfigValue(KipConfigValue_marikoCpuMaxVolt)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuMaxClock, config::GetConfigValue(KipConfigValue_marikoCpuMaxClock)); + + CUST_WRITE_FIELD_BATCH(&table, eristaCpuBoostClock, config::GetConfigValue(KipConfigValue_eristaCpuBoostClock)); + CUST_WRITE_FIELD_BATCH(&table, marikoCpuBoostClock, config::GetConfigValue(KipConfigValue_marikoCpuBoostClock)); + + CUST_WRITE_FIELD_BATCH(&table, eristaGpuUV, config::GetConfigValue(KipConfigValue_eristaGpuUV)); + CUST_WRITE_FIELD_BATCH(&table, eristaGpuVmin, config::GetConfigValue(KipConfigValue_eristaGpuVmin)); + + CUST_WRITE_FIELD_BATCH(&table, marikoGpuUV, config::GetConfigValue(KipConfigValue_marikoGpuUV)); + CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmin, config::GetConfigValue(KipConfigValue_marikoGpuVmin)); + CUST_WRITE_FIELD_BATCH(&table, marikoGpuVmax, config::GetConfigValue(KipConfigValue_marikoGpuVmax)); + + CUST_WRITE_FIELD_BATCH(&table, commonGpuVoltOffset, config::GetConfigValue(KipConfigValue_commonGpuVoltOffset)); + CUST_WRITE_FIELD_BATCH(&table, gpuSpeedo, config::GetConfigValue(KipConfigValue_gpuSpeedo)); + + for (int i = 0; i < 24; i++) { + table.marikoGpuVoltArray[i] = config::GetConfigValue((SysClkConfigValue)(KipConfigValue_g_volt_76800 + i)); + } + + for (int i = 0; i < 27; i++) { + table.eristaGpuVoltArray[i] = config::GetConfigValue((SysClkConfigValue)(KipConfigValue_g_volt_e_76800 + i)); + } + + CUST_WRITE_FIELD_BATCH(&table, t6_tRTW_fine_tune, config::GetConfigValue(KipConfigValue_t6_tRTW_fine_tune)); + CUST_WRITE_FIELD_BATCH(&table, t7_tWTR_fine_tune, config::GetConfigValue(KipConfigValue_t7_tWTR_fine_tune)); + + if (!cust_write_table("sdmc:/atmosphere/kips/hoc.kip", &table)) { + fileUtils::LogLine("[clock_manager] Failed to write KIP file"); + notification::writeNotification("Horizon OC\nKip write failed"); + } + + SysClkConfigValueList configValues; + config::GetConfigValues(&configValues); + + configValues.values[KipCrc32] = (u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum + + if (config::SetConfigValues(&configValues, false)) { + fileUtils::LogLine("[clock_manager] Successfully loaded KIP data into config"); + } else { + fileUtils::LogLine("[clock_manager] Warning: Failed to set config values from KIP"); + notification::writeNotification("Horizon OC\nKip config set failed"); + } + } + + // I know this is very hacky, but the config system in the sysmodule doesn't really support writing + + void GetKipData() + { + FILE* fp; + if (config::Refresh()) { + fp = fopen("sdmc:/atmosphere/kips/hoc.kip", "r"); + + if (fp == NULL) { + notification::writeNotification("Horizon OC\nKip opening failed"); + kipAvailable = false; + return; + } else { + kipAvailable = true; + fclose(fp); + } + + SysClkConfigValueList configValues; + config::GetConfigValues(&configValues); + + CustomizeTable table; + + if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) { + fileUtils::LogLine("[clock_manager] Failed to read KIP file for GetKipData"); + notification::writeNotification("Horizon OC\nKip read failed"); + return; + } + + if ((u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip") != config::GetConfigValue(KipCrc32) && !config::GetConfigValue(HocClkConfigValue_IsFirstLoad)) { + SetKipData(); + notification::writeNotification("Horizon OC\nKIP has been updated"); + notification::writeNotification("Horizon OC\nPlease reboot your console"); + notification::writeNotification("Horizon OC\nto complete the update"); + return; + } + if (config::GetConfigValue(HocClkConfigValue_IsFirstLoad) == true) { + configValues.values[HocClkConfigValue_IsFirstLoad] = (u64)false; + notification::writeNotification("Horizon OC has been installed"); + } + + configValues.values[KipCrc32] = (u64)crc32::checksum_file("sdmc:/atmosphere/kips/hoc.kip"); // write checksum + // configValues.values[KipConfigValue_mtcConf] = cust_get_mtc_conf(&table); + configValues.values[KipConfigValue_hpMode] = cust_get_hp_mode(&table); + + configValues.values[KipConfigValue_commonEmcMemVolt] = cust_get_common_emc_volt(&table); + configValues.values[KipConfigValue_eristaEmcMaxClock] = cust_get_erista_emc_max(&table); + configValues.values[KipConfigValue_eristaEmcMaxClock1] = cust_get_erista_emc_max1(&table); + configValues.values[KipConfigValue_eristaEmcMaxClock2] = cust_get_erista_emc_max2(&table); + configValues.values[KipConfigValue_marikoEmcMaxClock] = cust_get_mariko_emc_max(&table); + configValues.values[KipConfigValue_marikoEmcVddqVolt] = cust_get_mariko_emc_vddq(&table); + configValues.values[KipConfigValue_emcDvbShift] = cust_get_emc_dvb_shift(&table); + + configValues.values[KipConfigValue_t1_tRCD] = cust_get_tRCD(&table); + configValues.values[KipConfigValue_t2_tRP] = cust_get_tRP(&table); + configValues.values[KipConfigValue_t3_tRAS] = cust_get_tRAS(&table); + configValues.values[KipConfigValue_t4_tRRD] = cust_get_tRRD(&table); + configValues.values[KipConfigValue_t5_tRFC] = cust_get_tRFC(&table); + configValues.values[KipConfigValue_t6_tRTW] = cust_get_tRTW(&table); + configValues.values[KipConfigValue_t7_tWTR] = cust_get_tWTR(&table); + configValues.values[KipConfigValue_t8_tREFI] = cust_get_tREFI(&table); + configValues.values[KipConfigValue_mem_burst_read_latency] = cust_get_burst_read_lat(&table); + configValues.values[KipConfigValue_mem_burst_write_latency] = cust_get_burst_write_lat(&table); + + configValues.values[KipConfigValue_eristaCpuUV] = cust_get_erista_cpu_uv(&table); + configValues.values[KipConfigValue_eristaCpuVmin] = cust_get_eristaCpuVmin(&table); + configValues.values[KipConfigValue_eristaCpuMaxVolt] = cust_get_erista_cpu_max_volt(&table); + configValues.values[KipConfigValue_eristaCpuUnlock] = cust_get_eristaCpuUnlock(&table); + + configValues.values[KipConfigValue_marikoCpuUVLow] = cust_get_mariko_cpu_uv_low(&table); + configValues.values[KipConfigValue_marikoCpuUVHigh] = cust_get_mariko_cpu_uv_high(&table); + configValues.values[KipConfigValue_tableConf] = cust_get_table_conf(&table); + configValues.values[KipConfigValue_marikoCpuLowVmin] = cust_get_mariko_cpu_low_vmin(&table); + configValues.values[KipConfigValue_marikoCpuHighVmin] = cust_get_mariko_cpu_high_vmin(&table); + configValues.values[KipConfigValue_marikoCpuMaxVolt] = cust_get_mariko_cpu_max_volt(&table); + configValues.values[KipConfigValue_marikoCpuMaxClock] = cust_get_marikoCpuMaxClock(&table); + configValues.values[KipConfigValue_eristaCpuBoostClock] = cust_get_erista_cpu_boost(&table); + configValues.values[KipConfigValue_marikoCpuBoostClock] = cust_get_mariko_cpu_boost(&table); + + configValues.values[KipConfigValue_eristaGpuUV] = cust_get_erista_gpu_uv(&table); + configValues.values[KipConfigValue_eristaGpuVmin] = cust_get_erista_gpu_vmin(&table); + configValues.values[KipConfigValue_marikoGpuUV] = cust_get_mariko_gpu_uv(&table); + configValues.values[KipConfigValue_marikoGpuVmin] = cust_get_mariko_gpu_vmin(&table); + configValues.values[KipConfigValue_marikoGpuVmax] = cust_get_mariko_gpu_vmax(&table); + configValues.values[KipConfigValue_commonGpuVoltOffset] = cust_get_common_gpu_offset(&table); + configValues.values[KipConfigValue_gpuSpeedo] = board::GetFuseData()->gpuSpeedo; // cust_get_gpu_speedo(&table); + + for (int i = 0; i < 24; i++) { + configValues.values[KipConfigValue_g_volt_76800 + i] = cust_get_mariko_gpu_volt(&table, i); + } + + for (int i = 0; i < 27; i++) { + configValues.values[KipConfigValue_g_volt_e_76800 + i] = cust_get_erista_gpu_volt(&table, i); + } + + configValues.values[KipConfigValue_t7_tWTR_fine_tune] = cust_get_tWTR_fine_tune(&table); + configValues.values[KipConfigValue_t6_tRTW_fine_tune] = cust_get_tRTW_fine_tune(&table); + + // if(cust_get_cust_rev(&table) == KIP_CUST_REV) + // return; + + if (sizeof(SysClkConfigValueList) <= sizeof(configValues)) { + if (config::SetConfigValues(&configValues, false)) { + fileUtils::LogLine("[clock_manager] Successfully loaded KIP data into config"); + } else { + fileUtils::LogLine("[clock_manager] Warning: Failed to set config values from KIP"); + notification::writeNotification("Horizon OC\nKip config set failed"); + } + } else { + fileUtils::LogLine("[clock_manager] Error: Config value list buffer size mismatch"); + notification::writeNotification("Horizon OC\nConfig Buffer Mismatch"); + } + } else { + fileUtils::LogLine("[clock_manager] Config refresh error in GetKipData!"); + notification::writeNotification("Horizon OC\nConfig refresh failed"); + } + } +} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/kip.h b/Source/rewrite-hoc-clk/sysmodule/src/kip.h deleted file mode 100644 index 818b4937..00000000 --- a/Source/rewrite-hoc-clk/sysmodule/src/kip.h +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - - -#pragma once -#include -#include -#include -#include -#include - -#pragma pack(push, 1) - -typedef struct { - u8 cust[4]; - u32 custRev; - u32 placeholder; - u32 hpMode; - u32 commonEmcMemVolt; - u32 eristaEmcMaxClock; - u32 eristaEmcMaxClock1; - u32 eristaEmcMaxClock2; - u32 marikoEmcMaxClock; - u32 marikoEmcVddqVolt; - u32 emcDvbShift; - // advanced config - u32 t1_tRCD; - u32 t2_tRP; - u32 t3_tRAS; - u32 t4_tRRD; - u32 t5_tRFC; - u32 t6_tRTW; - u32 t7_tWTR; - u32 t8_tREFI; - - u32 mem_burst_read_latency; - u32 mem_burst_write_latency; - - u32 eristaCpuUV; - u32 eristaCpuVmin; - u32 eristaCpuMaxVolt; - u32 eristaCpuUnlock; - - u32 marikoCpuUVLow; - u32 marikoCpuUVHigh; - u32 tableConf; - u32 marikoCpuLowVmin; - u32 marikoCpuHighVmin; - u32 marikoCpuMaxVolt; - u32 marikoCpuMaxClock; - - u32 eristaCpuBoostClock; - u32 marikoCpuBoostClock; - - u32 eristaGpuUV; - u32 eristaGpuVmin; - - u32 marikoGpuUV; - u32 marikoGpuVmin; - u32 marikoGpuVmax; - - u32 commonGpuVoltOffset; - - u32 gpuSpeedo; - - u32 eristaGpuVoltArray[27]; - u32 marikoGpuVoltArray[24]; - - u32 t6_tRTW_fine_tune; - u32 t7_tWTR_fine_tune; - - u32 reserved[60]; -} CustomizeTable; - -#pragma pack(pop) - -#define CUST_MAGIC "CUST" -#define CUST_MAGIC_LEN 4 - -typedef struct { - FILE* file; - long offset; - CustomizeTable cached_table; - bool has_cache; -} CustHandle; - -static inline bool cust_find_offset(FILE* f, long* out_offset) { - u8 buf[512]; - long pos = 0; - fseek(f, 0, SEEK_SET); - - while (1) { - size_t r = fread(buf, 1, sizeof(buf), f); - if (r < CUST_MAGIC_LEN) break; - - for (size_t i = 0; i <= r - CUST_MAGIC_LEN; i++) { - if (memcmp(&buf[i], CUST_MAGIC, CUST_MAGIC_LEN) == 0) { - *out_offset = pos + (long)i; - return true; - } - } - pos += (long)(r - (CUST_MAGIC_LEN - 1)); - fseek(f, pos, SEEK_SET); - } - return false; -} - -static inline bool cust_read_table(const char* path, CustomizeTable* out) { - FILE* f = fopen(path, "rb"); - if (!f) return false; - - long off; - if (!cust_find_offset(f, &off)) { - fclose(f); - return false; - } - - fseek(f, 0, SEEK_END); - long size = ftell(f); - - if (off + (long)sizeof(CustomizeTable) > size) { - fclose(f); - return false; - } - - fseek(f, off, SEEK_SET); - bool ok = fread(out, 1, sizeof(CustomizeTable), f) == sizeof(CustomizeTable); - fclose(f); - - return ok && memcmp(out->cust, CUST_MAGIC, CUST_MAGIC_LEN) == 0; -} - -static inline bool cust_write_table(const char* path, const CustomizeTable* in) { - FILE* f = fopen(path, "r+b"); - if (!f) return false; - - long off; - if (!cust_find_offset(f, &off)) { - fclose(f); - return false; - } - - fseek(f, 0, SEEK_END); - long size = ftell(f); - - if (off + (long)sizeof(CustomizeTable) > size) { - fclose(f); - return false; - } - - fseek(f, off, SEEK_SET); - bool ok = fwrite(in, 1, sizeof(CustomizeTable), f) == sizeof(CustomizeTable); - fflush(f); - fclose(f); - - return ok; -} - - -static inline bool cust_read_and_cache(const char* path, CustomizeTable* out) { - return cust_read_table(path, out); -} - -#define CUST_WRITE_FIELD_BATCH(table, field, val) \ - do { \ - (table)->field = (val); \ - } while (0) - -#define CUST_WRITE_FIELD(path, field, val) \ - do { \ - CustomizeTable t; \ - if (!cust_read_table(path, &t)) return false; \ - t.field = (val); \ - return cust_write_table(path, &t); \ - } while (0) - -static inline bool cust_set_cust_rev(const char* p, u32 v) { CUST_WRITE_FIELD(p, custRev, v); } -// static inline bool cust_set_mtc_conf(const char* p, u32 v) { CUST_WRITE_FIELD(p, mtcConf, v); } -static inline bool cust_set_hp_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p, hpMode, v); } - -static inline bool cust_set_common_emc_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonEmcMemVolt, v); } -static inline bool cust_set_erista_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock, v); } -static inline bool cust_set_erista_emc_max1(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock1, v); } -static inline bool cust_set_erista_emc_max2(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock2, v); } -static inline bool cust_set_mariko_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcMaxClock, v); } -static inline bool cust_set_mariko_emc_vddq(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcVddqVolt, v); } -static inline bool cust_set_emc_dvb_shift(const char* p, u32 v) { CUST_WRITE_FIELD(p, emcDvbShift, v); } - -static inline bool cust_set_tRCD(const char* p, u32 v) { CUST_WRITE_FIELD(p, t1_tRCD, v); } -static inline bool cust_set_tRP(const char* p, u32 v) { CUST_WRITE_FIELD(p, t2_tRP, v); } -static inline bool cust_set_tRAS(const char* p, u32 v) { CUST_WRITE_FIELD(p, t3_tRAS, v); } -static inline bool cust_set_tRRD(const char* p, u32 v) { CUST_WRITE_FIELD(p, t4_tRRD, v); } -static inline bool cust_set_tRFC(const char* p, u32 v) { CUST_WRITE_FIELD(p, t5_tRFC, v); } -static inline bool cust_set_tRTW(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW, v); } -static inline bool cust_set_tWTR(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR, v); } -static inline bool cust_set_tREFI(const char* p, u32 v) { CUST_WRITE_FIELD(p, t8_tREFI, v); } -static inline bool cust_set_tRTW_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW_fine_tune, v); } -static inline bool cust_set_tWTR_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR_fine_tune, v); } -static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); } -static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); } - -static inline bool cust_set_erista_cpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuUV, v); } -static inline bool cust_set_eristaCpuVmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuVmin, v); } -static inline bool cust_set_erista_cpu_max_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuMaxVolt, v); } -static inline bool cust_set_eristaCpuUnlock(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuUnlock, v); } - -static inline bool cust_set_mariko_cpu_uv_low(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuUVLow, v); } -static inline bool cust_set_mariko_cpu_uv_high(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuUVHigh, v); } -static inline bool cust_set_mariko_cpu_low_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuLowVmin, v); } -static inline bool cust_set_mariko_cpu_high_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuHighVmin, v); } -static inline bool cust_set_mariko_cpu_max_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxVolt, v); } -static inline bool cust_set_erista_cpu_boost(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuBoostClock, v); } -static inline bool cust_set_mariko_cpu_boost(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuBoostClock, v); } - -static inline bool cust_set_erista_gpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaGpuUV, v); } -static inline bool cust_set_erista_gpu_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaGpuVmin, v); } -static inline bool cust_set_mariko_gpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuUV, v); } -static inline bool cust_set_mariko_gpu_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmin, v); } -static inline bool cust_set_mariko_gpu_vmax(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmax, v); } -static inline bool cust_set_common_gpu_offset(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonGpuVoltOffset, v); } -static inline bool cust_set_gpu_speedo(const char* p, u32 v) { CUST_WRITE_FIELD(p, gpuSpeedo, v); } -static inline bool cust_set_marikoCpuMaxClock(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxClock, v); } - -/* GPU VOLT ARRAY HELPERS */ -static inline bool cust_set_erista_gpu_volt(const char* p, int idx, u32 v) { - if (idx < 0 || idx >= 27) return false; - CustomizeTable t; - if (!cust_read_table(p, &t)) return false; - t.eristaGpuVoltArray[idx] = v; - return cust_write_table(p, &t); -} - -static inline bool cust_set_mariko_gpu_volt(const char* p, int idx, u32 v) { - if (idx < 0 || idx >= 24) return false; - CustomizeTable t; - if (!cust_read_table(p, &t)) return false; - t.marikoGpuVoltArray[idx] = v; - return cust_write_table(p, &t); -} - -static inline u32 cust_get_field(const CustomizeTable* t, u32 offset) { - if (!t) return 0; - return *(u32*)((u8*)t + offset); -} - -#define CUST_GET_FIELD(table, field) ((table) ? (table)->field : 0) - -static inline u32 cust_get_cust_rev(const CustomizeTable* t) { return CUST_GET_FIELD(t, custRev); } -// static inline u32 cust_get_mtc_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, mtcConf); } -static inline u32 cust_get_hp_mode(const CustomizeTable* t) { return CUST_GET_FIELD(t, hpMode); } - -static inline u32 cust_get_common_emc_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonEmcMemVolt); } -static inline u32 cust_get_erista_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock); } -static inline u32 cust_get_erista_emc_max1(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock1); } -static inline u32 cust_get_erista_emc_max2(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock2); } -static inline u32 cust_get_mariko_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcMaxClock); } -static inline u32 cust_get_mariko_emc_vddq(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcVddqVolt); } -static inline u32 cust_get_emc_dvb_shift(const CustomizeTable* t) { return CUST_GET_FIELD(t, emcDvbShift); } - -static inline u32 cust_get_tRCD(const CustomizeTable* t) { return CUST_GET_FIELD(t, t1_tRCD); } -static inline u32 cust_get_tRP(const CustomizeTable* t) { return CUST_GET_FIELD(t, t2_tRP); } -static inline u32 cust_get_tRAS(const CustomizeTable* t) { return CUST_GET_FIELD(t, t3_tRAS); } -static inline u32 cust_get_tRRD(const CustomizeTable* t) { return CUST_GET_FIELD(t, t4_tRRD); } -static inline u32 cust_get_tRFC(const CustomizeTable* t) { return CUST_GET_FIELD(t, t5_tRFC); } -static inline u32 cust_get_tRTW(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW); } -static inline u32 cust_get_tWTR(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR); } -static inline u32 cust_get_tREFI(const CustomizeTable* t) { return CUST_GET_FIELD(t, t8_tREFI); } -static inline u32 cust_get_tRTW_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW_fine_tune); } -static inline u32 cust_get_tWTR_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR_fine_tune); } -static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); } -static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); } - -static inline u32 cust_get_erista_cpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuUV); } -static inline u32 cust_get_eristaCpuVmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuVmin); } -static inline u32 cust_get_erista_cpu_max_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuMaxVolt); } -static inline u32 cust_get_eristaCpuUnlock(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuUnlock); } - -static inline u32 cust_get_mariko_cpu_uv_low(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuUVLow); } -static inline u32 cust_get_mariko_cpu_uv_high(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuUVHigh); } -static inline u32 cust_get_mariko_cpu_low_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuLowVmin); } -static inline u32 cust_get_mariko_cpu_high_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuHighVmin); } -static inline u32 cust_get_mariko_cpu_max_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxVolt); } -static inline u32 cust_get_erista_cpu_boost(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuBoostClock); } -static inline u32 cust_get_mariko_cpu_boost(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuBoostClock); } -static inline u32 cust_get_table_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, tableConf); } - -static inline u32 cust_get_erista_gpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaGpuUV); } -static inline u32 cust_get_erista_gpu_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaGpuVmin); } -static inline u32 cust_get_mariko_gpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuUV); } -static inline u32 cust_get_mariko_gpu_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmin); } -static inline u32 cust_get_mariko_gpu_vmax(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmax); } -static inline u32 cust_get_common_gpu_offset(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonGpuVoltOffset); } -static inline u32 cust_get_gpu_speedo(const CustomizeTable* t) { return CUST_GET_FIELD(t, gpuSpeedo); } -static inline u32 cust_get_marikoCpuMaxClock(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxClock); } - -static inline u32 cust_get_erista_gpu_volt(const CustomizeTable* t, int idx) { - if (!t || idx < 0 || idx >= 27) return 0; - return t->eristaGpuVoltArray[idx]; -} - -static inline u32 cust_get_mariko_gpu_volt(const CustomizeTable* t, int idx) { - if (!t || idx < 0 || idx >= 24) return 0; - return t->marikoGpuVoltArray[idx]; -} - -#define DECL_ERISTA_GPU_VOLT_HELPER(freq, idx) \ -static inline bool cust_set_erista_gpu_volt_##freq( \ - const char* p, u32 v) { \ - return cust_set_erista_gpu_volt(p, idx, v); \ -} - -#define DECL_MARIKO_GPU_VOLT_HELPER(freq, idx) \ -static inline bool cust_set_mariko_gpu_volt_##freq( \ - const char* p, u32 v) { \ - return cust_set_mariko_gpu_volt(p, idx, v); \ -} - -DECL_ERISTA_GPU_VOLT_HELPER(76800, 0) -DECL_ERISTA_GPU_VOLT_HELPER(115200, 1) -DECL_ERISTA_GPU_VOLT_HELPER(153600, 2) -DECL_ERISTA_GPU_VOLT_HELPER(192000, 3) -DECL_ERISTA_GPU_VOLT_HELPER(230400, 4) -DECL_ERISTA_GPU_VOLT_HELPER(268800, 5) -DECL_ERISTA_GPU_VOLT_HELPER(307200, 6) -DECL_ERISTA_GPU_VOLT_HELPER(345600, 7) -DECL_ERISTA_GPU_VOLT_HELPER(384000, 8) -DECL_ERISTA_GPU_VOLT_HELPER(422400, 9) -DECL_ERISTA_GPU_VOLT_HELPER(460800, 10) -DECL_ERISTA_GPU_VOLT_HELPER(499200, 11) -DECL_ERISTA_GPU_VOLT_HELPER(537600, 12) -DECL_ERISTA_GPU_VOLT_HELPER(576000, 13) -DECL_ERISTA_GPU_VOLT_HELPER(614400, 14) -DECL_ERISTA_GPU_VOLT_HELPER(652800, 15) -DECL_ERISTA_GPU_VOLT_HELPER(691200, 16) -DECL_ERISTA_GPU_VOLT_HELPER(729600, 17) -DECL_ERISTA_GPU_VOLT_HELPER(768000, 18) -DECL_ERISTA_GPU_VOLT_HELPER(806400, 19) -DECL_ERISTA_GPU_VOLT_HELPER(844800, 20) -DECL_ERISTA_GPU_VOLT_HELPER(883200, 21) -DECL_ERISTA_GPU_VOLT_HELPER(921600, 22) -DECL_ERISTA_GPU_VOLT_HELPER(960000, 23) -DECL_ERISTA_GPU_VOLT_HELPER(998400, 24) -DECL_ERISTA_GPU_VOLT_HELPER(1036800, 25) -DECL_ERISTA_GPU_VOLT_HELPER(1075200, 26) - -DECL_MARIKO_GPU_VOLT_HELPER(76800, 0) -DECL_MARIKO_GPU_VOLT_HELPER(153600, 1) -DECL_MARIKO_GPU_VOLT_HELPER(230400, 2) -DECL_MARIKO_GPU_VOLT_HELPER(307200, 3) -DECL_MARIKO_GPU_VOLT_HELPER(384000, 4) -DECL_MARIKO_GPU_VOLT_HELPER(460800, 5) -DECL_MARIKO_GPU_VOLT_HELPER(537600, 6) -DECL_MARIKO_GPU_VOLT_HELPER(614400, 7) -DECL_MARIKO_GPU_VOLT_HELPER(691200, 8) -DECL_MARIKO_GPU_VOLT_HELPER(768000, 9) -DECL_MARIKO_GPU_VOLT_HELPER(844800, 10) -DECL_MARIKO_GPU_VOLT_HELPER(921600, 11) -DECL_MARIKO_GPU_VOLT_HELPER(998400, 12) -DECL_MARIKO_GPU_VOLT_HELPER(1075200, 13) -DECL_MARIKO_GPU_VOLT_HELPER(1152000, 14) -DECL_MARIKO_GPU_VOLT_HELPER(1228800, 15) -DECL_MARIKO_GPU_VOLT_HELPER(1267200, 16) -DECL_MARIKO_GPU_VOLT_HELPER(1305600, 17) -DECL_MARIKO_GPU_VOLT_HELPER(1344000, 18) -DECL_MARIKO_GPU_VOLT_HELPER(1382400, 19) -DECL_MARIKO_GPU_VOLT_HELPER(1420800, 20) -DECL_MARIKO_GPU_VOLT_HELPER(1459200, 21) -DECL_MARIKO_GPU_VOLT_HELPER(1497600, 22) -DECL_MARIKO_GPU_VOLT_HELPER(1536000, 23) - - -#define DECL_ERISTA_GPU_VOLT_GET(freq, idx) \ -static inline u32 cust_get_erista_gpu_volt_##freq##_val(const char* p) { \ - CustomizeTable t; \ - if (!cust_read_table(p, &t)) return 0; \ - return cust_get_erista_gpu_volt(&t, idx); \ -} -#define DECL_MARIKO_GPU_VOLT_GET(freq, idx) \ -static inline u32 cust_get_mariko_gpu_volt_##freq##_val(const char* p) { \ - CustomizeTable t; \ - if (!cust_read_table(p, &t)) return 0; \ - return cust_get_mariko_gpu_volt(&t, idx); \ -} - -DECL_ERISTA_GPU_VOLT_GET(76800, 0) -DECL_ERISTA_GPU_VOLT_GET(115200, 1) -DECL_ERISTA_GPU_VOLT_GET(153600, 2) -DECL_ERISTA_GPU_VOLT_GET(192000, 3) -DECL_ERISTA_GPU_VOLT_GET(230400, 4) -DECL_ERISTA_GPU_VOLT_GET(268800, 5) -DECL_ERISTA_GPU_VOLT_GET(307200, 6) -DECL_ERISTA_GPU_VOLT_GET(345600, 7) -DECL_ERISTA_GPU_VOLT_GET(384000, 8) -DECL_ERISTA_GPU_VOLT_GET(422400, 9) -DECL_ERISTA_GPU_VOLT_GET(460800, 10) -DECL_ERISTA_GPU_VOLT_GET(499200, 11) -DECL_ERISTA_GPU_VOLT_GET(537600, 12) -DECL_ERISTA_GPU_VOLT_GET(576000, 13) -DECL_ERISTA_GPU_VOLT_GET(614400, 14) -DECL_ERISTA_GPU_VOLT_GET(652800, 15) -DECL_ERISTA_GPU_VOLT_GET(691200, 16) -DECL_ERISTA_GPU_VOLT_GET(729600, 17) -DECL_ERISTA_GPU_VOLT_GET(768000, 18) -DECL_ERISTA_GPU_VOLT_GET(806400, 19) -DECL_ERISTA_GPU_VOLT_GET(844800, 20) -DECL_ERISTA_GPU_VOLT_GET(883200, 21) -DECL_ERISTA_GPU_VOLT_GET(921600, 22) -DECL_ERISTA_GPU_VOLT_GET(960000, 23) -DECL_ERISTA_GPU_VOLT_GET(998400, 24) -DECL_ERISTA_GPU_VOLT_GET(1036800, 25) -DECL_ERISTA_GPU_VOLT_GET(1075200, 26) - -DECL_MARIKO_GPU_VOLT_GET(76800, 0) -DECL_MARIKO_GPU_VOLT_GET(153600, 1) -DECL_MARIKO_GPU_VOLT_GET(230400, 2) -DECL_MARIKO_GPU_VOLT_GET(307200, 3) -DECL_MARIKO_GPU_VOLT_GET(384000, 4) -DECL_MARIKO_GPU_VOLT_GET(460800, 5) -DECL_MARIKO_GPU_VOLT_GET(537600, 6) -DECL_MARIKO_GPU_VOLT_GET(614400, 7) -DECL_MARIKO_GPU_VOLT_GET(691200, 8) -DECL_MARIKO_GPU_VOLT_GET(768000, 9) -DECL_MARIKO_GPU_VOLT_GET(844800, 10) -DECL_MARIKO_GPU_VOLT_GET(921600, 11) -DECL_MARIKO_GPU_VOLT_GET(998400, 12) -DECL_MARIKO_GPU_VOLT_GET(1075200, 13) -DECL_MARIKO_GPU_VOLT_GET(1152000, 14) -DECL_MARIKO_GPU_VOLT_GET(1228800, 15) -DECL_MARIKO_GPU_VOLT_GET(1267200, 16) -DECL_MARIKO_GPU_VOLT_GET(1305600, 17) -DECL_MARIKO_GPU_VOLT_GET(1344000, 18) -DECL_MARIKO_GPU_VOLT_GET(1382400, 19) -DECL_MARIKO_GPU_VOLT_GET(1420800, 20) -DECL_MARIKO_GPU_VOLT_GET(1459200, 21) -DECL_MARIKO_GPU_VOLT_GET(1497600, 22) -DECL_MARIKO_GPU_VOLT_GET(1536000, 23) \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/kip.hpp b/Source/rewrite-hoc-clk/sysmodule/src/kip.hpp new file mode 100644 index 00000000..d85a9590 --- /dev/null +++ b/Source/rewrite-hoc-clk/sysmodule/src/kip.hpp @@ -0,0 +1,467 @@ +/* + * Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +/* -------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * , , + * 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 +#include +#include +#include +#include +#include "config.hpp" +#include "file_utils.hpp" +#include +#include + +#pragma pack(push, 1) + +namespace kip { + extern bool kipAvailable; + + typedef struct { + u8 cust[4]; + u32 custRev; + u32 placeholder; + u32 hpMode; + u32 commonEmcMemVolt; + u32 eristaEmcMaxClock; + u32 eristaEmcMaxClock1; + u32 eristaEmcMaxClock2; + u32 marikoEmcMaxClock; + u32 marikoEmcVddqVolt; + u32 emcDvbShift; + // advanced config + u32 t1_tRCD; + u32 t2_tRP; + u32 t3_tRAS; + u32 t4_tRRD; + u32 t5_tRFC; + u32 t6_tRTW; + u32 t7_tWTR; + u32 t8_tREFI; + + u32 mem_burst_read_latency; + u32 mem_burst_write_latency; + + u32 eristaCpuUV; + u32 eristaCpuVmin; + u32 eristaCpuMaxVolt; + u32 eristaCpuUnlock; + + u32 marikoCpuUVLow; + u32 marikoCpuUVHigh; + u32 tableConf; + u32 marikoCpuLowVmin; + u32 marikoCpuHighVmin; + u32 marikoCpuMaxVolt; + u32 marikoCpuMaxClock; + + u32 eristaCpuBoostClock; + u32 marikoCpuBoostClock; + + u32 eristaGpuUV; + u32 eristaGpuVmin; + + u32 marikoGpuUV; + u32 marikoGpuVmin; + u32 marikoGpuVmax; + + u32 commonGpuVoltOffset; + + u32 gpuSpeedo; + + u32 eristaGpuVoltArray[27]; + u32 marikoGpuVoltArray[24]; + + u32 t6_tRTW_fine_tune; + u32 t7_tWTR_fine_tune; + + u32 reserved[60]; + } CustomizeTable; + + #pragma pack(pop) + + #define CUST_MAGIC "CUST" + #define CUST_MAGIC_LEN 4 + + typedef struct { + FILE* file; + long offset; + CustomizeTable cached_table; + bool has_cache; + } CustHandle; + + static inline bool cust_find_offset(FILE* f, long* out_offset) { + u8 buf[512]; + long pos = 0; + fseek(f, 0, SEEK_SET); + + while (1) { + size_t r = fread(buf, 1, sizeof(buf), f); + if (r < CUST_MAGIC_LEN) break; + + for (size_t i = 0; i <= r - CUST_MAGIC_LEN; i++) { + if (memcmp(&buf[i], CUST_MAGIC, CUST_MAGIC_LEN) == 0) { + *out_offset = pos + (long)i; + return true; + } + } + pos += (long)(r - (CUST_MAGIC_LEN - 1)); + fseek(f, pos, SEEK_SET); + } + return false; + } + + static inline bool cust_read_table(const char* path, CustomizeTable* out) { + FILE* f = fopen(path, "rb"); + if (!f) return false; + + long off; + if (!cust_find_offset(f, &off)) { + fclose(f); + return false; + } + + fseek(f, 0, SEEK_END); + long size = ftell(f); + + if (off + (long)sizeof(CustomizeTable) > size) { + fclose(f); + return false; + } + + fseek(f, off, SEEK_SET); + bool ok = fread(out, 1, sizeof(CustomizeTable), f) == sizeof(CustomizeTable); + fclose(f); + + return ok && memcmp(out->cust, CUST_MAGIC, CUST_MAGIC_LEN) == 0; + } + + static inline bool cust_write_table(const char* path, const CustomizeTable* in) { + FILE* f = fopen(path, "r+b"); + if (!f) return false; + + long off; + if (!cust_find_offset(f, &off)) { + fclose(f); + return false; + } + + fseek(f, 0, SEEK_END); + long size = ftell(f); + + if (off + (long)sizeof(CustomizeTable) > size) { + fclose(f); + return false; + } + + fseek(f, off, SEEK_SET); + bool ok = fwrite(in, 1, sizeof(CustomizeTable), f) == sizeof(CustomizeTable); + fflush(f); + fclose(f); + + return ok; + } + + static inline bool cust_read_and_cache(const char* path, CustomizeTable* out) { + return cust_read_table(path, out); + } + + #define CUST_WRITE_FIELD_BATCH(table, field, val) \ + do { \ + (table)->field = (val); \ + } while (0) + + #define CUST_WRITE_FIELD(path, field, val) \ + do { \ + CustomizeTable t; \ + if (!cust_read_table(path, &t)) return false; \ + t.field = (val); \ + return cust_write_table(path, &t); \ + } while (0) + + static inline bool cust_set_cust_rev(const char* p, u32 v) { CUST_WRITE_FIELD(p, custRev, v); } + // static inline bool cust_set_mtc_conf(const char* p, u32 v) { CUST_WRITE_FIELD(p, mtcConf, v); } + static inline bool cust_set_hp_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p, hpMode, v); } + + static inline bool cust_set_common_emc_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonEmcMemVolt, v); } + static inline bool cust_set_erista_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock, v); } + static inline bool cust_set_erista_emc_max1(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock1, v); } + static inline bool cust_set_erista_emc_max2(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock2, v); } + static inline bool cust_set_mariko_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcMaxClock, v); } + static inline bool cust_set_mariko_emc_vddq(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcVddqVolt, v); } + static inline bool cust_set_emc_dvb_shift(const char* p, u32 v) { CUST_WRITE_FIELD(p, emcDvbShift, v); } + + static inline bool cust_set_tRCD(const char* p, u32 v) { CUST_WRITE_FIELD(p, t1_tRCD, v); } + static inline bool cust_set_tRP(const char* p, u32 v) { CUST_WRITE_FIELD(p, t2_tRP, v); } + static inline bool cust_set_tRAS(const char* p, u32 v) { CUST_WRITE_FIELD(p, t3_tRAS, v); } + static inline bool cust_set_tRRD(const char* p, u32 v) { CUST_WRITE_FIELD(p, t4_tRRD, v); } + static inline bool cust_set_tRFC(const char* p, u32 v) { CUST_WRITE_FIELD(p, t5_tRFC, v); } + static inline bool cust_set_tRTW(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW, v); } + static inline bool cust_set_tWTR(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR, v); } + static inline bool cust_set_tREFI(const char* p, u32 v) { CUST_WRITE_FIELD(p, t8_tREFI, v); } + static inline bool cust_set_tRTW_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW_fine_tune, v); } + static inline bool cust_set_tWTR_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR_fine_tune, v); } + static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); } + static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); } + + static inline bool cust_set_erista_cpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuUV, v); } + static inline bool cust_set_eristaCpuVmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuVmin, v); } + static inline bool cust_set_erista_cpu_max_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuMaxVolt, v); } + static inline bool cust_set_eristaCpuUnlock(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuUnlock, v); } + + static inline bool cust_set_mariko_cpu_uv_low(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuUVLow, v); } + static inline bool cust_set_mariko_cpu_uv_high(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuUVHigh, v); } + static inline bool cust_set_mariko_cpu_low_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuLowVmin, v); } + static inline bool cust_set_mariko_cpu_high_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuHighVmin, v); } + static inline bool cust_set_mariko_cpu_max_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxVolt, v); } + static inline bool cust_set_erista_cpu_boost(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaCpuBoostClock, v); } + static inline bool cust_set_mariko_cpu_boost(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuBoostClock, v); } + + static inline bool cust_set_erista_gpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaGpuUV, v); } + static inline bool cust_set_erista_gpu_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaGpuVmin, v); } + static inline bool cust_set_mariko_gpu_uv(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuUV, v); } + static inline bool cust_set_mariko_gpu_vmin(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmin, v); } + static inline bool cust_set_mariko_gpu_vmax(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoGpuVmax, v); } + static inline bool cust_set_common_gpu_offset(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonGpuVoltOffset, v); } + static inline bool cust_set_gpu_speedo(const char* p, u32 v) { CUST_WRITE_FIELD(p, gpuSpeedo, v); } + static inline bool cust_set_marikoCpuMaxClock(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoCpuMaxClock, v); } + + /* GPU VOLT ARRAY HELPERS */ + static inline bool cust_set_erista_gpu_volt(const char* p, int idx, u32 v) { + if (idx < 0 || idx >= 27) return false; + CustomizeTable t; + if (!cust_read_table(p, &t)) return false; + t.eristaGpuVoltArray[idx] = v; + return cust_write_table(p, &t); + } + + static inline bool cust_set_mariko_gpu_volt(const char* p, int idx, u32 v) { + if (idx < 0 || idx >= 24) return false; + CustomizeTable t; + if (!cust_read_table(p, &t)) return false; + t.marikoGpuVoltArray[idx] = v; + return cust_write_table(p, &t); + } + + static inline u32 cust_get_field(const CustomizeTable* t, u32 offset) { + if (!t) return 0; + return *(u32*)((u8*)t + offset); + } + + #define CUST_GET_FIELD(table, field) ((table) ? (table)->field : 0) + + static inline u32 cust_get_cust_rev(const CustomizeTable* t) { return CUST_GET_FIELD(t, custRev); } + // static inline u32 cust_get_mtc_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, mtcConf); } + static inline u32 cust_get_hp_mode(const CustomizeTable* t) { return CUST_GET_FIELD(t, hpMode); } + + static inline u32 cust_get_common_emc_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonEmcMemVolt); } + static inline u32 cust_get_erista_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock); } + static inline u32 cust_get_erista_emc_max1(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock1); } + static inline u32 cust_get_erista_emc_max2(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock2); } + static inline u32 cust_get_mariko_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcMaxClock); } + static inline u32 cust_get_mariko_emc_vddq(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcVddqVolt); } + static inline u32 cust_get_emc_dvb_shift(const CustomizeTable* t) { return CUST_GET_FIELD(t, emcDvbShift); } + + static inline u32 cust_get_tRCD(const CustomizeTable* t) { return CUST_GET_FIELD(t, t1_tRCD); } + static inline u32 cust_get_tRP(const CustomizeTable* t) { return CUST_GET_FIELD(t, t2_tRP); } + static inline u32 cust_get_tRAS(const CustomizeTable* t) { return CUST_GET_FIELD(t, t3_tRAS); } + static inline u32 cust_get_tRRD(const CustomizeTable* t) { return CUST_GET_FIELD(t, t4_tRRD); } + static inline u32 cust_get_tRFC(const CustomizeTable* t) { return CUST_GET_FIELD(t, t5_tRFC); } + static inline u32 cust_get_tRTW(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW); } + static inline u32 cust_get_tWTR(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR); } + static inline u32 cust_get_tREFI(const CustomizeTable* t) { return CUST_GET_FIELD(t, t8_tREFI); } + static inline u32 cust_get_tRTW_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW_fine_tune); } + static inline u32 cust_get_tWTR_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR_fine_tune); } + static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); } + static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); } + + static inline u32 cust_get_erista_cpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuUV); } + static inline u32 cust_get_eristaCpuVmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuVmin); } + static inline u32 cust_get_erista_cpu_max_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuMaxVolt); } + static inline u32 cust_get_eristaCpuUnlock(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuUnlock); } + + static inline u32 cust_get_mariko_cpu_uv_low(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuUVLow); } + static inline u32 cust_get_mariko_cpu_uv_high(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuUVHigh); } + static inline u32 cust_get_mariko_cpu_low_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuLowVmin); } + static inline u32 cust_get_mariko_cpu_high_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuHighVmin); } + static inline u32 cust_get_mariko_cpu_max_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxVolt); } + static inline u32 cust_get_erista_cpu_boost(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaCpuBoostClock); } + static inline u32 cust_get_mariko_cpu_boost(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuBoostClock); } + static inline u32 cust_get_table_conf(const CustomizeTable* t) { return CUST_GET_FIELD(t, tableConf); } + + static inline u32 cust_get_erista_gpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaGpuUV); } + static inline u32 cust_get_erista_gpu_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaGpuVmin); } + static inline u32 cust_get_mariko_gpu_uv(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuUV); } + static inline u32 cust_get_mariko_gpu_vmin(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmin); } + static inline u32 cust_get_mariko_gpu_vmax(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoGpuVmax); } + static inline u32 cust_get_common_gpu_offset(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonGpuVoltOffset); } + static inline u32 cust_get_gpu_speedo(const CustomizeTable* t) { return CUST_GET_FIELD(t, gpuSpeedo); } + static inline u32 cust_get_marikoCpuMaxClock(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoCpuMaxClock); } + + static inline u32 cust_get_erista_gpu_volt(const CustomizeTable* t, int idx) { + if (!t || idx < 0 || idx >= 27) return 0; + return t->eristaGpuVoltArray[idx]; + } + + static inline u32 cust_get_mariko_gpu_volt(const CustomizeTable* t, int idx) { + if (!t || idx < 0 || idx >= 24) return 0; + return t->marikoGpuVoltArray[idx]; + } + + #define DECL_ERISTA_GPU_VOLT_HELPER(freq, idx) \ + static inline bool cust_set_erista_gpu_volt_##freq( \ + const char* p, u32 v) { \ + return cust_set_erista_gpu_volt(p, idx, v); \ + } + + #define DECL_MARIKO_GPU_VOLT_HELPER(freq, idx) \ + static inline bool cust_set_mariko_gpu_volt_##freq( \ + const char* p, u32 v) { \ + return cust_set_mariko_gpu_volt(p, idx, v); \ + } + + DECL_ERISTA_GPU_VOLT_HELPER(76800, 0) + DECL_ERISTA_GPU_VOLT_HELPER(115200, 1) + DECL_ERISTA_GPU_VOLT_HELPER(153600, 2) + DECL_ERISTA_GPU_VOLT_HELPER(192000, 3) + DECL_ERISTA_GPU_VOLT_HELPER(230400, 4) + DECL_ERISTA_GPU_VOLT_HELPER(268800, 5) + DECL_ERISTA_GPU_VOLT_HELPER(307200, 6) + DECL_ERISTA_GPU_VOLT_HELPER(345600, 7) + DECL_ERISTA_GPU_VOLT_HELPER(384000, 8) + DECL_ERISTA_GPU_VOLT_HELPER(422400, 9) + DECL_ERISTA_GPU_VOLT_HELPER(460800, 10) + DECL_ERISTA_GPU_VOLT_HELPER(499200, 11) + DECL_ERISTA_GPU_VOLT_HELPER(537600, 12) + DECL_ERISTA_GPU_VOLT_HELPER(576000, 13) + DECL_ERISTA_GPU_VOLT_HELPER(614400, 14) + DECL_ERISTA_GPU_VOLT_HELPER(652800, 15) + DECL_ERISTA_GPU_VOLT_HELPER(691200, 16) + DECL_ERISTA_GPU_VOLT_HELPER(729600, 17) + DECL_ERISTA_GPU_VOLT_HELPER(768000, 18) + DECL_ERISTA_GPU_VOLT_HELPER(806400, 19) + DECL_ERISTA_GPU_VOLT_HELPER(844800, 20) + DECL_ERISTA_GPU_VOLT_HELPER(883200, 21) + DECL_ERISTA_GPU_VOLT_HELPER(921600, 22) + DECL_ERISTA_GPU_VOLT_HELPER(960000, 23) + DECL_ERISTA_GPU_VOLT_HELPER(998400, 24) + DECL_ERISTA_GPU_VOLT_HELPER(1036800, 25) + DECL_ERISTA_GPU_VOLT_HELPER(1075200, 26) + + DECL_MARIKO_GPU_VOLT_HELPER(76800, 0) + DECL_MARIKO_GPU_VOLT_HELPER(153600, 1) + DECL_MARIKO_GPU_VOLT_HELPER(230400, 2) + DECL_MARIKO_GPU_VOLT_HELPER(307200, 3) + DECL_MARIKO_GPU_VOLT_HELPER(384000, 4) + DECL_MARIKO_GPU_VOLT_HELPER(460800, 5) + DECL_MARIKO_GPU_VOLT_HELPER(537600, 6) + DECL_MARIKO_GPU_VOLT_HELPER(614400, 7) + DECL_MARIKO_GPU_VOLT_HELPER(691200, 8) + DECL_MARIKO_GPU_VOLT_HELPER(768000, 9) + DECL_MARIKO_GPU_VOLT_HELPER(844800, 10) + DECL_MARIKO_GPU_VOLT_HELPER(921600, 11) + DECL_MARIKO_GPU_VOLT_HELPER(998400, 12) + DECL_MARIKO_GPU_VOLT_HELPER(1075200, 13) + DECL_MARIKO_GPU_VOLT_HELPER(1152000, 14) + DECL_MARIKO_GPU_VOLT_HELPER(1228800, 15) + DECL_MARIKO_GPU_VOLT_HELPER(1267200, 16) + DECL_MARIKO_GPU_VOLT_HELPER(1305600, 17) + DECL_MARIKO_GPU_VOLT_HELPER(1344000, 18) + DECL_MARIKO_GPU_VOLT_HELPER(1382400, 19) + DECL_MARIKO_GPU_VOLT_HELPER(1420800, 20) + DECL_MARIKO_GPU_VOLT_HELPER(1459200, 21) + DECL_MARIKO_GPU_VOLT_HELPER(1497600, 22) + DECL_MARIKO_GPU_VOLT_HELPER(1536000, 23) + + #define DECL_ERISTA_GPU_VOLT_GET(freq, idx) \ + static inline u32 cust_get_erista_gpu_volt_##freq##_val(const char* p) { \ + CustomizeTable t; \ + if (!cust_read_table(p, &t)) return 0; \ + return cust_get_erista_gpu_volt(&t, idx); \ + } + #define DECL_MARIKO_GPU_VOLT_GET(freq, idx) \ + static inline u32 cust_get_mariko_gpu_volt_##freq##_val(const char* p) { \ + CustomizeTable t; \ + if (!cust_read_table(p, &t)) return 0; \ + return cust_get_mariko_gpu_volt(&t, idx); \ + } + + DECL_ERISTA_GPU_VOLT_GET(76800, 0) + DECL_ERISTA_GPU_VOLT_GET(115200, 1) + DECL_ERISTA_GPU_VOLT_GET(153600, 2) + DECL_ERISTA_GPU_VOLT_GET(192000, 3) + DECL_ERISTA_GPU_VOLT_GET(230400, 4) + DECL_ERISTA_GPU_VOLT_GET(268800, 5) + DECL_ERISTA_GPU_VOLT_GET(307200, 6) + DECL_ERISTA_GPU_VOLT_GET(345600, 7) + DECL_ERISTA_GPU_VOLT_GET(384000, 8) + DECL_ERISTA_GPU_VOLT_GET(422400, 9) + DECL_ERISTA_GPU_VOLT_GET(460800, 10) + DECL_ERISTA_GPU_VOLT_GET(499200, 11) + DECL_ERISTA_GPU_VOLT_GET(537600, 12) + DECL_ERISTA_GPU_VOLT_GET(576000, 13) + DECL_ERISTA_GPU_VOLT_GET(614400, 14) + DECL_ERISTA_GPU_VOLT_GET(652800, 15) + DECL_ERISTA_GPU_VOLT_GET(691200, 16) + DECL_ERISTA_GPU_VOLT_GET(729600, 17) + DECL_ERISTA_GPU_VOLT_GET(768000, 18) + DECL_ERISTA_GPU_VOLT_GET(806400, 19) + DECL_ERISTA_GPU_VOLT_GET(844800, 20) + DECL_ERISTA_GPU_VOLT_GET(883200, 21) + DECL_ERISTA_GPU_VOLT_GET(921600, 22) + DECL_ERISTA_GPU_VOLT_GET(960000, 23) + DECL_ERISTA_GPU_VOLT_GET(998400, 24) + DECL_ERISTA_GPU_VOLT_GET(1036800, 25) + DECL_ERISTA_GPU_VOLT_GET(1075200, 26) + + DECL_MARIKO_GPU_VOLT_GET(76800, 0) + DECL_MARIKO_GPU_VOLT_GET(153600, 1) + DECL_MARIKO_GPU_VOLT_GET(230400, 2) + DECL_MARIKO_GPU_VOLT_GET(307200, 3) + DECL_MARIKO_GPU_VOLT_GET(384000, 4) + DECL_MARIKO_GPU_VOLT_GET(460800, 5) + DECL_MARIKO_GPU_VOLT_GET(537600, 6) + DECL_MARIKO_GPU_VOLT_GET(614400, 7) + DECL_MARIKO_GPU_VOLT_GET(691200, 8) + DECL_MARIKO_GPU_VOLT_GET(768000, 9) + DECL_MARIKO_GPU_VOLT_GET(844800, 10) + DECL_MARIKO_GPU_VOLT_GET(921600, 11) + DECL_MARIKO_GPU_VOLT_GET(998400, 12) + DECL_MARIKO_GPU_VOLT_GET(1075200, 13) + DECL_MARIKO_GPU_VOLT_GET(1152000, 14) + DECL_MARIKO_GPU_VOLT_GET(1228800, 15) + DECL_MARIKO_GPU_VOLT_GET(1267200, 16) + DECL_MARIKO_GPU_VOLT_GET(1305600, 17) + DECL_MARIKO_GPU_VOLT_GET(1344000, 18) + DECL_MARIKO_GPU_VOLT_GET(1382400, 19) + DECL_MARIKO_GPU_VOLT_GET(1420800, 20) + DECL_MARIKO_GPU_VOLT_GET(1459200, 21) + DECL_MARIKO_GPU_VOLT_GET(1497600, 22) + DECL_MARIKO_GPU_VOLT_GET(1536000, 23) + + void SetKipData(); + void GetKipData(); +} \ No newline at end of file diff --git a/Source/rewrite-hoc-clk/sysmodule/src/main.cpp b/Source/rewrite-hoc-clk/sysmodule/src/main.cpp index 3e1e039b..2c6d2505 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/main.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/main.cpp @@ -30,12 +30,13 @@ #include -#include "errors.h" -#include "file_utils.h" +#include "errors.hpp" +#include "file_utils.hpp" #include "board/board.hpp" #include "process_management.hpp" -#include "clock_manager.h" -#include "ipc_service.h" +#include "clock_manager.hpp" +#include "ipc_service.hpp" +#include "config.hpp" #define INNER_HEAP_SIZE 0x40000 @@ -111,7 +112,7 @@ extern "C" int main(int argc, char** argv) { - Result rc = FileUtils::Initialize(); + Result rc = fileUtils::Initialize(); if (R_FAILED(rc)) { fatalThrow(rc); @@ -125,44 +126,44 @@ int main(int argc, char** argv) processManagement::WaitForQLaunch(); - ClockManager* clockMgr = new ClockManager(); - IpcService* ipcSrv = new IpcService(clockMgr); + clockManager::Initialize(); + ipcService::Initialize(); - FileUtils::LogLine("Ready"); + fileUtils::LogLine("Ready"); - clockMgr->SetRunning(true); - clockMgr->GetConfig()->SetEnabled(true); - ipcSrv->SetRunning(true); + clockManager::SetRunning(true); + config::SetEnabled(true); + ipcService::SetRunning(true); // TemperaturePoint *table; // ReadConfigFile(&table); // InitFanController(table); // StartFanControllerThread(); - while (clockMgr->Running()) + while (clockManager::Running()) { - clockMgr->Tick(); - clockMgr->WaitForNextTick(); + clockManager::Tick(); + clockManager::WaitForNextTick(); } - ipcSrv->SetRunning(false); - delete ipcSrv; - delete clockMgr; + ipcService::SetRunning(false); + ipcService::Exit(); + clockManager::Exit(); processManagement::Exit(); board::Exit(); } catch (const std::exception &ex) { - FileUtils::LogLine("[!] %s", ex.what()); + fileUtils::LogLine("[!] %s", ex.what()); } catch (...) { std::exception_ptr p = std::current_exception(); - FileUtils::LogLine("[!?] %s", p ? p.__cxa_exception_type()->name() : "..."); + fileUtils::LogLine("[!?] %s", p ? p.__cxa_exception_type()->name() : "..."); } - FileUtils::LogLine("Exit"); + fileUtils::LogLine("Exit"); svcSleepThread(1000000ULL); - FileUtils::Exit(); + fileUtils::Exit(); return 0; } diff --git a/Source/rewrite-hoc-clk/sysmodule/src/process_management.cpp b/Source/rewrite-hoc-clk/sysmodule/src/process_management.cpp index c5bdcdf4..a06ac0a3 100644 --- a/Source/rewrite-hoc-clk/sysmodule/src/process_management.cpp +++ b/Source/rewrite-hoc-clk/sysmodule/src/process_management.cpp @@ -26,8 +26,8 @@ #include "process_management.hpp" -#include "file_utils.h" -#include "errors.h" +#include "file_utils.hpp" +#include "errors.hpp" namespace processManagement { diff --git a/Source/sys-clk/sysmodule/src/board.cpp b/Source/sys-clk/sysmodule/src/board.cpp index 9d13413a..e98cf955 100644 --- a/Source/sys-clk/sysmodule/src/board.cpp +++ b/Source/sys-clk/sysmodule/src/board.cpp @@ -514,7 +514,7 @@ std::uint32_t Board::GetHz(SysClkModule module) ASSERT_RESULT_OK(rc, "clkrstOpenSession"); rc = clkrstGetClockRate(&session, &hz); - ASSERT_RESULT_OK(rc, "clkrstSetClockRate"); + ASSERT_RESULT_OK(rc, "clkrstGetClockRate"); clkrstCloseSession(&session); }