diff --git a/Source/sys-clk/common/include/crc32.h b/Source/sys-clk/common/include/crc32.h
new file mode 100644
index 00000000..67539c7d
--- /dev/null
+++ b/Source/sys-clk/common/include/crc32.h
@@ -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 .
+ *
+ */
+
+#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;
+}
+
+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/sys-clk/common/include/notification.h b/Source/sys-clk/common/include/notification.h
index 77c595ca..a6389b6f 100644
--- a/Source/sys-clk/common/include/notification.h
+++ b/Source/sys-clk/common/include/notification.h
@@ -22,7 +22,7 @@
#include
static void writeNotification(const std::string& message) {
- const char* flagPath = "sdmc:/config/ultrahand/flags/NOTIFICATIONS.flag";
+ static const char* flagPath = "sdmc:/config/ultrahand/flags/NOTIFICATIONS.flag";
FILE* flagFile = fopen(flagPath, "r");
if (!flagFile) {
diff --git a/Source/sys-clk/common/include/service_guard.h b/Source/sys-clk/common/include/service_guard.h
index d7ce9a7a..96a348a5 100644
--- a/Source/sys-clk/common/include/service_guard.h
+++ b/Source/sys-clk/common/include/service_guard.h
@@ -1,3 +1,20 @@
+/*
+ * Copyright (c) MasaGratoR
+ *
+ * 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
#ifdef __cplusplus
diff --git a/Source/sys-clk/common/include/sysclk/config.h b/Source/sys-clk/common/include/sysclk/config.h
index 79b41765..05a502ab 100644
--- a/Source/sys-clk/common/include/sysclk/config.h
+++ b/Source/sys-clk/common/include/sysclk/config.h
@@ -158,6 +158,8 @@ typedef enum {
KipConfigValue_g_volt_e_1036800,
KipConfigValue_g_volt_e_1075200,
+ KipCrc32,
+ HocClkConfigValue_IsFirstLoad,
SysClkConfigValue_EnumMax,
} SysClkConfigValue;
@@ -368,7 +370,10 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
case KipConfigValue_g_volt_e_998400: return pretty ? "Erista GPU Volt 998 MHz" : "g_volt_e_998400";
case KipConfigValue_g_volt_e_1036800: return pretty ? "Erista GPU Volt 1036 MHz" : "g_volt_e_1036800";
case KipConfigValue_g_volt_e_1075200: return pretty ? "Erista GPU Volt 1075 MHz" : "g_volt_e_1075200";
-
+ case KipCrc32:
+ return pretty ? "CRC32" : "crc32";
+ case HocClkConfigValue_IsFirstLoad:
+ return pretty ? "Is First Load" : "is_first_load";
default:
return pretty ? "[cfg] no enum format string" : "err_no_format_string";
}
@@ -400,6 +405,7 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
case HocClkConfigValue_HandheldTDP:
case HocClkConfigValue_EnforceBoardLimit:
case HocClkConfigValue_FixCpuVoltBug:
+ case HocClkConfigValue_IsFirstLoad:
return 1ULL;
case HocClkConfigValue_ThermalThrottleThreshold:
return 70ULL;
@@ -436,6 +442,7 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
case HorizonOCConfigValue_OverwriteRefreshRate:
case HocClkConfigValue_FixCpuVoltBug:
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
+ case HocClkConfigValue_IsFirstLoad:
return (input & 0x1) == input;
case KipConfigValue_custRev:
@@ -527,6 +534,7 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
case KipConfigValue_g_volt_e_1075200:
case KipConfigValue_eristaCpuVmin:
case KipConfigValue_eristaCpuUnlock:
+ case KipCrc32:
return true;
case HorizonOCConfigValue_BatteryChargeCurrent:
return ((input >= 1024) && (input <= 3072)) || !input;
diff --git a/Source/sys-clk/sysmodule/src/clock_manager.cpp b/Source/sys-clk/sysmodule/src/clock_manager.cpp
index ea9d7216..4f7e9c38 100644
--- a/Source/sys-clk/sysmodule/src/clock_manager.cpp
+++ b/Source/sys-clk/sysmodule/src/clock_manager.cpp
@@ -38,6 +38,7 @@
#include
#include
#include
+#include
#define HOSPPC_HAS_BOOST (hosversionAtLeast(7,0,0))
bool isGovernorEnabled = false; // to avoid thread messes
@@ -793,6 +794,18 @@ void ClockManager::SetKipData() {
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
@@ -812,6 +825,8 @@ void ClockManager::GetKipData() {
fclose(fp);
}
+
+
SysClkConfigValueList configValues;
this->config->GetConfigValues(&configValues);
@@ -822,9 +837,21 @@ void ClockManager::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;
+
if(writeBootConfigValues) {
writeBootConfigValues = false;
@@ -948,32 +975,6 @@ void ClockManager::GetKipData() {
}
void ClockManager::UpdateRamTimings() {
- 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);
- }
- CustomizeTable table;
-
- if (!cust_read_and_cache("sdmc:/atmosphere/kips/hoc.kip", &table)) {
- FileUtils::LogLine("[clock_manager] Failed to read KIP file for UpdateRamTimings");
- writeNotification("Horizon OC\nKip read failed");
- return;
- }
-
- // if(this->config->GetConfigValue(KipConfigValue_marikoEmcMaxClock) != initialConfigValues[KipConfigValue_marikoEmcMaxClock] ||
- // this->config->GetConfigValue(KipConfigValue_mem_burst_read_latency) != initialConfigValues[KipConfigValue_mem_burst_read_latency] ||
- // this->config->GetConfigValue(KipConfigValue_mem_burst_write_latency) != initialConfigValues[KipConfigValue_mem_burst_write_latency]
- // ) {
- // writeNotification("Horizon OC\nCritical values changed!\nUnable to write timings");
- // return;
- // }
u32 t1_tRCD = this->config->GetConfigValue(KipConfigValue_t1_tRCD);
u32 t2_tRP = this->config->GetConfigValue(KipConfigValue_t2_tRP);
u32 t3_tRAS = this->config->GetConfigValue(KipConfigValue_t3_tRAS);
diff --git a/dist/atmosphere/kips/hoc.kip b/dist/atmosphere/kips/hoc.kip
index 335f1ed2..a34de300 100644
Binary files a/dist/atmosphere/kips/hoc.kip and b/dist/atmosphere/kips/hoc.kip differ