summaryrefslogtreecommitdiff
path: root/src/core/loader/nsp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/loader/nsp.cpp')
-rw-r--r--src/core/loader/nsp.cpp135
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 @@
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/nca_metadata.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
25 if (nsp->GetStatus() != ResultStatus::Success)
26 return;
27 if (nsp->IsExtractedType())
28 return;
29
30 const auto control_nca =
31 nsp->GetNCA(nsp->GetFirstTitleID(), FileSys::ContentRecordType::Control);
32 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
33 return;
34
35 const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS());
36 if (romfs == nullptr)
37 return;
38
39 for (const auto& language : FileSys::LANGUAGE_NAMES) {
40 icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
41 if (icon_file != nullptr)
42 break;
43 }
44
45 const auto nacp_raw = romfs->GetFile("control.nacp");
46 if (nacp_raw == nullptr)
47 return;
48 nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
49}
50
51AppLoader_NSP::~AppLoader_NSP() = default;
52
53FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) {
54 FileSys::NSP nsp(file);
55
56 if (nsp.GetStatus() == ResultStatus::Success) {
57 // Extracted Type case
58 if (nsp.IsExtractedType() && nsp.GetExeFS() != nullptr &&
59 FileSys::IsDirectoryExeFS(nsp.GetExeFS()) && nsp.GetRomFS() != nullptr) {
60 return FileType::NSP;
61 }
62
63 // Non-Ectracted Type case
64 if (!nsp.IsExtractedType() &&
65 nsp.GetNCA(nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program) != nullptr &&
66 AppLoader_NCA::IdentifyType(nsp.GetNCAFile(
67 nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program)) == FileType::NCA) {
68 return FileType::NSP;
69 }
70 }
71
72 return FileType::Error;
73}
74
75ResultStatus AppLoader_NSP::Load(Kernel::SharedPtr<Kernel::Process>& process) {
76 if (is_loaded) {
77 return ResultStatus::ErrorAlreadyLoaded;
78 }
79
80 if (nsp->IsExtractedType()) {
81 secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS());
82 } else {
83 if (title_id == 0)
84 return ResultStatus::ErrorNSPMissingProgramNCA;
85
86 secondary_loader = std::make_unique<AppLoader_NCA>(
87 nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program));
88
89 if (nsp->GetStatus() != ResultStatus::Success)
90 return nsp->GetStatus();
91
92 if (nsp->GetProgramStatus(title_id) != ResultStatus::Success)
93 return nsp->GetProgramStatus(title_id);
94
95 if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) {
96 if (!Core::Crypto::KeyManager::KeyFileExists(false))
97 return ResultStatus::ErrorMissingProductionKeyFile;
98 return ResultStatus::ErrorNSPMissingProgramNCA;
99 }
100 }
101
102 const auto result = secondary_loader->Load(process);
103 if (result != ResultStatus::Success)
104 return result;
105
106 is_loaded = true;
107
108 return ResultStatus::Success;
109}
110
111ResultStatus AppLoader_NSP::ReadRomFS(FileSys::VirtualFile& dir) {
112 return secondary_loader->ReadRomFS(dir);
113}
114
115ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) {
116 if (title_id == 0)
117 return ResultStatus::ErrorNotInitialized;
118 out_program_id = title_id;
119 return ResultStatus::Success;
120}
121
122ResultStatus AppLoader_NSP::ReadIcon(std::vector<u8>& buffer) {
123 if (icon_file == nullptr)
124 return ResultStatus::ErrorNoControl;
125 buffer = icon_file->ReadAllBytes();
126 return ResultStatus::Success;
127}
128
129ResultStatus AppLoader_NSP::ReadTitle(std::string& title) {
130 if (nacp_file == nullptr)
131 return ResultStatus::ErrorNoControl;
132 title = nacp_file->GetApplicationName();
133 return ResultStatus::Success;
134}
135} // namespace Loader