From b555311438ae1e2ad1e9caea55cc9f77c9ed4661 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 25 Aug 2018 11:44:14 -0400 Subject: loader: Add NSP file type and NSP-specific errors --- src/core/loader/loader.cpp | 14 ++++++++++++-- src/core/loader/loader.h | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/core/loader') diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp index 5980cdb25..446adf557 100644 --- a/src/core/loader/loader.cpp +++ b/src/core/loader/loader.cpp @@ -15,6 +15,7 @@ #include "core/loader/nca.h" #include "core/loader/nro.h" #include "core/loader/nso.h" +#include "core/loader/nsp.h" #include "core/loader/xci.h" namespace Loader { @@ -34,6 +35,7 @@ FileType IdentifyFile(FileSys::VirtualFile file) { CHECK_TYPE(NCA) CHECK_TYPE(XCI) CHECK_TYPE(NAX) + CHECK_TYPE(NSP) #undef CHECK_TYPE @@ -59,6 +61,8 @@ FileType GuessFromFilename(const std::string& name) { return FileType::NCA; if (extension == "xci") return FileType::XCI; + if (extension == "nsp") + return FileType::NSP; return FileType::Unknown; } @@ -77,6 +81,8 @@ std::string GetFileTypeString(FileType type) { return "XCI"; case FileType::NAX: return "NAX"; + case FileType::NSP: + return "NSP"; case FileType::DeconstructedRomDirectory: return "Directory"; case FileType::Error: @@ -87,7 +93,7 @@ std::string GetFileTypeString(FileType type) { return "unknown"; } -constexpr std::array RESULT_MESSAGES{ +constexpr std::array RESULT_MESSAGES{ "The operation completed successfully.", "The loader requested to load is already loaded.", "The operation is not implemented.", @@ -137,7 +143,7 @@ constexpr std::array RESULT_MESSAGES{ "The AES Key Generation Source could not be found.", "The SD Save Key Source could not be found.", "The SD NCA Key Source could not be found.", -}; + "The NSP file is missing a Program-type NCA."}; std::ostream& operator<<(std::ostream& os, ResultStatus status) { os << RESULT_MESSAGES.at(static_cast(status)); @@ -182,6 +188,10 @@ static std::unique_ptr GetFileLoader(FileSys::VirtualFile file, FileT case FileType::NAX: return std::make_unique(std::move(file)); + // NX NSP (Nintendo Submission Package) file format + case FileType::NSP: + return std::make_unique(std::move(file)); + // NX deconstructed ROM directory. case FileType::DeconstructedRomDirectory: return std::make_unique(std::move(file)); diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index 5a8540b0e..be66b2257 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -29,6 +29,7 @@ enum class FileType { NSO, NRO, NCA, + NSP, XCI, NAX, DeconstructedRomDirectory, @@ -105,6 +106,7 @@ enum class ResultStatus : u16 { ErrorMissingAESKeyGenerationSource, ErrorMissingSDSaveKeySource, ErrorMissingSDNCAKeySource, + ErrorNSPMissingProgramNCA, }; std::ostream& operator<<(std::ostream& os, ResultStatus status); -- cgit v1.2.3 From a040929c90055b520d52fc062b297578ab119800 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 25 Aug 2018 11:44:52 -0400 Subject: drd: Load title ID from program metadata Previously only loaded from control metadata --- src/core/loader/deconstructed_rom_directory.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/core/loader') diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 921b899e2..1ae4bb656 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -61,7 +61,6 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys if (nacp_file != nullptr) { FileSys::NACP nacp(nacp_file); - title_id = nacp.GetTitleId(); name = nacp.GetApplicationName(); } } @@ -120,6 +119,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load( } auto& kernel = Core::System::GetInstance().Kernel(); + title_id = metadata.GetTitleID(); process->program_id = metadata.GetTitleID(); process->svc_access_mask.set(); process->resource_limit = @@ -159,8 +159,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadIcon(std::vector& buff } ResultStatus AppLoader_DeconstructedRomDirectory::ReadProgramId(u64& out_program_id) { - if (name.empty()) - return ResultStatus::ErrorNoControl; out_program_id = title_id; return ResultStatus::Success; } -- cgit v1.2.3 From 5c8aff984e47c0f471e9eafd071031bc49ad8efc Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 25 Aug 2018 11:48:23 -0400 Subject: card_image: Parse XCI secure partition with NSP Eliminated duplicate code and adds support for Rev1+ carts --- src/core/loader/xci.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src/core/loader') diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp index 9dc4d1f35..75b998faa 100644 --- a/src/core/loader/xci.cpp +++ b/src/core/loader/xci.cpp @@ -17,8 +17,7 @@ namespace Loader { AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) : AppLoader(file), xci(std::make_unique(file)), - nca_loader(std::make_unique( - xci->GetNCAFileByType(FileSys::NCAContentType::Program))) { + nca_loader(std::make_unique(xci->GetProgramNCAFile())) { if (xci->GetStatus() != ResultStatus::Success) return; const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); @@ -64,11 +63,11 @@ ResultStatus AppLoader_XCI::Load(Kernel::SharedPtr& process) { if (xci->GetProgramNCAStatus() != ResultStatus::Success) return xci->GetProgramNCAStatus(); - const auto nca = xci->GetNCAFileByType(FileSys::NCAContentType::Program); + const auto nca = xci->GetProgramNCA(); if (nca == nullptr && !Core::Crypto::KeyManager::KeyFileExists(false)) return ResultStatus::ErrorMissingProductionKeyFile; - auto result = nca_loader->Load(process); + const auto result = nca_loader->Load(process); if (result != ResultStatus::Success) return result; -- cgit v1.2.3 From d7518cf6e03184a25bffeef5d38257549012b98b Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 25 Aug 2018 11:49:31 -0400 Subject: loader: Add AppLoader for NSP files --- src/core/loader/nsp.cpp | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ src/core/loader/nsp.h | 54 ++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 src/core/loader/nsp.cpp create mode 100644 src/core/loader/nsp.h (limited to 'src/core/loader') diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp new file mode 100644 index 000000000..75d9fc1bc --- /dev/null +++ b/src/core/loader/nsp.cpp @@ -0,0 +1,128 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include + +#include "common/common_types.h" +#include "core/file_sys/card_image.h" +#include "core/file_sys/content_archive.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/registered_cache.h" +#include "core/file_sys/romfs.h" +#include "core/file_sys/submission_package.h" +#include "core/hle/kernel/process.h" +#include "core/loader/deconstructed_rom_directory.h" +#include "core/loader/nca.h" +#include "core/loader/nsp.h" + +namespace Loader { + +AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file) + : AppLoader(file), nsp(std::make_unique(file)), + title_id(nsp->GetProgramTitleID()) { + if (nsp->GetStatus() != ResultStatus::Success) + return; + if (nsp->IsExtractedType()) + return; + const auto control_nca = + nsp->GetNCA(nsp->GetFirstTitleID(), FileSys::ContentRecordType::Control); + if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) + return; + const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS()); + if (romfs == nullptr) + return; + for (const auto& language : FileSys::LANGUAGE_NAMES) { + icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat"); + if (icon_file != nullptr) + break; + } + const auto nacp_raw = romfs->GetFile("control.nacp"); + if (nacp_raw == nullptr) + return; + nacp_file = std::make_shared(nacp_raw); +} + +AppLoader_NSP::~AppLoader_NSP() = default; + +FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) { + FileSys::NSP nsp(file); + + if (nsp.GetStatus() == ResultStatus::Success) { + // Extracted Type case + if (nsp.IsExtractedType() && nsp.GetExeFS() != nullptr && + FileSys::IsDirectoryExeFS(nsp.GetExeFS()) && nsp.GetRomFS() != nullptr) + return FileType::NSP; + + // Non-Ectracted Type case + if (!nsp.IsExtractedType() && + nsp.GetNCA(nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program) != nullptr && + AppLoader_NCA::IdentifyType(nsp.GetNCAFile( + nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program)) == FileType::NCA) + return FileType::NSP; + } + + return FileType::Error; +} + +ResultStatus AppLoader_NSP::Load(Kernel::SharedPtr& process) { + if (is_loaded) { + return ResultStatus::ErrorAlreadyLoaded; + } + + if (nsp->IsExtractedType()) { + secondary_loader = std::make_unique(nsp->GetExeFS()); + } else { + if (title_id == 0) + return ResultStatus::ErrorNSPMissingProgramNCA; + + secondary_loader = std::make_unique( + nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program)); + + if (nsp->GetStatus() != ResultStatus::Success) + return nsp->GetStatus(); + + if (nsp->GetProgramStatus(title_id) != ResultStatus::Success) + return nsp->GetProgramStatus(title_id); + + if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) { + if (!Core::Crypto::KeyManager::KeyFileExists(false)) + return ResultStatus::ErrorMissingProductionKeyFile; + return ResultStatus::ErrorNSPMissingProgramNCA; + } + } + + const auto result = secondary_loader->Load(process); + if (result != ResultStatus::Success) + return result; + + is_loaded = true; + + return ResultStatus::Success; +} + +ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& dir) { + return secondary_loader->ReadRomFS(dir); +} + +ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) { + if (title_id == 0) + return ResultStatus::ErrorNotInitialized; + out_program_id = title_id; + return ResultStatus::Success; +} + +ResultStatus AppLoader_NSP::ReadIcon(std::vector& buffer) { + if (icon_file == nullptr) + return ResultStatus::ErrorNoControl; + buffer = icon_file->ReadAllBytes(); + return ResultStatus::Success; +} + +ResultStatus AppLoader_NSP::ReadTitle(std::string& title) { + if (nacp_file == nullptr) + return ResultStatus::ErrorNoControl; + title = nacp_file->GetApplicationName(); + return ResultStatus::Success; +} +} // namespace Loader diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h new file mode 100644 index 000000000..785feaf37 --- /dev/null +++ b/src/core/loader/nsp.h @@ -0,0 +1,54 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "common/common_types.h" +#include "core/file_sys/vfs.h" +#include "core/loader/loader.h" + +namespace FileSys { +class NACP; +class NSP; +} // namespace FileSys + +namespace Loader { + +class AppLoader_NCA; + +/// Loads an XCI file +class AppLoader_NSP final : public AppLoader { +public: + explicit AppLoader_NSP(FileSys::VirtualFile file); + ~AppLoader_NSP(); + + /** + * Returns the type of the file + * @param file std::shared_ptr open file + * @return FileType found, or FileType::Error if this loader doesn't know it + */ + static FileType IdentifyType(const FileSys::VirtualFile& file); + + FileType GetFileType() override { + return IdentifyType(file); + } + + ResultStatus Load(Kernel::SharedPtr& process) override; + + ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; + ResultStatus ReadProgramId(u64& out_program_id) override; + ResultStatus ReadIcon(std::vector& buffer) override; + ResultStatus ReadTitle(std::string& title) override; + +private: + std::unique_ptr nsp; + std::unique_ptr secondary_loader; + + FileSys::VirtualFile icon_file; + std::shared_ptr nacp_file; + u64 title_id; +}; + +} // namespace Loader -- cgit v1.2.3 From e4e55d064edd71fbf359dec9d6b5efad4f0d6c91 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sat, 25 Aug 2018 22:42:54 -0400 Subject: nsp: Comply with style and performance guidelines --- src/core/loader/nsp.cpp | 11 +++++++++-- src/core/loader/nsp.h | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'src/core/loader') diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index 75d9fc1bc..b59d40052 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp @@ -21,22 +21,27 @@ namespace Loader { AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file) : AppLoader(file), nsp(std::make_unique(file)), title_id(nsp->GetProgramTitleID()) { + if (nsp->GetStatus() != ResultStatus::Success) return; if (nsp->IsExtractedType()) return; + const auto control_nca = nsp->GetNCA(nsp->GetFirstTitleID(), FileSys::ContentRecordType::Control); if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) return; + const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS()); if (romfs == nullptr) return; + for (const auto& language : FileSys::LANGUAGE_NAMES) { icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat"); if (icon_file != nullptr) break; } + const auto nacp_raw = romfs->GetFile("control.nacp"); if (nacp_raw == nullptr) return; @@ -51,15 +56,17 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) { if (nsp.GetStatus() == ResultStatus::Success) { // Extracted Type case if (nsp.IsExtractedType() && nsp.GetExeFS() != nullptr && - FileSys::IsDirectoryExeFS(nsp.GetExeFS()) && nsp.GetRomFS() != nullptr) + FileSys::IsDirectoryExeFS(nsp.GetExeFS()) && nsp.GetRomFS() != nullptr) { return FileType::NSP; + } // Non-Ectracted Type case if (!nsp.IsExtractedType() && nsp.GetNCA(nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program) != nullptr && AppLoader_NCA::IdentifyType(nsp.GetNCAFile( - nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program)) == FileType::NCA) + nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program)) == FileType::NCA) { return FileType::NSP; + } } return FileType::Error; diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h index 785feaf37..7ef810499 100644 --- a/src/core/loader/nsp.h +++ b/src/core/loader/nsp.h @@ -22,7 +22,7 @@ class AppLoader_NCA; class AppLoader_NSP final : public AppLoader { public: explicit AppLoader_NSP(FileSys::VirtualFile file); - ~AppLoader_NSP(); + ~AppLoader_NSP() override; /** * Returns the type of the file -- cgit v1.2.3 From 87be4bc283eee72a51b5e8391147c60671351b80 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 4 Sep 2018 14:44:40 -0400 Subject: main: Only show DRD deprecation warning once --- src/core/loader/nsp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/loader') diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index b59d40052..7c06239f2 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp @@ -8,7 +8,7 @@ #include "core/file_sys/card_image.h" #include "core/file_sys/content_archive.h" #include "core/file_sys/control_metadata.h" -#include "core/file_sys/registered_cache.h" +#include "core/file_sys/nca_metadata.h" #include "core/file_sys/romfs.h" #include "core/file_sys/submission_package.h" #include "core/hle/kernel/process.h" -- cgit v1.2.3