[qt] clean up some orphaned_profiles bugs; add help (#2894)

Some weird edge cases of "phantom" profiles that are actually needed
for... reasons I guess

Also, fixed some of the logic w.r.t empty checking, plus added a help
page

Signed-off-by: crueter <crueter@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2894
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
This commit is contained in:
crueter 2025-10-30 11:03:08 +01:00
parent d989166044
commit e93159b047
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
6 changed files with 100 additions and 38 deletions

View file

@ -10,16 +10,19 @@
#include <iostream>
#include <random>
#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/find.hpp>
#include <fmt/ranges.h>
#include "common/fs/file.h"
#include "common/fs/fs.h"
#include "common/fs/fs_types.h"
#include "common/fs/path_util.h"
#include <ranges>
#include "common/settings.h"
#include "common/string_util.h"
#include "core/file_sys/savedata_factory.h"
#include "core/hle/service/acc/profile_manager.h"
#include <ranges>
namespace Service::Account {
@ -39,6 +42,7 @@ struct ProfileDataRaw {
INSERT_PADDING_BYTES(0x10);
std::array<UserRaw, MAX_USERS> users{};
};
static_assert(sizeof(ProfileDataRaw) == 0x650, "ProfileDataRaw has incorrect size.");
// TODO(ogniK): Get actual error codes
@ -490,8 +494,22 @@ void ProfileManager::ResetUserSaveFile()
std::vector<std::string> ProfileManager::FindGoodProfiles()
{
namespace fs = std::filesystem;
std::vector<std::string> good_uuids;
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir)
/ "user/save/0000000000000000";
// some exceptions because certain games just LOVE TO CAUSE ISSUES
static constexpr const std::array<const char* const, 2> EXCEPTION_UUIDS
= {"5755CC2A545A87128500000000000000", "00000000000000000000000000000000"};
for (const char *const uuid : EXCEPTION_UUIDS) {
if (fs::exists(path / uuid))
good_uuids.emplace_back(uuid);
}
for (const ProfileInfo& p : profiles) {
std::string uuid_string = [p]() -> std::string {
auto uuid = p.user_uuid;
@ -506,12 +524,9 @@ std::vector<std::string> ProfileManager::FindGoodProfiles()
return fmt::format("{:016X}{:016X}", user_id[1], user_id[0]);
}();
good_uuids.emplace_back(uuid_string);
if (uuid_string != "0") good_uuids.emplace_back(uuid_string);
}
// used for acnh, etc
good_uuids.emplace_back("00000000000000000000000000000000");
return good_uuids;
}
@ -519,6 +534,8 @@ std::vector<std::string> ProfileManager::FindOrphanedProfiles()
{
std::vector<std::string> good_uuids = FindGoodProfiles();
namespace fs = std::filesystem;
// TODO: fetch save_id programmatically
const auto path = Common::FS::GetEdenPath(Common::FS::EdenPath::NANDDir)
/ "user/save/0000000000000000";
@ -530,32 +547,47 @@ std::vector<std::string> ProfileManager::FindOrphanedProfiles()
[&good_uuids, &orphaned_profiles](const std::filesystem::directory_entry& entry) -> bool {
const std::string uuid = entry.path().stem().string();
bool override = false;
// first off, we should always clear empty profiles
// 99% of the time these are useless. If not, they are recreated anyways...
namespace fs = std::filesystem;
const auto is_empty = [&entry]() -> bool {
const auto is_empty = [&entry, &override]() -> bool {
try {
for (const auto& file : fs::recursive_directory_iterator(entry.path())) {
if (file.is_regular_file()) {
return true;
}
// TODO: .yuzu_save_size is a weird file that gets created by certain games
// I have no idea what its purpose is, but TEMPORARY SOLUTION: just mark the profile as valid if
// this file exists (???) e.g. for SSBU
// In short: if .yuzu_save_size is the ONLY file in a profile it's probably fine to keep
if (file.path().filename().string() == FileSys::GetSaveDataSizeFileName())
override = true;
// if there are any regular files (NOT directories) there, do NOT delete it :p
if (file.is_regular_file())
return false;
}
} catch (const fs::filesystem_error& e) {
// if we get an error--no worries, just pretend it's not empty
return false;
return true;
}
return false;
return true;
}();
if (!is_empty) {
if (is_empty) {
fs::remove_all(entry);
return true;
}
// edge-case: some filesystems forcefully change filenames to lowercase
// so we can just ignore any differences
// looking at you microsoft... ;)
std::string upper_uuid = uuid;
boost::to_upper(upper_uuid);
// if profiles.dat contains the UUID--all good
// if not--it's an orphaned profile and should be resolved by the user
if (std::find(good_uuids.begin(), good_uuids.end(), uuid) == good_uuids.end()) {
if (!override
&& std::find(good_uuids.begin(), good_uuids.end(), upper_uuid) == good_uuids.end()) {
orphaned_profiles.emplace_back(uuid);
}
return true;

View file

@ -69,7 +69,7 @@ enum class FatalType : u32 {
static void GenerateErrorReport(Core::System& system, Result error_code, const FatalInfo& info) {
const auto title_id = system.GetApplicationProcessProgramID();
std::string crash_report = fmt::format(
"Yuzu {}-{} crash report\n"
"Eden {}-{} crash report\n"
"Title ID: {:016x}\n"
"Result: {:#X} ({:04}-{:04d})\n"
"Set flags: 0x{:16X}\n"