summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/file_sys/bis_factory.cpp9
-rw-r--r--src/core/file_sys/bis_factory.h4
-rw-r--r--src/core/file_sys/patch_manager.cpp13
-rw-r--r--src/core/hle/kernel/thread.cpp48
-rw-r--r--src/core/hle/kernel/thread.h2
-rw-r--r--src/core/hle/service/audio/audren_u.cpp6
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp25
-rw-r--r--src/core/hle/service/filesystem/filesystem.h1
-rw-r--r--src/core/loader/nso.cpp2
-rw-r--r--src/core/settings.h1
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_debug.cpp2
-rw-r--r--src/yuzu/configuration/configure_debug.ui21
-rw-r--r--src/yuzu_cmd/config.cpp1
-rw-r--r--src/yuzu_cmd/default_ini.h2
15 files changed, 91 insertions, 48 deletions
diff --git a/src/core/file_sys/bis_factory.cpp b/src/core/file_sys/bis_factory.cpp
index 76a2b7e86..e29f70b3a 100644
--- a/src/core/file_sys/bis_factory.cpp
+++ b/src/core/file_sys/bis_factory.cpp
@@ -8,8 +8,9 @@
8 8
9namespace FileSys { 9namespace FileSys {
10 10
11BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_) 11BISFactory::BISFactory(VirtualDir nand_root_, VirtualDir load_root_, VirtualDir dump_root_)
12 : nand_root(std::move(nand_root_)), load_root(std::move(load_root_)), 12 : nand_root(std::move(nand_root_)), load_root(std::move(load_root_)),
13 dump_root(std::move(dump_root_)),
13 sysnand_cache(std::make_unique<RegisteredCache>( 14 sysnand_cache(std::make_unique<RegisteredCache>(
14 GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))), 15 GetOrCreateDirectoryRelative(nand_root, "/system/Contents/registered"))),
15 usrnand_cache(std::make_unique<RegisteredCache>( 16 usrnand_cache(std::make_unique<RegisteredCache>(
@@ -32,4 +33,10 @@ VirtualDir BISFactory::GetModificationLoadRoot(u64 title_id) const {
32 return GetOrCreateDirectoryRelative(load_root, fmt::format("/{:016X}", title_id)); 33 return GetOrCreateDirectoryRelative(load_root, fmt::format("/{:016X}", title_id));
33} 34}
34 35
36VirtualDir BISFactory::GetModificationDumpRoot(u64 title_id) const {
37 if (title_id == 0)
38 return nullptr;
39 return GetOrCreateDirectoryRelative(dump_root, fmt::format("/{:016X}", title_id));
40}
41
35} // namespace FileSys 42} // namespace FileSys
diff --git a/src/core/file_sys/bis_factory.h b/src/core/file_sys/bis_factory.h
index 364d309bd..453c11ad2 100644
--- a/src/core/file_sys/bis_factory.h
+++ b/src/core/file_sys/bis_factory.h
@@ -17,17 +17,19 @@ class RegisteredCache;
17/// registered caches. 17/// registered caches.
18class BISFactory { 18class BISFactory {
19public: 19public:
20 explicit BISFactory(VirtualDir nand_root, VirtualDir load_root); 20 explicit BISFactory(VirtualDir nand_root, VirtualDir load_root, VirtualDir dump_root);
21 ~BISFactory(); 21 ~BISFactory();
22 22
23 RegisteredCache* GetSystemNANDContents() const; 23 RegisteredCache* GetSystemNANDContents() const;
24 RegisteredCache* GetUserNANDContents() const; 24 RegisteredCache* GetUserNANDContents() const;
25 25
26 VirtualDir GetModificationLoadRoot(u64 title_id) const; 26 VirtualDir GetModificationLoadRoot(u64 title_id) const;
27 VirtualDir GetModificationDumpRoot(u64 title_id) const;
27 28
28private: 29private:
29 VirtualDir nand_root; 30 VirtualDir nand_root;
30 VirtualDir load_root; 31 VirtualDir load_root;
32 VirtualDir dump_root;
31 33
32 std::unique_ptr<RegisteredCache> sysnand_cache; 34 std::unique_ptr<RegisteredCache> sysnand_cache;
33 std::unique_ptr<RegisteredCache> usrnand_cache; 35 std::unique_ptr<RegisteredCache> usrnand_cache;
diff --git a/src/core/file_sys/patch_manager.cpp b/src/core/file_sys/patch_manager.cpp
index 0c1156989..8d062eb3e 100644
--- a/src/core/file_sys/patch_manager.cpp
+++ b/src/core/file_sys/patch_manager.cpp
@@ -19,6 +19,7 @@
19#include "core/file_sys/vfs_vector.h" 19#include "core/file_sys/vfs_vector.h"
20#include "core/hle/service/filesystem/filesystem.h" 20#include "core/hle/service/filesystem/filesystem.h"
21#include "core/loader/loader.h" 21#include "core/loader/loader.h"
22#include "core/settings.h"
22 23
23namespace FileSys { 24namespace FileSys {
24 25
@@ -119,6 +120,18 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso) const {
119 const auto build_id_raw = Common::HexArrayToString(header.build_id); 120 const auto build_id_raw = Common::HexArrayToString(header.build_id);
120 const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1); 121 const auto build_id = build_id_raw.substr(0, build_id_raw.find_last_not_of('0') + 1);
121 122
123 if (Settings::values.dump_nso) {
124 LOG_INFO(Loader, "Dumping NSO for build_id={}, title_id={:016X}", build_id, title_id);
125 const auto dump_dir = Service::FileSystem::GetModificationDumpRoot(title_id);
126 if (dump_dir != nullptr) {
127 const auto nso_dir = GetOrCreateDirectoryRelative(dump_dir, "/nso");
128 const auto file = nso_dir->CreateFile(fmt::format("{}.nso", build_id));
129
130 file->Resize(nso.size());
131 file->WriteBytes(nso);
132 }
133 }
134
122 LOG_INFO(Loader, "Patching NSO for build_id={}", build_id); 135 LOG_INFO(Loader, "Patching NSO for build_id={}", build_id);
123 136
124 const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id); 137 const auto load_dir = Service::FileSystem::GetModificationLoadRoot(title_id);
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index dd5cd9ced..4ffb76818 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -142,36 +142,7 @@ void Thread::ResumeFromWait() {
142 142
143 status = ThreadStatus::Ready; 143 status = ThreadStatus::Ready;
144 144
145 std::optional<s32> new_processor_id = GetNextProcessorId(affinity_mask); 145 ChangeScheduler();
146 if (!new_processor_id) {
147 new_processor_id = processor_id;
148 }
149 if (ideal_core != -1 &&
150 Core::System::GetInstance().Scheduler(ideal_core).GetCurrentThread() == nullptr) {
151 new_processor_id = ideal_core;
152 }
153
154 ASSERT(*new_processor_id < 4);
155
156 // Add thread to new core's scheduler
157 auto* next_scheduler = &Core::System::GetInstance().Scheduler(*new_processor_id);
158
159 if (*new_processor_id != processor_id) {
160 // Remove thread from previous core's scheduler
161 scheduler->RemoveThread(this);
162 next_scheduler->AddThread(this, current_priority);
163 }
164
165 processor_id = *new_processor_id;
166
167 // If the thread was ready, unschedule from the previous core and schedule on the new core
168 scheduler->UnscheduleThread(this, current_priority);
169 next_scheduler->ScheduleThread(this, current_priority);
170
171 // Change thread's scheduler
172 scheduler = next_scheduler;
173
174 Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
175} 146}
176 147
177/** 148/**
@@ -364,42 +335,45 @@ void Thread::UpdatePriority() {
364void Thread::ChangeCore(u32 core, u64 mask) { 335void Thread::ChangeCore(u32 core, u64 mask) {
365 ideal_core = core; 336 ideal_core = core;
366 affinity_mask = mask; 337 affinity_mask = mask;
338 ChangeScheduler();
339}
367 340
341void Thread::ChangeScheduler() {
368 if (status != ThreadStatus::Ready) { 342 if (status != ThreadStatus::Ready) {
369 return; 343 return;
370 } 344 }
371 345
346 auto& system = Core::System::GetInstance();
372 std::optional<s32> new_processor_id{GetNextProcessorId(affinity_mask)}; 347 std::optional<s32> new_processor_id{GetNextProcessorId(affinity_mask)};
373 348
374 if (!new_processor_id) { 349 if (!new_processor_id) {
375 new_processor_id = processor_id; 350 new_processor_id = processor_id;
376 } 351 }
377 if (ideal_core != -1 && 352 if (ideal_core != -1 && system.Scheduler(ideal_core).GetCurrentThread() == nullptr) {
378 Core::System::GetInstance().Scheduler(ideal_core).GetCurrentThread() == nullptr) {
379 new_processor_id = ideal_core; 353 new_processor_id = ideal_core;
380 } 354 }
381 355
382 ASSERT(*new_processor_id < 4); 356 ASSERT(*new_processor_id < 4);
383 357
384 // Add thread to new core's scheduler 358 // Add thread to new core's scheduler
385 auto* next_scheduler = &Core::System::GetInstance().Scheduler(*new_processor_id); 359 auto& next_scheduler = system.Scheduler(*new_processor_id);
386 360
387 if (*new_processor_id != processor_id) { 361 if (*new_processor_id != processor_id) {
388 // Remove thread from previous core's scheduler 362 // Remove thread from previous core's scheduler
389 scheduler->RemoveThread(this); 363 scheduler->RemoveThread(this);
390 next_scheduler->AddThread(this, current_priority); 364 next_scheduler.AddThread(this, current_priority);
391 } 365 }
392 366
393 processor_id = *new_processor_id; 367 processor_id = *new_processor_id;
394 368
395 // If the thread was ready, unschedule from the previous core and schedule on the new core 369 // If the thread was ready, unschedule from the previous core and schedule on the new core
396 scheduler->UnscheduleThread(this, current_priority); 370 scheduler->UnscheduleThread(this, current_priority);
397 next_scheduler->ScheduleThread(this, current_priority); 371 next_scheduler.ScheduleThread(this, current_priority);
398 372
399 // Change thread's scheduler 373 // Change thread's scheduler
400 scheduler = next_scheduler; 374 scheduler = &next_scheduler;
401 375
402 Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); 376 system.CpuCore(processor_id).PrepareReschedule();
403} 377}
404 378
405bool Thread::AllWaitObjectsReady() { 379bool Thread::AllWaitObjectsReady() {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 4a6e11239..d384d50db 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -374,6 +374,8 @@ private:
374 explicit Thread(KernelCore& kernel); 374 explicit Thread(KernelCore& kernel);
375 ~Thread() override; 375 ~Thread() override;
376 376
377 void ChangeScheduler();
378
377 Core::ARM_Interface::ThreadContext context{}; 379 Core::ARM_Interface::ThreadContext context{};
378 380
379 u32 thread_id = 0; 381 u32 thread_id = 0;
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 35a8bef6c..d3ea57ea7 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -28,13 +28,13 @@ public:
28 {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"}, 28 {1, &IAudioRenderer::GetSampleCount, "GetSampleCount"},
29 {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"}, 29 {2, &IAudioRenderer::GetMixBufferCount, "GetMixBufferCount"},
30 {3, &IAudioRenderer::GetState, "GetState"}, 30 {3, &IAudioRenderer::GetState, "GetState"},
31 {4, &IAudioRenderer::RequestUpdate, "RequestUpdate"}, 31 {4, &IAudioRenderer::RequestUpdateImpl, "RequestUpdate"},
32 {5, &IAudioRenderer::Start, "Start"}, 32 {5, &IAudioRenderer::Start, "Start"},
33 {6, &IAudioRenderer::Stop, "Stop"}, 33 {6, &IAudioRenderer::Stop, "Stop"},
34 {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"}, 34 {7, &IAudioRenderer::QuerySystemEvent, "QuerySystemEvent"},
35 {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"}, 35 {8, &IAudioRenderer::SetRenderingTimeLimit, "SetRenderingTimeLimit"},
36 {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"}, 36 {9, &IAudioRenderer::GetRenderingTimeLimit, "GetRenderingTimeLimit"},
37 {10, nullptr, "RequestUpdateAuto"}, 37 {10, &IAudioRenderer::RequestUpdateImpl, "RequestUpdateAuto"},
38 {11, nullptr, "ExecuteAudioRendererRendering"}, 38 {11, nullptr, "ExecuteAudioRendererRendering"},
39 }; 39 };
40 // clang-format on 40 // clang-format on
@@ -79,7 +79,7 @@ private:
79 LOG_DEBUG(Service_Audio, "called"); 79 LOG_DEBUG(Service_Audio, "called");
80 } 80 }
81 81
82 void RequestUpdate(Kernel::HLERequestContext& ctx) { 82 void RequestUpdateImpl(Kernel::HLERequestContext& ctx) {
83 ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer())); 83 ctx.WriteBuffer(renderer->UpdateAudioRenderer(ctx.ReadBuffer()));
84 IPC::ResponseBuilder rb{ctx, 2}; 84 IPC::ResponseBuilder rb{ctx, 2};
85 rb.Push(RESULT_SUCCESS); 85 rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index ea8fd965a..a92cf7815 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -370,6 +370,15 @@ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) {
370 return bis_factory->GetModificationLoadRoot(title_id); 370 return bis_factory->GetModificationLoadRoot(title_id);
371} 371}
372 372
373FileSys::VirtualDir GetModificationDumpRoot(u64 title_id) {
374 LOG_TRACE(Service_FS, "Opening mod dump root for tid={:016X}", title_id);
375
376 if (bis_factory == nullptr)
377 return nullptr;
378
379 return bis_factory->GetModificationDumpRoot(title_id);
380}
381
373void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) { 382void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
374 if (overwrite) { 383 if (overwrite) {
375 bis_factory = nullptr; 384 bis_factory = nullptr;
@@ -383,13 +392,21 @@ void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
383 FileSys::Mode::ReadWrite); 392 FileSys::Mode::ReadWrite);
384 auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), 393 auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
385 FileSys::Mode::ReadWrite); 394 FileSys::Mode::ReadWrite);
395 auto dump_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::DumpDir),
396 FileSys::Mode::ReadWrite);
386 397
387 if (bis_factory == nullptr) 398 if (bis_factory == nullptr) {
388 bis_factory = std::make_unique<FileSys::BISFactory>(nand_directory, load_directory); 399 bis_factory =
389 if (save_data_factory == nullptr) 400 std::make_unique<FileSys::BISFactory>(nand_directory, load_directory, dump_directory);
401 }
402
403 if (save_data_factory == nullptr) {
390 save_data_factory = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory)); 404 save_data_factory = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
391 if (sdmc_factory == nullptr) 405 }
406
407 if (sdmc_factory == nullptr) {
392 sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory)); 408 sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory));
409 }
393} 410}
394 411
395void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) { 412void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) {
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 2cbb70c87..e38f02869 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -55,6 +55,7 @@ FileSys::RegisteredCache* GetUserNANDContents();
55FileSys::RegisteredCache* GetSDMCContents(); 55FileSys::RegisteredCache* GetSDMCContents();
56 56
57FileSys::VirtualDir GetModificationLoadRoot(u64 title_id); 57FileSys::VirtualDir GetModificationLoadRoot(u64 title_id);
58FileSys::VirtualDir GetModificationDumpRoot(u64 title_id);
58 59
59// Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function 60// Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
60// above is called. 61// above is called.
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index 68efca5c0..aaf006309 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -154,7 +154,7 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(const FileSys::VfsFile& file, VAd
154 program_image.resize(image_size); 154 program_image.resize(image_size);
155 155
156 // Apply patches if necessary 156 // Apply patches if necessary
157 if (pm && pm->HasNSOPatch(nso_header.build_id)) { 157 if (pm && (pm->HasNSOPatch(nso_header.build_id) || Settings::values.dump_nso)) {
158 std::vector<u8> pi_header(program_image.size() + 0x100); 158 std::vector<u8> pi_header(program_image.size() + 0x100);
159 std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader)); 159 std::memcpy(pi_header.data(), &nso_header, sizeof(NsoHeader));
160 std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size()); 160 std::memcpy(pi_header.data() + 0x100, program_image.data(), program_image.size());
diff --git a/src/core/settings.h b/src/core/settings.h
index 84dc5050b..e424479f2 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -159,6 +159,7 @@ struct Values {
159 bool use_gdbstub; 159 bool use_gdbstub;
160 u16 gdbstub_port; 160 u16 gdbstub_port;
161 std::string program_args; 161 std::string program_args;
162 bool dump_nso;
162 163
163 // WebService 164 // WebService
164 bool enable_telemetry; 165 bool enable_telemetry;
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index d3b7fa59d..60606bb33 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -153,6 +153,7 @@ void Config::ReadValues() {
153 Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool(); 153 Settings::values.use_gdbstub = qt_config->value("use_gdbstub", false).toBool();
154 Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt(); 154 Settings::values.gdbstub_port = qt_config->value("gdbstub_port", 24689).toInt();
155 Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString(); 155 Settings::values.program_args = qt_config->value("program_args", "").toString().toStdString();
156 Settings::values.dump_nso = qt_config->value("dump_nso", false).toBool();
156 qt_config->endGroup(); 157 qt_config->endGroup();
157 158
158 qt_config->beginGroup("WebService"); 159 qt_config->beginGroup("WebService");
@@ -295,6 +296,7 @@ void Config::SaveValues() {
295 qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub); 296 qt_config->setValue("use_gdbstub", Settings::values.use_gdbstub);
296 qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port); 297 qt_config->setValue("gdbstub_port", Settings::values.gdbstub_port);
297 qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args)); 298 qt_config->setValue("program_args", QString::fromStdString(Settings::values.program_args));
299 qt_config->setValue("dump_nso", Settings::values.dump_nso);
298 qt_config->endGroup(); 300 qt_config->endGroup();
299 301
300 qt_config->beginGroup("WebService"); 302 qt_config->beginGroup("WebService");
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index 9e765fc93..fd5876b41 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_decompressed_nso->setChecked(Settings::values.dump_nso);
37} 38}
38 39
39void ConfigureDebug::applyConfiguration() { 40void ConfigureDebug::applyConfiguration() {
@@ -42,6 +43,7 @@ void ConfigureDebug::applyConfiguration() {
42 UISettings::values.show_console = ui->toggle_console->isChecked(); 43 UISettings::values.show_console = ui->toggle_console->isChecked();
43 Settings::values.log_filter = ui->log_filter_edit->text().toStdString(); 44 Settings::values.log_filter = ui->log_filter_edit->text().toStdString();
44 Settings::values.program_args = ui->homebrew_args_edit->text().toStdString(); 45 Settings::values.program_args = ui->homebrew_args_edit->text().toStdString();
46 Settings::values.dump_nso = ui->dump_decompressed_nso->isChecked();
45 Debugger::ToggleConsole(); 47 Debugger::ToggleConsole();
46 Log::Filter filter; 48 Log::Filter filter;
47 filter.ParseFilterString(Settings::values.log_filter); 49 filter.ParseFilterString(Settings::values.log_filter);
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index ff4987604..9c5b702f8 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -7,7 +7,7 @@
7 <x>0</x> 7 <x>0</x>
8 <y>0</y> 8 <y>0</y>
9 <width>400</width> 9 <width>400</width>
10 <height>300</height> 10 <height>357</height>
11 </rect> 11 </rect>
12 </property> 12 </property>
13 <property name="windowTitle"> 13 <property name="windowTitle">
@@ -130,6 +130,25 @@
130 </widget> 130 </widget>
131 </item> 131 </item>
132 <item> 132 <item>
133 <widget class="QGroupBox" name="groupBox_4">
134 <property name="title">
135 <string>Dump</string>
136 </property>
137 <layout class="QVBoxLayout" name="verticalLayout_4">
138 <item>
139 <widget class="QCheckBox" name="dump_decompressed_nso">
140 <property name="whatsThis">
141 <string>When checked, any NSO yuzu tries to load or patch will be copied decompressed to the yuzu/dump directory.</string>
142 </property>
143 <property name="text">
144 <string>Dump Decompressed NSOs</string>
145 </property>
146 </widget>
147 </item>
148 </layout>
149 </widget>
150 </item>
151 <item>
133 <spacer name="verticalSpacer"> 152 <spacer name="verticalSpacer">
134 <property name="orientation"> 153 <property name="orientation">
135 <enum>Qt::Vertical</enum> 154 <enum>Qt::Vertical</enum>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index f3134d4cb..9cc409fd5 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -148,6 +148,7 @@ void Config::ReadValues() {
148 Settings::values.gdbstub_port = 148 Settings::values.gdbstub_port =
149 static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); 149 static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689));
150 Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", ""); 150 Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", "");
151 Settings::values.dump_nso = sdl2_config->GetBoolean("Debugging", "dump_nso", false);
151 152
152 // Web Service 153 // Web Service
153 Settings::values.enable_telemetry = 154 Settings::values.enable_telemetry =
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index dd6644d79..ecf625e7b 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.
207use_gdbstub=false 207use_gdbstub=false
208gdbstub_port=24689 208gdbstub_port=24689
209# Determines whether or not yuzu will dump all NSOs it attempts to load while loading them
210dump_nso=false
209 211
210[WebService] 212[WebService]
211# Whether or not to enable telemetry 213# Whether or not to enable telemetry