diff options
Diffstat (limited to 'src/core/loader/nsp.cpp')
-rw-r--r-- | src/core/loader/nsp.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp new file mode 100644 index 000000000..7c06239f2 --- /dev/null +++ b/src/core/loader/nsp.cpp @@ -0,0 +1,135 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <vector> + +#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/nca_metadata.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<FileSys::NSP>(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<FileSys::NACP>(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<Kernel::Process>& process) { + if (is_loaded) { + return ResultStatus::ErrorAlreadyLoaded; + } + + if (nsp->IsExtractedType()) { + secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS()); + } else { + if (title_id == 0) + return ResultStatus::ErrorNSPMissingProgramNCA; + + secondary_loader = std::make_unique<AppLoader_NCA>( + 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<u8>& 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 |