complete config refactor

This commit is contained in:
souldbminersmwc committed 2026-09-05 15:58:08 -04:00
1 parent 0169e44b3b
commit 28265faedc
10 files changed
+504 -85

No files matched your search

+469 -64
View File
@@ -26,6 +26,7 @@
#include <algorithm>
#include <atomic>
#include <cstdio>
#include <cstring>
#include <ctime>
#include <i2c.h>
@@ -55,30 +56,37 @@ namespace config {
namespace {
bool gLoaded = false;
std::string gPath;
time_t gMtime = 0;
std::string gSettingsPath;
std::string gKipPath;
std::string gProfilesDir;
std::string gLegacyPath;
time_t gSettingsMtime = 0;
time_t gKipMtime = 0;
std::atomic_bool gEnabled{ false };
std::uint32_t gOverrideFreqs[HocClkModule_EnumMax];
std::map<std::tuple<std::uint64_t, HocClkProfile, HocClkModule>, std::uint32_t> gProfileMHzMap;
std::map<std::uint64_t, std::uint8_t> gProfileCountMap;
std::set<std::uint64_t> gLoadedTids;
std::map<std::uint64_t, time_t> gProfileMtimes;
std::uint64_t gCurrentGameTid = 0;
bool gProfilesDirty = false;
bool gMigrationHappened = false;
LockableMutex gConfigMutex;
LockableMutex gOverrideMutex;
time_t CheckModificationTime() {
time_t CheckFileMtime(const std::string &path) {
time_t mtime = 0;
struct stat st;
if (stat(gPath.c_str(), &st) == 0) {
if (stat(path.c_str(), &st) == 0) {
mtime = st.st_mtime;
}
return mtime;
}
std::uint32_t FindClockMHz(std::uint64_t tid, HocClkModule module, HocClkProfile profile) {
if (gLoaded) {
auto it = gProfileMHzMap.find(std::make_tuple(tid, profile, module));
if (it != gProfileMHzMap.end()) {
return it->second;
}
auto it = gProfileMHzMap.find(std::make_tuple(tid, profile, module));
if (it != gProfileMHzMap.end()) {
return it->second;
}
return 0;
}
@@ -99,33 +107,59 @@ namespace config {
return std::max((std::uint32_t)0, mhz * mhzMultiplier);
}
int BrowseIniFunc(const char *section, const char *key, const char *value, void *userdata) {
int BrowseSettingsIni(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 < HocClkConfigValue_EnumMax; kval++) {
if (!strcmp(key, hocclkFormatConfigValue((HocClkConfigValue)kval, false))) {
input = strtoul(value, NULL, 0);
if (!hocclkValidConfigValue((HocClkConfigValue)kval, input)) {
input = hocclkDefaultConfigValue((HocClkConfigValue)kval);
fileUtils::LogLine("[cfg] Invalid value for key '%s' in section '%s': using default %d", key, section, input);
}
configValues[kval] = input;
return 1;
}
if (strcmp(section, CONFIG_VAL_SECTION) != 0) {
return 1;
}
for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) {
if (hocclkIsKipConfigValue((HocClkConfigValue)kval)) {
continue;
}
if (!strcmp(key, hocclkFormatConfigValue((HocClkConfigValue)kval, false))) {
std::uint64_t input = strtoul(value, NULL, 0);
if (!hocclkValidConfigValue((HocClkConfigValue)kval, input)) {
input = hocclkDefaultConfigValue((HocClkConfigValue)kval);
fileUtils::LogLine("[cfg] Invalid value for key '%s': using default %llu", key, input);
}
configValues[kval] = input;
return 1;
}
}
fileUtils::LogLine("[cfg] Skipping key '%s' in section '%s': Unrecognized config value", key, section);
fileUtils::LogLine("[cfg] Skipping key '%s' in settings: Unrecognized config value", key);
return 1;
}
int BrowseKipIni(const char *section, const char *key, const char *value, void *userdata) {
(void)userdata;
if (strcmp(section, CONFIG_VAL_SECTION) != 0) {
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;
for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) {
if (!hocclkIsKipConfigValue((HocClkConfigValue)kval)) {
continue;
}
if (!strcmp(key, hocclkFormatConfigValue((HocClkConfigValue)kval, false))) {
std::uint64_t input = strtoul(value, NULL, 0);
if (!hocclkValidConfigValue((HocClkConfigValue)kval, input)) {
input = hocclkDefaultConfigValue((HocClkConfigValue)kval);
fileUtils::LogLine("[cfg] Invalid value for key '%s': using default %llu", key, input);
}
configValues[kval] = input;
return 1;
}
}
fileUtils::LogLine("[cfg] Skipping key '%s' in kip: Unrecognized config value", key);
return 1;
}
int BrowseProfileIni(const char *section, const char *key, const char *value, void *userdata) {
std::uint64_t tid = (std::uint64_t)(uintptr_t)userdata;
HocClkProfile parsedProfile = HocClkProfile_EnumMax;
HocClkModule parsedModule = HocClkModule_EnumMax;
@@ -148,13 +182,11 @@ namespace config {
}
if (parsedModule == HocClkModule_EnumMax || parsedProfile == HocClkProfile_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;
}
@@ -173,33 +205,305 @@ namespace config {
gLoaded = false;
gProfileMHzMap.clear();
gProfileCountMap.clear();
gLoadedTids.clear();
gProfileMtimes.clear();
gCurrentGameTid = 0;
gProfilesDirty = false;
for (unsigned int i = 0; i < HocClkConfigValue_EnumMax; i++) {
configValues[i] = hocclkDefaultConfigValue((HocClkConfigValue)i);
}
}
void Load() {
fileUtils::LogLine("[cfg] Reading %s", gPath.c_str());
void LoadSettings() {
fileUtils::LogLine("[cfg] Reading %s", gSettingsPath.c_str());
gSettingsMtime = CheckFileMtime(gSettingsPath);
if (!gSettingsMtime) {
fileUtils::LogLine("[cfg] Settings file not found, using defaults");
return;
}
if (!ini_browse(&BrowseSettingsIni, nullptr, gSettingsPath.c_str())) {
fileUtils::LogLine("[cfg] Error loading settings file");
}
}
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");
void LoadKip() {
fileUtils::LogLine("[cfg] Reading %s", gKipPath.c_str());
gKipMtime = CheckFileMtime(gKipPath);
if (!gKipMtime) {
fileUtils::LogLine("[cfg] KIP config file not found, using defaults");
return;
}
if (!ini_browse(&BrowseKipIni, nullptr, gKipPath.c_str())) {
fileUtils::LogLine("[cfg] Error loading KIP config file");
}
}
std::string ProfilePathForTid(std::uint64_t tid) {
char filename[32];
snprintf(filename, sizeof(filename), "%016lX.ini", tid);
return gProfilesDir + "/" + filename;
}
void EvictProfile(std::uint64_t tid) {
if (tid == HOCCLK_GLOBAL_PROFILE_TID) {
return;
}
for (unsigned int profile = 0; profile < HocClkProfile_EnumMax; profile++) {
for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) {
gProfileMHzMap.erase(std::make_tuple(tid, (HocClkProfile)profile, (HocClkModule)module));
}
}
gProfileCountMap.erase(tid);
gProfileMtimes.erase(tid);
gLoadedTids.erase(tid);
}
void LoadProfileTid(std::uint64_t tid) {
if (tid == 0) {
return;
}
if (gLoadedTids.count(tid)) {
return;
}
if (tid != HOCCLK_GLOBAL_PROFILE_TID && gCurrentGameTid != 0) {
EvictProfile(gCurrentGameTid);
}
std::string path = ProfilePathForTid(tid);
struct stat st;
if (stat(path.c_str(), &st) == 0) {
fileUtils::LogLine("[cfg] Loading profile %s", path.c_str());
ini_browse(&BrowseProfileIni, (void *)(uintptr_t)tid, path.c_str());
gProfileMtimes[tid] = st.st_mtime;
} else {
gProfileMtimes.erase(tid);
}
gLoadedTids.insert(tid);
if (tid != HOCCLK_GLOBAL_PROFILE_TID) {
gCurrentGameTid = tid;
}
}
void Load() {
gLoaded = false;
for (unsigned int i = 0; i < HocClkConfigValue_EnumMax; i++) {
configValues[i] = hocclkDefaultConfigValue((HocClkConfigValue)i);
}
LoadSettings();
LoadKip();
gLoaded = true;
}
struct MigrationData {
std::vector<std::pair<std::string, std::string>> settingsKeys;
std::vector<std::pair<std::string, std::string>> kipKeys;
std::vector<std::pair<std::uint64_t, std::pair<std::string, std::string>>> profileEntries;
};
int MigrationBrowseFunc(const char *section, const char *key, const char *value, void *userdata) {
MigrationData *data = static_cast<MigrationData *>(userdata);
if (!strcmp(section, CONFIG_VAL_SECTION)) {
for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) {
if (!strcmp(key, hocclkFormatConfigValue((HocClkConfigValue)kval, false))) {
if (hocclkIsKipConfigValue((HocClkConfigValue)kval)) {
data->kipKeys.push_back({key, value});
return 1;
}
data->settingsKeys.push_back({key, value});
return 1;
}
}
fileUtils::LogLine("[cfg] Skipping unrecognized key '%s'", key);
} else {
std::uint64_t tid = strtoul(section, NULL, 16);
if (tid && strlen(section) == 16) {
data->profileEntries.push_back({tid, {key, value}});
}
}
return 1;
}
void MigrateLegacyConfig() {
struct stat st;
if (stat(gLegacyPath.c_str(), &st) != 0) {
return;
}
fileUtils::LogLine("[cfg] Migrating legacy config.ini");
fileUtils::LogLine("[cfg] Legacy path: %s", gLegacyPath.c_str());
fileUtils::LogLine("[cfg] Settings path: %s", gSettingsPath.c_str());
fileUtils::LogLine("[cfg] Profiles dir: %s", gProfilesDir.c_str());
MigrationData data;
fileUtils::LogLine("[cfg] Parsing legacy config.ini...");
ini_browse(&MigrationBrowseFunc, &data, gLegacyPath.c_str());
fileUtils::LogLine("[cfg] Found %zu settings keys, %zu KIP keys, %zu profile entries",
data.settingsKeys.size(), data.kipKeys.size(), data.profileEntries.size());
if (!data.settingsKeys.empty()) {
fileUtils::LogLine("[cfg] Creating kip directory: %s", FILE_KIP_DIR);
mkdir(FILE_KIP_DIR, 0777);
fileUtils::LogLine("[cfg] Writing %zu settings to %s", data.settingsKeys.size(), gSettingsPath.c_str());
std::vector<std::string> sKeys;
std::vector<std::string> sVals;
sKeys.reserve(data.settingsKeys.size());
sVals.reserve(data.settingsKeys.size());
for (const auto &entry : data.settingsKeys) {
fileUtils::LogLine("[cfg] %s = %s", entry.first.c_str(), entry.second.c_str());
sKeys.push_back(entry.first);
sVals.push_back(entry.second);
}
std::vector<const char *> keyPtrs;
std::vector<const char *> valPtrs;
keyPtrs.reserve(sKeys.size() + 1);
valPtrs.reserve(sVals.size() + 1);
for (size_t i = 0; i < sKeys.size(); i++) {
keyPtrs.push_back(sKeys[i].c_str());
valPtrs.push_back(sVals[i].c_str());
}
keyPtrs.push_back(NULL);
valPtrs.push_back(NULL);
if (!ini_putsection(CONFIG_VAL_SECTION, keyPtrs.data(), valPtrs.data(), gSettingsPath.c_str())) {
fileUtils::LogLine("[cfg] FAILED to write settings section");
} else {
fileUtils::LogLine("[cfg] Settings migration done");
}
} else {
fileUtils::LogLine("[cfg] No settings keys to migrate");
}
if (!data.kipKeys.empty()) {
fileUtils::LogLine("[cfg] Writing %zu KIP keys to %s", data.kipKeys.size(), gKipPath.c_str());
std::vector<std::string> kKeys;
std::vector<std::string> kVals;
kKeys.reserve(data.kipKeys.size());
kVals.reserve(data.kipKeys.size());
for (const auto &entry : data.kipKeys) {
fileUtils::LogLine("[cfg] %s = %s", entry.first.c_str(), entry.second.c_str());
kKeys.push_back(entry.first);
kVals.push_back(entry.second);
}
std::vector<const char *> kKeyPtrs;
std::vector<const char *> kValPtrs;
kKeyPtrs.reserve(kKeys.size() + 1);
kValPtrs.reserve(kVals.size() + 1);
for (size_t i = 0; i < kKeys.size(); i++) {
kKeyPtrs.push_back(kKeys[i].c_str());
kValPtrs.push_back(kVals[i].c_str());
}
kKeyPtrs.push_back(NULL);
kValPtrs.push_back(NULL);
if (!ini_putsection(CONFIG_VAL_SECTION, kKeyPtrs.data(), kValPtrs.data(), gKipPath.c_str())) {
fileUtils::LogLine("[cfg] FAILED to write KIP section");
} else {
fileUtils::LogLine("[cfg] KIP migration done");
}
for (const auto &entry : data.kipKeys) {
for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) {
if (!hocclkIsKipConfigValue((HocClkConfigValue)kval)) {
continue;
}
if (!strcmp(entry.first.c_str(), hocclkFormatConfigValue((HocClkConfigValue)kval, false))) {
std::uint64_t input = strtoul(entry.second.c_str(), NULL, 0);
if (hocclkValidConfigValue((HocClkConfigValue)kval, input)) {
configValues[kval] = input;
}
break;
}
}
}
} else {
fileUtils::LogLine("[cfg] No KIP keys to migrate");
}
fileUtils::LogLine("[cfg] Creating profiles directory: %s", FILE_PROFILES_DIR);
mkdir(FILE_PROFILES_DIR, 0777);
std::map<std::uint64_t, std::vector<std::pair<std::string, std::string>>> profileBuckets;
for (const auto &entry : data.profileEntries) {
profileBuckets[entry.first].push_back(entry.second);
}
fileUtils::LogLine("[cfg] Writing %zu profiles (%zu TIDs)", data.profileEntries.size(), profileBuckets.size());
for (const auto &bucket : profileBuckets) {
char filename[32];
snprintf(filename, sizeof(filename), "%016lX.ini", bucket.first);
std::string profilePath = gProfilesDir + "/" + filename;
fileUtils::LogLine("[cfg] TID=%016lX %zu keys -> %s", bucket.first, bucket.second.size(), profilePath.c_str());
std::vector<std::string> pKeys;
std::vector<std::string> pVals;
pKeys.reserve(bucket.second.size());
pVals.reserve(bucket.second.size());
for (const auto &kv : bucket.second) {
fileUtils::LogLine("[cfg] %s = %s", kv.first.c_str(), kv.second.c_str());
pKeys.push_back(kv.first);
pVals.push_back(kv.second);
}
std::vector<const char *> keyPtrs;
std::vector<const char *> valPtrs;
keyPtrs.reserve(pKeys.size() + 1);
valPtrs.reserve(pVals.size() + 1);
for (size_t i = 0; i < pKeys.size(); i++) {
keyPtrs.push_back(pKeys[i].c_str());
valPtrs.push_back(pVals[i].c_str());
}
keyPtrs.push_back(NULL);
valPtrs.push_back(NULL);
if (!ini_putsection(CONFIG_VAL_SECTION, keyPtrs.data(), valPtrs.data(), profilePath.c_str())) {
fileUtils::LogLine("[cfg] FAILED to write profile for TID %016lX", bucket.first);
}
}
fileUtils::LogLine("[cfg] Profiles migration done");
fileUtils::LogLine("[cfg] Renaming legacy config to config.ini.migrated");
if (rename(gLegacyPath.c_str(), (gLegacyPath + ".migrated").c_str()) != 0) {
fileUtils::LogLine("[cfg] WARNING: Failed to rename legacy config file");
}
gMigrationHappened = true;
fileUtils::LogLine("[cfg] Migration complete");
}
} // namespace
bool IsProfileDirty() {
return gProfilesDirty;
}
void SetProfileDirty(bool dirty) {
gProfilesDirty = dirty;
}
void Initialize() {
gPath = FILE_CONFIG_DIR "/config.ini";
gSettingsPath = FILE_SETTINGS_PATH;
gKipPath = FILE_KIP_CONFIG_PATH;
gProfilesDir = FILE_PROFILES_DIR;
gLegacyPath = FILE_LEGACY_CONFIG_PATH;
gLoaded = false;
gMigrationHappened = false;
gProfileMHzMap.clear();
gProfileCountMap.clear();
gMtime = 0;
gLoadedTids.clear();
gProfileMtimes.clear();
gCurrentGameTid = 0;
gProfilesDirty = false;
gSettingsMtime = 0;
gKipMtime = 0;
gEnabled = false;
for (unsigned int i = 0; i < HocClkModule_EnumMax; i++) {
gOverrideFreqs[i] = 0;
@@ -207,6 +511,15 @@ namespace config {
for (unsigned int i = 0; i < HocClkConfigValue_EnumMax; i++) {
configValues[i] = hocclkDefaultConfigValue((HocClkConfigValue)i);
}
mkdir(FILE_CONFIG_DIR, 0777);
mkdir(FILE_KIP_DIR, 0777);
mkdir(FILE_PROFILES_DIR, 0777);
MigrateLegacyConfig();
gLoaded = true;
LoadProfileTid(HOCCLK_GLOBAL_PROFILE_TID);
}
void Exit() {
@@ -216,11 +529,38 @@ namespace config {
bool Refresh() {
std::scoped_lock lock{ gConfigMutex };
if (!gLoaded || gMtime != CheckModificationTime()) {
time_t settingsMtime = CheckFileMtime(gSettingsPath);
time_t kipMtime = CheckFileMtime(gKipPath);
if (!gLoaded || gSettingsMtime != settingsMtime || gKipMtime != kipMtime) {
Load();
return true;
}
return false;
if (IsProfileDirty()) {
SetProfileDirty(false);
return true;
}
std::vector<std::uint64_t> staleTids;
for (std::uint64_t tid : gLoadedTids) {
time_t mtime = CheckFileMtime(ProfilePathForTid(tid));
auto it = gProfileMtimes.find(tid);
time_t known = (it != gProfileMtimes.end()) ? it->second : 0;
if (mtime != known) {
staleTids.push_back(tid);
}
}
for (std::uint64_t tid : staleTids) {
fileUtils::LogLine("[cfg] Profile %016lX changed on disk, dropping cache", tid);
for (unsigned int profile = 0; profile < HocClkProfile_EnumMax; profile++) {
for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) {
gProfileMHzMap.erase(std::make_tuple(tid, (HocClkProfile)profile, (HocClkModule)module));
}
}
gProfileCountMap.erase(tid);
gProfileMtimes.erase(tid);
gLoadedTids.erase(tid);
}
return !staleTids.empty();
}
bool HasProfilesLoaded() {
@@ -230,6 +570,9 @@ namespace config {
std::uint32_t GetAutoClockHz(std::uint64_t tid, HocClkModule module, HocClkProfile profile, bool returnRaw) {
std::scoped_lock lock{ gConfigMutex };
if (gLoaded && !gLoadedTids.count(tid)) {
LoadProfileTid(tid);
}
switch (profile) {
case HocClkProfile_Handheld:
return FindClockHzFromProfiles(tid, module, { HocClkProfile_Handheld }, returnRaw ? 1 : 1000000);
@@ -252,6 +595,7 @@ namespace config {
void GetProfiles(std::uint64_t tid, HocClkTitleProfileList *out_profiles) {
std::scoped_lock lock{ gConfigMutex };
LoadProfileTid(tid);
for (unsigned int profile = 0; profile < HocClkProfile_EnumMax; profile++) {
for (unsigned int module = 0; module < HocClkModule_EnumMax; module++) {
out_profiles->mhzMap[profile][module] = FindClockMHz(tid, (HocClkModule)module, (HocClkProfile)profile);
@@ -261,10 +605,12 @@ namespace config {
bool SetProfiles(std::uint64_t tid, HocClkTitleProfileList *profiles, bool immediate) {
std::scoped_lock lock{ gConfigMutex };
uint8_t numProfiles = 0;
char section[17] = { 0 };
snprintf(section, sizeof(section), "%016lX", tid);
mkdir(FILE_PROFILES_DIR, 0777);
std::string profilePath = ProfilePathForTid(tid);
uint8_t numProfiles = 0;
std::vector<std::string> keys;
std::vector<std::string> values;
@@ -301,10 +647,18 @@ namespace config {
keyPointers.push_back(NULL);
valuePointers.push_back(NULL);
if (!ini_putsection(section, keyPointers.data(), valuePointers.data(), gPath.c_str())) {
if (keys.empty()) {
struct stat st;
if (stat(profilePath.c_str(), &st) == 0 && remove(profilePath.c_str()) != 0) {
fileUtils::LogLine("[cfg] Failed to remove empty profile %s", profilePath.c_str());
return false;
}
} else if (!ini_putsection(CONFIG_VAL_SECTION, keyPointers.data(), valuePointers.data(), profilePath.c_str())) {
return false;
}
gProfileMtimes[tid] = CheckFileMtime(profilePath);
if (immediate) {
mhz = &profiles->mhz[0];
gProfileCountMap[tid] = numProfiles;
@@ -318,12 +672,22 @@ namespace config {
mhz++;
}
}
gLoadedTids.insert(tid);
if (tid != HOCCLK_GLOBAL_PROFILE_TID) {
gCurrentGameTid = tid;
}
SetProfileDirty(true);
}
return true;
}
std::uint8_t GetProfileCount(std::uint64_t tid) {
std::scoped_lock lock{ gConfigMutex };
if (tid != 0 && gLoaded && !gLoadedTids.count(tid)) {
LoadProfileTid(tid);
}
auto it = gProfileCountMap.find(tid);
if (it == gProfileCountMap.end()) {
return 0;
@@ -339,6 +703,10 @@ namespace config {
return gEnabled;
}
bool MigrationHappened() {
return gMigrationHappened;
}
void SetOverrideHz(HocClkModule module, std::uint32_t hz) {
ASSERT_ENUM_VALID(HocClkModule, module);
std::scoped_lock lock{ gOverrideMutex };
@@ -372,31 +740,60 @@ namespace config {
bool SetConfigValues(HocClkConfigValueList *configValues, bool immediate) {
std::scoped_lock lock{ gConfigMutex };
std::vector<const char *> iniKeys;
std::vector<std::string> iniValues;
iniKeys.reserve(HocClkConfigValue_EnumMax + 1);
iniValues.reserve(HocClkConfigValue_EnumMax);
std::vector<std::string> settingsKeys;
std::vector<std::string> settingsValues;
std::vector<std::string> kipKeys;
std::vector<std::string> kipValues;
for (unsigned int kval = 0; kval < HocClkConfigValue_EnumMax; kval++) {
if (!hocclkValidConfigValue((HocClkConfigValue)kval, configValues->values[kval]) ||
configValues->values[kval] == hocclkDefaultConfigValue((HocClkConfigValue)kval)) {
continue;
}
iniValues.push_back(std::to_string(configValues->values[kval]));
iniKeys.push_back(hocclkFormatConfigValue((HocClkConfigValue)kval, false));
std::string key = hocclkFormatConfigValue((HocClkConfigValue)kval, false);
std::string value = std::to_string(configValues->values[kval]);
if (hocclkIsKipConfigValue((HocClkConfigValue)kval)) {
kipKeys.push_back(key);
kipValues.push_back(value);
} else {
settingsKeys.push_back(key);
settingsValues.push_back(value);
}
}
iniKeys.push_back(NULL);
bool success = true;
std::vector<const char *> valuePointers;
valuePointers.reserve(iniValues.size() + 1);
for (const auto &val : iniValues) {
valuePointers.push_back(val.c_str());
if (!settingsKeys.empty()) {
std::vector<const char *> sKeyPtrs;
std::vector<const char *> sValPtrs;
sKeyPtrs.reserve(settingsKeys.size() + 1);
sValPtrs.reserve(settingsValues.size() + 1);
for (size_t i = 0; i < settingsKeys.size(); i++) {
sKeyPtrs.push_back(settingsKeys[i].c_str());
sValPtrs.push_back(settingsValues[i].c_str());
}
sKeyPtrs.push_back(NULL);
sValPtrs.push_back(NULL);
if (!ini_putsection(CONFIG_VAL_SECTION, sKeyPtrs.data(), sValPtrs.data(), gSettingsPath.c_str())) {
success = false;
}
}
valuePointers.push_back(NULL);
if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) {
return false;
if (!kipKeys.empty()) {
std::vector<const char *> kKeyPtrs;
std::vector<const char *> kValPtrs;
kKeyPtrs.reserve(kipKeys.size() + 1);
kValPtrs.reserve(kipValues.size() + 1);
for (size_t i = 0; i < kipKeys.size(); i++) {
kKeyPtrs.push_back(kipKeys[i].c_str());
kValPtrs.push_back(kipValues[i].c_str());
}
kKeyPtrs.push_back(NULL);
kValPtrs.push_back(NULL);
if (!ini_putsection(CONFIG_VAL_SECTION, kKeyPtrs.data(), kValPtrs.data(), gKipPath.c_str())) {
success = false;
}
}
if (immediate) {
@@ -407,9 +804,10 @@ namespace config {
config::configValues[kval] = hocclkDefaultConfigValue((HocClkConfigValue)kval);
}
}
SetProfileDirty(true);
}
return true;
return success;
}
bool ResetConfigValue(HocClkConfigValue kval) {
@@ -438,13 +836,16 @@ namespace config {
}
valuePointers.push_back(NULL);
if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) {
const char *targetPath = hocclkIsKipConfigValue(kval) ? gKipPath.c_str() : gSettingsPath.c_str();
if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), targetPath)) {
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);
SetProfileDirty(true);
return true;
}
@@ -473,12 +874,15 @@ namespace config {
valuePointers.push_back(iniValues[0].c_str());
valuePointers.push_back(NULL);
if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), gPath.c_str())) {
const char *targetPath = hocclkIsKipConfigValue(kval) ? gKipPath.c_str() : gSettingsPath.c_str();
if (!ini_putsection(CONFIG_VAL_SECTION, iniKeys.data(), valuePointers.data(), targetPath)) {
return false;
}
if (immediate) {
configValues[kval] = value;
SetProfileDirty(true);
}
return true;
@@ -486,6 +890,7 @@ namespace config {
void DeleteKey(const char *section, const char *key) {
std::scoped_lock lock{ gConfigMutex };
ini_puts(section, key, NULL, gPath.c_str());
ini_puts(section, key, NULL, gSettingsPath.c_str());
ini_puts(section, key, NULL, gKipPath.c_str());
}
} // namespace config
@@ -26,6 +26,8 @@
#pragma once
#include <set>
#include <vector>
#include <hocclk.h>
#include <switch.h>
@@ -39,6 +41,9 @@ namespace config {
bool Refresh();
bool HasProfilesLoaded();
bool IsProfileDirty();
void SetProfileDirty(bool dirty);
std::uint8_t GetProfileCount(std::uint64_t tid);
void GetProfiles(std::uint64_t tid, HocClkTitleProfileList *out_profiles);
bool SetProfiles(std::uint64_t tid, HocClkTitleProfileList *profiles, bool immediate);
@@ -46,6 +51,7 @@ namespace config {
void SetEnabled(bool enabled);
bool Enabled();
bool MigrationHappened();
void SetOverrideHz(HocClkModule module, std::uint32_t hz);
std::uint32_t GetOverrideHz(HocClkModule module);
@@ -39,6 +39,11 @@
#define FILE_LOG_FLAG_PATH FILE_CONFIG_DIR "/log.flag"
#define FILE_UART_FLAG_PATH FILE_CONFIG_DIR "/uart.flag"
#define FILE_LOG_FILE_PATH FILE_CONFIG_DIR "/log.txt"
#define FILE_SETTINGS_PATH FILE_CONFIG_DIR "/settings.ini"
#define FILE_KIP_DIR FILE_CONFIG_DIR "/kip"
#define FILE_KIP_CONFIG_PATH FILE_KIP_DIR "/current.ini"
#define FILE_PROFILES_DIR FILE_CONFIG_DIR "/profiles"
#define FILE_LEGACY_CONFIG_PATH FILE_CONFIG_DIR "/config.ini"
namespace fileUtils {
+1 -1
View File
@@ -38,7 +38,7 @@
#include "mgr/clock_manager.hpp"
#define INNER_HEAP_SIZE 0x41000
#define INNER_HEAP_SIZE 0x40000
extern "C" {
void virtmemSetup(void);