diff options
| author | 2018-11-23 23:31:48 -0500 | |
|---|---|---|
| committer | 2018-11-23 23:31:48 -0500 | |
| commit | 67ff974387abed516bdadf780561a51562e77525 (patch) | |
| tree | de6a480bda17727f5ba93f6740a00736c0629af2 /src/core/file_sys | |
| parent | Merge pull request #1769 from ReinUsesLisp/cc (diff) | |
| parent | patch_manager: Show LayeredExeFS patch in add-ons column (diff) | |
| download | yuzu-67ff974387abed516bdadf780561a51562e77525.tar.gz yuzu-67ff974387abed516bdadf780561a51562e77525.tar.xz yuzu-67ff974387abed516bdadf780561a51562e77525.zip | |
Merge pull request #1747 from DarkLordZach/exefs-lfs
patch_manager: Add support for applying LayeredFS patches to ExeFS
Diffstat (limited to 'src/core/file_sys')
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 49 |
1 files changed, 47 insertions, 2 deletions
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp index 8d062eb3e..e8df08724 100644 --- a/src/core/file_sys/patch_manager.cpp +++ b/src/core/file_sys/patch_manager.cpp | |||
| @@ -26,6 +26,11 @@ namespace FileSys { | |||
| 26 | constexpr u64 SINGLE_BYTE_MODULUS = 0x100; | 26 | constexpr u64 SINGLE_BYTE_MODULUS = 0x100; |
| 27 | constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000; | 27 | constexpr u64 DLC_BASE_TITLE_ID_MASK = 0xFFFFFFFFFFFFE000; |
| 28 | 28 | ||
| 29 | constexpr std::array<const char*, 14> EXEFS_FILE_NAMES{ | ||
| 30 | "main", "main.npdm", "rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", | ||
| 31 | "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "subsdk8", "subsdk9", | ||
| 32 | }; | ||
| 33 | |||
| 29 | struct NSOBuildHeader { | 34 | struct NSOBuildHeader { |
| 30 | u32_le magic; | 35 | u32_le magic; |
| 31 | INSERT_PADDING_BYTES(0x3C); | 36 | INSERT_PADDING_BYTES(0x3C); |
| @@ -57,6 +62,15 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { | |||
| 57 | if (exefs == nullptr) | 62 | if (exefs == nullptr) |
| 58 | return exefs; | 63 | return exefs; |
| 59 | 64 | ||
| 65 | if (Settings::values.dump_exefs) { | ||
| 66 | LOG_INFO(Loader, "Dumping ExeFS for title_id={:016X}", title_id); | ||
| 67 | const auto dump_dir = Service::FileSystem::GetModificationDumpRoot(title_id); | ||
| 68 | if (dump_dir != nullptr) { | ||
| 69 | const auto exefs_dir = GetOrCreateDirectoryRelative(dump_dir, "/exefs"); | ||
| 70 | VfsRawCopyD(exefs, exefs_dir); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 60 | const auto installed = Service::FileSystem::GetUnionContents(); | 74 | const auto installed = Service::FileSystem::GetUnionContents(); |
| 61 | 75 | ||
| 62 | // Game Updates | 76 | // Game Updates |
| @@ -70,6 +84,30 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const { | |||
| 70 | exefs = update->GetExeFS(); | 84 | exefs = update->GetExeFS(); |
| 71 | } | 85 | } |
| 72 | 86 | ||
| 87 | // LayeredExeFS | ||
| 88 | const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); | ||
| 89 | if (load_dir != nullptr && load_dir->GetSize() > 0) { | ||
| 90 | auto patch_dirs = load_dir->GetSubdirectories(); | ||
| 91 | std::sort( | ||
| 92 | patch_dirs.begin(), patch_dirs.end(), | ||
| 93 | [](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); }); | ||
| 94 | |||
| 95 | std::vector<VirtualDir> layers; | ||
| 96 | layers.reserve(patch_dirs.size() + 1); | ||
| 97 | for (const auto& subdir : patch_dirs) { | ||
| 98 | auto exefs_dir = subdir->GetSubdirectory("exefs"); | ||
| 99 | if (exefs_dir != nullptr) | ||
| 100 | layers.push_back(std::move(exefs_dir)); | ||
| 101 | } | ||
| 102 | layers.push_back(exefs); | ||
| 103 | |||
| 104 | auto layered = LayeredVfsDirectory::MakeLayeredDirectory(std::move(layers)); | ||
| 105 | if (layered != nullptr) { | ||
| 106 | LOG_INFO(Loader, " ExeFS: LayeredExeFS patches applied successfully"); | ||
| 107 | exefs = std::move(layered); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 73 | return exefs; | 111 | return exefs; |
| 74 | } | 112 | } |
| 75 | 113 | ||
| @@ -314,18 +352,25 @@ std::map<std::string, std::string, std::less<>> PatchManager::GetPatchVersionNam | |||
| 314 | if (IsDirValidAndNonEmpty(exefs_dir)) { | 352 | if (IsDirValidAndNonEmpty(exefs_dir)) { |
| 315 | bool ips = false; | 353 | bool ips = false; |
| 316 | bool ipswitch = false; | 354 | bool ipswitch = false; |
| 355 | bool layeredfs = false; | ||
| 317 | 356 | ||
| 318 | for (const auto& file : exefs_dir->GetFiles()) { | 357 | for (const auto& file : exefs_dir->GetFiles()) { |
| 319 | if (file->GetExtension() == "ips") | 358 | if (file->GetExtension() == "ips") { |
| 320 | ips = true; | 359 | ips = true; |
| 321 | else if (file->GetExtension() == "pchtxt") | 360 | } else if (file->GetExtension() == "pchtxt") { |
| 322 | ipswitch = true; | 361 | ipswitch = true; |
| 362 | } else if (std::find(EXEFS_FILE_NAMES.begin(), EXEFS_FILE_NAMES.end(), | ||
| 363 | file->GetName()) != EXEFS_FILE_NAMES.end()) { | ||
| 364 | layeredfs = true; | ||
| 365 | } | ||
| 323 | } | 366 | } |
| 324 | 367 | ||
| 325 | if (ips) | 368 | if (ips) |
| 326 | AppendCommaIfNotEmpty(types, "IPS"); | 369 | AppendCommaIfNotEmpty(types, "IPS"); |
| 327 | if (ipswitch) | 370 | if (ipswitch) |
| 328 | AppendCommaIfNotEmpty(types, "IPSwitch"); | 371 | AppendCommaIfNotEmpty(types, "IPSwitch"); |
| 372 | if (layeredfs) | ||
| 373 | AppendCommaIfNotEmpty(types, "LayeredExeFS"); | ||
| 329 | } | 374 | } |
| 330 | if (IsDirValidAndNonEmpty(mod->GetSubdirectory("romfs"))) | 375 | if (IsDirValidAndNonEmpty(mod->GetSubdirectory("romfs"))) |
| 331 | AppendCommaIfNotEmpty(types, "LayeredFS"); | 376 | AppendCommaIfNotEmpty(types, "LayeredFS"); |