summaryrefslogtreecommitdiff
path: root/src/core/loader
diff options
context:
space:
mode:
authorGravatar bunnei2018-09-04 16:20:40 -0400
committerGravatar GitHub2018-09-04 16:20:40 -0400
commitfaa9e066aba320bcd38fd023ee58c6f9e1d3efdd (patch)
treec369b13af5a30698564ee54acbae639be4576482 /src/core/loader
parentMerge pull request #1238 from lioncash/explicit (diff)
parentmain: Only show DRD deprecation warning once (diff)
downloadyuzu-faa9e066aba320bcd38fd023ee58c6f9e1d3efdd.tar.gz
yuzu-faa9e066aba320bcd38fd023ee58c6f9e1d3efdd.tar.xz
yuzu-faa9e066aba320bcd38fd023ee58c6f9e1d3efdd.zip
Merge pull request #1178 from DarkLordZach/nsp
file_sys: Add Nintendo Submissions Package (NSP) file format
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp4
-rw-r--r--src/core/loader/loader.cpp14
-rw-r--r--src/core/loader/loader.h2
-rw-r--r--src/core/loader/nsp.cpp135
-rw-r--r--src/core/loader/nsp.h54
-rw-r--r--src/core/loader/xci.cpp7
6 files changed, 207 insertions, 9 deletions
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
61 61
62 if (nacp_file != nullptr) { 62 if (nacp_file != nullptr) {
63 FileSys::NACP nacp(nacp_file); 63 FileSys::NACP nacp(nacp_file);
64 title_id = nacp.GetTitleId();
65 name = nacp.GetApplicationName(); 64 name = nacp.GetApplicationName();
66 } 65 }
67} 66}
@@ -120,6 +119,7 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
120 } 119 }
121 120
122 auto& kernel = Core::System::GetInstance().Kernel(); 121 auto& kernel = Core::System::GetInstance().Kernel();
122 title_id = metadata.GetTitleID();
123 process->program_id = metadata.GetTitleID(); 123 process->program_id = metadata.GetTitleID();
124 process->svc_access_mask.set(); 124 process->svc_access_mask.set();
125 process->resource_limit = 125 process->resource_limit =
@@ -159,8 +159,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadIcon(std::vector<u8>& buff
159} 159}
160 160
161ResultStatus AppLoader_DeconstructedRomDirectory::ReadProgramId(u64& out_program_id) { 161ResultStatus AppLoader_DeconstructedRomDirectory::ReadProgramId(u64& out_program_id) {
162 if (name.empty())
163 return ResultStatus::ErrorNoControl;
164 out_program_id = title_id; 162 out_program_id = title_id;
165 return ResultStatus::Success; 163 return ResultStatus::Success;
166} 164}
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 @@
15#include "core/loader/nca.h" 15#include "core/loader/nca.h"
16#include "core/loader/nro.h" 16#include "core/loader/nro.h"
17#include "core/loader/nso.h" 17#include "core/loader/nso.h"
18#include "core/loader/nsp.h"
18#include "core/loader/xci.h" 19#include "core/loader/xci.h"
19 20
20namespace Loader { 21namespace Loader {
@@ -34,6 +35,7 @@ FileType IdentifyFile(FileSys::VirtualFile file) {
34 CHECK_TYPE(NCA) 35 CHECK_TYPE(NCA)
35 CHECK_TYPE(XCI) 36 CHECK_TYPE(XCI)
36 CHECK_TYPE(NAX) 37 CHECK_TYPE(NAX)
38 CHECK_TYPE(NSP)
37 39
38#undef CHECK_TYPE 40#undef CHECK_TYPE
39 41
@@ -59,6 +61,8 @@ FileType GuessFromFilename(const std::string& name) {
59 return FileType::NCA; 61 return FileType::NCA;
60 if (extension == "xci") 62 if (extension == "xci")
61 return FileType::XCI; 63 return FileType::XCI;
64 if (extension == "nsp")
65 return FileType::NSP;
62 66
63 return FileType::Unknown; 67 return FileType::Unknown;
64} 68}
@@ -77,6 +81,8 @@ std::string GetFileTypeString(FileType type) {
77 return "XCI"; 81 return "XCI";
78 case FileType::NAX: 82 case FileType::NAX:
79 return "NAX"; 83 return "NAX";
84 case FileType::NSP:
85 return "NSP";
80 case FileType::DeconstructedRomDirectory: 86 case FileType::DeconstructedRomDirectory:
81 return "Directory"; 87 return "Directory";
82 case FileType::Error: 88 case FileType::Error:
@@ -87,7 +93,7 @@ std::string GetFileTypeString(FileType type) {
87 return "unknown"; 93 return "unknown";
88} 94}
89 95
90constexpr std::array<const char*, 49> RESULT_MESSAGES{ 96constexpr std::array<const char*, 50> RESULT_MESSAGES{
91 "The operation completed successfully.", 97 "The operation completed successfully.",
92 "The loader requested to load is already loaded.", 98 "The loader requested to load is already loaded.",
93 "The operation is not implemented.", 99 "The operation is not implemented.",
@@ -137,7 +143,7 @@ constexpr std::array<const char*, 49> RESULT_MESSAGES{
137 "The AES Key Generation Source could not be found.", 143 "The AES Key Generation Source could not be found.",
138 "The SD Save Key Source could not be found.", 144 "The SD Save Key Source could not be found.",
139 "The SD NCA Key Source could not be found.", 145 "The SD NCA Key Source could not be found.",
140}; 146 "The NSP file is missing a Program-type NCA."};
141 147
142std::ostream& operator<<(std::ostream& os, ResultStatus status) { 148std::ostream& operator<<(std::ostream& os, ResultStatus status) {
143 os << RESULT_MESSAGES.at(static_cast<size_t>(status)); 149 os << RESULT_MESSAGES.at(static_cast<size_t>(status));
@@ -182,6 +188,10 @@ static std::unique_ptr<AppLoader> GetFileLoader(FileSys::VirtualFile file, FileT
182 case FileType::NAX: 188 case FileType::NAX:
183 return std::make_unique<AppLoader_NAX>(std::move(file)); 189 return std::make_unique<AppLoader_NAX>(std::move(file));
184 190
191 // NX NSP (Nintendo Submission Package) file format
192 case FileType::NSP:
193 return std::make_unique<AppLoader_NSP>(std::move(file));
194
185 // NX deconstructed ROM directory. 195 // NX deconstructed ROM directory.
186 case FileType::DeconstructedRomDirectory: 196 case FileType::DeconstructedRomDirectory:
187 return std::make_unique<AppLoader_DeconstructedRomDirectory>(std::move(file)); 197 return std::make_unique<AppLoader_DeconstructedRomDirectory>(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 {
29 NSO, 29 NSO,
30 NRO, 30 NRO,
31 NCA, 31 NCA,
32 NSP,
32 XCI, 33 XCI,
33 NAX, 34 NAX,
34 DeconstructedRomDirectory, 35 DeconstructedRomDirectory,
@@ -105,6 +106,7 @@ enum class ResultStatus : u16 {
105 ErrorMissingAESKeyGenerationSource, 106 ErrorMissingAESKeyGenerationSource,
106 ErrorMissingSDSaveKeySource, 107 ErrorMissingSDSaveKeySource,
107 ErrorMissingSDNCAKeySource, 108 ErrorMissingSDNCAKeySource,
109 ErrorNSPMissingProgramNCA,
108}; 110};
109 111
110std::ostream& operator<<(std::ostream& os, ResultStatus status); 112std::ostream& operator<<(std::ostream& os, ResultStatus status);
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
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
new file mode 100644
index 000000000..7ef810499
--- /dev/null
+++ b/src/core/loader/nsp.h
@@ -0,0 +1,54 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include "common/common_types.h"
9#include "core/file_sys/vfs.h"
10#include "core/loader/loader.h"
11
12namespace FileSys {
13class NACP;
14class NSP;
15} // namespace FileSys
16
17namespace Loader {
18
19class AppLoader_NCA;
20
21/// Loads an XCI file
22class AppLoader_NSP final : public AppLoader {
23public:
24 explicit AppLoader_NSP(FileSys::VirtualFile file);
25 ~AppLoader_NSP() override;
26
27 /**
28 * Returns the type of the file
29 * @param file std::shared_ptr<VfsFile> open file
30 * @return FileType found, or FileType::Error if this loader doesn't know it
31 */
32 static FileType IdentifyType(const FileSys::VirtualFile& file);
33
34 FileType GetFileType() override {
35 return IdentifyType(file);
36 }
37
38 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
39
40 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
41 ResultStatus ReadProgramId(u64& out_program_id) override;
42 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
43 ResultStatus ReadTitle(std::string& title) override;
44
45private:
46 std::unique_ptr<FileSys::NSP> nsp;
47 std::unique_ptr<AppLoader> secondary_loader;
48
49 FileSys::VirtualFile icon_file;
50 std::shared_ptr<FileSys::NACP> nacp_file;
51 u64 title_id;
52};
53
54} // namespace 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 {
17 17
18AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file) 18AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
19 : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)), 19 : AppLoader(file), xci(std::make_unique<FileSys::XCI>(file)),
20 nca_loader(std::make_unique<AppLoader_NCA>( 20 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) {
21 xci->GetNCAFileByType(FileSys::NCAContentType::Program))) {
22 if (xci->GetStatus() != ResultStatus::Success) 21 if (xci->GetStatus() != ResultStatus::Success)
23 return; 22 return;
24 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); 23 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
@@ -64,11 +63,11 @@ ResultStatus AppLoader_XCI::Load(Kernel::SharedPtr<Kernel::Process>& process) {
64 if (xci->GetProgramNCAStatus() != ResultStatus::Success) 63 if (xci->GetProgramNCAStatus() != ResultStatus::Success)
65 return xci->GetProgramNCAStatus(); 64 return xci->GetProgramNCAStatus();
66 65
67 const auto nca = xci->GetNCAFileByType(FileSys::NCAContentType::Program); 66 const auto nca = xci->GetProgramNCA();
68 if (nca == nullptr && !Core::Crypto::KeyManager::KeyFileExists(false)) 67 if (nca == nullptr && !Core::Crypto::KeyManager::KeyFileExists(false))
69 return ResultStatus::ErrorMissingProductionKeyFile; 68 return ResultStatus::ErrorMissingProductionKeyFile;
70 69
71 auto result = nca_loader->Load(process); 70 const auto result = nca_loader->Load(process);
72 if (result != ResultStatus::Success) 71 if (result != ResultStatus::Success)
73 return result; 72 return result;
74 73