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.cpp48
1 files changed, 39 insertions, 9 deletions
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 90e23ccc11..92e2e2f602 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -82,23 +82,27 @@ std::shared_ptr<FileSys::NSP> OpenContainerAsNsp(FileSys::VirtualFile file, File
return nullptr;
}
- if (type == FileType::NSP) {
+ if (type == FileType::NSP || type == FileType::NSZ) {
auto nsp = std::make_shared<FileSys::NSP>(file, program_id, program_index);
return nsp->GetStatus() == ResultStatus::Success ? nsp : nullptr;
}
- if (type == FileType::XCI) {
+ if (type == FileType::XCI || type == FileType::XCZ) {
FileSys::XCI xci{file, program_id, program_index};
- if (xci.GetStatus() != ResultStatus::Success) {
- return nullptr;
+ if (xci.GetStatus() == ResultStatus::Success) {
+ auto secure_nsp = xci.GetSecurePartitionNSP();
+ if (secure_nsp != nullptr && secure_nsp->GetStatus() == ResultStatus::Success) {
+ return secure_nsp;
+ }
}
- auto secure_nsp = xci.GetSecurePartitionNSP();
- if (secure_nsp == nullptr || secure_nsp->GetStatus() != ResultStatus::Success) {
- return nullptr;
+ // PFS0-shaped .xcz (NSZ-style container) does not parse as XCI; fall back to NSP.
+ if (type == FileType::XCZ) {
+ auto nsp = std::make_shared<FileSys::NSP>(file, program_id, program_index);
+ return nsp->GetStatus() == ResultStatus::Success ? nsp : nullptr;
}
- return secure_nsp;
+ return nullptr;
}
return nullptr;
@@ -144,7 +148,8 @@ FileType IdentifyFile(FileSys::VirtualFile file) {
}
bool IsContainerType(FileType type) {
- return type == FileType::NSP || type == FileType::XCI;
+ return type == FileType::NSP || type == FileType::NSZ || type == FileType::XCI ||
+ type == FileType::XCZ;
}
bool IsBootableGameContainer(FileSys::VirtualFile file, FileType type, u64 program_id,
@@ -180,8 +185,12 @@ FileType GuessFromFilename(const std::string& name) {
return FileType::NCA;
else if (extension == "xci")
return FileType::XCI;
+ else if (extension == "xcz")
+ return FileType::XCZ;
else if (extension == "nsp")
return FileType::NSP;
+ else if (extension == "nsz")
+ return FileType::NSZ;
else if (extension == "kip")
return FileType::KIP;
return FileType::Unknown;
@@ -197,10 +206,14 @@ std::string GetFileTypeString(FileType type) {
return "NCA";
case FileType::XCI:
return "XCI";
+ case FileType::XCZ:
+ return "XCZ";
case FileType::NAX:
return "NAX";
case FileType::NSP:
return "NSP";
+ case FileType::NSZ:
+ return "NSZ";
case FileType::KIP:
return "KIP";
case FileType::DeconstructedRomDirectory:
@@ -326,12 +339,29 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
system.GetContentProvider(), program_id,
program_index);
+ // NCZ-compressed XCI container. XCI-shaped .xcz goes to the XCI loader, while
+ // PFS0-shaped (NSZ-style) .xcz containers fall back to the NSP loader.
+ case FileType::XCZ: {
+ FileSys::XCI probe{file, program_id, program_index};
+ if (probe.GetStatus() == ResultStatus::Success &&
+ probe.GetSecurePartitionNSP() != nullptr) {
+ return std::make_unique<AppLoader_XCI>(std::move(file),
+ system.GetFileSystemController(),
+ system.GetContentProvider(), program_id,
+ program_index);
+ }
+ return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(),
+ system.GetContentProvider(), program_id,
+ program_index);
+ }
+
// NX NAX (NintendoAesXts) file format.
case FileType::NAX:
return std::make_unique<AppLoader_NAX>(std::move(file));
// NX NSP (Nintendo Submission Package) file format
case FileType::NSP:
+ case FileType::NSZ:
return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(),
system.GetContentProvider(), program_id,
program_index);