summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/settings.cpp1
-rw-r--r--src/common/settings.h1
-rw-r--r--src/core/core.cpp11
-rw-r--r--src/core/device_memory.cpp5
-rw-r--r--src/core/device_memory.h4
-rw-r--r--src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp24
-rw-r--r--src/core/hle/kernel/k_event.cpp14
-rw-r--r--src/core/hle/kernel/k_event.h2
-rw-r--r--src/core/hle/kernel/k_process.cpp11
-rw-r--r--src/core/hle/kernel/k_process.h2
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp19
-rw-r--r--src/core/hle/kernel/k_resource_limit.h3
-rw-r--r--src/core/hle/kernel/kernel.cpp7
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/core/hle/service/kernel_helpers.cpp17
-rw-r--r--src/core/memory.cpp3
-rw-r--r--src/yuzu/configuration/config.cpp2
-rw-r--r--src/yuzu/configuration/configure_general.cpp9
-rw-r--r--src/yuzu/configuration/configure_general.h1
-rw-r--r--src/yuzu/configuration/configure_general.ui7
-rw-r--r--src/yuzu_cmd/config.cpp1
21 files changed, 91 insertions, 55 deletions
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 6964a8273..2810cec15 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -167,6 +167,7 @@ void RestoreGlobalState(bool is_powered_on) {
167 167
168 // Core 168 // Core
169 values.use_multi_core.SetGlobal(true); 169 values.use_multi_core.SetGlobal(true);
170 values.use_extended_memory_layout.SetGlobal(true);
170 171
171 // CPU 172 // CPU
172 values.cpu_accuracy.SetGlobal(true); 173 values.cpu_accuracy.SetGlobal(true);
diff --git a/src/common/settings.h b/src/common/settings.h
index 9bee6e10f..d06b23a14 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -466,6 +466,7 @@ struct Values {
466 466
467 // Core 467 // Core
468 Setting<bool> use_multi_core{true, "use_multi_core"}; 468 Setting<bool> use_multi_core{true, "use_multi_core"};
469 Setting<bool> use_extended_memory_layout{false, "use_extended_memory_layout"};
469 470
470 // Cpu 471 // Cpu
471 RangedSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, 472 RangedSetting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto,
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 3f9a7f44b..b0cfee3ee 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -28,7 +28,9 @@
28#include "core/file_sys/vfs_real.h" 28#include "core/file_sys/vfs_real.h"
29#include "core/hardware_interrupt_manager.h" 29#include "core/hardware_interrupt_manager.h"
30#include "core/hid/hid_core.h" 30#include "core/hid/hid_core.h"
31#include "core/hle/kernel/k_memory_manager.h"
31#include "core/hle/kernel/k_process.h" 32#include "core/hle/kernel/k_process.h"
33#include "core/hle/kernel/k_resource_limit.h"
32#include "core/hle/kernel/k_scheduler.h" 34#include "core/hle/kernel/k_scheduler.h"
33#include "core/hle/kernel/kernel.h" 35#include "core/hle/kernel/kernel.h"
34#include "core/hle/kernel/physical_core.h" 36#include "core/hle/kernel/physical_core.h"
@@ -252,9 +254,16 @@ struct System::Impl {
252 } 254 }
253 255
254 telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider); 256 telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
257
258 // Create a resource limit for the process.
259 const auto physical_memory_size =
260 kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application);
261 auto* resource_limit = Kernel::CreateResourceLimitForProcess(system, physical_memory_size);
262
263 // Create the process.
255 auto main_process = Kernel::KProcess::Create(system.Kernel()); 264 auto main_process = Kernel::KProcess::Create(system.Kernel());
256 ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", 265 ASSERT(Kernel::KProcess::Initialize(main_process, system, "main",
257 Kernel::KProcess::ProcessType::Userland) 266 Kernel::KProcess::ProcessType::Userland, resource_limit)
258 .IsSuccess()); 267 .IsSuccess());
259 const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); 268 const auto [load_result, load_parameters] = app_loader->Load(*main_process, system);
260 if (load_result != Loader::ResultStatus::Success) { 269 if (load_result != Loader::ResultStatus::Success) {
diff --git a/src/core/device_memory.cpp b/src/core/device_memory.cpp
index f19c0515f..e6bc63086 100644
--- a/src/core/device_memory.cpp
+++ b/src/core/device_memory.cpp
@@ -3,10 +3,13 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/device_memory.h" 5#include "core/device_memory.h"
6#include "hle/kernel/board/nintendo/nx/k_system_control.h"
6 7
7namespace Core { 8namespace Core {
8 9
9DeviceMemory::DeviceMemory() : buffer{DramMemoryMap::Size, 1ULL << 39} {} 10DeviceMemory::DeviceMemory()
11 : buffer{Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize(),
12 1ULL << 39} {}
10DeviceMemory::~DeviceMemory() = default; 13DeviceMemory::~DeviceMemory() = default;
11 14
12} // namespace Core 15} // namespace Core
diff --git a/src/core/device_memory.h b/src/core/device_memory.h
index c4d17705f..daeb551ea 100644
--- a/src/core/device_memory.h
+++ b/src/core/device_memory.h
@@ -12,12 +12,8 @@ namespace Core {
12namespace DramMemoryMap { 12namespace DramMemoryMap {
13enum : u64 { 13enum : u64 {
14 Base = 0x80000000ULL, 14 Base = 0x80000000ULL,
15 Size = 0x100000000ULL,
16 End = Base + Size,
17 KernelReserveBase = Base + 0x60000, 15 KernelReserveBase = Base + 0x60000,
18 SlabHeapBase = KernelReserveBase + 0x85000, 16 SlabHeapBase = KernelReserveBase + 0x85000,
19 SlapHeapSize = 0xa21000,
20 SlabHeapEnd = SlabHeapBase + SlapHeapSize,
21}; 17};
22}; // namespace DramMemoryMap 18}; // namespace DramMemoryMap
23 19
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
index 6f335c251..702cacffc 100644
--- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
+++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp
@@ -5,6 +5,7 @@
5#include <random> 5#include <random>
6 6
7#include "common/literals.h" 7#include "common/literals.h"
8#include "common/settings.h"
8 9
9#include "core/hle/kernel/board/nintendo/nx/k_system_control.h" 10#include "core/hle/kernel/board/nintendo/nx/k_system_control.h"
10#include "core/hle/kernel/board/nintendo/nx/secure_monitor.h" 11#include "core/hle/kernel/board/nintendo/nx/secure_monitor.h"
@@ -28,30 +29,13 @@ namespace {
28 29
29using namespace Common::Literals; 30using namespace Common::Literals;
30 31
31u32 GetMemoryModeForInit() {
32 return 0x01;
33}
34
35u32 GetMemorySizeForInit() { 32u32 GetMemorySizeForInit() {
36 return 0; 33 return Settings::values.use_extended_memory_layout ? Smc::MemorySize_6GB : Smc::MemorySize_4GB;
37} 34}
38 35
39Smc::MemoryArrangement GetMemoryArrangeForInit() { 36Smc::MemoryArrangement GetMemoryArrangeForInit() {
40 switch (GetMemoryModeForInit() & 0x3F) { 37 return Settings::values.use_extended_memory_layout ? Smc::MemoryArrangement_6GB
41 case 0x01: 38 : Smc::MemoryArrangement_4GB;
42 default:
43 return Smc::MemoryArrangement_4GB;
44 case 0x02:
45 return Smc::MemoryArrangement_4GBForAppletDev;
46 case 0x03:
47 return Smc::MemoryArrangement_4GBForSystemDev;
48 case 0x11:
49 return Smc::MemoryArrangement_6GB;
50 case 0x12:
51 return Smc::MemoryArrangement_6GBForAppletDev;
52 case 0x21:
53 return Smc::MemoryArrangement_8GB;
54 }
55} 39}
56} // namespace 40} // namespace
57 41
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp
index 0720efece..2e0e8de80 100644
--- a/src/core/hle/kernel/k_event.cpp
+++ b/src/core/hle/kernel/k_event.cpp
@@ -14,7 +14,7 @@ KEvent::KEvent(KernelCore& kernel_)
14 14
15KEvent::~KEvent() = default; 15KEvent::~KEvent() = default;
16 16
17void KEvent::Initialize(std::string&& name_) { 17void KEvent::Initialize(std::string&& name_, KProcess* owner_) {
18 // Increment reference count. 18 // Increment reference count.
19 // Because reference count is one on creation, this will result 19 // Because reference count is one on creation, this will result
20 // in a reference count of two. Thus, when both readable and 20 // in a reference count of two. Thus, when both readable and
@@ -30,10 +30,8 @@ void KEvent::Initialize(std::string&& name_) {
30 writable_event.Initialize(this, name_ + ":Writable"); 30 writable_event.Initialize(this, name_ + ":Writable");
31 31
32 // Set our owner process. 32 // Set our owner process.
33 owner = kernel.CurrentProcess(); 33 owner = owner_;
34 if (owner) { 34 owner->Open();
35 owner->Open();
36 }
37 35
38 // Mark initialized. 36 // Mark initialized.
39 name = std::move(name_); 37 name = std::move(name_);
@@ -47,10 +45,8 @@ void KEvent::Finalize() {
47void KEvent::PostDestroy(uintptr_t arg) { 45void KEvent::PostDestroy(uintptr_t arg) {
48 // Release the event count resource the owner process holds. 46 // Release the event count resource the owner process holds.
49 KProcess* owner = reinterpret_cast<KProcess*>(arg); 47 KProcess* owner = reinterpret_cast<KProcess*>(arg);
50 if (owner) { 48 owner->GetResourceLimit()->Release(LimitableResource::Events, 1);
51 owner->GetResourceLimit()->Release(LimitableResource::Events, 1); 49 owner->Close();
52 owner->Close();
53 }
54} 50}
55 51
56} // namespace Kernel 52} // namespace Kernel
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
index 3d3ec99e2..de9732ddf 100644
--- a/src/core/hle/kernel/k_event.h
+++ b/src/core/hle/kernel/k_event.h
@@ -22,7 +22,7 @@ public:
22 explicit KEvent(KernelCore& kernel_); 22 explicit KEvent(KernelCore& kernel_);
23 ~KEvent() override; 23 ~KEvent() override;
24 24
25 void Initialize(std::string&& name); 25 void Initialize(std::string&& name, KProcess* owner_);
26 26
27 void Finalize() override; 27 void Finalize() override;
28 28
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 85c506979..9233261cd 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -123,12 +123,11 @@ private:
123}; 123};
124 124
125ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name, 125ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::string process_name,
126 ProcessType type) { 126 ProcessType type, KResourceLimit* res_limit) {
127 auto& kernel = system.Kernel(); 127 auto& kernel = system.Kernel();
128 128
129 process->name = std::move(process_name); 129 process->name = std::move(process_name);
130 130 process->resource_limit = res_limit;
131 process->resource_limit = kernel.GetSystemResourceLimit();
132 process->status = ProcessStatus::Created; 131 process->status = ProcessStatus::Created;
133 process->program_id = 0; 132 process->program_id = 0;
134 process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID() 133 process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
@@ -143,9 +142,6 @@ ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::st
143 142
144 kernel.AppendNewProcess(process); 143 kernel.AppendNewProcess(process);
145 144
146 // Open a reference to the resource limit.
147 process->resource_limit->Open();
148
149 // Clear remaining fields. 145 // Clear remaining fields.
150 process->num_running_threads = 0; 146 process->num_running_threads = 0;
151 process->is_signaled = false; 147 process->is_signaled = false;
@@ -153,6 +149,9 @@ ResultCode KProcess::Initialize(KProcess* process, Core::System& system, std::st
153 process->is_suspended = false; 149 process->is_suspended = false;
154 process->schedule_count = 0; 150 process->schedule_count = 0;
155 151
152 // Open a reference to the resource limit.
153 process->resource_limit->Open();
154
156 return ResultSuccess; 155 return ResultSuccess;
157} 156}
158 157
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 38b446350..cf1b67428 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -91,7 +91,7 @@ public:
91 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4; 91 static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
92 92
93 static ResultCode Initialize(KProcess* process, Core::System& system, std::string process_name, 93 static ResultCode Initialize(KProcess* process, Core::System& system, std::string process_name,
94 ProcessType type); 94 ProcessType type, KResourceLimit* res_limit);
95 95
96 /// Gets a reference to the process' page table. 96 /// Gets a reference to the process' page table.
97 KPageTable& PageTable() { 97 KPageTable& PageTable() {
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index 0c4bba66b..a84977c68 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/core.h"
6#include "core/core_timing.h" 7#include "core/core_timing.h"
7#include "core/hle/kernel/k_resource_limit.h" 8#include "core/hle/kernel/k_resource_limit.h"
8#include "core/hle/kernel/svc_results.h" 9#include "core/hle/kernel/svc_results.h"
@@ -151,4 +152,22 @@ void KResourceLimit::Release(LimitableResource which, s64 value, s64 hint) {
151 } 152 }
152} 153}
153 154
155KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size) {
156 auto* resource_limit = KResourceLimit::Create(system.Kernel());
157 resource_limit->Initialize(&system.CoreTiming());
158
159 // Initialize default resource limit values.
160 // TODO(bunnei): These values are the system defaults, the limits for service processes are
161 // lower. These should use the correct limit values.
162
163 ASSERT(resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, physical_memory_size)
164 .IsSuccess());
165 ASSERT(resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
166 ASSERT(resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess());
167 ASSERT(resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200).IsSuccess());
168 ASSERT(resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess());
169
170 return resource_limit;
171}
172
154} // namespace Kernel 173} // namespace Kernel
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index fab6005ff..d23d16aa4 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -67,4 +67,7 @@ private:
67 KLightConditionVariable cond_var; 67 KLightConditionVariable cond_var;
68 const Core::Timing::CoreTiming* core_timing{}; 68 const Core::Timing::CoreTiming* core_timing{};
69}; 69};
70
71KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical_memory_size);
72
70} // namespace Kernel 73} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 49c0714ed..797f47021 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -240,13 +240,6 @@ struct KernelCore::Impl {
240 constexpr u64 secure_applet_memory_size{4_MiB}; 240 constexpr u64 secure_applet_memory_size{4_MiB};
241 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 241 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
242 secure_applet_memory_size)); 242 secure_applet_memory_size));
243
244 // This memory seems to be reserved on hardware, but is not reserved/used by yuzu.
245 // Likely Horizon OS reserved memory
246 // TODO(ameerj): Derive the memory rather than hardcode it.
247 constexpr u64 unknown_reserved_memory{0x2f896000};
248 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
249 unknown_reserved_memory));
250 } 243 }
251 244
252 void InitializePreemption(KernelCore& kernel) { 245 void InitializePreemption(KernelCore& kernel) {
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 9836809f2..839171e85 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -2332,7 +2332,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o
2332 R_UNLESS(event != nullptr, ResultOutOfResource); 2332 R_UNLESS(event != nullptr, ResultOutOfResource);
2333 2333
2334 // Initialize the event. 2334 // Initialize the event.
2335 event->Initialize("CreateEvent"); 2335 event->Initialize("CreateEvent", kernel.CurrentProcess());
2336 2336
2337 // Commit the thread reservation. 2337 // Commit the thread reservation.
2338 event_reservation.Commit(); 2338 event_reservation.Commit();
diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp
index 62f4cdfb2..b8c2c6e51 100644
--- a/src/core/hle/service/kernel_helpers.cpp
+++ b/src/core/hle/service/kernel_helpers.cpp
@@ -3,7 +3,9 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "core/core.h" 5#include "core/core.h"
6#include "core/core_timing.h"
6#include "core/hle/kernel/k_event.h" 7#include "core/hle/kernel/k_event.h"
8#include "core/hle/kernel/k_memory_manager.h"
7#include "core/hle/kernel/k_process.h" 9#include "core/hle/kernel/k_process.h"
8#include "core/hle/kernel/k_readable_event.h" 10#include "core/hle/kernel/k_readable_event.h"
9#include "core/hle/kernel/k_resource_limit.h" 11#include "core/hle/kernel/k_resource_limit.h"
@@ -15,10 +17,21 @@ namespace Service::KernelHelpers {
15 17
16ServiceContext::ServiceContext(Core::System& system_, std::string name_) 18ServiceContext::ServiceContext(Core::System& system_, std::string name_)
17 : kernel(system_.Kernel()) { 19 : kernel(system_.Kernel()) {
20
21 // Create a resource limit for the process.
22 const auto physical_memory_size =
23 kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::System);
24 auto* resource_limit = Kernel::CreateResourceLimitForProcess(system_, physical_memory_size);
25
26 // Create the process.
18 process = Kernel::KProcess::Create(kernel); 27 process = Kernel::KProcess::Create(kernel);
19 ASSERT(Kernel::KProcess::Initialize(process, system_, std::move(name_), 28 ASSERT(Kernel::KProcess::Initialize(process, system_, std::move(name_),
20 Kernel::KProcess::ProcessType::Userland) 29 Kernel::KProcess::ProcessType::KernelInternal,
30 resource_limit)
21 .IsSuccess()); 31 .IsSuccess());
32
33 // Close reference to our resource limit, as the process opens one.
34 resource_limit->Close();
22} 35}
23 36
24ServiceContext::~ServiceContext() { 37ServiceContext::~ServiceContext() {
@@ -43,7 +56,7 @@ Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) {
43 } 56 }
44 57
45 // Initialize the event. 58 // Initialize the event.
46 event->Initialize(std::move(name)); 59 event->Initialize(std::move(name), process);
47 60
48 // Commit the thread reservation. 61 // Commit the thread reservation.
49 event_reservation.Commit(); 62 event_reservation.Commit();
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 88d6ec908..28d30eee2 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -39,8 +39,7 @@ struct Memory::Impl {
39 void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { 39 void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) {
40 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); 40 ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size);
41 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); 41 ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base);
42 ASSERT_MSG(target >= DramMemoryMap::Base && target < DramMemoryMap::End, 42 ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", target);
43 "Out of bounds target: {:016X}", target);
44 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory); 43 MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory);
45 44
46 if (Settings::IsFastmemEnabled()) { 45 if (Settings::IsFastmemEnabled()) {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index d5ba86c03..f915bd856 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -445,6 +445,7 @@ void Config::ReadCoreValues() {
445 qt_config->beginGroup(QStringLiteral("Core")); 445 qt_config->beginGroup(QStringLiteral("Core"));
446 446
447 ReadGlobalSetting(Settings::values.use_multi_core); 447 ReadGlobalSetting(Settings::values.use_multi_core);
448 ReadGlobalSetting(Settings::values.use_extended_memory_layout);
448 449
449 qt_config->endGroup(); 450 qt_config->endGroup();
450} 451}
@@ -1019,6 +1020,7 @@ void Config::SaveCoreValues() {
1019 qt_config->beginGroup(QStringLiteral("Core")); 1020 qt_config->beginGroup(QStringLiteral("Core"));
1020 1021
1021 WriteGlobalSetting(Settings::values.use_multi_core); 1022 WriteGlobalSetting(Settings::values.use_multi_core);
1023 WriteGlobalSetting(Settings::values.use_extended_memory_layout);
1022 1024
1023 qt_config->endGroup(); 1025 qt_config->endGroup();
1024} 1026}
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp
index 978a29fe6..08d5444ec 100644
--- a/src/yuzu/configuration/configure_general.cpp
+++ b/src/yuzu/configuration/configure_general.cpp
@@ -42,6 +42,9 @@ void ConfigureGeneral::SetConfiguration() {
42 42
43 ui->use_multi_core->setEnabled(runtime_lock); 43 ui->use_multi_core->setEnabled(runtime_lock);
44 ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); 44 ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue());
45 ui->use_extended_memory_layout->setEnabled(runtime_lock);
46 ui->use_extended_memory_layout->setChecked(
47 Settings::values.use_extended_memory_layout.GetValue());
45 48
46 ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); 49 ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue());
47 ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue()); 50 ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue());
@@ -91,6 +94,9 @@ void ConfigureGeneral::ResetDefaults() {
91void ConfigureGeneral::ApplyConfiguration() { 94void ConfigureGeneral::ApplyConfiguration() {
92 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core, 95 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core,
93 use_multi_core); 96 use_multi_core);
97 ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_extended_memory_layout,
98 ui->use_extended_memory_layout,
99 use_extended_memory_layout);
94 100
95 if (Settings::IsConfiguringGlobal()) { 101 if (Settings::IsConfiguringGlobal()) {
96 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); 102 UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
@@ -160,6 +166,9 @@ void ConfigureGeneral::SetupPerGameUI() {
160 Settings::values.use_speed_limit, use_speed_limit); 166 Settings::values.use_speed_limit, use_speed_limit);
161 ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core, 167 ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core,
162 use_multi_core); 168 use_multi_core);
169 ConfigurationShared::SetColoredTristate(ui->use_extended_memory_layout,
170 Settings::values.use_extended_memory_layout,
171 use_extended_memory_layout);
163 172
164 connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() { 173 connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() {
165 ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() && 174 ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() &&
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h
index 85c1dd4a8..b6f3bb5ed 100644
--- a/src/yuzu/configuration/configure_general.h
+++ b/src/yuzu/configuration/configure_general.h
@@ -48,6 +48,7 @@ private:
48 48
49 ConfigurationShared::CheckState use_speed_limit; 49 ConfigurationShared::CheckState use_speed_limit;
50 ConfigurationShared::CheckState use_multi_core; 50 ConfigurationShared::CheckState use_multi_core;
51 ConfigurationShared::CheckState use_extended_memory_layout;
51 52
52 const Core::System& system; 53 const Core::System& system;
53}; 54};
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui
index bfc771135..c6ef2ab70 100644
--- a/src/yuzu/configuration/configure_general.ui
+++ b/src/yuzu/configuration/configure_general.ui
@@ -143,6 +143,13 @@
143 </widget> 143 </widget>
144 </item> 144 </item>
145 <item> 145 <item>
146 <widget class="QCheckBox" name="use_extended_memory_layout">
147 <property name="text">
148 <string>Extended memory layout (6GB DRAM)</string>
149 </property>
150 </widget>
151 </item>
152 <item>
146 <widget class="QCheckBox" name="toggle_check_exit"> 153 <widget class="QCheckBox" name="toggle_check_exit">
147 <property name="text"> 154 <property name="text">
148 <string>Confirm exit while emulation is running</string> 155 <string>Confirm exit while emulation is running</string>
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index ff616da70..30963a8bb 100644
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -266,6 +266,7 @@ void Config::ReadValues() {
266 266
267 // Core 267 // Core
268 ReadSetting("Core", Settings::values.use_multi_core); 268 ReadSetting("Core", Settings::values.use_multi_core);
269 ReadSetting("Core", Settings::values.use_extended_memory_layout);
269 270
270 // Cpu 271 // Cpu
271 ReadSetting("Cpu", Settings::values.cpu_accuracy); 272 ReadSetting("Cpu", Settings::values.cpu_accuracy);