summaryrefslogtreecommitdiff
path: root/src/core/loader/nsp.cpp
diff options
context:
space:
mode:
authorGravatar Zach Hilman2018-08-25 11:49:31 -0400
committerGravatar Zach Hilman2018-09-04 14:27:33 -0400
commitd7518cf6e03184a25bffeef5d38257549012b98b (patch)
treeb3142546999e57101f120e01b646311ef3dbd948 /src/core/loader/nsp.cpp
parentcard_image: Parse XCI secure partition with NSP (diff)
downloadyuzu-d7518cf6e03184a25bffeef5d38257549012b98b.tar.gz
yuzu-d7518cf6e03184a25bffeef5d38257549012b98b.tar.xz
yuzu-d7518cf6e03184a25bffeef5d38257549012b98b.zip
loader: Add AppLoader for NSP files
Diffstat (limited to 'src/core/loader/nsp.cpp')
-rw-r--r--src/core/loader/nsp.cpp128
1 files changed, 128 insertions, 0 deletions
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 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <vector>
6
7#include "common/common_types.h"
8#include "core/file_sys/card_image.h"
9#include "core/file_sys/content_archive.h"
10#include "core/file_sys/control_metadata.h"
11#include "core/file_sys/registered_cache.h"
12#include "core/file_sys/romfs.h"
13#include "core/file_sys/submission_package.h"
14#include "core/hle/kernel/process.h"
15#include "core/loader/deconstructed_rom_directory.h"
16#include "core/loader/nca.h"
17#include "core/loader/nsp.h"
18
19namespace Loader {
20
21AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file)
22 : AppLoader(file), nsp(std::make_unique<FileSys::NSP>(file)),
23 title_id(nsp->GetProgramTitleID()) {
24 if (nsp->GetStatus() != ResultStatus::Success)
25 return;
26 if (nsp->IsExtractedType())
27 return;
28 const auto control_nca =
29 nsp->GetNCA(nsp->GetFirstTitleID(), FileSys::ContentRecordType::Control);
30 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
31 return;
32 const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS());
33 if (romfs == nullptr)
34 return;
35 for (const auto& language : FileSys::LANGUAGE_NAMES) {
36 icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
37 if (icon_file != nullptr)
38 break;
39 }
40 const auto nacp_raw = romfs->GetFile("control.nacp");
41 if (nacp_raw == nullptr)
42 return;
43 nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
44}
45
46AppLoader_NSP::~AppLoader_NSP() = default;
47
48FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) {
49 FileSys::NSP nsp(file);
50
51 if (nsp.GetStatus() == ResultStatus::Success) {
52 // Extracted Type case
53 if (nsp.IsExtractedType() && nsp.GetExeFS() != nullptr &&
54 FileSys::IsDirectoryExeFS(nsp.GetExeFS()) && nsp.GetRomFS() != nullptr)
55 return FileType::NSP;
56
57 // Non-Ectracted Type case
58 if (!nsp.IsExtractedType() &&
59 nsp.GetNCA(nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program) != nullptr &&
60 AppLoader_NCA::IdentifyType(nsp.GetNCAFile(
61 nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program)) == FileType::NCA)
62 return FileType::NSP;
63 }
64
65 return FileType::Error;
66}
67
68ResultStatus AppLoader_NSP::Load(Kernel::SharedPtr<Kernel::Process>& process) {
69 if (is_loaded) {
70 return ResultStatus::ErrorAlreadyLoaded;
71 }
72
73 if (nsp->IsExtractedType()) {
74 secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS());
75 } else {
76 if (title_id == 0)
77 return ResultStatus::ErrorNSPMissingProgramNCA;
78
79 secondary_loader = std::make_unique<AppLoader_NCA>(
80 nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program));
81
82 if (nsp->GetStatus() != ResultStatus::Success)
83 return nsp->GetStatus();
84
85 if (nsp->GetProgramStatus(title_id) != ResultStatus::Success)
86 return nsp->GetProgramStatus(title_id);
87
88 if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) {
89 if (!Core::Crypto::KeyManager::KeyFileExists(false))
90 return ResultStatus::ErrorMissingProductionKeyFile;
91 return ResultStatus::ErrorNSPMissingProgramNCA;
92 }
93 }
94
95 const auto result = secondary_loader->Load(process);
96 if (result != ResultStatus::Success)
97 return result;
98
99 is_loaded = true;
100
101 return ResultStatus::Success;
102}
103
104ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& dir) {
105 return secondary_loader->ReadRomFS(dir);
106}
107
108ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) {
109 if (title_id == 0)
110 return ResultStatus::ErrorNotInitialized;
111 out_program_id = title_id;
112 return ResultStatus::Success;
113}
114
115ResultStatus AppLoader_NSP::ReadIcon(std::vector<u8>& buffer) {
116 if (icon_file == nullptr)
117 return ResultStatus::ErrorNoControl;
118 buffer = icon_file->ReadAllBytes();
119 return ResultStatus::Success;
120}
121
122ResultStatus AppLoader_NSP::ReadTitle(std::string& title) {
123 if (nacp_file == nullptr)
124 return ResultStatus::ErrorNoControl;
125 title = nacp_file->GetApplicationName();
126 return ResultStatus::Success;
127}
128} // namespace Loader