aboutsummaryrefslogtreecommitdiff
path: root/src/core/loader/loader.cpp
diff options
context:
space:
mode:
authorxbzk <xbzk@eden-emu.dev>2026-03-04 22:51:35 +0100
committercrueter <crueter@eden-emu.dev>2026-03-04 22:51:35 +0100
commit7f5de6bcd651f8145e4746c76d0531b6560fd5e4 (patch)
treecaefce3d338f65309db1725ac84257c99c14784e /src/core/loader/loader.cpp
parentc682306788055c57953aea38fdded95a0c6dfc09 (diff)
[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>
Diffstat (limited to 'src/core/loader/loader.cpp')
-rw-r--r--src/core/loader/loader.cpp70
1 files changed, 69 insertions, 1 deletions
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 4379634d03..b4d50227d3 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -9,11 +9,15 @@
#include <ostream>
#include <string>
#include <concepts>
+#include <algorithm>
#include "common/concepts.h"
#include "common/fs/path_util.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/core.h"
+#include "core/file_sys/card_image.h"
+#include "core/file_sys/common_funcs.h"
+#include "core/file_sys/submission_package.h"
#include "core/hle/kernel/k_process.h"
#include "core/loader/deconstructed_rom_directory.h"
#include "core/loader/kip.h"
@@ -37,6 +41,49 @@ std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) {
return std::nullopt;
}
+std::shared_ptr<FileSys::NSP> OpenContainerAsNsp(FileSys::VirtualFile file, FileType type,
+ u64 program_id = 0,
+ std::size_t program_index = 0) {
+ if (!file) {
+ return nullptr;
+ }
+
+ if (type == FileType::NSP) {
+ auto nsp = std::make_shared<FileSys::NSP>(file, program_id, program_index);
+ return nsp->GetStatus() == ResultStatus::Success ? nsp : nullptr;
+ }
+
+ if (type == FileType::XCI) {
+ FileSys::XCI xci{file, program_id, program_index};
+ if (xci.GetStatus() != ResultStatus::Success) {
+ return nullptr;
+ }
+
+ auto secure_nsp = xci.GetSecurePartitionNSP();
+ if (secure_nsp == nullptr || secure_nsp->GetStatus() != ResultStatus::Success) {
+ return nullptr;
+ }
+
+ return secure_nsp;
+ }
+
+ return nullptr;
+}
+
+bool HasApplicationProgramContent(const std::shared_ptr<FileSys::NSP>& nsp) {
+ if (!nsp) {
+ return false;
+ }
+
+ const auto& ncas = nsp->GetNCAs();
+ return std::any_of(ncas.cbegin(), ncas.cend(), [](const auto& title_entry) {
+ const auto& nca_map = title_entry.second;
+ return nca_map.find(
+ {FileSys::TitleType::Application, FileSys::ContentRecordType::Program}) !=
+ nca_map.end();
+ });
+}
+
} // namespace
FileType IdentifyFile(FileSys::VirtualFile file) {
@@ -62,6 +109,27 @@ FileType IdentifyFile(FileSys::VirtualFile file) {
}
}
+bool IsContainerType(FileType type) {
+ return type == FileType::NSP || type == FileType::XCI;
+}
+
+bool IsBootableGameContainer(FileSys::VirtualFile file, FileType type, u64 program_id,
+ std::size_t program_index) {
+ if (!file) {
+ return false;
+ }
+
+ if (type == FileType::Unknown) {
+ type = IdentifyFile(file);
+ }
+
+ if (!IsContainerType(type)) {
+ return false;
+ }
+
+ return HasApplicationProgramContent(OpenContainerAsNsp(file, type, program_id, program_index));
+}
+
FileType GuessFromFilename(const std::string& name) {
if (name == "main")
return FileType::DeconstructedRomDirectory;