[android/fs] external content loader + nca/xci patches (#3596)

Foreword: WHY DON'T EVERYBODY USE ONE FOLDER FOR EACH GAME+CONTENTS? AIN'T THIS THE FORMAT GAMES COME WHEN YOU BUE THEM? DO YOU LIVE WITH ALL YOUR FRIENDS AND HAVE A 2ND HOUSE FOR ALL THE CHILDREN?

Nice, i feel better now.

This feat extends Maufeat's work on external content loading. It harmonically additions:
"...also, if in each game folder X, you find a folder Y, and in this folder Y you detect ONLY a single game, then mount all external content for that game found in that folder Y and its subfolders."
Permanent (not toggleable). External Content folders are supported equally.

Also:
-Reworked several routines for preserving single source of truth between android and other systems;
-Fixed the annoying unknown format error for content files, by providing proper format detection.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3596
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
This commit is contained in:
xbzk 2026-03-04 22:51:35 +01:00 committed by crueter
parent c682306788
commit 7f5de6bcd6
No known key found for this signature in database
GPG key ID: 425ACD2D4830EBC6
18 changed files with 477 additions and 424 deletions

View file

@ -4,6 +4,7 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <filesystem>
#include <memory>
#include <string>
#include <utility>
@ -16,14 +17,17 @@
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/card_image.h"
#include "core/file_sys/common_funcs.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/fs_filesystem.h"
#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/file_sys/romfs.h"
#include "core/file_sys/submission_package.h"
#include "core/loader/loader.h"
#include "yuzu/compatibility_list.h"
@ -375,6 +379,12 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
return true;
}
if (target == ScanTarget::PopulateGameList &&
(file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP) &&
!Loader::IsBootableGameContainer(file, file_type)) {
return true;
}
u64 program_id = 0;
const auto res2 = loader->ReadProgramId(program_id);
@ -383,18 +393,10 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
provider->AddEntry(FileSys::TitleType::Application,
FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()),
program_id, file);
} else if (res2 == Loader::ResultStatus::Success &&
} else if (Settings::values.ext_content_from_game_dirs.GetValue() &&
(file_type == Loader::FileType::XCI ||
file_type == Loader::FileType::NSP)) {
const auto nsp = file_type == Loader::FileType::NSP
? std::make_shared<FileSys::NSP>(file)
: FileSys::XCI{file}.GetSecurePartitionNSP();
for (const auto& title : nsp->GetNCAs()) {
for (const auto& entry : title.second) {
provider->AddEntry(entry.first.first, entry.first.second, title.first,
entry.second->GetBaseFile());
}
}
void(provider->AddEntriesFromContainer(file));
}
} else {
std::vector<u64> program_ids;

View file

@ -2019,6 +2019,10 @@ void MainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
return;
}
if (QtCommon::provider->AddEntriesFromContainer(file)) {
return;
}
auto loader = Loader::GetLoader(*QtCommon::system, file);
if (!loader) {
return;
@ -2033,19 +2037,8 @@ void MainWindow::ConfigureFilesystemProvider(const std::string& filepath) {
const auto res2 = loader->ReadProgramId(program_id);
if (res2 == Loader::ResultStatus::Success && file_type == Loader::FileType::NCA) {
QtCommon::provider->AddEntry(FileSys::TitleType::Application,
FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()), program_id,
file);
} else if (res2 == Loader::ResultStatus::Success &&
(file_type == Loader::FileType::XCI || file_type == Loader::FileType::NSP)) {
const auto nsp = file_type == Loader::FileType::NSP
? std::make_shared<FileSys::NSP>(file)
: FileSys::XCI{file}.GetSecurePartitionNSP();
for (const auto& title : nsp->GetNCAs()) {
for (const auto& entry : title.second) {
QtCommon::provider->AddEntry(entry.first.first, entry.first.second, title.first,
entry.second->GetBaseFile());
}
}
FileSys::GetCRTypeFromNCAType(FileSys::NCA{file}.GetType()),
program_id, file);
}
}