summaryrefslogtreecommitdiff
path: root/src/core/loader
diff options
context:
space:
mode:
authorGravatar bunnei2018-09-05 18:06:11 -0400
committerGravatar GitHub2018-09-05 18:06:11 -0400
commita6ae7654105fe6ec46ff0bcabb714b8447b83899 (patch)
tree0ff4d2396cb0730ec5952181e4e67947b64832ec /src/core/loader
parentMerge pull request #1245 from degasus/optimizations (diff)
parentbktr: Fix bucket overlap error (diff)
downloadyuzu-a6ae7654105fe6ec46ff0bcabb714b8447b83899.tar.gz
yuzu-a6ae7654105fe6ec46ff0bcabb714b8447b83899.tar.xz
yuzu-a6ae7654105fe6ec46ff0bcabb714b8447b83899.zip
Merge pull request #1179 from DarkLordZach/bktr
file_sys: Add support for BKTR format (Game Updates)
Diffstat (limited to 'src/core/loader')
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp42
-rw-r--r--src/core/loader/deconstructed_rom_directory.h8
-rw-r--r--src/core/loader/loader.cpp13
-rw-r--r--src/core/loader/loader.h29
-rw-r--r--src/core/loader/nca.cpp8
-rw-r--r--src/core/loader/nca.h1
-rw-r--r--src/core/loader/nro.cpp5
-rw-r--r--src/core/loader/nro.h1
-rw-r--r--src/core/loader/nsp.cpp20
-rw-r--r--src/core/loader/xci.cpp18
10 files changed, 101 insertions, 44 deletions
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 1ae4bb656..2b8f78136 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -9,6 +9,7 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/file_sys/content_archive.h" 10#include "core/file_sys/content_archive.h"
11#include "core/file_sys/control_metadata.h" 11#include "core/file_sys/control_metadata.h"
12#include "core/file_sys/patch_manager.h"
12#include "core/file_sys/romfs_factory.h" 13#include "core/file_sys/romfs_factory.h"
13#include "core/gdbstub/gdbstub.h" 14#include "core/gdbstub/gdbstub.h"
14#include "core/hle/kernel/kernel.h" 15#include "core/hle/kernel/kernel.h"
@@ -21,10 +22,19 @@
21 22
22namespace Loader { 23namespace Loader {
23 24
24AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_) 25AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_,
25 : AppLoader(std::move(file_)) { 26 bool override_update)
27 : AppLoader(std::move(file_)), override_update(override_update) {
26 const auto dir = file->GetContainingDirectory(); 28 const auto dir = file->GetContainingDirectory();
27 29
30 // Title ID
31 const auto npdm = dir->GetFile("main.npdm");
32 if (npdm != nullptr) {
33 const auto res = metadata.Load(npdm);
34 if (res == ResultStatus::Success)
35 title_id = metadata.GetTitleID();
36 }
37
28 // Icon 38 // Icon
29 FileSys::VirtualFile icon_file = nullptr; 39 FileSys::VirtualFile icon_file = nullptr;
30 for (const auto& language : FileSys::LANGUAGE_NAMES) { 40 for (const auto& language : FileSys::LANGUAGE_NAMES) {
@@ -66,8 +76,9 @@ AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys
66} 76}
67 77
68AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory( 78AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(
69 FileSys::VirtualDir directory) 79 FileSys::VirtualDir directory, bool override_update)
70 : AppLoader(directory->GetFile("main")), dir(std::move(directory)) {} 80 : AppLoader(directory->GetFile("main")), dir(std::move(directory)),
81 override_update(override_update) {}
71 82
72FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& file) { 83FileType AppLoader_DeconstructedRomDirectory::IdentifyType(const FileSys::VirtualFile& file) {
73 if (FileSys::IsDirectoryExeFS(file->GetContainingDirectory())) { 84 if (FileSys::IsDirectoryExeFS(file->GetContainingDirectory())) {
@@ -89,7 +100,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
89 dir = file->GetContainingDirectory(); 100 dir = file->GetContainingDirectory();
90 } 101 }
91 102
92 const FileSys::VirtualFile npdm = dir->GetFile("main.npdm"); 103 // Read meta to determine title ID
104 FileSys::VirtualFile npdm = dir->GetFile("main.npdm");
93 if (npdm == nullptr) 105 if (npdm == nullptr)
94 return ResultStatus::ErrorMissingNPDM; 106 return ResultStatus::ErrorMissingNPDM;
95 107
@@ -97,6 +109,21 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
97 if (result != ResultStatus::Success) { 109 if (result != ResultStatus::Success) {
98 return result; 110 return result;
99 } 111 }
112
113 if (override_update) {
114 const FileSys::PatchManager patch_manager(metadata.GetTitleID());
115 dir = patch_manager.PatchExeFS(dir);
116 }
117
118 // Reread in case PatchExeFS affected the main.npdm
119 npdm = dir->GetFile("main.npdm");
120 if (npdm == nullptr)
121 return ResultStatus::ErrorMissingNPDM;
122
123 ResultStatus result2 = metadata.Load(npdm);
124 if (result2 != ResultStatus::Success) {
125 return result2;
126 }
100 metadata.Print(); 127 metadata.Print();
101 128
102 const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()}; 129 const FileSys::ProgramAddressSpaceType arch_bits{metadata.GetAddressSpaceType()};
@@ -119,7 +146,6 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
119 } 146 }
120 147
121 auto& kernel = Core::System::GetInstance().Kernel(); 148 auto& kernel = Core::System::GetInstance().Kernel();
122 title_id = metadata.GetTitleID();
123 process->program_id = metadata.GetTitleID(); 149 process->program_id = metadata.GetTitleID();
124 process->svc_access_mask.set(); 150 process->svc_access_mask.set();
125 process->resource_limit = 151 process->resource_limit =
@@ -170,4 +196,8 @@ ResultStatus AppLoader_DeconstructedRomDirectory::ReadTitle(std::string& title)
170 return ResultStatus::Success; 196 return ResultStatus::Success;
171} 197}
172 198
199bool AppLoader_DeconstructedRomDirectory::IsRomFSUpdatable() const {
200 return false;
201}
202
173} // namespace Loader 203} // namespace Loader
diff --git a/src/core/loader/deconstructed_rom_directory.h b/src/core/loader/deconstructed_rom_directory.h
index b20804f75..8a0dc1b1e 100644
--- a/src/core/loader/deconstructed_rom_directory.h
+++ b/src/core/loader/deconstructed_rom_directory.h
@@ -20,10 +20,12 @@ namespace Loader {
20 */ 20 */
21class AppLoader_DeconstructedRomDirectory final : public AppLoader { 21class AppLoader_DeconstructedRomDirectory final : public AppLoader {
22public: 22public:
23 explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file); 23 explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile main_file,
24 bool override_update = false);
24 25
25 // Overload to accept exefs directory. Must contain 'main' and 'main.npdm' 26 // Overload to accept exefs directory. Must contain 'main' and 'main.npdm'
26 explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory); 27 explicit AppLoader_DeconstructedRomDirectory(FileSys::VirtualDir directory,
28 bool override_update = false);
27 29
28 /** 30 /**
29 * Returns the type of the file 31 * Returns the type of the file
@@ -42,6 +44,7 @@ public:
42 ResultStatus ReadIcon(std::vector<u8>& buffer) override; 44 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
43 ResultStatus ReadProgramId(u64& out_program_id) override; 45 ResultStatus ReadProgramId(u64& out_program_id) override;
44 ResultStatus ReadTitle(std::string& title) override; 46 ResultStatus ReadTitle(std::string& title) override;
47 bool IsRomFSUpdatable() const override;
45 48
46private: 49private:
47 FileSys::ProgramMetadata metadata; 50 FileSys::ProgramMetadata metadata;
@@ -51,6 +54,7 @@ private:
51 std::vector<u8> icon_data; 54 std::vector<u8> icon_data;
52 std::string name; 55 std::string name;
53 u64 title_id{}; 56 u64 title_id{};
57 bool override_update;
54}; 58};
55 59
56} // namespace Loader 60} // namespace Loader
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index 446adf557..fa43a2650 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -93,7 +93,7 @@ std::string GetFileTypeString(FileType type) {
93 return "unknown"; 93 return "unknown";
94} 94}
95 95
96constexpr std::array<const char*, 50> RESULT_MESSAGES{ 96constexpr std::array<const char*, 58> RESULT_MESSAGES{
97 "The operation completed successfully.", 97 "The operation completed successfully.",
98 "The loader requested to load is already loaded.", 98 "The loader requested to load is already loaded.",
99 "The operation is not implemented.", 99 "The operation is not implemented.",
@@ -143,7 +143,16 @@ constexpr std::array<const char*, 50> RESULT_MESSAGES{
143 "The AES Key Generation Source could not be found.", 143 "The AES Key Generation Source could not be found.",
144 "The SD Save Key Source could not be found.", 144 "The SD Save Key Source could not be found.",
145 "The SD NCA Key Source could not be found.", 145 "The SD NCA Key Source could not be found.",
146 "The NSP file is missing a Program-type NCA."}; 146 "The NSP file is missing a Program-type NCA.",
147 "The BKTR-type NCA has a bad BKTR header.",
148 "The BKTR Subsection entry is not located immediately after the Relocation entry.",
149 "The BKTR Subsection entry is not at the end of the media block.",
150 "The BKTR-type NCA has a bad Relocation block.",
151 "The BKTR-type NCA has a bad Subsection block.",
152 "The BKTR-type NCA has a bad Relocation bucket.",
153 "The BKTR-type NCA has a bad Subsection bucket.",
154 "The BKTR-type NCA is missing the base RomFS.",
155};
147 156
148std::ostream& operator<<(std::ostream& os, ResultStatus status) { 157std::ostream& operator<<(std::ostream& os, ResultStatus status) {
149 os << RESULT_MESSAGES.at(static_cast<size_t>(status)); 158 os << RESULT_MESSAGES.at(static_cast<size_t>(status));
diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h
index be66b2257..843c4bb91 100644
--- a/src/core/loader/loader.h
+++ b/src/core/loader/loader.h
@@ -107,6 +107,14 @@ enum class ResultStatus : u16 {
107 ErrorMissingSDSaveKeySource, 107 ErrorMissingSDSaveKeySource,
108 ErrorMissingSDNCAKeySource, 108 ErrorMissingSDNCAKeySource,
109 ErrorNSPMissingProgramNCA, 109 ErrorNSPMissingProgramNCA,
110 ErrorBadBKTRHeader,
111 ErrorBKTRSubsectionNotAfterRelocation,
112 ErrorBKTRSubsectionNotAtEnd,
113 ErrorBadRelocationBlock,
114 ErrorBadSubsectionBlock,
115 ErrorBadRelocationBuckets,
116 ErrorBadSubsectionBuckets,
117 ErrorMissingBKTRBaseRomFS,
110}; 118};
111 119
112std::ostream& operator<<(std::ostream& os, ResultStatus status); 120std::ostream& operator<<(std::ostream& os, ResultStatus status);
@@ -197,13 +205,22 @@ public:
197 } 205 }
198 206
199 /** 207 /**
200 * Get the update RomFS of the application 208 * Get whether or not updates can be applied to the RomFS.
201 * Since the RomFS can be huge, we return a file reference instead of copying to a buffer 209 * By default, this is true, however for formats where it cannot be guaranteed that the RomFS is
202 * @param file The file containing the RomFS 210 * the base game it should be set to false.
203 * @return ResultStatus result of function 211 * @return bool whether or not updatable.
204 */ 212 */
205 virtual ResultStatus ReadUpdateRomFS(FileSys::VirtualFile& file) { 213 virtual bool IsRomFSUpdatable() const {
206 return ResultStatus::ErrorNotImplemented; 214 return true;
215 }
216
217 /**
218 * Gets the difference between the start of the IVFC header and the start of level 6 (RomFS)
219 * data. Needed for bktr patching.
220 * @return IVFC offset for romfs.
221 */
222 virtual u64 ReadRomFSIVFCOffset() const {
223 return 0;
207 } 224 }
208 225
209 /** 226 /**
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index c036a8a1c..6aaffae59 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -48,7 +48,7 @@ ResultStatus AppLoader_NCA::Load(Kernel::SharedPtr<Kernel::Process>& process) {
48 if (exefs == nullptr) 48 if (exefs == nullptr)
49 return ResultStatus::ErrorNoExeFS; 49 return ResultStatus::ErrorNoExeFS;
50 50
51 directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs); 51 directory_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(exefs, true);
52 52
53 const auto load_result = directory_loader->Load(process); 53 const auto load_result = directory_loader->Load(process);
54 if (load_result != ResultStatus::Success) 54 if (load_result != ResultStatus::Success)
@@ -71,6 +71,12 @@ ResultStatus AppLoader_NCA::ReadRomFS(FileSys::VirtualFile& dir) {
71 return ResultStatus::Success; 71 return ResultStatus::Success;
72} 72}
73 73
74u64 AppLoader_NCA::ReadRomFSIVFCOffset() const {
75 if (nca == nullptr)
76 return 0;
77 return nca->GetBaseIVFCOffset();
78}
79
74ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) { 80ResultStatus AppLoader_NCA::ReadProgramId(u64& out_program_id) {
75 if (nca == nullptr || nca->GetStatus() != ResultStatus::Success) 81 if (nca == nullptr || nca->GetStatus() != ResultStatus::Success)
76 return ResultStatus::ErrorNotInitialized; 82 return ResultStatus::ErrorNotInitialized;
diff --git a/src/core/loader/nca.h b/src/core/loader/nca.h
index 326f84857..10be197c4 100644
--- a/src/core/loader/nca.h
+++ b/src/core/loader/nca.h
@@ -37,6 +37,7 @@ public:
37 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; 37 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
38 38
39 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; 39 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
40 u64 ReadRomFSIVFCOffset() const override;
40 ResultStatus ReadProgramId(u64& out_program_id) override; 41 ResultStatus ReadProgramId(u64& out_program_id) override;
41 42
42private: 43private:
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 77026b850..bb89a9da3 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -232,4 +232,9 @@ ResultStatus AppLoader_NRO::ReadTitle(std::string& title) {
232 title = nacp->GetApplicationName(); 232 title = nacp->GetApplicationName();
233 return ResultStatus::Success; 233 return ResultStatus::Success;
234} 234}
235
236bool AppLoader_NRO::IsRomFSUpdatable() const {
237 return false;
238}
239
235} // namespace Loader 240} // namespace Loader
diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h
index bb01c9e25..96d2de305 100644
--- a/src/core/loader/nro.h
+++ b/src/core/loader/nro.h
@@ -39,6 +39,7 @@ public:
39 ResultStatus ReadProgramId(u64& out_program_id) override; 39 ResultStatus ReadProgramId(u64& out_program_id) override;
40 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override; 40 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
41 ResultStatus ReadTitle(std::string& title) override; 41 ResultStatus ReadTitle(std::string& title) override;
42 bool IsRomFSUpdatable() const override;
42 43
43private: 44private:
44 bool LoadNro(FileSys::VirtualFile file, VAddr load_base); 45 bool LoadNro(FileSys::VirtualFile file, VAddr load_base);
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp
index 7c06239f2..291a9876d 100644
--- a/src/core/loader/nsp.cpp
+++ b/src/core/loader/nsp.cpp
@@ -9,6 +9,8 @@
9#include "core/file_sys/content_archive.h" 9#include "core/file_sys/content_archive.h"
10#include "core/file_sys/control_metadata.h" 10#include "core/file_sys/control_metadata.h"
11#include "core/file_sys/nca_metadata.h" 11#include "core/file_sys/nca_metadata.h"
12#include "core/file_sys/patch_manager.h"
13#include "core/file_sys/registered_cache.h"
12#include "core/file_sys/romfs.h" 14#include "core/file_sys/romfs.h"
13#include "core/file_sys/submission_package.h" 15#include "core/file_sys/submission_package.h"
14#include "core/hle/kernel/process.h" 16#include "core/hle/kernel/process.h"
@@ -28,24 +30,12 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file)
28 return; 30 return;
29 31
30 const auto control_nca = 32 const auto control_nca =
31 nsp->GetNCA(nsp->GetFirstTitleID(), FileSys::ContentRecordType::Control); 33 nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control);
32 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) 34 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
33 return; 35 return;
34 36
35 const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS()); 37 std::tie(nacp_file, icon_file) =
36 if (romfs == nullptr) 38 FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(control_nca);
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} 39}
50 40
51AppLoader_NSP::~AppLoader_NSP() = default; 41AppLoader_NSP::~AppLoader_NSP() = default;
diff --git a/src/core/loader/xci.cpp b/src/core/loader/xci.cpp
index 75b998faa..16509229f 100644
--- a/src/core/loader/xci.cpp
+++ b/src/core/loader/xci.cpp
@@ -8,7 +8,9 @@
8#include "core/file_sys/card_image.h" 8#include "core/file_sys/card_image.h"
9#include "core/file_sys/content_archive.h" 9#include "core/file_sys/content_archive.h"
10#include "core/file_sys/control_metadata.h" 10#include "core/file_sys/control_metadata.h"
11#include "core/file_sys/patch_manager.h"
11#include "core/file_sys/romfs.h" 12#include "core/file_sys/romfs.h"
13#include "core/file_sys/submission_package.h"
12#include "core/hle/kernel/process.h" 14#include "core/hle/kernel/process.h"
13#include "core/loader/nca.h" 15#include "core/loader/nca.h"
14#include "core/loader/xci.h" 16#include "core/loader/xci.h"
@@ -20,21 +22,13 @@ AppLoader_XCI::AppLoader_XCI(FileSys::VirtualFile file)
20 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) { 22 nca_loader(std::make_unique<AppLoader_NCA>(xci->GetProgramNCAFile())) {
21 if (xci->GetStatus() != ResultStatus::Success) 23 if (xci->GetStatus() != ResultStatus::Success)
22 return; 24 return;
25
23 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control); 26 const auto control_nca = xci->GetNCAByType(FileSys::NCAContentType::Control);
24 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) 27 if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success)
25 return; 28 return;
26 const auto romfs = FileSys::ExtractRomFS(control_nca->GetRomFS()); 29
27 if (romfs == nullptr) 30 std::tie(nacp_file, icon_file) =
28 return; 31 FileSys::PatchManager(xci->GetProgramTitleID()).ParseControlNCA(control_nca);
29 for (const auto& language : FileSys::LANGUAGE_NAMES) {
30 icon_file = romfs->GetFile("icon_" + std::string(language) + ".dat");
31 if (icon_file != nullptr)
32 break;
33 }
34 const auto nacp_raw = romfs->GetFile("control.nacp");
35 if (nacp_raw == nullptr)
36 return;
37 nacp_file = std::make_shared<FileSys::NACP>(nacp_raw);
38} 32}
39 33
40AppLoader_XCI::~AppLoader_XCI() = default; 34AppLoader_XCI::~AppLoader_XCI() = default;