mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #1618 from DarkLordZach/dump-nso
patch_manager: Add support for dumping uncompressed NSOs
This commit is contained in:
		
						commit
						97605e36f7
					
				@ -8,8 +8,9 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace FileSys {
 | 
					namespace FileSys {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_)
 | 
					BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_, VirtualDir dump_root_)
 | 
				
			||||||
    : nand_root(std::move(nand_root_)), load_root(std::move(load_root_)),
 | 
					    : nand_root(std::move(nand_root_)), load_root(std::move(load_root_)),
 | 
				
			||||||
 | 
					      dump_root(std::move(dump_root_)),
 | 
				
			||||||
      sysnand_cache(std::make_unique<RegisteredCache>(
 | 
					      sysnand_cache(std::make_unique<RegisteredCache>(
 | 
				
			||||||
          GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))),
 | 
					          GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))),
 | 
				
			||||||
      usrnand_cache(std::make_unique<RegisteredCache>(
 | 
					      usrnand_cache(std::make_unique<RegisteredCache>(
 | 
				
			||||||
@ -32,4 +33,10 @@ VirtualDir BISFactory::GetModificationLoadRoot(u64 title_id) const {
 | 
				
			|||||||
    return GetOrCreateDirectoryRelative(load_root, fmt::format("/{:016X}", title_id));
 | 
					    return GetOrCreateDirectoryRelative(load_root, fmt::format("/{:016X}", title_id));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					VirtualDir BISFactory::GetModificationDumpRoot(u64 title_id) const {
 | 
				
			||||||
 | 
					    if (title_id == 0)
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					    return GetOrCreateDirectoryRelative(dump_root, fmt::format("/{:016X}", title_id));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace FileSys
 | 
					} // namespace FileSys
 | 
				
			||||||
 | 
				
			|||||||
@ -17,17 +17,19 @@ class RegisteredCache;
 | 
				
			|||||||
/// registered caches.
 | 
					/// registered caches.
 | 
				
			||||||
class BISFactory {
 | 
					class BISFactory {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    explicit BISFactory(VirtualDir nand_root, VirtualDir load_root);
 | 
					    explicit BISFactory(VirtualDir nand_root, VirtualDir load_root, VirtualDir dump_root);
 | 
				
			||||||
    ~BISFactory();
 | 
					    ~BISFactory();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    RegisteredCache* GetSystemNANDContents() const;
 | 
					    RegisteredCache* GetSystemNANDContents() const;
 | 
				
			||||||
    RegisteredCache* GetUserNANDContents() const;
 | 
					    RegisteredCache* GetUserNANDContents() const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    VirtualDir GetModificationLoadRoot(u64 title_id) const;
 | 
					    VirtualDir GetModificationLoadRoot(u64 title_id) const;
 | 
				
			||||||
 | 
					    VirtualDir GetModificationDumpRoot(u64 title_id) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
    VirtualDir nand_root;
 | 
					    VirtualDir nand_root;
 | 
				
			||||||
    VirtualDir load_root;
 | 
					    VirtualDir load_root;
 | 
				
			||||||
 | 
					    VirtualDir dump_root;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::unique_ptr<RegisteredCache> sysnand_cache;
 | 
					    std::unique_ptr<RegisteredCache> sysnand_cache;
 | 
				
			||||||
    std::unique_ptr<RegisteredCache> usrnand_cache;
 | 
					    std::unique_ptr<RegisteredCache> usrnand_cache;
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,7 @@
 | 
				
			|||||||
#include "core/file_sys/vfs_vector.h"
 | 
					#include "core/file_sys/vfs_vector.h"
 | 
				
			||||||
#include "core/hle/service/filesystem/filesystem.h"
 | 
					#include "core/hle/service/filesystem/filesystem.h"
 | 
				
			||||||
#include "core/loader/loader.h"
 | 
					#include "core/loader/loader.h"
 | 
				
			||||||
 | 
					#include "core/settings.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace FileSys {
 | 
					namespace FileSys {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -119,6 +120,18 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const {
 | 
				
			|||||||
    const auto build_id_raw = Common::HexArrayToString(header.build_id);
 | 
					    const auto build_id_raw = Common::HexArrayToString(header.build_id);
 | 
				
			||||||
    const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
 | 
					    const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (Settings::values.dump_nso) {
 | 
				
			||||||
 | 
					        LOG_INFO(Loader, "Dumping NSO for build_id={}, title_id={:016X}", build_id, title_id);
 | 
				
			||||||
 | 
					        const auto dump_dir = Service::FileSystem::GetModificationDumpRoot(title_id);
 | 
				
			||||||
 | 
					        if (dump_dir != nullptr) {
 | 
				
			||||||
 | 
					            const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso");
 | 
				
			||||||
 | 
					            const auto file = nso_dir->CreateFile(fmt::format("{}.nso", build_id));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            file->Resize(nso.size());
 | 
				
			||||||
 | 
					            file->WriteBytes(nso);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LOG_INFO(Loader, "Patching NSO for build_id={}", build_id);
 | 
					    LOG_INFO(Loader, "Patching NSO for build_id={}", build_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id);
 | 
					    const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id);
 | 
				
			||||||
 | 
				
			|||||||
@ -370,6 +370,15 @@ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) {
 | 
				
			|||||||
    return bis_factory->GetModificationLoadRoot(title_id);
 | 
					    return bis_factory->GetModificationLoadRoot(title_id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					FileSys::VirtualDir GetModificationDumpRoot(u64 title_id) {
 | 
				
			||||||
 | 
					    LOG_TRACE(Service_FS, "Opening mod dump root for tid={:016X}", title_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (bis_factory == nullptr)
 | 
				
			||||||
 | 
					        return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return bis_factory->GetModificationDumpRoot(title_id);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
 | 
					void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
 | 
				
			||||||
    if (overwrite) {
 | 
					    if (overwrite) {
 | 
				
			||||||
        bis_factory = nullptr;
 | 
					        bis_factory = nullptr;
 | 
				
			||||||
@ -383,13 +392,21 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
 | 
				
			|||||||
                                          FileSys::Mode::ReadWrite);
 | 
					                                          FileSys::Mode::ReadWrite);
 | 
				
			||||||
    auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
 | 
					    auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
 | 
				
			||||||
                                            FileSys::Mode::ReadWrite);
 | 
					                                            FileSys::Mode::ReadWrite);
 | 
				
			||||||
 | 
					    auto dump_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::DumpDir),
 | 
				
			||||||
 | 
					                                            FileSys::Mode::ReadWrite);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (bis_factory == nullptr)
 | 
					    if (bis_factory == nullptr) {
 | 
				
			||||||
        bis_factory = std::make_unique<FileSys::BISFactory>(nand_directory, load_directory);
 | 
					        bis_factory =
 | 
				
			||||||
    if (save_data_factory == nullptr)
 | 
					            std::make_unique<FileSys::BISFactory>(nand_directory, load_directory, dump_directory);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (save_data_factory == nullptr) {
 | 
				
			||||||
        save_data_factory = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
 | 
					        save_data_factory = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
 | 
				
			||||||
    if (sdmc_factory == nullptr)
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (sdmc_factory == nullptr) {
 | 
				
			||||||
        sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory));
 | 
					        sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) {
 | 
					void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) {
 | 
				
			||||||
 | 
				
			|||||||
@ -55,6 +55,7 @@ FileSys::RegisteredCache* GetUserNANDContents();
 | 
				
			|||||||
FileSys::RegisteredCache* GetSDMCContents();
 | 
					FileSys::RegisteredCache* GetSDMCContents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FileSys::VirtualDir GetModificationLoadRoot(u64 title_id);
 | 
					FileSys::VirtualDir GetModificationLoadRoot(u64 title_id);
 | 
				
			||||||
 | 
					FileSys::VirtualDir GetModificationDumpRoot(u64 title_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
 | 
					// Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
 | 
				
			||||||
// above is called.
 | 
					// above is called.
 | 
				
			||||||
 | 
				
			|||||||
@ -154,7 +154,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(const FileSys::VfsFile& file, VAd
 | 
				
			|||||||
    program_image.resize(image_size);
 | 
					    program_image.resize(image_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Apply patches if necessary
 | 
					    // Apply patches if necessary
 | 
				
			||||||
    if (pm && pm->HasNSOPatch(nso_header.build_id)) {
 | 
					    if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
 | 
				
			||||||
        std::vector<u8> pi_header(program_image.size() + 0x100);
 | 
					        std::vector<u8> pi_header(program_image.size() + 0x100);
 | 
				
			||||||
        std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader));
 | 
					        std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader));
 | 
				
			||||||
        std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size());
 | 
					        std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size());
 | 
				
			||||||
 | 
				
			|||||||
@ -159,6 +159,7 @@ struct Values {
 | 
				
			|||||||
    bool use_gdbstub;
 | 
					    bool use_gdbstub;
 | 
				
			||||||
    u16 gdbstub_port;
 | 
					    u16 gdbstub_port;
 | 
				
			||||||
    std::string program_args;
 | 
					    std::string program_args;
 | 
				
			||||||
 | 
					    bool dump_nso;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // WebService
 | 
					    // WebService
 | 
				
			||||||
    bool enable_telemetry;
 | 
					    bool enable_telemetry;
 | 
				
			||||||
 | 
				
			|||||||
@ -153,6 +153,7 @@ void Config::ReadValues() {
 | 
				
			|||||||
    Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool();
 | 
					    Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool();
 | 
				
			||||||
    Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt();
 | 
					    Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt();
 | 
				
			||||||
    Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString();
 | 
					    Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString();
 | 
				
			||||||
 | 
					    Settings::values.dump_nso = qt_config->value("dump_nso", false).toBool();
 | 
				
			||||||
    qt_config->endGroup();
 | 
					    qt_config->endGroup();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qt_config->beginGroup("WebService");
 | 
					    qt_config->beginGroup("WebService");
 | 
				
			||||||
@ -295,6 +296,7 @@ void Config::SaveValues() {
 | 
				
			|||||||
    qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub);
 | 
					    qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub);
 | 
				
			||||||
    qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port);
 | 
					    qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port);
 | 
				
			||||||
    qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args));
 | 
					    qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args));
 | 
				
			||||||
 | 
					    qt_config->setValue("dump_nso", Settings::values.dump_nso);
 | 
				
			||||||
    qt_config->endGroup();
 | 
					    qt_config->endGroup();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qt_config->beginGroup("WebService");
 | 
					    qt_config->beginGroup("WebService");
 | 
				
			||||||
 | 
				
			|||||||
@ -34,6 +34,7 @@ void ConfigureDebug::setConfiguration() {
 | 
				
			|||||||
    ui->toggle_console->setChecked(UISettings::values.show_console);
 | 
					    ui->toggle_console->setChecked(UISettings::values.show_console);
 | 
				
			||||||
    ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter));
 | 
					    ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter));
 | 
				
			||||||
    ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args));
 | 
					    ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args));
 | 
				
			||||||
 | 
					    ui->dump_decompressed_nso->setChecked(Settings::values.dump_nso);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ConfigureDebug::applyConfiguration() {
 | 
					void ConfigureDebug::applyConfiguration() {
 | 
				
			||||||
@ -42,6 +43,7 @@ void ConfigureDebug::applyConfiguration() {
 | 
				
			|||||||
    UISettings::values.show_console = ui->toggle_console->isChecked();
 | 
					    UISettings::values.show_console = ui->toggle_console->isChecked();
 | 
				
			||||||
    Settings::values.log_filter = ui->log_filter_edit->text().toStdString();
 | 
					    Settings::values.log_filter = ui->log_filter_edit->text().toStdString();
 | 
				
			||||||
    Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
 | 
					    Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
 | 
				
			||||||
 | 
					    Settings::values.dump_nso = ui->dump_decompressed_nso->isChecked();
 | 
				
			||||||
    Debugger::ToggleConsole();
 | 
					    Debugger::ToggleConsole();
 | 
				
			||||||
    Log::Filter filter;
 | 
					    Log::Filter filter;
 | 
				
			||||||
    filter.ParseFilterString(Settings::values.log_filter);
 | 
					    filter.ParseFilterString(Settings::values.log_filter);
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
    <x>0</x>
 | 
					    <x>0</x>
 | 
				
			||||||
    <y>0</y>
 | 
					    <y>0</y>
 | 
				
			||||||
    <width>400</width>
 | 
					    <width>400</width>
 | 
				
			||||||
    <height>300</height>
 | 
					    <height>357</height>
 | 
				
			||||||
   </rect>
 | 
					   </rect>
 | 
				
			||||||
  </property>
 | 
					  </property>
 | 
				
			||||||
  <property name="windowTitle">
 | 
					  <property name="windowTitle">
 | 
				
			||||||
@ -129,6 +129,25 @@
 | 
				
			|||||||
     </layout>
 | 
					     </layout>
 | 
				
			||||||
    </widget>
 | 
					    </widget>
 | 
				
			||||||
   </item>
 | 
					   </item>
 | 
				
			||||||
 | 
					   <item>
 | 
				
			||||||
 | 
					    <widget class="QGroupBox" name="groupBox_4">
 | 
				
			||||||
 | 
					     <property name="title">
 | 
				
			||||||
 | 
					      <string>Dump</string>
 | 
				
			||||||
 | 
					     </property>
 | 
				
			||||||
 | 
					     <layout class="QVBoxLayout" name="verticalLayout_4">
 | 
				
			||||||
 | 
					      <item>
 | 
				
			||||||
 | 
					       <widget class="QCheckBox" name="dump_decompressed_nso">
 | 
				
			||||||
 | 
					        <property name="whatsThis">
 | 
				
			||||||
 | 
					         <string>When checked, any NSO yuzu tries to load or patch will be copied decompressed to the yuzu/dump directory.</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					        <property name="text">
 | 
				
			||||||
 | 
					         <string>Dump Decompressed NSOs</string>
 | 
				
			||||||
 | 
					        </property>
 | 
				
			||||||
 | 
					       </widget>
 | 
				
			||||||
 | 
					      </item>
 | 
				
			||||||
 | 
					     </layout>
 | 
				
			||||||
 | 
					    </widget>
 | 
				
			||||||
 | 
					   </item>
 | 
				
			||||||
   <item>
 | 
					   <item>
 | 
				
			||||||
    <spacer name="verticalSpacer">
 | 
					    <spacer name="verticalSpacer">
 | 
				
			||||||
     <property name="orientation">
 | 
					     <property name="orientation">
 | 
				
			||||||
 | 
				
			|||||||
@ -148,6 +148,7 @@ void Config::ReadValues() {
 | 
				
			|||||||
    Settings::values.gdbstub_port =
 | 
					    Settings::values.gdbstub_port =
 | 
				
			||||||
        static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689));
 | 
					        static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689));
 | 
				
			||||||
    Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", "");
 | 
					    Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", "");
 | 
				
			||||||
 | 
					    Settings::values.dump_nso = sdl2_config->GetBoolean("Debugging", "dump_nso", false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Web Service
 | 
					    // Web Service
 | 
				
			||||||
    Settings::values.enable_telemetry =
 | 
					    Settings::values.enable_telemetry =
 | 
				
			||||||
 | 
				
			|||||||
@ -206,6 +206,8 @@ log_filter = *:Trace
 | 
				
			|||||||
# Port for listening to GDB connections.
 | 
					# Port for listening to GDB connections.
 | 
				
			||||||
use_gdbstub=false
 | 
					use_gdbstub=false
 | 
				
			||||||
gdbstub_port=24689
 | 
					gdbstub_port=24689
 | 
				
			||||||
 | 
					# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
 | 
				
			||||||
 | 
					dump_nso=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[WebService]
 | 
					[WebService]
 | 
				
			||||||
# Whether or not to enable telemetry
 | 
					# Whether or not to enable telemetry
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user