summaryrefslogtreecommitdiff
path: root/src/core/loader
diff options
context:
space:
mode:
authorGravatar Feng Chen2021-07-20 13:10:05 +0800
committerGravatar GitHub2021-07-20 01:10:05 -0400
commit07073734ed3785d1dee487f0c898a645fbd5f03c (patch)
treee7c72b615b7a551cc1fb8a6a336bce60e5a0d314 /src/core/loader
parentMerge pull request #6580 from ReinUsesLisp/xfb-radv (diff)
downloadyuzu-07073734ed3785d1dee487f0c898a645fbd5f03c.tar.gz
yuzu-07073734ed3785d1dee487f0c898a645fbd5f03c.tar.xz
yuzu-07073734ed3785d1dee487f0c898a645fbd5f03c.zip
file_sys: Support load game collection (#6582)
Adds support for loading games with multiple programs embedded within such as the Dragon Quest 1+2+3 Collection
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/loader.cpp13
-rw-r--r--src/core/loader/loader.h13
-rw-r--r--src/core/loader/nsp.cpp34
-rw-r--r--src/core/loader/nsp.h4
-rw-r--r--src/core/loader/xci.cpp14
-rw-r--r--src/core/loader/xci.h3
6 files changed, 52 insertions, 29 deletions
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 228dc6389..199e69e89 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -206,7 +206,8 @@ AppLoader::~AppLoader() = default;
206 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type 206 * @return std::unique_ptr<AppLoader> a pointer to a loader object; nullptr for unsupported type
207 */ 207 */
208static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file, 208static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::VirtualFile file,
209 FileType type, std::size_t program_index) { 209 FileType type, u64 program_id,
210 std::size_t program_index) {
210 switch (type) { 211 switch (type) {
211 // Standard ELF file format. 212 // Standard ELF file format.
212 case FileType::ELF: 213 case FileType::ELF:
@@ -227,7 +228,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
227 // NX XCI (nX Card Image) file format. 228 // NX XCI (nX Card Image) file format.
228 case FileType::XCI: 229 case FileType::XCI:
229 return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(), 230 return std::make_unique<AppLoader_XCI>(std::move(file), system.GetFileSystemController(),
230 system.GetContentProvider(), program_index); 231 system.GetContentProvider(), program_id,
232 program_index);
231 233
232 // NX NAX (NintendoAesXts) file format. 234 // NX NAX (NintendoAesXts) file format.
233 case FileType::NAX: 235 case FileType::NAX:
@@ -236,7 +238,8 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
236 // NX NSP (Nintendo Submission Package) file format 238 // NX NSP (Nintendo Submission Package) file format
237 case FileType::NSP: 239 case FileType::NSP:
238 return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(), 240 return std::make_unique<AppLoader_NSP>(std::move(file), system.GetFileSystemController(),
239 system.GetContentProvider(), program_index); 241 system.GetContentProvider(), program_id,
242 program_index);
240 243
241 // NX KIP (Kernel Internal Process) file format 244 // NX KIP (Kernel Internal Process) file format
242 case FileType::KIP: 245 case FileType::KIP:
@@ -252,7 +255,7 @@ static std::unique_ptr<AppLoader> GetFileLoader(Core::System& system, FileSys::V
252} 255}
253 256
254std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, 257std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file,
255 std::size_t program_index) { 258 u64 program_id, std::size_t program_index) {
256 FileType type = IdentifyFile(file); 259 FileType type = IdentifyFile(file);
257 const FileType filename_type = GuessFromFilename(file->GetName()); 260 const FileType filename_type = GuessFromFilename(file->GetName());
258 261
@@ -266,7 +269,7 @@ std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile
266 269
267 LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type)); 270 LOG_DEBUG(Loader, "Loading file {} as {}...", file->GetName(), GetFileTypeString(type));
268 271
269 return GetFileLoader(system, std::move(file), type, program_index); 272 return GetFileLoader(system, std::move(file), type, program_id, program_index);
270} 273}
271 274
272} // namespace Loader 275} // namespace Loader
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index edc8bb257..7b1bac3f7 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -227,6 +227,17 @@ public:
227 } 227 }
228 228
229 /** 229 /**
230 * Get the program ids of the application
231 *
232 * @param[out] out_program_ids Reference to store program ids into
233 *
234 * @return ResultStatus result of function
235 */
236 virtual ResultStatus ReadProgramIds(std::vector<u64>& out_program_ids) {
237 return ResultStatus::ErrorNotImplemented;
238 }
239
240 /**
230 * Get the RomFS of the application 241 * Get the RomFS of the application
231 * Since the RomFS can be huge, we return a file reference instead of copying to a buffer 242 * Since the RomFS can be huge, we return a file reference instead of copying to a buffer
232 * 243 *
@@ -324,6 +335,6 @@ protected:
324 * @return the best loader for this file. 335 * @return the best loader for this file.
325 */ 336 */
326std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file, 337std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile file,
327 std::size_t program_index = 0); 338 u64 program_id = 0, std::size_t program_index = 0);
328 339
329} // namespace Loader 340} // namespace Loader
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index d815a7cd3..8b167ad3c 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -23,10 +23,9 @@ namespace Loader {
23 23
24AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_, 24AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_,
25 const Service::FileSystem::FileSystemController& fsc, 25 const Service::FileSystem::FileSystemController& fsc,
26 const FileSys::ContentProvider& content_provider, 26 const FileSys::ContentProvider& content_provider, u64 program_id,
27 std::size_t program_index) 27 std::size_t program_index)
28 : AppLoader(file_), nsp(std::make_unique<FileSys::NSP>(file_, program_index)), 28 : AppLoader(file_), nsp(std::make_unique<FileSys::NSP>(file_, program_id, program_index)) {
29 title_id(nsp->GetProgramTitleID()) {
30 29
31 if (nsp->GetStatus() != ResultStatus::Success) { 30 if (nsp->GetStatus() != ResultStatus::Success) {
32 return; 31 return;
@@ -46,12 +45,8 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file_,
46 return pm.ParseControlNCA(*control_nca); 45 return pm.ParseControlNCA(*control_nca);
47 }(); 46 }();
48 47
49 if (title_id == 0) {
50 return;
51 }
52
53 secondary_loader = std::make_unique<AppLoader_NCA>( 48 secondary_loader = std::make_unique<AppLoader_NCA>(
54 nsp->GetNCAFile(title_id, FileSys::ContentRecordType::Program)); 49 nsp->GetNCAFile(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Program));
55 } 50 }
56} 51}
57 52
@@ -68,10 +63,11 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& nsp_file) {
68 } 63 }
69 64
70 // Non-Extracted Type case 65 // Non-Extracted Type case
66 const auto program_id = nsp.GetProgramTitleID();
71 if (!nsp.IsExtractedType() && 67 if (!nsp.IsExtractedType() &&
72 nsp.GetNCA(nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program) != nullptr && 68 nsp.GetNCA(program_id, FileSys::ContentRecordType::Program) != nullptr &&
73 AppLoader_NCA::IdentifyType(nsp.GetNCAFile( 69 AppLoader_NCA::IdentifyType(
74 nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program)) == FileType::NCA) { 70 nsp.GetNCAFile(program_id, FileSys::ContentRecordType::Program)) == FileType::NCA) {
75 return FileType::NSP; 71 return FileType::NSP;
76 } 72 }
77 } 73 }
@@ -84,6 +80,8 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S
84 return {ResultStatus::ErrorAlreadyLoaded, {}}; 80 return {ResultStatus::ErrorAlreadyLoaded, {}};
85 } 81 }
86 82
83 const auto title_id = nsp->GetProgramTitleID();
84
87 if (!nsp->IsExtractedType() && title_id == 0) { 85 if (!nsp->IsExtractedType() && title_id == 0) {
88 return {ResultStatus::ErrorNSPMissingProgramNCA, {}}; 86 return {ResultStatus::ErrorNSPMissingProgramNCA, {}};
89 } 87 }
@@ -93,7 +91,7 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::KProcess& process, Core::S
93 return {nsp_status, {}}; 91 return {nsp_status, {}};
94 } 92 }
95 93
96 const auto nsp_program_status = nsp->GetProgramStatus(title_id); 94 const auto nsp_program_status = nsp->GetProgramStatus();
97 if (nsp_program_status != ResultStatus::Success) { 95 if (nsp_program_status != ResultStatus::Success) {
98 return {nsp_program_status, {}}; 96 return {nsp_program_status, {}};
99 } 97 }
@@ -134,8 +132,8 @@ ResultStatus AppLoader_NSP::ReadUpdateRaw(FileSys::VirtualFile& out_file) {
134 return ResultStatus::ErrorNoPackedUpdate; 132 return ResultStatus::ErrorNoPackedUpdate;
135 } 133 }
136 134
137 const auto read = 135 const auto read = nsp->GetNCAFile(FileSys::GetUpdateTitleID(nsp->GetProgramTitleID()),
138 nsp->GetNCAFile(FileSys::GetUpdateTitleID(title_id), FileSys::ContentRecordType::Program); 136 FileSys::ContentRecordType::Program);
139 137
140 if (read == nullptr) { 138 if (read == nullptr) {
141 return ResultStatus::ErrorNoPackedUpdate; 139 return ResultStatus::ErrorNoPackedUpdate;
@@ -151,11 +149,15 @@ ResultStatus AppLoader_NSP::ReadUpdateRaw(FileSys::VirtualFile& out_file) {
151} 149}
152 150
153ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) { 151ResultStatus AppLoader_NSP::ReadProgramId(u64& out_program_id) {
154 if (title_id == 0) { 152 out_program_id = nsp->GetProgramTitleID();
153 if (out_program_id == 0) {
155 return ResultStatus::ErrorNotInitialized; 154 return ResultStatus::ErrorNotInitialized;
156 } 155 }
156 return ResultStatus::Success;
157}
157 158
158 out_program_id = title_id; 159ResultStatus AppLoader_NSP::ReadProgramIds(std::vector<u64>& out_program_ids) {
160 out_program_ids = nsp->GetProgramTitleIDs();
159 return ResultStatus::Success; 161 return ResultStatus::Success;
160} 162}
161 163
diff --git a/src/core/loader/nsp.h b/src/core/loader/nsp.h
index 644c0ff58..50406a92e 100644
--- a/src/core/loader/nsp.h
+++ b/src/core/loader/nsp.h
@@ -28,7 +28,7 @@ class AppLoader_NSP final : public AppLoader {
28public: 28public:
29 explicit AppLoader_NSP(FileSys::VirtualFile file_, 29 explicit AppLoader_NSP(FileSys::VirtualFile file_,
30 const Service::FileSystem::FileSystemController& fsc, 30 const Service::FileSystem::FileSystemController& fsc,
31 const FileSys::ContentProvider& content_provider, 31 const FileSys::ContentProvider& content_provider, u64 program_id,
32 std::size_t program_index); 32 std::size_t program_index);
33 ~AppLoader_NSP() override; 33 ~AppLoader_NSP() override;
34 34
@@ -51,6 +51,7 @@ public:
51 u64 ReadRomFSIVFCOffset() const override; 51 u64 ReadRomFSIVFCOffset() const override;
52 ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override; 52 ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override;
53 ResultStatus ReadProgramId(u64& out_program_id) override; 53 ResultStatus ReadProgramId(u64& out_program_id) override;
54 ResultStatus ReadProgramIds(std::vector<u64>& out_program_ids) override;
54 ResultStatus ReadIcon(std::vector<u8>& buffer) override; 55 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
55 ResultStatus ReadTitle(std::string& title) override; 56 ResultStatus ReadTitle(std::string& title) override;
56 ResultStatus ReadControlData(FileSys::NACP& nacp) override; 57 ResultStatus ReadControlData(FileSys::NACP& nacp) override;
@@ -67,7 +68,6 @@ private:
67 68
68 FileSys::VirtualFile icon_file; 69 FileSys::VirtualFile icon_file;
69 std::unique_ptr<FileSys::NACP> nacp_file; 70 std::unique_ptr<FileSys::NACP> nacp_file;
70 u64 title_id;
71}; 71};
72 72
73} // namespace Loader 73} // namespace Loader
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 635d6ae15..269603eef 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -22,9 +22,9 @@ namespace Loader {
22 22
23AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file_, 23AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file_,
24 const Service::FileSystem::FileSystemController& fsc, 24 const Service::FileSystem::FileSystemController& fsc,
25 const FileSys::ContentProvider& content_provider, 25 const FileSys::ContentProvider& content_provider, u64 program_id,
26 std::size_t program_index) 26 std::size_t program_index)
27 : AppLoader(file_), xci(std::make_unique<FileSys::XCI>(file_, program_index)), 27 : AppLoader(file_), xci(std::make_unique<FileSys::XCI>(file_, program_id, program_index)),
28 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { 28 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) {
29 if (xci->GetStatus() != ResultStatus::Success) { 29 if (xci->GetStatus() != ResultStatus::Success) {
30 return; 30 return;
@@ -121,6 +121,11 @@ ResultStatus AppLoader_XCI::ReadProgramId(u64& out_program_id) {
121 return nca_loader->ReadProgramId(out_program_id); 121 return nca_loader->ReadProgramId(out_program_id);
122} 122}
123 123
124ResultStatus AppLoader_XCI::ReadProgramIds(std::vector<u64>& out_program_ids) {
125 out_program_ids = xci->GetProgramTitleIDs();
126 return ResultStatus::Success;
127}
128
124ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) { 129ResultStatus AppLoader_XCI::ReadIcon(std::vector<u8>& buffer) {
125 if (icon_file == nullptr) { 130 if (icon_file == nullptr) {
126 return ResultStatus::ErrorNoControl; 131 return ResultStatus::ErrorNoControl;
@@ -149,8 +154,9 @@ ResultStatus AppLoader_XCI::ReadControlData(FileSys::NACP& control) {
149} 154}
150 155
151ResultStatus AppLoader_XCI::ReadManualRomFS(FileSys::VirtualFile& out_file) { 156ResultStatus AppLoader_XCI::ReadManualRomFS(FileSys::VirtualFile& out_file) {
152 const auto nca = xci->GetSecurePartitionNSP()->GetNCA(xci->GetProgramTitleID(), 157 const auto nca =
153 FileSys::ContentRecordType::HtmlDocument); 158 xci->GetSecurePartitionNSP()->GetNCA(xci->GetSecurePartitionNSP()->GetProgramTitleID(),
159 FileSys::ContentRecordType::HtmlDocument);
154 if (xci->GetStatus() != ResultStatus::Success || nca == nullptr) { 160 if (xci->GetStatus() != ResultStatus::Success || nca == nullptr) {
155 return ResultStatus::ErrorXCIMissingPartition; 161 return ResultStatus::ErrorXCIMissingPartition;
156 } 162 }
diff --git a/src/core/loader/xci.h b/src/core/loader/xci.h
index 708155c30..30caaf90e 100644
--- a/src/core/loader/xci.h
+++ b/src/core/loader/xci.h
@@ -28,7 +28,7 @@ class AppLoader_XCI final : public AppLoader {
28public: 28public:
29 explicit AppLoader_XCI(FileSys::VirtualFile file_, 29 explicit AppLoader_XCI(FileSys::VirtualFile file_,
30 const Service::FileSystem::FileSystemController& fsc, 30 const Service::FileSystem::FileSystemController& fsc,
31 const FileSys::ContentProvider& content_provider, 31 const FileSys::ContentProvider& content_provider, u64 program_id,
32 std::size_t program_index); 32 std::size_t program_index);
33 ~AppLoader_XCI() override; 33 ~AppLoader_XCI() override;
34 34
@@ -51,6 +51,7 @@ public:
51 u64 ReadRomFSIVFCOffset() const override; 51 u64 ReadRomFSIVFCOffset() const override;
52 ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override; 52 ResultStatus ReadUpdateRaw(FileSys::VirtualFile& out_file) override;
53 ResultStatus ReadProgramId(u64& out_program_id) override; 53 ResultStatus ReadProgramId(u64& out_program_id) override;
54 ResultStatus ReadProgramIds(std::vector<u64>& out_program_ids) override;
54 ResultStatus ReadIcon(std::vector<u8>& buffer) override; 55 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
55 ResultStatus ReadTitle(std::string& title) override; 56 ResultStatus ReadTitle(std::string& title) override;
56 ResultStatus ReadControlData(FileSys::NACP& control) override; 57 ResultStatus ReadControlData(FileSys::NACP& control) override;