mirror of
https://git.eden-emu.dev/archive/citron
synced 2026-04-19 11:10:44 -04:00
Merge pull request 'feat(fs): Correct save path hierarchy to prioritize mirroring and per-game paths' (#109) from fix/path-ordering-for-saves into main
Reviewed-on: https://git.citron-emu.org/Citron/Emulator/pulls/109
This commit is contained in:
@@ -2426,13 +2426,38 @@ void GMainWindow::OnGameListOpenFolder(u64 program_id, GameListOpenTarget target
|
|||||||
case GameListOpenTarget::SaveData: {
|
case GameListOpenTarget::SaveData: {
|
||||||
open_target = tr("Save Data");
|
open_target = tr("Save Data");
|
||||||
|
|
||||||
if (Settings::values.custom_save_paths.count(program_id)) {
|
// 1. Check for Mirrored Path FIRST (opens the external directory)
|
||||||
|
if (Settings::values.mirrored_save_paths.count(program_id)) {
|
||||||
|
const std::string& mirrored_path_str =
|
||||||
|
Settings::values.mirrored_save_paths.at(program_id);
|
||||||
|
if (!mirrored_path_str.empty() && Common::FS::IsDir(mirrored_path_str)) {
|
||||||
|
LOG_INFO(Frontend, "Opening mirrored save data path for program_id={:016x}",
|
||||||
|
program_id);
|
||||||
|
QDesktopServices::openUrl(
|
||||||
|
QUrl::fromLocalFile(QString::fromStdString(mirrored_path_str)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2. Check for Per-Game Custom Path
|
||||||
|
else if (Settings::values.custom_save_paths.count(program_id)) {
|
||||||
const std::string& custom_path_str = Settings::values.custom_save_paths.at(program_id);
|
const std::string& custom_path_str = Settings::values.custom_save_paths.at(program_id);
|
||||||
const std::filesystem::path custom_path = custom_path_str;
|
if (!custom_path_str.empty() && Common::FS::IsDir(custom_path_str)) {
|
||||||
|
LOG_INFO(Frontend, "Opening custom save data path for program_id={:016x}",
|
||||||
if (!custom_path_str.empty() && Common::FS::IsDir(custom_path)) {
|
program_id);
|
||||||
LOG_INFO(Frontend, "Opening custom save data path for program_id={:016x}", program_id);
|
QDesktopServices::openUrl(
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(custom_path_str)));
|
QUrl::fromLocalFile(QString::fromStdString(custom_path_str)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 3. Check for Global Custom Save Path
|
||||||
|
else if (Settings::values.global_custom_save_path_enabled.GetValue()) {
|
||||||
|
const std::string& global_path_str =
|
||||||
|
Settings::values.global_custom_save_path.GetValue();
|
||||||
|
if (!global_path_str.empty() && Common::FS::IsDir(global_path_str)) {
|
||||||
|
LOG_INFO(Frontend, "Opening global custom save data path for program_id={:016x}",
|
||||||
|
program_id);
|
||||||
|
QDesktopServices::openUrl(
|
||||||
|
QUrl::fromLocalFile(QString::fromStdString(global_path_str)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -422,15 +422,30 @@ std::shared_ptr<FileSys::SaveDataFactory> FileSystemController::CreateSaveDataFa
|
|||||||
const auto rw_mode = FileSys::OpenMode::ReadWrite;
|
const auto rw_mode = FileSys::OpenMode::ReadWrite;
|
||||||
auto vfs = system.GetFilesystem();
|
auto vfs = system.GetFilesystem();
|
||||||
|
|
||||||
|
// 1. Priority 1: Mirrored Path Override (Forces NAND)
|
||||||
|
if (Settings::values.mirrored_save_paths.count(program_id)) {
|
||||||
|
LOG_INFO(Service_FS,
|
||||||
|
"Save Path: Mirroring detected for Program ID {:016X}. Forcing use of NAND "
|
||||||
|
"directory for syncing.",
|
||||||
|
program_id);
|
||||||
|
const auto nand_directory =
|
||||||
|
vfs->OpenDirectory(Common::FS::GetCitronPathString(CitronPath::NANDDir), rw_mode);
|
||||||
|
return std::make_shared<FileSys::SaveDataFactory>(system, program_id,
|
||||||
|
std::move(nand_directory));
|
||||||
|
}
|
||||||
|
|
||||||
std::string custom_path_str;
|
std::string custom_path_str;
|
||||||
|
|
||||||
// 1. Priority 1: Global Override
|
|
||||||
if (Settings::values.global_custom_save_path_enabled.GetValue()) {
|
|
||||||
custom_path_str = Settings::values.global_custom_save_path.GetValue();
|
|
||||||
}
|
|
||||||
// 2. Priority 2: Individual Game Override
|
// 2. Priority 2: Individual Game Override
|
||||||
else if (Settings::values.custom_save_paths.count(program_id)) {
|
if (Settings::values.custom_save_paths.count(program_id)) {
|
||||||
custom_path_str = Settings::values.custom_save_paths.at(program_id);
|
custom_path_str = Settings::values.custom_save_paths.at(program_id);
|
||||||
|
LOG_INFO(Service_FS, "Save Path: Using Per-Game Custom Path for Program ID {:016X}: {}",
|
||||||
|
program_id, custom_path_str);
|
||||||
|
}
|
||||||
|
// 3. Priority 3: Global Override
|
||||||
|
else if (Settings::values.global_custom_save_path_enabled.GetValue()) {
|
||||||
|
custom_path_str = Settings::values.global_custom_save_path.GetValue();
|
||||||
|
LOG_INFO(Service_FS, "Save Path: Using Global Custom Save Path: {}", custom_path_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any custom logic is hit, use that path but KEEP NAND as backup target
|
// If any custom logic is hit, use that path but KEEP NAND as backup target
|
||||||
@@ -438,17 +453,21 @@ std::shared_ptr<FileSys::SaveDataFactory> FileSystemController::CreateSaveDataFa
|
|||||||
const std::filesystem::path custom_path = custom_path_str;
|
const std::filesystem::path custom_path = custom_path_str;
|
||||||
if (Common::FS::IsDir(custom_path)) {
|
if (Common::FS::IsDir(custom_path)) {
|
||||||
auto custom_save_directory = vfs->OpenDirectory(custom_path_str, rw_mode);
|
auto custom_save_directory = vfs->OpenDirectory(custom_path_str, rw_mode);
|
||||||
auto nand_directory = vfs->OpenDirectory(Common::FS::GetCitronPathString(CitronPath::NANDDir), rw_mode);
|
auto nand_directory =
|
||||||
|
vfs->OpenDirectory(Common::FS::GetCitronPathString(CitronPath::NANDDir), rw_mode);
|
||||||
|
|
||||||
return std::make_shared<FileSys::SaveDataFactory>(
|
return std::make_shared<FileSys::SaveDataFactory>(
|
||||||
system, program_id, std::move(custom_save_directory), std::move(nand_directory));
|
system, program_id, std::move(custom_save_directory), std::move(nand_directory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Fallback: Standard NAND
|
// 4. Fallback: Standard NAND
|
||||||
const auto nand_directory = vfs->OpenDirectory(Common::FS::GetCitronPathString(CitronPath::NANDDir), rw_mode);
|
LOG_INFO(Service_FS, "Save Path: No custom paths found. Falling back to default NAND.");
|
||||||
return std::make_shared<FileSys::SaveDataFactory>(system, program_id, std::move(nand_directory));
|
const auto nand_directory =
|
||||||
}
|
vfs->OpenDirectory(Common::FS::GetCitronPathString(CitronPath::NANDDir), rw_mode);
|
||||||
|
return std::make_shared<FileSys::SaveDataFactory>(system, program_id,
|
||||||
|
std::move(nand_directory));
|
||||||
|
}
|
||||||
|
|
||||||
Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const {
|
Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const {
|
||||||
LOG_TRACE(Service_FS, "Opening SDMC");
|
LOG_TRACE(Service_FS, "Opening SDMC");
|
||||||
|
|||||||
Reference in New Issue
Block a user