From 4c70da2508632c22817b08c357eaceb0107619ea Mon Sep 17 00:00:00 2001 From: SIrHrVedel <38987957+SirHrVedel@users.noreply.github.com> Date: Mon, 27 Apr 2026 02:44:19 +0200 Subject: [PATCH] Whoopsies: Restore persisId.dat code --- src/Cafe/Account/Account.cpp | 232 +++++++---------------------------- src/Cafe/Account/Account.h | 3 +- 2 files changed, 45 insertions(+), 190 deletions(-) diff --git a/src/Cafe/Account/Account.cpp b/src/Cafe/Account/Account.cpp index 0d7dc575..09f667d7 100644 --- a/src/Cafe/Account/Account.cpp +++ b/src/Cafe/Account/Account.cpp @@ -6,8 +6,6 @@ #include "Cafe/IOSU/legacy/iosu_crypto.h" #include "Common/FileStream.h" #include -#include -#include #include @@ -302,12 +300,11 @@ void Account::SetMiiName(std::wstring_view name) const std::vector& Account::RefreshAccounts() { - // Step 1: Scan all account directories into a sorted map - std::map accountMap; - const fs::path act_path = ActiveSettings::GetMlcPath("usr/save/system/act"); - if (fs::exists(act_path)) + std::vector result; + const fs::path path = ActiveSettings::GetMlcPath("usr/save/system/act"); + if (fs::exists(path)) { - for (const auto& it : fs::directory_iterator(act_path)) + for (const auto& it : fs::directory_iterator(path)) { if (!fs::is_directory(it)) continue; @@ -323,198 +320,35 @@ const std::vector& Account::RefreshAccounts() Account account(persistent_id); const auto error = account.Load(); if (!error) - accountMap.emplace(persistent_id, std::move(account)); + result.emplace_back(account); } } - std::vector result; - - // Step 2: Place accounts in common.dat order - for (const uint32 id : ReadCommonDat()) - { - auto it = accountMap.find(id); - if (it == accountMap.end()) - { - cemuLog_log(LogType::Force, - "User with persistentId {:08x} does not exist, please do not delete users from the MLC manually. Use 'File > General Settings > Accounts' to delete users!", id); - continue; - } - result.emplace_back(std::move(it->second)); - accountMap.erase(it); - } - - // Step 3: Append remaining accounts not in common.dat, sorted by persistent ID - for (auto& [id, account] : accountMap) - result.emplace_back(std::move(account)); - - // Step 4: Always force at least one account + // we always force at least one account if (result.empty()) { result.emplace_back(kMinPersistendId, L"default"); result.begin()->Save(); } - - s_account_list = std::move(result); - - // Write updated common.dat (also updates PersistentIdHead and DefaultAccountPersistentId) - std::vector orderedIds; - orderedIds.reserve(s_account_list.size()); - for (const auto& acc : s_account_list) - orderedIds.push_back(acc.GetPersistentId()); - WriteCommonDat(orderedIds); - + s_account_list = result; + UpdatePersisidDat(); return s_account_list; } -std::vector Account::ReadCommonDat() +void Account::UpdatePersisidDat() { - std::vector result; - const auto file_path = ActiveSettings::GetMlcPath("usr/save/system/act/common.dat"); - if (!fs::exists(file_path)) - return result; - - std::ifstream f(file_path); - if (!f.is_open()) - return result; - - std::string line; - while (std::getline(f, line)) + const auto max_id = std::max(kMinPersistendId, GetNextPersistentId() - 1); + const auto file = ActiveSettings::GetMlcPath("usr/save/system/act/persisid.dat"); + std::ofstream f(file); + if(f.is_open()) { - if (!boost::starts_with(line, "PersistentIdList=")) - continue; - - std::string list = line.substr(sizeof("PersistentIdList=") - 1); - // Strip trailing \r if present - if (!list.empty() && list.back() == '\r') - list.pop_back(); - - // Entries are separated by literal "\0" (backslash + '0'). Stop at "0" (empty slot). - size_t pos = 0; - while (pos < list.size()) - { - const size_t sep = list.find("\\0", pos); - const std::string entry = (sep == std::string::npos) ? list.substr(pos) : list.substr(pos, sep - pos); - - if (entry.empty() || entry == "0") - break; // reached first empty slot — no real users after this - - const auto id = ConvertString(entry, 16); - if (id >= kMinPersistendId) - result.push_back(id); - - if (sep == std::string::npos) - break; - pos = sep + 2; // skip past "\0" - } - break; // PersistentIdList line processed + f << "PersistentIdManager_20120607" << std::endl << "PersistentIdHead=" << std::hex << max_id << std::endl << std::endl; + f.flush(); + f.close(); } - return result; -} - -void Account::WriteCommonDat(const std::vector& orderedIds) -{ - const auto file_path = ActiveSettings::GetMlcPath("usr/save/system/act/common.dat"); - - // Read existing file to preserve the header and all metadata lines - std::string header = "AccountManager_20120607"; - std::vector> meta_lines; - - if (fs::exists(file_path)) - { - std::ifstream f(file_path); - if (f.is_open()) - { - std::string line; - bool first_line = true; - while (std::getline(f, line)) - { - if (!line.empty() && line.back() == '\r') - line.pop_back(); - if (first_line) - { - header = line; - first_line = false; - continue; - } - if (line.empty() || boost::starts_with(line, "PersistentIdList=")) - continue; - const auto eq = line.find('='); - if (eq != std::string::npos) - meta_lines.emplace_back(line.substr(0, eq), line.substr(eq + 1)); - } - } - } - - // Populate defaults if the file was absent or had no metadata - if (meta_lines.empty()) - { - meta_lines.emplace_back("DefaultAccountPersistentId", "0"); - meta_lines.emplace_back("CommonTransferableIdBase", "0"); - meta_lines.emplace_back("CommonUuid", "0"); - meta_lines.emplace_back("IsApplicationUpdateRequired", "0"); - meta_lines.emplace_back("DefaultNnasType", "0"); - meta_lines.emplace_back("DefaultNfsType", "0"); - meta_lines.emplace_back("DefaultNfsNo", "1"); - meta_lines.emplace_back("DefaultNnasDomain", ""); - meta_lines.emplace_back("DefaultNnasNfsEnv", "L1"); - } - - // Helper to update an existing key or append a new one - auto set_meta = [&](const std::string& key, const std::string& val) - { - for (auto& [k, v] : meta_lines) - { - if (k == key) - { - v = val; - return; - } - } - meta_lines.emplace_back(key, val); - }; - - // Update DefaultAccountPersistentId to the currently active account - set_meta("DefaultAccountPersistentId", fmt::format("{:08x}", ActiveSettings::GetPersistentId())); - - // Ensure the directory exists - const auto dir = file_path.parent_path(); - if (!fs::exists(dir)) - { - std::error_code ec; - fs::create_directories(dir, ec); - if (ec) - { - cemuLog_log(LogType::Force, "Unable to create directory for common.dat"); - return; - } - } - - std::ofstream f(file_path); - if (!f.is_open()) - { - cemuLog_log(LogType::Force, "Unable to save common.dat"); - return; - } - - f << header << "\n"; - - // Write PersistentIdList: always exactly 12 slots, each followed by literal "\0" - f << "PersistentIdList="; - for (size_t i = 0; i < 12; i++) - { - if (i < orderedIds.size()) - f << fmt::format("{:08x}", orderedIds[i]); - else - f << "0"; - f << "\\0"; - } - f << "\n"; - - for (const auto& [key, value] : meta_lines) - f << key << "=" << value << "\n"; - - f.flush(); + else + cemuLog_log(LogType::Force, "Unable to save persisid.dat"); } @@ -549,11 +383,33 @@ const Account& Account::GetCurrentAccount() uint32 Account::GetNextPersistentId() { - const auto it = std::max_element(s_account_list.cbegin(), s_account_list.cend(), - [](const Account& acc1, const Account& acc2) { return acc1.GetPersistentId() < acc2.GetPersistentId(); }); + uint32 result = kMinPersistendId; + const auto file = ActiveSettings::GetMlcPath("usr/save/system/act/persisid.dat"); + if(fs::exists(file)) + { + std::ifstream f(file); + if(f.is_open()) + { + std::string line; + while(std::getline(f, line)) + { + if(boost::starts_with(line, "PersistentIdHead=")) + { + result = ConvertString(line.data() + sizeof("PersistentIdHead=") - 1, 16); + break; + } + } + } + } + + // next id + ++result; + + const auto it = std::max_element(s_account_list.cbegin(), s_account_list.cend(), [](const Account& acc1, const Account& acc2) {return acc1.GetPersistentId() < acc2.GetPersistentId(); }); if (it != s_account_list.cend()) - return it->GetPersistentId() + 1; - return kMinPersistendId; + return std::max(result, it->GetPersistentId() + 1); + else + return result; } fs::path Account::GetFileName(uint32 persistent_id) diff --git a/src/Cafe/Account/Account.h b/src/Cafe/Account/Account.h index e9e80a49..c9abd395 100644 --- a/src/Cafe/Account/Account.h +++ b/src/Cafe/Account/Account.h @@ -93,8 +93,7 @@ public: // this will always return at least one account (default one) static const std::vector& RefreshAccounts(); - static std::vector ReadCommonDat(); - static void WriteCommonDat(const std::vector& orderedIds); + static void UpdatePersisidDat(); [[nodiscard]] static bool HasFreeAccountSlots(); [[nodiscard]] static const std::vector& GetAccounts();