summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/audio_core/CMakeLists.txt2
-rw-r--r--src/common/common_funcs.h4
-rw-r--r--src/common/host_memory.cpp6
-rw-r--r--src/common/settings.cpp1
-rw-r--r--src/core/CMakeLists.txt14
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp5
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.cpp22
-rw-r--r--src/core/arm/exclusive_monitor.cpp4
-rw-r--r--src/core/hle/ipc_helpers.h2
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp3
-rw-r--r--src/core/hle/kernel/k_client_port.cpp2
-rw-r--r--src/core/hle/kernel/k_event.cpp2
-rw-r--r--src/core/hle/kernel/k_memory_block.h12
-rw-r--r--src/core/hle/kernel/k_page_table.cpp14
-rw-r--r--src/core/hle/kernel/k_process.cpp14
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp11
-rw-r--r--src/core/hle/kernel/k_resource_limit.h11
-rw-r--r--src/core/hle/kernel/k_session.cpp2
-rw-r--r--src/core/hle/kernel/k_shared_memory.cpp6
-rw-r--r--src/core/hle/kernel/k_thread.cpp4
-rw-r--r--src/core/hle/kernel/k_transfer_memory.cpp2
-rw-r--r--src/core/hle/kernel/kernel.cpp18
-rw-r--r--src/core/hle/kernel/physical_core.cpp4
-rw-r--r--src/core/hle/kernel/service_thread.cpp4
-rw-r--r--src/core/hle/kernel/svc.cpp117
-rw-r--r--src/core/hle/kernel/svc_types.h470
-rw-r--r--src/core/hle/service/kernel_helpers.cpp2
-rw-r--r--src/core/hle/service/sm/sm_controller.cpp4
-rw-r--r--src/shader_recompiler/frontend/maxwell/translate_program.cpp2
-rw-r--r--src/shader_recompiler/host_translate_info.h1
-rw-r--r--src/shader_recompiler/ir_opt/passes.h6
-rw-r--r--src/shader_recompiler/ir_opt/texture_pass.cpp12
-rw-r--r--src/video_core/CMakeLists.txt15
-rw-r--r--src/video_core/engines/maxwell_3d.h4
-rw-r--r--src/video_core/macro/macro.cpp3
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp1
-rw-r--r--src/video_core/renderer_opengl/gl_state_tracker.cpp4
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp1
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp2
-rw-r--r--src/video_core/renderer_vulkan/vk_state_tracker.cpp2
-rw-r--r--src/video_core/shader_environment.cpp2
-rw-r--r--src/yuzu/CMakeLists.txt2
-rw-r--r--src/yuzu/bootmanager.cpp337
-rw-r--r--src/yuzu/main.cpp46
-rw-r--r--src/yuzu/main.h7
46 files changed, 797 insertions, 414 deletions
diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt
index 0a1f3bf18..8e3a8f5a8 100644
--- a/src/audio_core/CMakeLists.txt
+++ b/src/audio_core/CMakeLists.txt
@@ -217,7 +217,7 @@ else()
217endif() 217endif()
218 218
219target_link_libraries(audio_core PUBLIC common core) 219target_link_libraries(audio_core PUBLIC common core)
220if (ARCHITECTURE_x86_64) 220if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
221 target_link_libraries(audio_core PRIVATE dynarmic) 221 target_link_libraries(audio_core PRIVATE dynarmic)
222endif() 222endif()
223 223
diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h
index e1e2a90fc..0dad9338a 100644
--- a/src/common/common_funcs.h
+++ b/src/common/common_funcs.h
@@ -31,8 +31,10 @@
31 31
32#ifndef _MSC_VER 32#ifndef _MSC_VER
33 33
34#ifdef ARCHITECTURE_x86_64 34#if defined(ARCHITECTURE_x86_64)
35#define Crash() __asm__ __volatile__("int $3") 35#define Crash() __asm__ __volatile__("int $3")
36#elif defined(ARCHITECTURE_arm64)
37#define Crash() __asm__ __volatile__("brk #0")
36#else 38#else
37#define Crash() exit(1) 39#define Crash() exit(1)
38#endif 40#endif
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp
index 7f9659612..909f6cf3f 100644
--- a/src/common/host_memory.cpp
+++ b/src/common/host_memory.cpp
@@ -359,6 +359,12 @@ public:
359 } 359 }
360 }); 360 });
361 361
362 long page_size = sysconf(_SC_PAGESIZE);
363 if (page_size != 0x1000) {
364 LOG_CRITICAL(HW_Memory, "page size {:#x} is incompatible with 4K paging", page_size);
365 throw std::bad_alloc{};
366 }
367
362 // Backing memory initialization 368 // Backing memory initialization
363#if defined(__FreeBSD__) && __FreeBSD__ < 13 369#if defined(__FreeBSD__) && __FreeBSD__ < 13
364 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 370 // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
diff --git a/src/common/settings.cpp b/src/common/settings.cpp
index 0a560ebb7..8173462cb 100644
--- a/src/common/settings.cpp
+++ b/src/common/settings.cpp
@@ -151,6 +151,7 @@ void UpdateRescalingInfo() {
151 ASSERT(false); 151 ASSERT(false);
152 info.up_scale = 1; 152 info.up_scale = 1;
153 info.down_shift = 0; 153 info.down_shift = 0;
154 break;
154 } 155 }
155 info.up_factor = static_cast<f32>(info.up_scale) / (1U << info.down_shift); 156 info.up_factor = static_cast<f32>(info.up_scale) / (1U << info.down_shift);
156 info.down_factor = static_cast<f32>(1U << info.down_shift) / info.up_scale; 157 info.down_factor = static_cast<f32>(1U << info.down_shift) / info.up_scale;
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f6e082c36..f67f1ce92 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -497,10 +497,6 @@ add_library(core STATIC
497 hle/service/hid/irsensor/processor_base.h 497 hle/service/hid/irsensor/processor_base.h
498 hle/service/hid/irsensor/tera_plugin_processor.cpp 498 hle/service/hid/irsensor/tera_plugin_processor.cpp
499 hle/service/hid/irsensor/tera_plugin_processor.h 499 hle/service/hid/irsensor/tera_plugin_processor.h
500 hle/service/jit/jit_context.cpp
501 hle/service/jit/jit_context.h
502 hle/service/jit/jit.cpp
503 hle/service/jit/jit.h
504 hle/service/lbl/lbl.cpp 500 hle/service/lbl/lbl.cpp
505 hle/service/lbl/lbl.h 501 hle/service/lbl/lbl.h
506 hle/service/ldn/lan_discovery.cpp 502 hle/service/ldn/lan_discovery.cpp
@@ -805,14 +801,18 @@ if (ENABLE_WEB_SERVICE)
805 target_link_libraries(core PRIVATE web_service) 801 target_link_libraries(core PRIVATE web_service)
806endif() 802endif()
807 803
808if (ARCHITECTURE_x86_64) 804if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
809 target_sources(core PRIVATE 805 target_sources(core PRIVATE
810 arm/dynarmic/arm_dynarmic_32.cpp
811 arm/dynarmic/arm_dynarmic_32.h
812 arm/dynarmic/arm_dynarmic_64.cpp 806 arm/dynarmic/arm_dynarmic_64.cpp
813 arm/dynarmic/arm_dynarmic_64.h 807 arm/dynarmic/arm_dynarmic_64.h
808 arm/dynarmic/arm_dynarmic_32.cpp
809 arm/dynarmic/arm_dynarmic_32.h
814 arm/dynarmic/arm_dynarmic_cp15.cpp 810 arm/dynarmic/arm_dynarmic_cp15.cpp
815 arm/dynarmic/arm_dynarmic_cp15.h 811 arm/dynarmic/arm_dynarmic_cp15.h
812 hle/service/jit/jit_context.cpp
813 hle/service/jit/jit_context.h
814 hle/service/jit/jit.cpp
815 hle/service/jit/jit.h
816 ) 816 )
817 target_link_libraries(core PRIVATE dynarmic) 817 target_link_libraries(core PRIVATE dynarmic)
818endif() 818endif()
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 287ba102e..227e06ea1 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -301,6 +301,11 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
301 } 301 }
302 } 302 }
303 303
304#ifdef ARCHITECTURE_arm64
305 // TODO: remove when fixed in dynarmic
306 config.optimizations &= ~Dynarmic::OptimizationFlag::BlockLinking;
307#endif
308
304 return std::make_unique<Dynarmic::A32::Jit>(config); 309 return std::make_unique<Dynarmic::A32::Jit>(config);
305} 310}
306 311
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
index 200efe4db..5a4eba3eb 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.cpp
@@ -52,12 +52,16 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1
52 case 4: 52 case 4:
53 // CP15_DATA_SYNC_BARRIER 53 // CP15_DATA_SYNC_BARRIER
54 return Callback{ 54 return Callback{
55 [](Dynarmic::A32::Jit*, void*, std::uint32_t, std::uint32_t) -> std::uint64_t { 55 [](void*, std::uint32_t, std::uint32_t) -> std::uint64_t {
56#ifdef _MSC_VER 56#if defined(_MSC_VER) && defined(ARCHITECTURE_x86_64)
57 _mm_mfence(); 57 _mm_mfence();
58 _mm_lfence(); 58 _mm_lfence();
59#else 59#elif defined(ARCHITECTURE_x86_64)
60 asm volatile("mfence\n\tlfence\n\t" : : : "memory"); 60 asm volatile("mfence\n\tlfence\n\t" : : : "memory");
61#elif defined(ARCHITECTURE_arm64)
62 asm volatile("dsb sy\n\t" : : : "memory");
63#else
64#error Unsupported architecture
61#endif 65#endif
62 return 0; 66 return 0;
63 }, 67 },
@@ -66,11 +70,15 @@ CallbackOrAccessOneWord DynarmicCP15::CompileSendOneWord(bool two, unsigned opc1
66 case 5: 70 case 5:
67 // CP15_DATA_MEMORY_BARRIER 71 // CP15_DATA_MEMORY_BARRIER
68 return Callback{ 72 return Callback{
69 [](Dynarmic::A32::Jit*, void*, std::uint32_t, std::uint32_t) -> std::uint64_t { 73 [](void*, std::uint32_t, std::uint32_t) -> std::uint64_t {
70#ifdef _MSC_VER 74#if defined(_MSC_VER) && defined(ARCHITECTURE_x86_64)
71 _mm_mfence(); 75 _mm_mfence();
72#else 76#elif defined(ARCHITECTURE_x86_64)
73 asm volatile("mfence\n\t" : : : "memory"); 77 asm volatile("mfence\n\t" : : : "memory");
78#elif defined(ARCHITECTURE_arm64)
79 asm volatile("dmb sy\n\t" : : : "memory");
80#else
81#error Unsupported architecture
74#endif 82#endif
75 return 0; 83 return 0;
76 }, 84 },
@@ -115,7 +123,7 @@ CallbackOrAccessOneWord DynarmicCP15::CompileGetOneWord(bool two, unsigned opc1,
115CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) { 123CallbackOrAccessTwoWords DynarmicCP15::CompileGetTwoWords(bool two, unsigned opc, CoprocReg CRm) {
116 if (!two && opc == 0 && CRm == CoprocReg::C14) { 124 if (!two && opc == 0 && CRm == CoprocReg::C14) {
117 // CNTPCT 125 // CNTPCT
118 const auto callback = [](Dynarmic::A32::Jit*, void* arg, u32, u32) -> u64 { 126 const auto callback = [](void* arg, u32, u32) -> u64 {
119 const auto& parent_arg = *static_cast<ARM_Dynarmic_32*>(arg); 127 const auto& parent_arg = *static_cast<ARM_Dynarmic_32*>(arg);
120 return parent_arg.system.CoreTiming().GetClockTicks(); 128 return parent_arg.system.CoreTiming().GetClockTicks();
121 }; 129 };
diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp
index 2db0b035d..20550faeb 100644
--- a/src/core/arm/exclusive_monitor.cpp
+++ b/src/core/arm/exclusive_monitor.cpp
@@ -1,7 +1,7 @@
1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#ifdef ARCHITECTURE_x86_64 4#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
5#include "core/arm/dynarmic/arm_exclusive_monitor.h" 5#include "core/arm/dynarmic/arm_exclusive_monitor.h"
6#endif 6#endif
7#include "core/arm/exclusive_monitor.h" 7#include "core/arm/exclusive_monitor.h"
@@ -13,7 +13,7 @@ ExclusiveMonitor::~ExclusiveMonitor() = default;
13 13
14std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory, 14std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
15 std::size_t num_cores) { 15 std::size_t num_cores) {
16#ifdef ARCHITECTURE_x86_64 16#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
17 return std::make_unique<Core::DynarmicExclusiveMonitor>(memory, num_cores); 17 return std::make_unique<Core::DynarmicExclusiveMonitor>(memory, num_cores);
18#else 18#else
19 // TODO(merry): Passthrough exclusive monitor 19 // TODO(merry): Passthrough exclusive monitor
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 3bb111748..a86bec252 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -149,7 +149,7 @@ public:
149 context->AddDomainObject(std::move(iface)); 149 context->AddDomainObject(std::move(iface));
150 } else { 150 } else {
151 kernel.CurrentProcess()->GetResourceLimit()->Reserve( 151 kernel.CurrentProcess()->GetResourceLimit()->Reserve(
152 Kernel::LimitableResource::Sessions, 1); 152 Kernel::LimitableResource::SessionCountMax, 1);
153 153
154 auto* session = Kernel::KSession::Create(kernel); 154 auto* session = Kernel::KSession::Create(kernel);
155 session->Initialize(nullptr, iface->GetServiceName()); 155 session->Initialize(nullptr, iface->GetServiceName());
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index aa2dddcc6..bda098511 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -265,7 +265,8 @@ void KPageBufferSlabHeap::Initialize(Core::System& system) {
265 const size_t slab_size = num_pages * PageSize; 265 const size_t slab_size = num_pages * PageSize;
266 266
267 // Reserve memory from the system resource limit. 267 // Reserve memory from the system resource limit.
268 ASSERT(kernel.GetSystemResourceLimit()->Reserve(LimitableResource::PhysicalMemory, slab_size)); 268 ASSERT(
269 kernel.GetSystemResourceLimit()->Reserve(LimitableResource::PhysicalMemoryMax, slab_size));
269 270
270 // Allocate memory for the slab. 271 // Allocate memory for the slab.
271 constexpr auto AllocateOption = KMemoryManager::EncodeOption( 272 constexpr auto AllocateOption = KMemoryManager::EncodeOption(
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp
index eaa2e094c..2ec623a58 100644
--- a/src/core/hle/kernel/k_client_port.cpp
+++ b/src/core/hle/kernel/k_client_port.cpp
@@ -61,7 +61,7 @@ bool KClientPort::IsSignaled() const {
61Result KClientPort::CreateSession(KClientSession** out) { 61Result KClientPort::CreateSession(KClientSession** out) {
62 // Reserve a new session from the resource limit. 62 // Reserve a new session from the resource limit.
63 KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), 63 KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
64 LimitableResource::Sessions); 64 LimitableResource::SessionCountMax);
65 R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); 65 R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
66 66
67 // Update the session counts. 67 // Update the session counts.
diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp
index 78ca59463..27f70e5c5 100644
--- a/src/core/hle/kernel/k_event.cpp
+++ b/src/core/hle/kernel/k_event.cpp
@@ -50,7 +50,7 @@ Result KEvent::Clear() {
50void KEvent::PostDestroy(uintptr_t arg) { 50void KEvent::PostDestroy(uintptr_t arg) {
51 // Release the event count resource the owner process holds. 51 // Release the event count resource the owner process holds.
52 KProcess* owner = reinterpret_cast<KProcess*>(arg); 52 KProcess* owner = reinterpret_cast<KProcess*>(arg);
53 owner->GetResourceLimit()->Release(LimitableResource::Events, 1); 53 owner->GetResourceLimit()->Release(LimitableResource::EventCountMax, 1);
54 owner->Close(); 54 owner->Close();
55} 55}
56 56
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h
index 6f845d675..3b6e7baff 100644
--- a/src/core/hle/kernel/k_memory_block.h
+++ b/src/core/hle/kernel/k_memory_block.h
@@ -216,13 +216,15 @@ struct KMemoryInfo {
216 216
217 constexpr Svc::MemoryInfo GetSvcMemoryInfo() const { 217 constexpr Svc::MemoryInfo GetSvcMemoryInfo() const {
218 return { 218 return {
219 .addr = m_address, 219 .base_address = m_address,
220 .size = m_size, 220 .size = m_size,
221 .state = static_cast<Svc::MemoryState>(m_state & KMemoryState::Mask), 221 .state = static_cast<Svc::MemoryState>(m_state & KMemoryState::Mask),
222 .attr = static_cast<Svc::MemoryAttribute>(m_attribute & KMemoryAttribute::UserMask), 222 .attribute =
223 .perm = static_cast<Svc::MemoryPermission>(m_permission & KMemoryPermission::UserMask), 223 static_cast<Svc::MemoryAttribute>(m_attribute & KMemoryAttribute::UserMask),
224 .ipc_refcount = m_ipc_lock_count, 224 .permission =
225 .device_refcount = m_device_use_count, 225 static_cast<Svc::MemoryPermission>(m_permission & KMemoryPermission::UserMask),
226 .ipc_count = m_ipc_lock_count,
227 .device_count = m_device_use_count,
226 .padding = {}, 228 .padding = {},
227 }; 229 };
228 } 230 }
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index fab55a057..5387bf5fe 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -920,8 +920,8 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add
920 920
921 // Reserve space for any partial pages we allocate. 921 // Reserve space for any partial pages we allocate.
922 const size_t unmapped_size = aligned_src_size - mapping_src_size; 922 const size_t unmapped_size = aligned_src_size - mapping_src_size;
923 KScopedResourceReservation memory_reservation(m_resource_limit, 923 KScopedResourceReservation memory_reservation(
924 LimitableResource::PhysicalMemory, unmapped_size); 924 m_resource_limit, LimitableResource::PhysicalMemoryMax, unmapped_size);
925 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); 925 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
926 926
927 // Ensure that we manage page references correctly. 927 // Ensure that we manage page references correctly.
@@ -1227,7 +1227,7 @@ Result KPageTable::CleanupForIpcServer(VAddr address, size_t size, KMemoryState
1227 const VAddr mapping_start = Common::AlignUp((address), PageSize); 1227 const VAddr mapping_start = Common::AlignUp((address), PageSize);
1228 const VAddr mapping_end = Common::AlignDown((address) + size, PageSize); 1228 const VAddr mapping_end = Common::AlignDown((address) + size, PageSize);
1229 const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0; 1229 const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0;
1230 m_resource_limit->Release(LimitableResource::PhysicalMemory, aligned_size - mapping_size); 1230 m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, aligned_size - mapping_size);
1231 1231
1232 R_SUCCEED(); 1232 R_SUCCEED();
1233} 1233}
@@ -1568,7 +1568,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) {
1568 { 1568 {
1569 // Reserve the memory from the process resource limit. 1569 // Reserve the memory from the process resource limit.
1570 KScopedResourceReservation memory_reservation( 1570 KScopedResourceReservation memory_reservation(
1571 m_resource_limit, LimitableResource::PhysicalMemory, size - mapped_size); 1571 m_resource_limit, LimitableResource::PhysicalMemoryMax, size - mapped_size);
1572 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); 1572 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
1573 1573
1574 // Allocate pages for the new memory. 1574 // Allocate pages for the new memory.
@@ -1908,7 +1908,7 @@ Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) {
1908 1908
1909 // Release the memory resource. 1909 // Release the memory resource.
1910 m_mapped_physical_memory_size -= mapped_size; 1910 m_mapped_physical_memory_size -= mapped_size;
1911 m_resource_limit->Release(LimitableResource::PhysicalMemory, mapped_size); 1911 m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, mapped_size);
1912 1912
1913 // Update memory blocks. 1913 // Update memory blocks.
1914 m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize, 1914 m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize,
@@ -2492,7 +2492,7 @@ Result KPageTable::SetHeapSize(VAddr* out, size_t size) {
2492 OperationType::Unmap)); 2492 OperationType::Unmap));
2493 2493
2494 // Release the memory from the resource limit. 2494 // Release the memory from the resource limit.
2495 m_resource_limit->Release(LimitableResource::PhysicalMemory, num_pages * PageSize); 2495 m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, num_pages * PageSize);
2496 2496
2497 // Apply the memory block update. 2497 // Apply the memory block update.
2498 m_memory_block_manager.Update(std::addressof(allocator), m_heap_region_start + size, 2498 m_memory_block_manager.Update(std::addressof(allocator), m_heap_region_start + size,
@@ -2522,7 +2522,7 @@ Result KPageTable::SetHeapSize(VAddr* out, size_t size) {
2522 2522
2523 // Reserve memory for the heap extension. 2523 // Reserve memory for the heap extension.
2524 KScopedResourceReservation memory_reservation( 2524 KScopedResourceReservation memory_reservation(
2525 m_resource_limit, LimitableResource::PhysicalMemory, allocation_size); 2525 m_resource_limit, LimitableResource::PhysicalMemoryMax, allocation_size);
2526 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); 2526 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
2527 2527
2528 // Allocate pages for the heap extension. 2528 // Allocate pages for the heap extension.
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 4ddeea73b..55a9c5fae 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -38,7 +38,7 @@ namespace {
38 */ 38 */
39void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) { 39void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) {
40 const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); 40 const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart();
41 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1)); 41 ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1));
42 42
43 KThread* thread = KThread::Create(system.Kernel()); 43 KThread* thread = KThread::Create(system.Kernel());
44 SCOPE_EXIT({ thread->Close(); }); 44 SCOPE_EXIT({ thread->Close(); });
@@ -124,7 +124,7 @@ void KProcess::DecrementRunningThreadCount() {
124} 124}
125 125
126u64 KProcess::GetTotalPhysicalMemoryAvailable() { 126u64 KProcess::GetTotalPhysicalMemoryAvailable() {
127 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + 127 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemoryMax) +
128 page_table.GetNormalMemorySize() + GetSystemResourceSize() + image_size + 128 page_table.GetNormalMemorySize() + GetSystemResourceSize() + image_size +
129 main_thread_stack_size}; 129 main_thread_stack_size};
130 if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); 130 if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application);
@@ -349,8 +349,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
349 // We currently do not support process-specific system resource 349 // We currently do not support process-specific system resource
350 UNIMPLEMENTED_IF(system_resource_size != 0); 350 UNIMPLEMENTED_IF(system_resource_size != 0);
351 351
352 KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, 352 KScopedResourceReservation memory_reservation(
353 code_size + system_resource_size); 353 resource_limit, LimitableResource::PhysicalMemoryMax, code_size + system_resource_size);
354 if (!memory_reservation.Succeeded()) { 354 if (!memory_reservation.Succeeded()) {
355 LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", 355 LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes",
356 code_size + system_resource_size); 356 code_size + system_resource_size);
@@ -406,8 +406,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
406 406
407void KProcess::Run(s32 main_thread_priority, u64 stack_size) { 407void KProcess::Run(s32 main_thread_priority, u64 stack_size) {
408 AllocateMainThreadStack(stack_size); 408 AllocateMainThreadStack(stack_size);
409 resource_limit->Reserve(LimitableResource::Threads, 1); 409 resource_limit->Reserve(LimitableResource::ThreadCountMax, 1);
410 resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); 410 resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, main_thread_stack_size);
411 411
412 const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)}; 412 const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)};
413 ASSERT(!page_table.SetMaxHeapSize(heap_capacity).IsError()); 413 ASSERT(!page_table.SetMaxHeapSize(heap_capacity).IsError());
@@ -442,7 +442,7 @@ void KProcess::PrepareForTermination() {
442 plr_address = 0; 442 plr_address = 0;
443 443
444 if (resource_limit) { 444 if (resource_limit) {
445 resource_limit->Release(LimitableResource::PhysicalMemory, 445 resource_limit->Release(LimitableResource::PhysicalMemoryMax,
446 main_thread_stack_size + image_size); 446 main_thread_stack_size + image_size);
447 } 447 }
448 448
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index 010dcf99e..b9d22b414 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -159,12 +159,13 @@ KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical
159 // TODO(bunnei): These values are the system defaults, the limits for service processes are 159 // TODO(bunnei): These values are the system defaults, the limits for service processes are
160 // lower. These should use the correct limit values. 160 // lower. These should use the correct limit values.
161 161
162 ASSERT(resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, physical_memory_size) 162 ASSERT(resource_limit->SetLimitValue(LimitableResource::PhysicalMemoryMax, physical_memory_size)
163 .IsSuccess()); 163 .IsSuccess());
164 ASSERT(resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); 164 ASSERT(resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800).IsSuccess());
165 ASSERT(resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); 165 ASSERT(resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900).IsSuccess());
166 ASSERT(resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200).IsSuccess()); 166 ASSERT(
167 ASSERT(resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); 167 resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200).IsSuccess());
168 ASSERT(resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133).IsSuccess());
168 169
169 return resource_limit; 170 return resource_limit;
170} 171}
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 65c98c979..2573d1b7c 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -16,15 +16,8 @@ class CoreTiming;
16 16
17namespace Kernel { 17namespace Kernel {
18class KernelCore; 18class KernelCore;
19enum class LimitableResource : u32 { 19
20 PhysicalMemory = 0, 20using LimitableResource = Svc::LimitableResource;
21 Threads = 1,
22 Events = 2,
23 TransferMemory = 3,
24 Sessions = 4,
25
26 Count,
27};
28 21
29constexpr bool IsValidResourceType(LimitableResource type) { 22constexpr bool IsValidResourceType(LimitableResource type) {
30 return type < LimitableResource::Count; 23 return type < LimitableResource::Count;
diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp
index 7a6534ac3..b6f6fe9d9 100644
--- a/src/core/hle/kernel/k_session.cpp
+++ b/src/core/hle/kernel/k_session.cpp
@@ -76,7 +76,7 @@ void KSession::OnClientClosed() {
76void KSession::PostDestroy(uintptr_t arg) { 76void KSession::PostDestroy(uintptr_t arg) {
77 // Release the session count resource the owner process holds. 77 // Release the session count resource the owner process holds.
78 KProcess* owner = reinterpret_cast<KProcess*>(arg); 78 KProcess* owner = reinterpret_cast<KProcess*>(arg);
79 owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1); 79 owner->GetResourceLimit()->Release(LimitableResource::SessionCountMax, 1);
80 owner->Close(); 80 owner->Close();
81} 81}
82 82
diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp
index a039cc591..10cd4c43d 100644
--- a/src/core/hle/kernel/k_shared_memory.cpp
+++ b/src/core/hle/kernel/k_shared_memory.cpp
@@ -14,7 +14,7 @@ namespace Kernel {
14KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} 14KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {}
15 15
16KSharedMemory::~KSharedMemory() { 16KSharedMemory::~KSharedMemory() {
17 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); 17 kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, size);
18} 18}
19 19
20Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, 20Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_,
@@ -35,7 +35,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o
35 KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); 35 KResourceLimit* reslimit = kernel.GetSystemResourceLimit();
36 36
37 // Reserve memory for ourselves. 37 // Reserve memory for ourselves.
38 KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemory, 38 KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemoryMax,
39 size_); 39 size_);
40 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); 40 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
41 41
@@ -57,7 +57,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o
57 57
58void KSharedMemory::Finalize() { 58void KSharedMemory::Finalize() {
59 // Release the memory reservation. 59 // Release the memory reservation.
60 resource_limit->Release(LimitableResource::PhysicalMemory, size); 60 resource_limit->Release(LimitableResource::PhysicalMemoryMax, size);
61 resource_limit->Close(); 61 resource_limit->Close();
62 62
63 // Perform inherited finalization. 63 // Perform inherited finalization.
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 78076a346..21207fe99 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -303,7 +303,7 @@ void KThread::PostDestroy(uintptr_t arg) {
303 const bool resource_limit_release_hint = (arg & 1); 303 const bool resource_limit_release_hint = (arg & 1);
304 const s64 hint_value = (resource_limit_release_hint ? 0 : 1); 304 const s64 hint_value = (resource_limit_release_hint ? 0 : 1);
305 if (owner != nullptr) { 305 if (owner != nullptr) {
306 owner->GetResourceLimit()->Release(LimitableResource::Threads, 1, hint_value); 306 owner->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1, hint_value);
307 owner->Close(); 307 owner->Close();
308 } 308 }
309} 309}
@@ -1054,7 +1054,7 @@ void KThread::Exit() {
1054 1054
1055 // Release the thread resource hint, running thread count from parent. 1055 // Release the thread resource hint, running thread count from parent.
1056 if (parent != nullptr) { 1056 if (parent != nullptr) {
1057 parent->GetResourceLimit()->Release(Kernel::LimitableResource::Threads, 0, 1); 1057 parent->GetResourceLimit()->Release(Kernel::LimitableResource::ThreadCountMax, 0, 1);
1058 resource_limit_release_hint = true; 1058 resource_limit_release_hint = true;
1059 parent->DecrementRunningThreadCount(); 1059 parent->DecrementRunningThreadCount();
1060 } 1060 }
diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp
index b0320eb73..9f34c2d46 100644
--- a/src/core/hle/kernel/k_transfer_memory.cpp
+++ b/src/core/hle/kernel/k_transfer_memory.cpp
@@ -37,7 +37,7 @@ void KTransferMemory::Finalize() {
37 37
38void KTransferMemory::PostDestroy(uintptr_t arg) { 38void KTransferMemory::PostDestroy(uintptr_t arg) {
39 KProcess* owner = reinterpret_cast<KProcess*>(arg); 39 KProcess* owner = reinterpret_cast<KProcess*>(arg);
40 owner->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1); 40 owner->GetResourceLimit()->Release(LimitableResource::TransferMemoryCountMax, 1);
41 owner->Close(); 41 owner->Close();
42} 42}
43 43
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 7f800d860..b77723503 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -229,18 +229,22 @@ struct KernelCore::Impl {
229 const auto kernel_size{sizes.second}; 229 const auto kernel_size{sizes.second};
230 230
231 // If setting the default system values fails, then something seriously wrong has occurred. 231 // If setting the default system values fails, then something seriously wrong has occurred.
232 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size) 232 ASSERT(
233 system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemoryMax, total_size)
234 .IsSuccess());
235 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800)
233 .IsSuccess()); 236 .IsSuccess());
234 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); 237 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900)
235 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess());
236 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
237 .IsSuccess()); 238 .IsSuccess());
238 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); 239 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200)
239 system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size); 240 .IsSuccess());
241 ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133)
242 .IsSuccess());
243 system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, kernel_size);
240 244
241 // Reserve secure applet memory, introduced in firmware 5.0.0 245 // Reserve secure applet memory, introduced in firmware 5.0.0
242 constexpr u64 secure_applet_memory_size{4_MiB}; 246 constexpr u64 secure_applet_memory_size{4_MiB};
243 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, 247 ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax,
244 secure_applet_memory_size)); 248 secure_applet_memory_size));
245 } 249 }
246 250
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp
index d4375962f..3044922ac 100644
--- a/src/core/hle/kernel/physical_core.cpp
+++ b/src/core/hle/kernel/physical_core.cpp
@@ -12,7 +12,7 @@ namespace Kernel {
12 12
13PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_) 13PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_)
14 : core_index{core_index_}, system{system_}, scheduler{scheduler_} { 14 : core_index{core_index_}, system{system_}, scheduler{scheduler_} {
15#ifdef ARCHITECTURE_x86_64 15#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
16 // TODO(bunnei): Initialization relies on a core being available. We may later replace this with 16 // TODO(bunnei): Initialization relies on a core being available. We may later replace this with
17 // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. 17 // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
18 auto& kernel = system.Kernel(); 18 auto& kernel = system.Kernel();
@@ -26,7 +26,7 @@ PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KSche
26PhysicalCore::~PhysicalCore() = default; 26PhysicalCore::~PhysicalCore() = default;
27 27
28void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) { 28void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) {
29#ifdef ARCHITECTURE_x86_64 29#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
30 auto& kernel = system.Kernel(); 30 auto& kernel = system.Kernel();
31 if (!is_64_bit) { 31 if (!is_64_bit) {
32 // We already initialized a 64-bit core, replace with a 32-bit one. 32 // We already initialized a 64-bit core, replace with a 32-bit one.
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp
index 7a85be77f..f5c2ab23f 100644
--- a/src/core/hle/kernel/service_thread.cpp
+++ b/src/core/hle/kernel/service_thread.cpp
@@ -193,7 +193,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name)
193 KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit()); 193 KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit());
194 194
195 // Reserve a new event from the process resource limit 195 // Reserve a new event from the process resource limit
196 KScopedResourceReservation event_reservation(m_process, LimitableResource::Events); 196 KScopedResourceReservation event_reservation(m_process, LimitableResource::EventCountMax);
197 ASSERT(event_reservation.Succeeded()); 197 ASSERT(event_reservation.Succeeded());
198 198
199 // Initialize event. 199 // Initialize event.
@@ -204,7 +204,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name)
204 event_reservation.Commit(); 204 event_reservation.Commit();
205 205
206 // Reserve a new thread from the process resource limit 206 // Reserve a new thread from the process resource limit
207 KScopedResourceReservation thread_reservation(m_process, LimitableResource::Threads); 207 KScopedResourceReservation thread_reservation(m_process, LimitableResource::ThreadCountMax);
208 ASSERT(thread_reservation.Succeeded()); 208 ASSERT(thread_reservation.Succeeded());
209 209
210 // Initialize thread. 210 // Initialize thread.
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index ecac97a52..9962ad171 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -267,7 +267,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien
267 267
268 // Reserve a new session from the process resource limit. 268 // Reserve a new session from the process resource limit.
269 // FIXME: LimitableResource_SessionCountMax 269 // FIXME: LimitableResource_SessionCountMax
270 KScopedResourceReservation session_reservation(&process, LimitableResource::Sessions); 270 KScopedResourceReservation session_reservation(&process, LimitableResource::SessionCountMax);
271 if (session_reservation.Succeeded()) { 271 if (session_reservation.Succeeded()) {
272 session = T::Create(system.Kernel()); 272 session = T::Create(system.Kernel());
273 } else { 273 } else {
@@ -298,7 +298,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien
298 298
299 // We successfully allocated a session, so add the object we allocated to the resource 299 // We successfully allocated a session, so add the object we allocated to the resource
300 // limit. 300 // limit.
301 // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::Sessions, 1); 301 // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::SessionCountMax, 1);
302 } 302 }
303 303
304 // Check that we successfully created a session. 304 // Check that we successfully created a session.
@@ -656,27 +656,12 @@ static Result ArbitrateUnlock32(Core::System& system, u32 address) {
656 return ArbitrateUnlock(system, address); 656 return ArbitrateUnlock(system, address);
657} 657}
658 658
659enum class BreakType : u32 {
660 Panic = 0,
661 AssertionFailed = 1,
662 PreNROLoad = 3,
663 PostNROLoad = 4,
664 PreNROUnload = 5,
665 PostNROUnload = 6,
666 CppException = 7,
667};
668
669struct BreakReason {
670 union {
671 u32 raw;
672 BitField<0, 30, BreakType> break_type;
673 BitField<31, 1, u32> signal_debugger;
674 };
675};
676
677/// Break program execution 659/// Break program execution
678static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { 660static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
679 BreakReason break_reason{reason}; 661 BreakReason break_reason =
662 static_cast<BreakReason>(reason & ~static_cast<u32>(BreakReason::NotificationOnlyFlag));
663 bool notification_only = (reason & static_cast<u32>(BreakReason::NotificationOnlyFlag)) != 0;
664
680 bool has_dumped_buffer{}; 665 bool has_dumped_buffer{};
681 std::vector<u8> debug_buffer; 666 std::vector<u8> debug_buffer;
682 667
@@ -705,57 +690,56 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
705 } 690 }
706 has_dumped_buffer = true; 691 has_dumped_buffer = true;
707 }; 692 };
708 switch (break_reason.break_type) { 693 switch (break_reason) {
709 case BreakType::Panic: 694 case BreakReason::Panic:
710 LOG_CRITICAL(Debug_Emulated, "Signalling debugger, PANIC! info1=0x{:016X}, info2=0x{:016X}", 695 LOG_CRITICAL(Debug_Emulated, "Userspace PANIC! info1=0x{:016X}, info2=0x{:016X}", info1,
711 info1, info2); 696 info2);
712 handle_debug_buffer(info1, info2); 697 handle_debug_buffer(info1, info2);
713 break; 698 break;
714 case BreakType::AssertionFailed: 699 case BreakReason::Assert:
715 LOG_CRITICAL(Debug_Emulated, 700 LOG_CRITICAL(Debug_Emulated, "Userspace Assertion failed! info1=0x{:016X}, info2=0x{:016X}",
716 "Signalling debugger, Assertion failed! info1=0x{:016X}, info2=0x{:016X}",
717 info1, info2); 701 info1, info2);
718 handle_debug_buffer(info1, info2); 702 handle_debug_buffer(info1, info2);
719 break; 703 break;
720 case BreakType::PreNROLoad: 704 case BreakReason::User:
721 LOG_WARNING( 705 LOG_WARNING(Debug_Emulated, "Userspace Break! 0x{:016X} with size 0x{:016X}", info1, info2);
722 Debug_Emulated, 706 handle_debug_buffer(info1, info2);
723 "Signalling debugger, Attempting to load an NRO at 0x{:016X} with size 0x{:016X}",
724 info1, info2);
725 break; 707 break;
726 case BreakType::PostNROLoad: 708 case BreakReason::PreLoadDll:
727 LOG_WARNING(Debug_Emulated, 709 LOG_INFO(Debug_Emulated,
728 "Signalling debugger, Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, 710 "Userspace Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", info1,
729 info2); 711 info2);
730 break; 712 break;
731 case BreakType::PreNROUnload: 713 case BreakReason::PostLoadDll:
732 LOG_WARNING( 714 LOG_INFO(Debug_Emulated, "Userspace Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1,
733 Debug_Emulated, 715 info2);
734 "Signalling debugger, Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}",
735 info1, info2);
736 break; 716 break;
737 case BreakType::PostNROUnload: 717 case BreakReason::PreUnloadDll:
738 LOG_WARNING(Debug_Emulated, 718 LOG_INFO(Debug_Emulated,
739 "Signalling debugger, Unloaded an NRO at 0x{:016X} with size 0x{:016X}", info1, 719 "Userspace Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", info1,
740 info2); 720 info2);
741 break; 721 break;
742 case BreakType::CppException: 722 case BreakReason::PostUnloadDll:
723 LOG_INFO(Debug_Emulated, "Userspace Unloaded an NRO at 0x{:016X} with size 0x{:016X}",
724 info1, info2);
725 break;
726 case BreakReason::CppException:
743 LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered."); 727 LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered.");
744 break; 728 break;
745 default: 729 default:
746 LOG_WARNING( 730 LOG_WARNING(
747 Debug_Emulated, 731 Debug_Emulated,
748 "Signalling debugger, Unknown break reason {}, info1=0x{:016X}, info2=0x{:016X}", 732 "Signalling debugger, Unknown break reason {:#X}, info1=0x{:016X}, info2=0x{:016X}",
749 static_cast<u32>(break_reason.break_type.Value()), info1, info2); 733 reason, info1, info2);
750 handle_debug_buffer(info1, info2); 734 handle_debug_buffer(info1, info2);
751 break; 735 break;
752 } 736 }
753 737
754 system.GetReporter().SaveSvcBreakReport( 738 system.GetReporter().SaveSvcBreakReport(reason, notification_only, info1, info2,
755 static_cast<u32>(break_reason.break_type.Value()), break_reason.signal_debugger.As<bool>(), 739 has_dumped_buffer ? std::make_optional(debug_buffer)
756 info1, info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); 740 : std::nullopt);
757 741
758 if (!break_reason.signal_debugger) { 742 if (!notification_only) {
759 LOG_CRITICAL( 743 LOG_CRITICAL(
760 Debug_Emulated, 744 Debug_Emulated,
761 "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", 745 "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
@@ -1716,13 +1700,13 @@ static Result QueryProcessMemory(Core::System& system, VAddr memory_info_address
1716 auto& memory{system.Memory()}; 1700 auto& memory{system.Memory()};
1717 const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; 1701 const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
1718 1702
1719 memory.Write64(memory_info_address + 0x00, memory_info.addr); 1703 memory.Write64(memory_info_address + 0x00, memory_info.base_address);
1720 memory.Write64(memory_info_address + 0x08, memory_info.size); 1704 memory.Write64(memory_info_address + 0x08, memory_info.size);
1721 memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff); 1705 memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff);
1722 memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attr)); 1706 memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attribute));
1723 memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.perm)); 1707 memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.permission));
1724 memory.Write32(memory_info_address + 0x1c, memory_info.ipc_refcount); 1708 memory.Write32(memory_info_address + 0x1c, memory_info.ipc_count);
1725 memory.Write32(memory_info_address + 0x20, memory_info.device_refcount); 1709 memory.Write32(memory_info_address + 0x20, memory_info.device_count);
1726 memory.Write32(memory_info_address + 0x24, 0); 1710 memory.Write32(memory_info_address + 0x24, 0);
1727 1711
1728 // Page info appears to be currently unused by the kernel and is always set to zero. 1712 // Page info appears to be currently unused by the kernel and is always set to zero.
@@ -1943,7 +1927,7 @@ static Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry
1943 1927
1944 // Reserve a new thread from the process resource limit (waiting up to 100ms). 1928 // Reserve a new thread from the process resource limit (waiting up to 100ms).
1945 KScopedResourceReservation thread_reservation( 1929 KScopedResourceReservation thread_reservation(
1946 kernel.CurrentProcess(), LimitableResource::Threads, 1, 1930 kernel.CurrentProcess(), LimitableResource::ThreadCountMax, 1,
1947 system.CoreTiming().GetGlobalTimeNs().count() + 100000000); 1931 system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
1948 if (!thread_reservation.Succeeded()) { 1932 if (!thread_reservation.Succeeded()) {
1949 LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); 1933 LOG_ERROR(Kernel_SVC, "Could not reserve a new thread");
@@ -2344,7 +2328,7 @@ static Result CreateTransferMemory(Core::System& system, Handle* out, VAddr addr
2344 2328
2345 // Reserve a new transfer memory from the process resource limit. 2329 // Reserve a new transfer memory from the process resource limit.
2346 KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), 2330 KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(),
2347 LimitableResource::TransferMemory); 2331 LimitableResource::TransferMemoryCountMax);
2348 R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); 2332 R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached);
2349 2333
2350 // Create the transfer memory. 2334 // Create the transfer memory.
@@ -2496,7 +2480,7 @@ static Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_r
2496 2480
2497 // Reserve a new event from the process resource limit 2481 // Reserve a new event from the process resource limit
2498 KScopedResourceReservation event_reservation(kernel.CurrentProcess(), 2482 KScopedResourceReservation event_reservation(kernel.CurrentProcess(),
2499 LimitableResource::Events); 2483 LimitableResource::EventCountMax);
2500 R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); 2484 R_UNLESS(event_reservation.Succeeded(), ResultLimitReached);
2501 2485
2502 // Create a new event. 2486 // Create a new event.
@@ -2539,11 +2523,6 @@ static Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out
2539static Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { 2523static Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
2540 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); 2524 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type);
2541 2525
2542 // This function currently only allows retrieving a process' status.
2543 enum class InfoType {
2544 Status,
2545 };
2546
2547 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 2526 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
2548 KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); 2527 KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
2549 if (process.IsNull()) { 2528 if (process.IsNull()) {
@@ -2552,9 +2531,9 @@ static Result GetProcessInfo(Core::System& system, u64* out, Handle process_hand
2552 return ResultInvalidHandle; 2531 return ResultInvalidHandle;
2553 } 2532 }
2554 2533
2555 const auto info_type = static_cast<InfoType>(type); 2534 const auto info_type = static_cast<ProcessInfoType>(type);
2556 if (info_type != InfoType::Status) { 2535 if (info_type != ProcessInfoType::ProcessState) {
2557 LOG_ERROR(Kernel_SVC, "Expected info_type to be Status but got {} instead", type); 2536 LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead", type);
2558 return ResultInvalidEnumValue; 2537 return ResultInvalidEnumValue;
2559 } 2538 }
2560 2539
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h
index 9b0305552..33eebcef6 100644
--- a/src/core/hle/kernel/svc_types.h
+++ b/src/core/hle/kernel/svc_types.h
@@ -8,6 +8,8 @@
8 8
9namespace Kernel::Svc { 9namespace Kernel::Svc {
10 10
11using Handle = u32;
12
11enum class MemoryState : u32 { 13enum class MemoryState : u32 {
12 Free = 0x00, 14 Free = 0x00,
13 Io = 0x01, 15 Io = 0x01,
@@ -55,17 +57,6 @@ enum class MemoryPermission : u32 {
55}; 57};
56DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission); 58DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission);
57 59
58struct MemoryInfo {
59 u64 addr{};
60 u64 size{};
61 MemoryState state{};
62 MemoryAttribute attr{};
63 MemoryPermission perm{};
64 u32 ipc_refcount{};
65 u32 device_refcount{};
66 u32 padding{};
67};
68
69enum class SignalType : u32 { 60enum class SignalType : u32 {
70 Signal = 0, 61 Signal = 0,
71 SignalAndIncrementIfEqual = 1, 62 SignalAndIncrementIfEqual = 1,
@@ -124,7 +115,57 @@ enum class ProcessExitReason : u32 {
124 115
125constexpr inline size_t ThreadLocalRegionSize = 0x200; 116constexpr inline size_t ThreadLocalRegionSize = 0x200;
126 117
127// Debug types. 118struct PageInfo {
119 u32 flags;
120};
121
122// Info Types.
123enum class InfoType : u32 {
124 CoreMask = 0,
125 PriorityMask = 1,
126 AliasRegionAddress = 2,
127 AliasRegionSize = 3,
128 HeapRegionAddress = 4,
129 HeapRegionSize = 5,
130 TotalMemorySize = 6,
131 UsedMemorySize = 7,
132 DebuggerAttached = 8,
133 ResourceLimit = 9,
134 IdleTickCount = 10,
135 RandomEntropy = 11,
136 AslrRegionAddress = 12,
137 AslrRegionSize = 13,
138 StackRegionAddress = 14,
139 StackRegionSize = 15,
140 SystemResourceSizeTotal = 16,
141 SystemResourceSizeUsed = 17,
142 ProgramId = 18,
143 InitialProcessIdRange = 19,
144 UserExceptionContextAddress = 20,
145 TotalNonSystemMemorySize = 21,
146 UsedNonSystemMemorySize = 22,
147 IsApplication = 23,
148 FreeThreadCount = 24,
149 ThreadTickCount = 25,
150 IsSvcPermitted = 26,
151
152 MesosphereMeta = 65000,
153 MesosphereCurrentProcess = 65001,
154};
155
156enum class BreakReason : u32 {
157 Panic = 0,
158 Assert = 1,
159 User = 2,
160 PreLoadDll = 3,
161 PostLoadDll = 4,
162 PreUnloadDll = 5,
163 PostUnloadDll = 6,
164 CppException = 7,
165
166 NotificationOnlyFlag = 0x80000000,
167};
168
128enum class DebugEvent : u32 { 169enum class DebugEvent : u32 {
129 CreateProcess = 0, 170 CreateProcess = 0,
130 CreateThread = 1, 171 CreateThread = 1,
@@ -133,6 +174,14 @@ enum class DebugEvent : u32 {
133 Exception = 4, 174 Exception = 4,
134}; 175};
135 176
177enum class DebugThreadParam : u32 {
178 Priority = 0,
179 State = 1,
180 IdealCore = 2,
181 CurrentCore = 3,
182 AffinityMask = 4,
183};
184
136enum class DebugException : u32 { 185enum class DebugException : u32 {
137 UndefinedInstruction = 0, 186 UndefinedInstruction = 0,
138 InstructionAbort = 1, 187 InstructionAbort = 1,
@@ -146,4 +195,401 @@ enum class DebugException : u32 {
146 MemorySystemError = 9, 195 MemorySystemError = 9,
147}; 196};
148 197
198enum class DebugEventFlag : u32 {
199 Stopped = (1u << 0),
200};
201
202enum class BreakPointType : u32 {
203 HardwareInstruction = 0,
204 HardwareData = 1,
205};
206
207enum class HardwareBreakPointRegisterName : u32 {
208 I0 = 0,
209 I1 = 1,
210 I2 = 2,
211 I3 = 3,
212 I4 = 4,
213 I5 = 5,
214 I6 = 6,
215 I7 = 7,
216 I8 = 8,
217 I9 = 9,
218 I10 = 10,
219 I11 = 11,
220 I12 = 12,
221 I13 = 13,
222 I14 = 14,
223 I15 = 15,
224 D0 = 16,
225 D1 = 17,
226 D2 = 18,
227 D3 = 19,
228 D4 = 20,
229 D5 = 21,
230 D6 = 22,
231 D7 = 23,
232 D8 = 24,
233 D9 = 25,
234 D10 = 26,
235 D11 = 27,
236 D12 = 28,
237 D13 = 29,
238 D14 = 30,
239 D15 = 31,
240};
241
242namespace lp64 {
243struct LastThreadContext {
244 u64 fp;
245 u64 sp;
246 u64 lr;
247 u64 pc;
248};
249
250struct PhysicalMemoryInfo {
251 PAddr physical_address;
252 u64 virtual_address;
253 u64 size;
254};
255
256struct DebugInfoCreateProcess {
257 u64 program_id;
258 u64 process_id;
259 std::array<char, 0xC> name;
260 u32 flags;
261 u64 user_exception_context_address; // 5.0.0+
262};
263
264struct DebugInfoCreateThread {
265 u64 thread_id;
266 u64 tls_address;
267 // Removed in 11.0.0 u64 entrypoint;
268};
269
270struct DebugInfoExitProcess {
271 ProcessExitReason reason;
272};
273
274struct DebugInfoExitThread {
275 ThreadExitReason reason;
276};
277
278struct DebugInfoUndefinedInstructionException {
279 u32 insn;
280};
281
282struct DebugInfoDataAbortException {
283 u64 address;
284};
285
286struct DebugInfoAlignmentFaultException {
287 u64 address;
288};
289
290struct DebugInfoBreakPointException {
291 BreakPointType type;
292 u64 address;
293};
294
295struct DebugInfoUserBreakException {
296 BreakReason break_reason;
297 u64 address;
298 u64 size;
299};
300
301struct DebugInfoDebuggerBreakException {
302 std::array<u64, 4> active_thread_ids;
303};
304
305struct DebugInfoUndefinedSystemCallException {
306 u32 id;
307};
308
309union DebugInfoSpecificException {
310 DebugInfoUndefinedInstructionException undefined_instruction;
311 DebugInfoDataAbortException data_abort;
312 DebugInfoAlignmentFaultException alignment_fault;
313 DebugInfoBreakPointException break_point;
314 DebugInfoUserBreakException user_break;
315 DebugInfoDebuggerBreakException debugger_break;
316 DebugInfoUndefinedSystemCallException undefined_system_call;
317 u64 raw;
318};
319
320struct DebugInfoException {
321 DebugException type;
322 u64 address;
323 DebugInfoSpecificException specific;
324};
325
326union DebugInfo {
327 DebugInfoCreateProcess create_process;
328 DebugInfoCreateThread create_thread;
329 DebugInfoExitProcess exit_process;
330 DebugInfoExitThread exit_thread;
331 DebugInfoException exception;
332};
333
334struct DebugEventInfo {
335 DebugEvent type;
336 u32 flags;
337 u64 thread_id;
338 DebugInfo info;
339};
340static_assert(sizeof(DebugEventInfo) >= 0x40);
341
342struct SecureMonitorArguments {
343 std::array<u64, 8> r;
344};
345static_assert(sizeof(SecureMonitorArguments) == 0x40);
346} // namespace lp64
347
348namespace ilp32 {
349struct LastThreadContext {
350 u32 fp;
351 u32 sp;
352 u32 lr;
353 u32 pc;
354};
355
356struct PhysicalMemoryInfo {
357 PAddr physical_address;
358 u32 virtual_address;
359 u32 size;
360};
361
362struct DebugInfoCreateProcess {
363 u64 program_id;
364 u64 process_id;
365 std::array<char, 0xC> name;
366 u32 flags;
367 u32 user_exception_context_address; // 5.0.0+
368};
369
370struct DebugInfoCreateThread {
371 u64 thread_id;
372 u32 tls_address;
373 // Removed in 11.0.0 u32 entrypoint;
374};
375
376struct DebugInfoExitProcess {
377 ProcessExitReason reason;
378};
379
380struct DebugInfoExitThread {
381 ThreadExitReason reason;
382};
383
384struct DebugInfoUndefinedInstructionException {
385 u32 insn;
386};
387
388struct DebugInfoDataAbortException {
389 u32 address;
390};
391
392struct DebugInfoAlignmentFaultException {
393 u32 address;
394};
395
396struct DebugInfoBreakPointException {
397 BreakPointType type;
398 u32 address;
399};
400
401struct DebugInfoUserBreakException {
402 BreakReason break_reason;
403 u32 address;
404 u32 size;
405};
406
407struct DebugInfoDebuggerBreakException {
408 std::array<u64, 4> active_thread_ids;
409};
410
411struct DebugInfoUndefinedSystemCallException {
412 u32 id;
413};
414
415union DebugInfoSpecificException {
416 DebugInfoUndefinedInstructionException undefined_instruction;
417 DebugInfoDataAbortException data_abort;
418 DebugInfoAlignmentFaultException alignment_fault;
419 DebugInfoBreakPointException break_point;
420 DebugInfoUserBreakException user_break;
421 DebugInfoDebuggerBreakException debugger_break;
422 DebugInfoUndefinedSystemCallException undefined_system_call;
423 u64 raw;
424};
425
426struct DebugInfoException {
427 DebugException type;
428 u32 address;
429 DebugInfoSpecificException specific;
430};
431
432union DebugInfo {
433 DebugInfoCreateProcess create_process;
434 DebugInfoCreateThread create_thread;
435 DebugInfoExitProcess exit_process;
436 DebugInfoExitThread exit_thread;
437 DebugInfoException exception;
438};
439
440struct DebugEventInfo {
441 DebugEvent type;
442 u32 flags;
443 u64 thread_id;
444 DebugInfo info;
445};
446
447struct SecureMonitorArguments {
448 std::array<u32, 8> r;
449};
450static_assert(sizeof(SecureMonitorArguments) == 0x20);
451} // namespace ilp32
452
453struct ThreadContext {
454 std::array<u64, 29> r;
455 u64 fp;
456 u64 lr;
457 u64 sp;
458 u64 pc;
459 u32 pstate;
460 u32 padding;
461 std::array<u128, 32> v;
462 u32 fpcr;
463 u32 fpsr;
464 u64 tpidr;
465};
466static_assert(sizeof(ThreadContext) == 0x320);
467
468struct MemoryInfo {
469 u64 base_address;
470 u64 size;
471 MemoryState state;
472 MemoryAttribute attribute;
473 MemoryPermission permission;
474 u32 ipc_count;
475 u32 device_count;
476 u32 padding;
477};
478
479enum class LimitableResource : u32 {
480 PhysicalMemoryMax = 0,
481 ThreadCountMax = 1,
482 EventCountMax = 2,
483 TransferMemoryCountMax = 3,
484 SessionCountMax = 4,
485 Count,
486};
487
488enum class IoPoolType : u32 {
489 // Not supported.
490 Count = 0,
491};
492
493enum class MemoryMapping : u32 {
494 IoRegister = 0,
495 Uncached = 1,
496 Memory = 2,
497};
498
499enum class KernelDebugType : u32 {
500 Thread = 0,
501 ThreadCallStack = 1,
502 KernelObject = 2,
503 Handle_ = 3,
504 Memory = 4,
505 PageTable = 5,
506 CpuUtilization = 6,
507 Process = 7,
508 SuspendProcess = 8,
509 ResumeProcess = 9,
510 Port = 10,
511};
512
513enum class KernelTraceState : u32 {
514 Disabled = 0,
515 Enabled = 1,
516};
517
518enum class CodeMemoryOperation : u32 {
519 Map = 0,
520 MapToOwner = 1,
521 Unmap = 2,
522 UnmapFromOwner = 3,
523};
524
525enum class InterruptType : u32 {
526 Edge = 0,
527 Level = 1,
528};
529
530enum class DeviceName {
531 Afi = 0,
532 Avpc = 1,
533 Dc = 2,
534 Dcb = 3,
535 Hc = 4,
536 Hda = 5,
537 Isp2 = 6,
538 MsencNvenc = 7,
539 Nv = 8,
540 Nv2 = 9,
541 Ppcs = 10,
542 Sata = 11,
543 Vi = 12,
544 Vic = 13,
545 XusbHost = 14,
546 XusbDev = 15,
547 Tsec = 16,
548 Ppcs1 = 17,
549 Dc1 = 18,
550 Sdmmc1a = 19,
551 Sdmmc2a = 20,
552 Sdmmc3a = 21,
553 Sdmmc4a = 22,
554 Isp2b = 23,
555 Gpu = 24,
556 Gpub = 25,
557 Ppcs2 = 26,
558 Nvdec = 27,
559 Ape = 28,
560 Se = 29,
561 Nvjpg = 30,
562 Hc1 = 31,
563 Se1 = 32,
564 Axiap = 33,
565 Etr = 34,
566 Tsecb = 35,
567 Tsec1 = 36,
568 Tsecb1 = 37,
569 Nvdec1 = 38,
570 Count,
571};
572
573enum class SystemInfoType : u32 {
574 TotalPhysicalMemorySize = 0,
575 UsedPhysicalMemorySize = 1,
576 InitialProcessIdRange = 2,
577};
578
579enum class ProcessInfoType : u32 {
580 ProcessState = 0,
581};
582
583struct CreateProcessParameter {
584 std::array<char, 12> name;
585 u32 version;
586 u64 program_id;
587 u64 code_address;
588 s32 code_num_pages;
589 u32 flags;
590 Handle reslimit;
591 s32 system_resource_num_pages;
592};
593static_assert(sizeof(CreateProcessParameter) == 0x30);
594
149} // namespace Kernel::Svc 595} // namespace Kernel::Svc
diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp
index af133af93..42991928e 100644
--- a/src/core/hle/service/kernel_helpers.cpp
+++ b/src/core/hle/service/kernel_helpers.cpp
@@ -31,7 +31,7 @@ ServiceContext::~ServiceContext() {
31Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { 31Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) {
32 // Reserve a new event from the process resource limit 32 // Reserve a new event from the process resource limit
33 Kernel::KScopedResourceReservation event_reservation(process, 33 Kernel::KScopedResourceReservation event_reservation(process,
34 Kernel::LimitableResource::Events); 34 Kernel::LimitableResource::EventCountMax);
35 if (!event_reservation.Succeeded()) { 35 if (!event_reservation.Succeeded()) {
36 LOG_CRITICAL(Service, "Resource limit reached!"); 36 LOG_CRITICAL(Service, "Resource limit reached!");
37 return {}; 37 return {};
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp
index 69e0fe808..1cf9dd1c4 100644
--- a/src/core/hle/service/sm/sm_controller.cpp
+++ b/src/core/hle/service/sm/sm_controller.cpp
@@ -34,8 +34,8 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) {
34 // once this is a proper process 34 // once this is a proper process
35 35
36 // Reserve a new session from the process resource limit. 36 // Reserve a new session from the process resource limit.
37 Kernel::KScopedResourceReservation session_reservation(&process, 37 Kernel::KScopedResourceReservation session_reservation(
38 Kernel::LimitableResource::Sessions); 38 &process, Kernel::LimitableResource::SessionCountMax);
39 ASSERT(session_reservation.Succeeded()); 39 ASSERT(session_reservation.Succeeded());
40 40
41 // Create the session. 41 // Create the session.
diff --git a/src/shader_recompiler/frontend/maxwell/translate_program.cpp b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
index b7162f719..376aae0ea 100644
--- a/src/shader_recompiler/frontend/maxwell/translate_program.cpp
+++ b/src/shader_recompiler/frontend/maxwell/translate_program.cpp
@@ -223,7 +223,7 @@ IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Blo
223 Optimization::PositionPass(env, program); 223 Optimization::PositionPass(env, program);
224 224
225 Optimization::GlobalMemoryToStorageBufferPass(program); 225 Optimization::GlobalMemoryToStorageBufferPass(program);
226 Optimization::TexturePass(env, program); 226 Optimization::TexturePass(env, program, host_info);
227 227
228 if (Settings::values.resolution_info.active) { 228 if (Settings::values.resolution_info.active) {
229 Optimization::RescalingPass(program); 229 Optimization::RescalingPass(program);
diff --git a/src/shader_recompiler/host_translate_info.h b/src/shader_recompiler/host_translate_info.h
index 881874310..cc1500690 100644
--- a/src/shader_recompiler/host_translate_info.h
+++ b/src/shader_recompiler/host_translate_info.h
@@ -13,6 +13,7 @@ struct HostTranslateInfo {
13 bool support_float16{}; ///< True when the device supports 16-bit floats 13 bool support_float16{}; ///< True when the device supports 16-bit floats
14 bool support_int64{}; ///< True when the device supports 64-bit integers 14 bool support_int64{}; ///< True when the device supports 64-bit integers
15 bool needs_demote_reorder{}; ///< True when the device needs DemoteToHelperInvocation reordered 15 bool needs_demote_reorder{}; ///< True when the device needs DemoteToHelperInvocation reordered
16 bool support_snorm_render_buffer{}; ///< True when the device supports SNORM render buffers
16}; 17};
17 18
18} // namespace Shader 19} // namespace Shader
diff --git a/src/shader_recompiler/ir_opt/passes.h b/src/shader_recompiler/ir_opt/passes.h
index 24f609d69..586a0668f 100644
--- a/src/shader_recompiler/ir_opt/passes.h
+++ b/src/shader_recompiler/ir_opt/passes.h
@@ -6,6 +6,10 @@
6#include "shader_recompiler/environment.h" 6#include "shader_recompiler/environment.h"
7#include "shader_recompiler/frontend/ir/program.h" 7#include "shader_recompiler/frontend/ir/program.h"
8 8
9namespace Shader {
10struct HostTranslateInfo;
11}
12
9namespace Shader::Optimization { 13namespace Shader::Optimization {
10 14
11void CollectShaderInfoPass(Environment& env, IR::Program& program); 15void CollectShaderInfoPass(Environment& env, IR::Program& program);
@@ -18,7 +22,7 @@ void LowerInt64ToInt32(IR::Program& program);
18void RescalingPass(IR::Program& program); 22void RescalingPass(IR::Program& program);
19void SsaRewritePass(IR::Program& program); 23void SsaRewritePass(IR::Program& program);
20void PositionPass(Environment& env, IR::Program& program); 24void PositionPass(Environment& env, IR::Program& program);
21void TexturePass(Environment& env, IR::Program& program); 25void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info);
22void VerificationPass(const IR::Program& program); 26void VerificationPass(const IR::Program& program);
23 27
24// Dual Vertex 28// Dual Vertex
diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp
index 9eff84a3d..f5c86fcb1 100644
--- a/src/shader_recompiler/ir_opt/texture_pass.cpp
+++ b/src/shader_recompiler/ir_opt/texture_pass.cpp
@@ -7,11 +7,11 @@
7 7
8#include <boost/container/small_vector.hpp> 8#include <boost/container/small_vector.hpp>
9 9
10#include "common/settings.h"
11#include "shader_recompiler/environment.h" 10#include "shader_recompiler/environment.h"
12#include "shader_recompiler/frontend/ir/basic_block.h" 11#include "shader_recompiler/frontend/ir/basic_block.h"
13#include "shader_recompiler/frontend/ir/breadth_first_search.h" 12#include "shader_recompiler/frontend/ir/breadth_first_search.h"
14#include "shader_recompiler/frontend/ir/ir_emitter.h" 13#include "shader_recompiler/frontend/ir/ir_emitter.h"
14#include "shader_recompiler/host_translate_info.h"
15#include "shader_recompiler/ir_opt/passes.h" 15#include "shader_recompiler/ir_opt/passes.h"
16#include "shader_recompiler/shader_info.h" 16#include "shader_recompiler/shader_info.h"
17 17
@@ -461,7 +461,7 @@ void PatchImageSampleImplicitLod(IR::Block& block, IR::Inst& inst) {
461 ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1)))))); 461 ir.FPRecip(ir.ConvertUToF(32, 32, ir.CompositeExtract(texture_size, 1))))));
462} 462}
463 463
464void PathTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) { 464void PatchTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_format) {
465 const auto it{IR::Block::InstructionList::s_iterator_to(inst)}; 465 const auto it{IR::Block::InstructionList::s_iterator_to(inst)};
466 IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; 466 IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
467 auto get_max_value = [pixel_format]() -> float { 467 auto get_max_value = [pixel_format]() -> float {
@@ -494,7 +494,7 @@ void PathTexelFetch(IR::Block& block, IR::Inst& inst, TexturePixelFormat pixel_f
494} 494}
495} // Anonymous namespace 495} // Anonymous namespace
496 496
497void TexturePass(Environment& env, IR::Program& program) { 497void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo& host_info) {
498 TextureInstVector to_replace; 498 TextureInstVector to_replace;
499 for (IR::Block* const block : program.post_order_blocks) { 499 for (IR::Block* const block : program.post_order_blocks) {
500 for (IR::Inst& inst : block->Instructions()) { 500 for (IR::Inst& inst : block->Instructions()) {
@@ -639,11 +639,11 @@ void TexturePass(Environment& env, IR::Program& program) {
639 inst->SetArg(0, IR::Value{}); 639 inst->SetArg(0, IR::Value{});
640 } 640 }
641 641
642 if (Settings::values.renderer_backend.GetValue() == Settings::RendererBackend::OpenGL && 642 if (!host_info.support_snorm_render_buffer && inst->GetOpcode() == IR::Opcode::ImageFetch &&
643 inst->GetOpcode() == IR::Opcode::ImageFetch && flags.type == TextureType::Buffer) { 643 flags.type == TextureType::Buffer) {
644 const auto pixel_format = ReadTexturePixelFormat(env, cbuf); 644 const auto pixel_format = ReadTexturePixelFormat(env, cbuf);
645 if (pixel_format != TexturePixelFormat::OTHER) { 645 if (pixel_format != TexturePixelFormat::OTHER) {
646 PathTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format); 646 PatchTexelFetch(*texture_inst.block, *texture_inst.inst, pixel_format);
647 } 647 }
648 } 648 }
649 } 649 }
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 106991969..d7f7d336c 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -73,8 +73,6 @@ add_library(video_core STATIC
73 macro/macro_hle.h 73 macro/macro_hle.h
74 macro/macro_interpreter.cpp 74 macro/macro_interpreter.cpp
75 macro/macro_interpreter.h 75 macro/macro_interpreter.h
76 macro/macro_jit_x64.cpp
77 macro/macro_jit_x64.h
78 fence_manager.h 76 fence_manager.h
79 gpu.cpp 77 gpu.cpp
80 gpu.h 78 gpu.h
@@ -245,7 +243,7 @@ add_library(video_core STATIC
245create_target_directory_groups(video_core) 243create_target_directory_groups(video_core)
246 244
247target_link_libraries(video_core PUBLIC common core) 245target_link_libraries(video_core PUBLIC common core)
248target_link_libraries(video_core PUBLIC glad shader_recompiler xbyak) 246target_link_libraries(video_core PUBLIC glad shader_recompiler)
249 247
250if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32) 248if (YUZU_USE_BUNDLED_FFMPEG AND NOT WIN32)
251 add_dependencies(video_core ffmpeg-build) 249 add_dependencies(video_core ffmpeg-build)
@@ -282,8 +280,19 @@ else()
282 280
283 -Wno-sign-conversion 281 -Wno-sign-conversion
284 ) 282 )
283
284 # xbyak
285 set_source_files_properties(macro/macro_jit_x64.cpp PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-shadow")
285endif() 286endif()
286 287
287if (ARCHITECTURE_x86_64) 288if (ARCHITECTURE_x86_64)
289 target_sources(video_core PRIVATE
290 macro/macro_jit_x64.cpp
291 macro/macro_jit_x64.h
292 )
293 target_link_libraries(video_core PUBLIC xbyak)
294endif()
295
296if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
288 target_link_libraries(video_core PRIVATE dynarmic) 297 target_link_libraries(video_core PRIVATE dynarmic)
289endif() 298endif()
diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h
index a948fcb14..910ab213a 100644
--- a/src/video_core/engines/maxwell_3d.h
+++ b/src/video_core/engines/maxwell_3d.h
@@ -2970,7 +2970,7 @@ public:
2970 CullFace gl_cull_face; ///< 0x1920 2970 CullFace gl_cull_face; ///< 0x1920
2971 Viewport::PixelCenter viewport_pixel_center; ///< 0x1924 2971 Viewport::PixelCenter viewport_pixel_center; ///< 0x1924
2972 INSERT_PADDING_BYTES_NOINIT(0x4); 2972 INSERT_PADDING_BYTES_NOINIT(0x4);
2973 u32 viewport_scale_offset_enbled; ///< 0x192C 2973 u32 viewport_scale_offset_enabled; ///< 0x192C
2974 INSERT_PADDING_BYTES_NOINIT(0xC); 2974 INSERT_PADDING_BYTES_NOINIT(0xC);
2975 ViewportClipControl viewport_clip_control; ///< 0x193C 2975 ViewportClipControl viewport_clip_control; ///< 0x193C
2976 UserClip::Op user_clip_op; ///< 0x1940 2976 UserClip::Op user_clip_op; ///< 0x1940
@@ -3482,7 +3482,7 @@ ASSERT_REG_POSITION(gl_cull_test_enabled, 0x1918);
3482ASSERT_REG_POSITION(gl_front_face, 0x191C); 3482ASSERT_REG_POSITION(gl_front_face, 0x191C);
3483ASSERT_REG_POSITION(gl_cull_face, 0x1920); 3483ASSERT_REG_POSITION(gl_cull_face, 0x1920);
3484ASSERT_REG_POSITION(viewport_pixel_center, 0x1924); 3484ASSERT_REG_POSITION(viewport_pixel_center, 0x1924);
3485ASSERT_REG_POSITION(viewport_scale_offset_enbled, 0x192C); 3485ASSERT_REG_POSITION(viewport_scale_offset_enabled, 0x192C);
3486ASSERT_REG_POSITION(viewport_clip_control, 0x193C); 3486ASSERT_REG_POSITION(viewport_clip_control, 0x193C);
3487ASSERT_REG_POSITION(user_clip_op, 0x1940); 3487ASSERT_REG_POSITION(user_clip_op, 0x1940);
3488ASSERT_REG_POSITION(render_enable_override, 0x1944); 3488ASSERT_REG_POSITION(render_enable_override, 0x1944);
diff --git a/src/video_core/macro/macro.cpp b/src/video_core/macro/macro.cpp
index f61d5998e..505d81c1e 100644
--- a/src/video_core/macro/macro.cpp
+++ b/src/video_core/macro/macro.cpp
@@ -16,7 +16,10 @@
16#include "video_core/macro/macro.h" 16#include "video_core/macro/macro.h"
17#include "video_core/macro/macro_hle.h" 17#include "video_core/macro/macro_hle.h"
18#include "video_core/macro/macro_interpreter.h" 18#include "video_core/macro/macro_interpreter.h"
19
20#ifdef ARCHITECTURE_x86_64
19#include "video_core/macro/macro_jit_x64.h" 21#include "video_core/macro/macro_jit_x64.h"
22#endif
20 23
21namespace Tegra { 24namespace Tegra {
22 25
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 72e314d39..8a8b5ce54 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -618,7 +618,7 @@ void RasterizerOpenGL::SyncViewport() {
618 } 618 }
619 flags[Dirty::Viewport0 + index] = false; 619 flags[Dirty::Viewport0 + index] = false;
620 620
621 if (!regs.viewport_scale_offset_enbled) { 621 if (!regs.viewport_scale_offset_enabled) {
622 const auto x = static_cast<GLfloat>(regs.surface_clip.x); 622 const auto x = static_cast<GLfloat>(regs.surface_clip.x);
623 const auto y = static_cast<GLfloat>(regs.surface_clip.y); 623 const auto y = static_cast<GLfloat>(regs.surface_clip.y);
624 const auto width = static_cast<GLfloat>(regs.surface_clip.width); 624 const auto width = static_cast<GLfloat>(regs.surface_clip.width);
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index 977709518..4221c2774 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -218,6 +218,7 @@ ShaderCache::ShaderCache(RasterizerOpenGL& rasterizer_, Core::Frontend::EmuWindo
218 .support_float16 = false, 218 .support_float16 = false,
219 .support_int64 = device.HasShaderInt64(), 219 .support_int64 = device.HasShaderInt64(),
220 .needs_demote_reorder = device.IsAmd(), 220 .needs_demote_reorder = device.IsAmd(),
221 .support_snorm_render_buffer = false,
221 } { 222 } {
222 if (use_asynchronous_shaders) { 223 if (use_asynchronous_shaders) {
223 workers = CreateWorkers(); 224 workers = CreateWorkers();
diff --git a/src/video_core/renderer_opengl/gl_state_tracker.cpp b/src/video_core/renderer_opengl/gl_state_tracker.cpp
index a359f96f1..d53b422ca 100644
--- a/src/video_core/renderer_opengl/gl_state_tracker.cpp
+++ b/src/video_core/renderer_opengl/gl_state_tracker.cpp
@@ -70,8 +70,8 @@ void SetupDirtyViewports(Tables& tables) {
70 FillBlock(tables[1], OFF(viewport_transform), NUM(viewport_transform), Viewports); 70 FillBlock(tables[1], OFF(viewport_transform), NUM(viewport_transform), Viewports);
71 FillBlock(tables[1], OFF(viewports), NUM(viewports), Viewports); 71 FillBlock(tables[1], OFF(viewports), NUM(viewports), Viewports);
72 72
73 tables[0][OFF(viewport_scale_offset_enbled)] = ViewportTransform; 73 tables[0][OFF(viewport_scale_offset_enabled)] = ViewportTransform;
74 tables[1][OFF(viewport_scale_offset_enbled)] = Viewports; 74 tables[1][OFF(viewport_scale_offset_enabled)] = Viewports;
75} 75}
76 76
77void SetupDirtyScissors(Tables& tables) { 77void SetupDirtyScissors(Tables& tables) {
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index b42e5be1e..e216b90d9 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -325,6 +325,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
325 .support_int64 = device.IsShaderInt64Supported(), 325 .support_int64 = device.IsShaderInt64Supported(),
326 .needs_demote_reorder = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY_KHR || 326 .needs_demote_reorder = driver_id == VK_DRIVER_ID_AMD_PROPRIETARY_KHR ||
327 driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR, 327 driver_id == VK_DRIVER_ID_AMD_OPEN_SOURCE_KHR,
328 .support_snorm_render_buffer = true,
328 }; 329 };
329} 330}
330 331
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index f79fa8313..f69c0c50f 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -683,7 +683,7 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
683 if (!state_tracker.TouchViewports()) { 683 if (!state_tracker.TouchViewports()) {
684 return; 684 return;
685 } 685 }
686 if (!regs.viewport_scale_offset_enbled) { 686 if (!regs.viewport_scale_offset_enabled) {
687 const auto x = static_cast<float>(regs.surface_clip.x); 687 const auto x = static_cast<float>(regs.surface_clip.x);
688 const auto y = static_cast<float>(regs.surface_clip.y); 688 const auto y = static_cast<float>(regs.surface_clip.y);
689 const auto width = static_cast<float>(regs.surface_clip.width); 689 const auto width = static_cast<float>(regs.surface_clip.width);
diff --git a/src/video_core/renderer_vulkan/vk_state_tracker.cpp b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
index b87c3be66..edb41b171 100644
--- a/src/video_core/renderer_vulkan/vk_state_tracker.cpp
+++ b/src/video_core/renderer_vulkan/vk_state_tracker.cpp
@@ -51,7 +51,7 @@ Flags MakeInvalidationFlags() {
51void SetupDirtyViewports(Tables& tables) { 51void SetupDirtyViewports(Tables& tables) {
52 FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports); 52 FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
53 FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports); 53 FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
54 tables[0][OFF(viewport_scale_offset_enbled)] = Viewports; 54 tables[0][OFF(viewport_scale_offset_enabled)] = Viewports;
55 tables[1][OFF(window_origin)] = Viewports; 55 tables[1][OFF(window_origin)] = Viewports;
56} 56}
57 57
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp
index 37bb76b72..f24f320b6 100644
--- a/src/video_core/shader_environment.cpp
+++ b/src/video_core/shader_environment.cpp
@@ -352,7 +352,7 @@ Shader::TexturePixelFormat GraphicsEnvironment::ReadTexturePixelFormat(u32 handl
352 352
353u32 GraphicsEnvironment::ReadViewportTransformState() { 353u32 GraphicsEnvironment::ReadViewportTransformState() {
354 const auto& regs{maxwell3d->regs}; 354 const auto& regs{maxwell3d->regs};
355 viewport_transform_state = regs.viewport_scale_offset_enbled; 355 viewport_transform_state = regs.viewport_scale_offset_enabled;
356 return viewport_transform_state; 356 return viewport_transform_state;
357} 357}
358 358
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 239f12382..5cc1fbf32 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -385,6 +385,6 @@ if (NOT APPLE)
385 target_compile_definitions(yuzu PRIVATE HAS_OPENGL) 385 target_compile_definitions(yuzu PRIVATE HAS_OPENGL)
386endif() 386endif()
387 387
388if (ARCHITECTURE_x86_64) 388if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
389 target_link_libraries(yuzu PRIVATE dynarmic) 389 target_link_libraries(yuzu PRIVATE dynarmic)
390endif() 390endif()
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 6acfb7b06..d88efacd7 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -401,224 +401,127 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {
401} 401}
402 402
403int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { 403int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) {
404 switch (qt_key) { 404 static constexpr std::array<std::pair<Qt::Key, Settings::NativeKeyboard::Keys>, 106> key_map = {
405 case Qt::Key_A: 405 std::pair<Qt::Key, Settings::NativeKeyboard::Keys>{Qt::Key_A, Settings::NativeKeyboard::A},
406 return Settings::NativeKeyboard::A; 406 {Qt::Key_A, Settings::NativeKeyboard::A},
407 case Qt::Key_B: 407 {Qt::Key_B, Settings::NativeKeyboard::B},
408 return Settings::NativeKeyboard::B; 408 {Qt::Key_C, Settings::NativeKeyboard::C},
409 case Qt::Key_C: 409 {Qt::Key_D, Settings::NativeKeyboard::D},
410 return Settings::NativeKeyboard::C; 410 {Qt::Key_E, Settings::NativeKeyboard::E},
411 case Qt::Key_D: 411 {Qt::Key_F, Settings::NativeKeyboard::F},
412 return Settings::NativeKeyboard::D; 412 {Qt::Key_G, Settings::NativeKeyboard::G},
413 case Qt::Key_E: 413 {Qt::Key_H, Settings::NativeKeyboard::H},
414 return Settings::NativeKeyboard::E; 414 {Qt::Key_I, Settings::NativeKeyboard::I},
415 case Qt::Key_F: 415 {Qt::Key_J, Settings::NativeKeyboard::J},
416 return Settings::NativeKeyboard::F; 416 {Qt::Key_K, Settings::NativeKeyboard::K},
417 case Qt::Key_G: 417 {Qt::Key_L, Settings::NativeKeyboard::L},
418 return Settings::NativeKeyboard::G; 418 {Qt::Key_M, Settings::NativeKeyboard::M},
419 case Qt::Key_H: 419 {Qt::Key_N, Settings::NativeKeyboard::N},
420 return Settings::NativeKeyboard::H; 420 {Qt::Key_O, Settings::NativeKeyboard::O},
421 case Qt::Key_I: 421 {Qt::Key_P, Settings::NativeKeyboard::P},
422 return Settings::NativeKeyboard::I; 422 {Qt::Key_Q, Settings::NativeKeyboard::Q},
423 case Qt::Key_J: 423 {Qt::Key_R, Settings::NativeKeyboard::R},
424 return Settings::NativeKeyboard::J; 424 {Qt::Key_S, Settings::NativeKeyboard::S},
425 case Qt::Key_K: 425 {Qt::Key_T, Settings::NativeKeyboard::T},
426 return Settings::NativeKeyboard::K; 426 {Qt::Key_U, Settings::NativeKeyboard::U},
427 case Qt::Key_L: 427 {Qt::Key_V, Settings::NativeKeyboard::V},
428 return Settings::NativeKeyboard::L; 428 {Qt::Key_W, Settings::NativeKeyboard::W},
429 case Qt::Key_M: 429 {Qt::Key_X, Settings::NativeKeyboard::X},
430 return Settings::NativeKeyboard::M; 430 {Qt::Key_Y, Settings::NativeKeyboard::Y},
431 case Qt::Key_N: 431 {Qt::Key_Z, Settings::NativeKeyboard::Z},
432 return Settings::NativeKeyboard::N; 432 {Qt::Key_1, Settings::NativeKeyboard::N1},
433 case Qt::Key_O: 433 {Qt::Key_2, Settings::NativeKeyboard::N2},
434 return Settings::NativeKeyboard::O; 434 {Qt::Key_3, Settings::NativeKeyboard::N3},
435 case Qt::Key_P: 435 {Qt::Key_4, Settings::NativeKeyboard::N4},
436 return Settings::NativeKeyboard::P; 436 {Qt::Key_5, Settings::NativeKeyboard::N5},
437 case Qt::Key_Q: 437 {Qt::Key_6, Settings::NativeKeyboard::N6},
438 return Settings::NativeKeyboard::Q; 438 {Qt::Key_7, Settings::NativeKeyboard::N7},
439 case Qt::Key_R: 439 {Qt::Key_8, Settings::NativeKeyboard::N8},
440 return Settings::NativeKeyboard::R; 440 {Qt::Key_9, Settings::NativeKeyboard::N9},
441 case Qt::Key_S: 441 {Qt::Key_0, Settings::NativeKeyboard::N0},
442 return Settings::NativeKeyboard::S; 442 {Qt::Key_Return, Settings::NativeKeyboard::Return},
443 case Qt::Key_T: 443 {Qt::Key_Escape, Settings::NativeKeyboard::Escape},
444 return Settings::NativeKeyboard::T; 444 {Qt::Key_Backspace, Settings::NativeKeyboard::Backspace},
445 case Qt::Key_U: 445 {Qt::Key_Tab, Settings::NativeKeyboard::Tab},
446 return Settings::NativeKeyboard::U; 446 {Qt::Key_Space, Settings::NativeKeyboard::Space},
447 case Qt::Key_V: 447 {Qt::Key_Minus, Settings::NativeKeyboard::Minus},
448 return Settings::NativeKeyboard::V; 448 {Qt::Key_Plus, Settings::NativeKeyboard::Plus},
449 case Qt::Key_W: 449 {Qt::Key_questiondown, Settings::NativeKeyboard::Plus},
450 return Settings::NativeKeyboard::W; 450 {Qt::Key_BracketLeft, Settings::NativeKeyboard::OpenBracket},
451 case Qt::Key_X: 451 {Qt::Key_BraceLeft, Settings::NativeKeyboard::OpenBracket},
452 return Settings::NativeKeyboard::X; 452 {Qt::Key_BracketRight, Settings::NativeKeyboard::CloseBracket},
453 case Qt::Key_Y: 453 {Qt::Key_BraceRight, Settings::NativeKeyboard::CloseBracket},
454 return Settings::NativeKeyboard::Y; 454 {Qt::Key_Bar, Settings::NativeKeyboard::Pipe},
455 case Qt::Key_Z: 455 {Qt::Key_Dead_Tilde, Settings::NativeKeyboard::Tilde},
456 return Settings::NativeKeyboard::Z; 456 {Qt::Key_Ntilde, Settings::NativeKeyboard::Semicolon},
457 case Qt::Key_1: 457 {Qt::Key_Semicolon, Settings::NativeKeyboard::Semicolon},
458 return Settings::NativeKeyboard::N1; 458 {Qt::Key_Apostrophe, Settings::NativeKeyboard::Quote},
459 case Qt::Key_2: 459 {Qt::Key_Dead_Grave, Settings::NativeKeyboard::Backquote},
460 return Settings::NativeKeyboard::N2; 460 {Qt::Key_Comma, Settings::NativeKeyboard::Comma},
461 case Qt::Key_3: 461 {Qt::Key_Period, Settings::NativeKeyboard::Period},
462 return Settings::NativeKeyboard::N3; 462 {Qt::Key_Slash, Settings::NativeKeyboard::Slash},
463 case Qt::Key_4: 463 {Qt::Key_CapsLock, Settings::NativeKeyboard::CapsLockKey},
464 return Settings::NativeKeyboard::N4; 464 {Qt::Key_F1, Settings::NativeKeyboard::F1},
465 case Qt::Key_5: 465 {Qt::Key_F2, Settings::NativeKeyboard::F2},
466 return Settings::NativeKeyboard::N5; 466 {Qt::Key_F3, Settings::NativeKeyboard::F3},
467 case Qt::Key_6: 467 {Qt::Key_F4, Settings::NativeKeyboard::F4},
468 return Settings::NativeKeyboard::N6; 468 {Qt::Key_F5, Settings::NativeKeyboard::F5},
469 case Qt::Key_7: 469 {Qt::Key_F6, Settings::NativeKeyboard::F6},
470 return Settings::NativeKeyboard::N7; 470 {Qt::Key_F7, Settings::NativeKeyboard::F7},
471 case Qt::Key_8: 471 {Qt::Key_F8, Settings::NativeKeyboard::F8},
472 return Settings::NativeKeyboard::N8; 472 {Qt::Key_F9, Settings::NativeKeyboard::F9},
473 case Qt::Key_9: 473 {Qt::Key_F10, Settings::NativeKeyboard::F10},
474 return Settings::NativeKeyboard::N9; 474 {Qt::Key_F11, Settings::NativeKeyboard::F11},
475 case Qt::Key_0: 475 {Qt::Key_F12, Settings::NativeKeyboard::F12},
476 return Settings::NativeKeyboard::N0; 476 {Qt::Key_Print, Settings::NativeKeyboard::PrintScreen},
477 case Qt::Key_Return: 477 {Qt::Key_ScrollLock, Settings::NativeKeyboard::ScrollLockKey},
478 return Settings::NativeKeyboard::Return; 478 {Qt::Key_Pause, Settings::NativeKeyboard::Pause},
479 case Qt::Key_Escape: 479 {Qt::Key_Insert, Settings::NativeKeyboard::Insert},
480 return Settings::NativeKeyboard::Escape; 480 {Qt::Key_Home, Settings::NativeKeyboard::Home},
481 case Qt::Key_Backspace: 481 {Qt::Key_PageUp, Settings::NativeKeyboard::PageUp},
482 return Settings::NativeKeyboard::Backspace; 482 {Qt::Key_Delete, Settings::NativeKeyboard::Delete},
483 case Qt::Key_Tab: 483 {Qt::Key_End, Settings::NativeKeyboard::End},
484 return Settings::NativeKeyboard::Tab; 484 {Qt::Key_PageDown, Settings::NativeKeyboard::PageDown},
485 case Qt::Key_Space: 485 {Qt::Key_Right, Settings::NativeKeyboard::Right},
486 return Settings::NativeKeyboard::Space; 486 {Qt::Key_Left, Settings::NativeKeyboard::Left},
487 case Qt::Key_Minus: 487 {Qt::Key_Down, Settings::NativeKeyboard::Down},
488 return Settings::NativeKeyboard::Minus; 488 {Qt::Key_Up, Settings::NativeKeyboard::Up},
489 case Qt::Key_Plus: 489 {Qt::Key_NumLock, Settings::NativeKeyboard::NumLockKey},
490 case Qt::Key_questiondown: 490 // Numpad keys are missing here
491 return Settings::NativeKeyboard::Plus; 491 {Qt::Key_F13, Settings::NativeKeyboard::F13},
492 case Qt::Key_BracketLeft: 492 {Qt::Key_F14, Settings::NativeKeyboard::F14},
493 case Qt::Key_BraceLeft: 493 {Qt::Key_F15, Settings::NativeKeyboard::F15},
494 return Settings::NativeKeyboard::OpenBracket; 494 {Qt::Key_F16, Settings::NativeKeyboard::F16},
495 case Qt::Key_BracketRight: 495 {Qt::Key_F17, Settings::NativeKeyboard::F17},
496 case Qt::Key_BraceRight: 496 {Qt::Key_F18, Settings::NativeKeyboard::F18},
497 return Settings::NativeKeyboard::CloseBracket; 497 {Qt::Key_F19, Settings::NativeKeyboard::F19},
498 case Qt::Key_Bar: 498 {Qt::Key_F20, Settings::NativeKeyboard::F20},
499 return Settings::NativeKeyboard::Pipe; 499 {Qt::Key_F21, Settings::NativeKeyboard::F21},
500 case Qt::Key_Dead_Tilde: 500 {Qt::Key_F22, Settings::NativeKeyboard::F22},
501 return Settings::NativeKeyboard::Tilde; 501 {Qt::Key_F23, Settings::NativeKeyboard::F23},
502 case Qt::Key_Ntilde: 502 {Qt::Key_F24, Settings::NativeKeyboard::F24},
503 case Qt::Key_Semicolon: 503 // {Qt::..., Settings::NativeKeyboard::KPComma},
504 return Settings::NativeKeyboard::Semicolon; 504 // {Qt::..., Settings::NativeKeyboard::Ro},
505 case Qt::Key_Apostrophe: 505 {Qt::Key_Hiragana_Katakana, Settings::NativeKeyboard::KatakanaHiragana},
506 return Settings::NativeKeyboard::Quote; 506 {Qt::Key_yen, Settings::NativeKeyboard::Yen},
507 case Qt::Key_Dead_Grave: 507 {Qt::Key_Henkan, Settings::NativeKeyboard::Henkan},
508 return Settings::NativeKeyboard::Backquote; 508 {Qt::Key_Muhenkan, Settings::NativeKeyboard::Muhenkan},
509 case Qt::Key_Comma: 509 // {Qt::..., Settings::NativeKeyboard::NumPadCommaPc98},
510 return Settings::NativeKeyboard::Comma; 510 {Qt::Key_Hangul, Settings::NativeKeyboard::HangulEnglish},
511 case Qt::Key_Period: 511 {Qt::Key_Hangul_Hanja, Settings::NativeKeyboard::Hanja},
512 return Settings::NativeKeyboard::Period; 512 {Qt::Key_Katakana, Settings::NativeKeyboard::KatakanaKey},
513 case Qt::Key_Slash: 513 {Qt::Key_Hiragana, Settings::NativeKeyboard::HiraganaKey},
514 return Settings::NativeKeyboard::Slash; 514 {Qt::Key_Zenkaku_Hankaku, Settings::NativeKeyboard::ZenkakuHankaku},
515 case Qt::Key_CapsLock: 515 // Modifier keys are handled by the modifier property
516 return Settings::NativeKeyboard::CapsLock; 516 };
517 case Qt::Key_F1: 517
518 return Settings::NativeKeyboard::F1; 518 for (const auto& [qkey, nkey] : key_map) {
519 case Qt::Key_F2: 519 if (qt_key == qkey) {
520 return Settings::NativeKeyboard::F2; 520 return nkey;
521 case Qt::Key_F3: 521 }
522 return Settings::NativeKeyboard::F3;
523 case Qt::Key_F4:
524 return Settings::NativeKeyboard::F4;
525 case Qt::Key_F5:
526 return Settings::NativeKeyboard::F5;
527 case Qt::Key_F6:
528 return Settings::NativeKeyboard::F6;
529 case Qt::Key_F7:
530 return Settings::NativeKeyboard::F7;
531 case Qt::Key_F8:
532 return Settings::NativeKeyboard::F8;
533 case Qt::Key_F9:
534 return Settings::NativeKeyboard::F9;
535 case Qt::Key_F10:
536 return Settings::NativeKeyboard::F10;
537 case Qt::Key_F11:
538 return Settings::NativeKeyboard::F11;
539 case Qt::Key_F12:
540 return Settings::NativeKeyboard::F12;
541 case Qt::Key_Print:
542 return Settings::NativeKeyboard::PrintScreen;
543 case Qt::Key_ScrollLock:
544 return Settings::NativeKeyboard::ScrollLock;
545 case Qt::Key_Pause:
546 return Settings::NativeKeyboard::Pause;
547 case Qt::Key_Insert:
548 return Settings::NativeKeyboard::Insert;
549 case Qt::Key_Home:
550 return Settings::NativeKeyboard::Home;
551 case Qt::Key_PageUp:
552 return Settings::NativeKeyboard::PageUp;
553 case Qt::Key_Delete:
554 return Settings::NativeKeyboard::Delete;
555 case Qt::Key_End:
556 return Settings::NativeKeyboard::End;
557 case Qt::Key_PageDown:
558 return Settings::NativeKeyboard::PageDown;
559 case Qt::Key_Right:
560 return Settings::NativeKeyboard::Right;
561 case Qt::Key_Left:
562 return Settings::NativeKeyboard::Left;
563 case Qt::Key_Down:
564 return Settings::NativeKeyboard::Down;
565 case Qt::Key_Up:
566 return Settings::NativeKeyboard::Up;
567 case Qt::Key_NumLock:
568 return Settings::NativeKeyboard::NumLock;
569 // Numpad keys are missing here
570 case Qt::Key_F13:
571 return Settings::NativeKeyboard::F13;
572 case Qt::Key_F14:
573 return Settings::NativeKeyboard::F14;
574 case Qt::Key_F15:
575 return Settings::NativeKeyboard::F15;
576 case Qt::Key_F16:
577 return Settings::NativeKeyboard::F16;
578 case Qt::Key_F17:
579 return Settings::NativeKeyboard::F17;
580 case Qt::Key_F18:
581 return Settings::NativeKeyboard::F18;
582 case Qt::Key_F19:
583 return Settings::NativeKeyboard::F19;
584 case Qt::Key_F20:
585 return Settings::NativeKeyboard::F20;
586 case Qt::Key_F21:
587 return Settings::NativeKeyboard::F21;
588 case Qt::Key_F22:
589 return Settings::NativeKeyboard::F22;
590 case Qt::Key_F23:
591 return Settings::NativeKeyboard::F23;
592 case Qt::Key_F24:
593 return Settings::NativeKeyboard::F24;
594 // case Qt:::
595 // return Settings::NativeKeyboard::KPComma;
596 // case Qt:::
597 // return Settings::NativeKeyboard::Ro;
598 case Qt::Key_Hiragana_Katakana:
599 return Settings::NativeKeyboard::KatakanaHiragana;
600 case Qt::Key_yen:
601 return Settings::NativeKeyboard::Yen;
602 case Qt::Key_Henkan:
603 return Settings::NativeKeyboard::Henkan;
604 case Qt::Key_Muhenkan:
605 return Settings::NativeKeyboard::Muhenkan;
606 // case Qt:::
607 // return Settings::NativeKeyboard::NumPadCommaPc98;
608 case Qt::Key_Hangul:
609 return Settings::NativeKeyboard::HangulEnglish;
610 case Qt::Key_Hangul_Hanja:
611 return Settings::NativeKeyboard::Hanja;
612 case Qt::Key_Katakana:
613 return Settings::NativeKeyboard::KatakanaKey;
614 case Qt::Key_Hiragana:
615 return Settings::NativeKeyboard::HiraganaKey;
616 case Qt::Key_Zenkaku_Hankaku:
617 return Settings::NativeKeyboard::ZenkakuHankaku;
618 // Modifier keys are handled by the modifier property
619 default:
620 return Settings::NativeKeyboard::None;
621 } 522 }
523
524 return Settings::NativeKeyboard::None;
622} 525}
623 526
624int GRenderWindow::QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers) { 527int GRenderWindow::QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers) {
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 693eaef02..01a002e4f 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2020,38 +2020,50 @@ static bool RomFSRawCopy(QProgressDialog& dialog, const FileSys::VirtualDir& src
2020 return true; 2020 return true;
2021} 2021}
2022 2022
2023QString GMainWindow::GetGameListErrorRemoving(InstalledEntryType type) const {
2024 switch (type) {
2025 case InstalledEntryType::Game:
2026 return tr("Error Removing Contents");
2027 case InstalledEntryType::Update:
2028 return tr("Error Removing Update");
2029 case InstalledEntryType::AddOnContent:
2030 return tr("Error Removing DLC");
2031 default:
2032 return QStringLiteral("Error Removing <Invalid Type>");
2033 }
2034}
2023void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type) { 2035void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type) {
2024 const QString entry_type = [type] { 2036 const QString entry_question = [type] {
2025 switch (type) { 2037 switch (type) {
2026 case InstalledEntryType::Game: 2038 case InstalledEntryType::Game:
2027 return tr("Contents"); 2039 return tr("Remove Installed Game Contents?");
2028 case InstalledEntryType::Update: 2040 case InstalledEntryType::Update:
2029 return tr("Update"); 2041 return tr("Remove Installed Game Update?");
2030 case InstalledEntryType::AddOnContent: 2042 case InstalledEntryType::AddOnContent:
2031 return tr("DLC"); 2043 return tr("Remove Installed Game DLC?");
2032 default: 2044 default:
2033 return QString{}; 2045 return QStringLiteral("Remove Installed Game <Invalid Type>?");
2034 } 2046 }
2035 }(); 2047 }();
2036 2048
2037 if (QMessageBox::question( 2049 if (QMessageBox::question(this, tr("Remove Entry"), entry_question,
2038 this, tr("Remove Entry"), tr("Remove Installed Game %1?").arg(entry_type), 2050 QMessageBox::Yes | QMessageBox::No,
2039 QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) { 2051 QMessageBox::No) != QMessageBox::Yes) {
2040 return; 2052 return;
2041 } 2053 }
2042 2054
2043 switch (type) { 2055 switch (type) {
2044 case InstalledEntryType::Game: 2056 case InstalledEntryType::Game:
2045 RemoveBaseContent(program_id, entry_type); 2057 RemoveBaseContent(program_id, type);
2046 [[fallthrough]]; 2058 [[fallthrough]];
2047 case InstalledEntryType::Update: 2059 case InstalledEntryType::Update:
2048 RemoveUpdateContent(program_id, entry_type); 2060 RemoveUpdateContent(program_id, type);
2049 if (type != InstalledEntryType::Game) { 2061 if (type != InstalledEntryType::Game) {
2050 break; 2062 break;
2051 } 2063 }
2052 [[fallthrough]]; 2064 [[fallthrough]];
2053 case InstalledEntryType::AddOnContent: 2065 case InstalledEntryType::AddOnContent:
2054 RemoveAddOnContent(program_id, entry_type); 2066 RemoveAddOnContent(program_id, type);
2055 break; 2067 break;
2056 } 2068 }
2057 Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / 2069 Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) /
@@ -2059,7 +2071,7 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT
2059 game_list->PopulateAsync(UISettings::values.game_dirs); 2071 game_list->PopulateAsync(UISettings::values.game_dirs);
2060} 2072}
2061 2073
2062void GMainWindow::RemoveBaseContent(u64 program_id, const QString& entry_type) { 2074void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) {
2063 const auto& fs_controller = system->GetFileSystemController(); 2075 const auto& fs_controller = system->GetFileSystemController();
2064 const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) || 2076 const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) ||
2065 fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id); 2077 fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id);
@@ -2069,12 +2081,12 @@ void GMainWindow::RemoveBaseContent(u64 program_id, const QString& entry_type) {
2069 tr("Successfully removed the installed base game.")); 2081 tr("Successfully removed the installed base game."));
2070 } else { 2082 } else {
2071 QMessageBox::warning( 2083 QMessageBox::warning(
2072 this, tr("Error Removing %1").arg(entry_type), 2084 this, GetGameListErrorRemoving(type),
2073 tr("The base game is not installed in the NAND and cannot be removed.")); 2085 tr("The base game is not installed in the NAND and cannot be removed."));
2074 } 2086 }
2075} 2087}
2076 2088
2077void GMainWindow::RemoveUpdateContent(u64 program_id, const QString& entry_type) { 2089void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) {
2078 const auto update_id = program_id | 0x800; 2090 const auto update_id = program_id | 0x800;
2079 const auto& fs_controller = system->GetFileSystemController(); 2091 const auto& fs_controller = system->GetFileSystemController();
2080 const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) || 2092 const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) ||
@@ -2084,12 +2096,12 @@ void GMainWindow::RemoveUpdateContent(u64 program_id, const QString& entry_type)
2084 QMessageBox::information(this, tr("Successfully Removed"), 2096 QMessageBox::information(this, tr("Successfully Removed"),
2085 tr("Successfully removed the installed update.")); 2097 tr("Successfully removed the installed update."));
2086 } else { 2098 } else {
2087 QMessageBox::warning(this, tr("Error Removing %1").arg(entry_type), 2099 QMessageBox::warning(this, GetGameListErrorRemoving(type),
2088 tr("There is no update installed for this title.")); 2100 tr("There is no update installed for this title."));
2089 } 2101 }
2090} 2102}
2091 2103
2092void GMainWindow::RemoveAddOnContent(u64 program_id, const QString& entry_type) { 2104void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) {
2093 u32 count{}; 2105 u32 count{};
2094 const auto& fs_controller = system->GetFileSystemController(); 2106 const auto& fs_controller = system->GetFileSystemController();
2095 const auto dlc_entries = system->GetContentProvider().ListEntriesFilter( 2107 const auto dlc_entries = system->GetContentProvider().ListEntriesFilter(
@@ -2107,7 +2119,7 @@ void GMainWindow::RemoveAddOnContent(u64 program_id, const QString& entry_type)
2107 } 2119 }
2108 2120
2109 if (count == 0) { 2121 if (count == 0) {
2110 QMessageBox::warning(this, tr("Error Removing %1").arg(entry_type), 2122 QMessageBox::warning(this, GetGameListErrorRemoving(type),
2111 tr("There are no DLC installed for this title.")); 2123 tr("There are no DLC installed for this title."));
2112 return; 2124 return;
2113 } 2125 }
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 150ada84c..b73f550dd 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -324,9 +324,10 @@ private slots:
324 void OnMouseActivity(); 324 void OnMouseActivity();
325 325
326private: 326private:
327 void RemoveBaseContent(u64 program_id, const QString& entry_type); 327 QString GetGameListErrorRemoving(InstalledEntryType type) const;
328 void RemoveUpdateContent(u64 program_id, const QString& entry_type); 328 void RemoveBaseContent(u64 program_id, InstalledEntryType type);
329 void RemoveAddOnContent(u64 program_id, const QString& entry_type); 329 void RemoveUpdateContent(u64 program_id, InstalledEntryType type);
330 void RemoveAddOnContent(u64 program_id, InstalledEntryType type);
330 void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target); 331 void RemoveTransferableShaderCache(u64 program_id, GameListRemoveTarget target);
331 void RemoveAllTransferableShaderCaches(u64 program_id); 332 void RemoveAllTransferableShaderCaches(u64 program_id);
332 void RemoveCustomConfiguration(u64 program_id, const std::string& game_path); 333 void RemoveCustomConfiguration(u64 program_id, const std::string& game_path);