aboutsummaryrefslogtreecommitdiff
path: root/src/core/loader/loader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader/loader.cpp')
-rw-r--r--src/core/loader/loader.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 69bfa2e879..90e23ccc11 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -17,6 +17,8 @@
#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/registered_cache.h"
#include "core/file_sys/submission_package.h"
#include "core/hle/kernel/k_process.h"
#include "core/loader/deconstructed_rom_directory.h"
@@ -41,6 +43,38 @@ std::optional<FileType> IdentifyFileLoader(FileSys::VirtualFile file) {
return std::nullopt;
}
+struct IndexedProgram {
+ FileSys::VirtualFile file;
+ u64 program_id;
+ bool update_only;
+};
+
+std::optional<IndexedProgram> ResolveIndexedProgram(Core::System& system, u64 program_id,
+ std::size_t program_index) {
+ if (program_index == 0 || program_id == 0) {
+ return std::nullopt;
+ }
+
+ const auto target_id = FileSys::GetBaseTitleIDWithProgramIndex(program_id, program_index);
+ const auto& provider = system.GetContentProvider();
+
+ if (auto base = provider.GetEntryRaw(target_id, FileSys::ContentRecordType::Program)) {
+ LOG_INFO(Loader, "Program index {} resolved to {:016X}", program_index, target_id);
+ return IndexedProgram{std::move(base), target_id, false};
+ }
+
+ const auto update_id = FileSys::GetUpdateTitleID(target_id);
+ if (auto update = provider.GetEntryRaw(update_id, FileSys::ContentRecordType::Program)) {
+ LOG_INFO(Loader, "Program index {} has no base program, loading it from update {:016X}",
+ program_index, update_id);
+ return IndexedProgram{std::move(update), target_id, true};
+ }
+
+ LOG_WARNING(Loader, "No program NCA for {:016X} (index {}), falling back to the container",
+ target_id, program_index);
+ return std::nullopt;
+}
+
std::shared_ptr<FileSys::NSP> OpenContainerAsNsp(FileSys::VirtualFile file, FileType type,
u64 program_id = 0,
std::size_t program_index = 0) {
@@ -321,6 +355,11 @@ std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile
return nullptr;
}
+ if (const auto indexed = ResolveIndexedProgram(system, program_id, program_index)) {
+ return std::make_unique<AppLoader_NCA>(
+ indexed->file, indexed->update_only ? indexed->program_id : 0);
+ }
+
FileType type = IdentifyFile(file);
const FileType filename_type = GuessFromFilename(file->GetName());