diff options
| author | 2018-11-23 23:31:48 -0500 | |
|---|---|---|
| committer | 2018-11-23 23:31:48 -0500 | |
| commit | 67ff974387abed516bdadf780561a51562e77525 (patch) | |
| tree | de6a480bda17727f5ba93f6740a00736c0629af2 | |
| 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
| -rw-r--r-- | src/core/file_sys/patch_manager.cpp | 49 | ||||
| -rw-r--r-- | src/core/settings.h | 1 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_debug.ui | 10 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 1 | ||||
| -rw-r--r-- | src/yuzu_cmd/default_ini.h | 2 |
7 files changed, 65 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"); |
diff --git a/src/core/settings.h b/src/core/settings.h index e63134f80..a0c5fd447 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -403,6 +403,7 @@ struct Values { | |||
| 403 | bool use_gdbstub; | 403 | bool use_gdbstub; |
| 404 | u16 gdbstub_port; | 404 | u16 gdbstub_port; |
| 405 | std::string program_args; | 405 | std::string program_args; |
| 406 | bool dump_exefs; | ||
| 406 | bool dump_nso; | 407 | bool dump_nso; |
| 407 | 408 | ||
| 408 | // WebService | 409 | // WebService |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index e24ed5f2b..83ebbd1fe 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -432,6 +432,7 @@ void Config::ReadValues() { | |||
| 432 | Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool(); | 432 | Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool(); |
| 433 | Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt(); | 433 | Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt(); |
| 434 | Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString(); | 434 | Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString(); |
| 435 | Settings::values.dump_exefs = qt_config->value("dump_exefs", false).toBool(); | ||
| 435 | Settings::values.dump_nso = qt_config->value("dump_nso", false).toBool(); | 436 | Settings::values.dump_nso = qt_config->value("dump_nso", false).toBool(); |
| 436 | qt_config->endGroup(); | 437 | qt_config->endGroup(); |
| 437 | 438 | ||
| @@ -638,6 +639,7 @@ void Config::SaveValues() { | |||
| 638 | qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub); | 639 | qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub); |
| 639 | qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port); | 640 | qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port); |
| 640 | qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args)); | 641 | qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args)); |
| 642 | qt_config->setValue("dump_exefs", Settings::values.dump_exefs); | ||
| 641 | qt_config->setValue("dump_nso", Settings::values.dump_nso); | 643 | qt_config->setValue("dump_nso", Settings::values.dump_nso); |
| 642 | qt_config->endGroup(); | 644 | qt_config->endGroup(); |
| 643 | 645 | ||
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index fd5876b41..aa7de7b54 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -34,6 +34,7 @@ void ConfigureDebug::setConfiguration() { | |||
| 34 | ui->toggle_console->setChecked(UISettings::values.show_console); | 34 | ui->toggle_console->setChecked(UISettings::values.show_console); |
| 35 | ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter)); | 35 | ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter)); |
| 36 | ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); | 36 | ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); |
| 37 | ui->dump_exefs->setChecked(Settings::values.dump_exefs); | ||
| 37 | ui->dump_decompressed_nso->setChecked(Settings::values.dump_nso); | 38 | ui->dump_decompressed_nso->setChecked(Settings::values.dump_nso); |
| 38 | } | 39 | } |
| 39 | 40 | ||
| @@ -43,6 +44,7 @@ void ConfigureDebug::applyConfiguration() { | |||
| 43 | UISettings::values.show_console = ui->toggle_console->isChecked(); | 44 | UISettings::values.show_console = ui->toggle_console->isChecked(); |
| 44 | Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); | 45 | Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); |
| 45 | Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); | 46 | Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); |
| 47 | Settings::values.dump_exefs = ui->dump_exefs->isChecked(); | ||
| 46 | Settings::values.dump_nso = ui->dump_decompressed_nso->isChecked(); | 48 | Settings::values.dump_nso = ui->dump_decompressed_nso->isChecked(); |
| 47 | Debugger::ToggleConsole(); | 49 | Debugger::ToggleConsole(); |
| 48 | Log::Filter filter; | 50 | Log::Filter filter; |
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 9c5b702f8..758a92335 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -145,6 +145,16 @@ | |||
| 145 | </property> | 145 | </property> |
| 146 | </widget> | 146 | </widget> |
| 147 | </item> | 147 | </item> |
| 148 | <item> | ||
| 149 | <widget class="QCheckBox" name="dump_exefs"> | ||
| 150 | <property name="whatsThis"> | ||
| 151 | <string>When checked, any game that yuzu loads will have its ExeFS dumped to the yuzu/dump directory.</string> | ||
| 152 | </property> | ||
| 153 | <property name="text"> | ||
| 154 | <string>Dump ExeFS</string> | ||
| 155 | </property> | ||
| 156 | </widget> | ||
| 157 | </item> | ||
| 148 | </layout> | 158 | </layout> |
| 149 | </widget> | 159 | </widget> |
| 150 | </item> | 160 | </item> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index c66353a65..097c1fbe3 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -366,6 +366,7 @@ void Config::ReadValues() { | |||
| 366 | Settings::values.gdbstub_port = | 366 | Settings::values.gdbstub_port = |
| 367 | static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); | 367 | static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); |
| 368 | Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", ""); | 368 | Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", ""); |
| 369 | Settings::values.dump_exefs = sdl2_config->GetBoolean("Debugging", "dump_exefs", false); | ||
| 369 | Settings::values.dump_nso = sdl2_config->GetBoolean("Debugging", "dump_nso", false); | 370 | Settings::values.dump_nso = sdl2_config->GetBoolean("Debugging", "dump_nso", false); |
| 370 | 371 | ||
| 371 | // Web Service | 372 | // Web Service |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index ecf625e7b..d73669f36 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -206,6 +206,8 @@ log_filter = *:Trace | |||
| 206 | # Port for listening to GDB connections. | 206 | # Port for listening to GDB connections. |
| 207 | use_gdbstub=false | 207 | use_gdbstub=false |
| 208 | gdbstub_port=24689 | 208 | gdbstub_port=24689 |
| 209 | # Determines whether or not yuzu will dump the ExeFS of all games it attempts to load while loading them | ||
| 210 | dump_exefs=false | ||
| 209 | # Determines whether or not yuzu will dump all NSOs it attempts to load while loading them | 211 | # Determines whether or not yuzu will dump all NSOs it attempts to load while loading them |
| 210 | dump_nso=false | 212 | dump_nso=false |
| 211 | 213 | ||