diff options
| author | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-02 16:01:57 +0100 |
|---|---|---|
| committer | kraibse <33869366+kraibse@users.noreply.github.com> | 2026-11-02 16:01:57 +0100 |
| commit | b374709aa202d586dd09f81f3389da8d73fea0d7 (patch) | |
| tree | 5c4033d827c517aca9cc73dc497fbb3e81291bf1 /src/core/loader/loader.cpp | |
| parent | 021c9724371e45fa694c9ee3106b9011364d2853 (diff) | |
| parent | ce1b1de6f1beed36958368f89cda466937ff9716 (diff) | |
Merge remote-tracking branch 'origin/nx2' into codex/upstream-loading-hotkeys
Diffstat (limited to 'src/core/loader/loader.cpp')
| -rw-r--r-- | src/core/loader/loader.cpp | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 33a93573cf..839bb4d80b 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -29,6 +29,7 @@ #include "core/loader/nro.h" #include "core/loader/nso.h" #include "core/loader/nsp.h" +#include "core/loader/nup.h" #include "core/loader/xci.h" namespace Loader { @@ -130,6 +131,8 @@ FileType IdentifyFile(FileSys::VirtualFile file) { return *nsp_type; } else if (const auto xci_type = IdentifyFileLoader<AppLoader_XCI>(file)) { return *xci_type; + } else if (const auto nup_type = IdentifyFileLoader<AppLoader_NUP>(file)) { + return *nup_type; } else if (const auto nro_type = IdentifyFileLoader<AppLoader_NRO>(file)) { return *nro_type; } else if (const auto nca_type = IdentifyFileLoader<AppLoader_NCA>(file)) { @@ -150,7 +153,7 @@ FileType IdentifyFile(FileSys::VirtualFile file) { bool IsContainerType(FileType type) { return type == FileType::NSP || type == FileType::NSZ || type == FileType::XCI || - type == FileType::XCZ; + type == FileType::XCZ || type == FileType::NUP; } bool IsBootableGameContainer(FileSys::VirtualFile file, FileType type, u64 program_id, @@ -163,6 +166,24 @@ bool IsBootableGameContainer(FileSys::VirtualFile file, FileType type, u64 progr type = IdentifyFile(file); } + if (type == FileType::NUP) { + FileSys::NupContainer nup{file}; + if (nup.GetStatus() != ResultStatus::Success) { + return false; + } + // A base package boots normally; a standalone update (no base) carries + // a complete patched tree and boots on its own (SPEC section 4.1.2). + if (const auto base = nup.FindBasePackage(); + base.has_value() && nup.GetExeFSDir(*base) != nullptr) { + return true; + } + if (const auto update = nup.FindBestUpdatePackage(); + update.has_value() && nup.GetExeFSDir(*update) != nullptr) { + return true; + } + return false; + } + if (!IsContainerType(type)) { return false; } @@ -190,6 +211,8 @@ FileType GuessFromFilename(const std::string& name) { return FileType::XCZ; else if (extension == "nsp") return FileType::NSP; + else if (extension == "nup") + return FileType::NUP; else if (extension == "nsz") return FileType::NSZ; else if (extension == "kip") @@ -215,6 +238,8 @@ std::string GetFileTypeString(FileType type) { return "NSP"; case FileType::NSZ: return "NSZ"; + case FileType::NUP: + return "NUP"; case FileType::KIP: return "KIP"; case FileType::DeconstructedRomDirectory: @@ -227,7 +252,7 @@ std::string GetFileTypeString(FileType type) { return "unknown"; } -constexpr std::array<const char*, 68> RESULT_MESSAGES{ +constexpr std::array<const char*, 70> RESULT_MESSAGES{ "The operation completed successfully.", "The loader requested to load is already loaded.", "The operation is not implemented.", @@ -296,6 +321,8 @@ constexpr std::array<const char*, 68> RESULT_MESSAGES{ "The INI file contains more than the maximum allowable number of KIP files.", "Integrity verification could not be performed for this file.", "Integrity verification failed.", + "The NUP container is malformed or its TOC hash does not match.", + "The NUP container does not contain a loadable base package.", }; std::string GetResultStatusString(ResultStatus status) { @@ -380,6 +407,10 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V case FileType::KIP: return std::make_unique<AppLoader_KIP>(std::move(file)); + // NUP (NX Package) container format. + case FileType::NUP: + return std::make_unique<AppLoader_NUP>(std::move(file)); + // NX deconstructed ROM directory. case FileType::DeconstructedRomDirectory: return std::make_unique<AppLoader_DeconstructedRomDirectory>(std::move(file)); |
