diff options
25 files changed, 772 insertions, 398 deletions
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/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 { | |||
| 61 | Result KClientPort::CreateSession(KClientSession** out) { | 61 | Result 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() { | |||
| 50 | void KEvent::PostDestroy(uintptr_t arg) { | 50 | void 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 | */ |
| 39 | void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) { | 39 | void 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 | ||
| 126 | u64 KProcess::GetTotalPhysicalMemoryAvailable() { | 126 | u64 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 | ||
| 407 | void KProcess::Run(s32 main_thread_priority, u64 stack_size) { | 407 | void 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 | ||
| 17 | namespace Kernel { | 17 | namespace Kernel { |
| 18 | class KernelCore; | 18 | class KernelCore; |
| 19 | enum class LimitableResource : u32 { | 19 | |
| 20 | PhysicalMemory = 0, | 20 | using LimitableResource = Svc::LimitableResource; |
| 21 | Threads = 1, | ||
| 22 | Events = 2, | ||
| 23 | TransferMemory = 3, | ||
| 24 | Sessions = 4, | ||
| 25 | |||
| 26 | Count, | ||
| 27 | }; | ||
| 28 | 21 | ||
| 29 | constexpr bool IsValidResourceType(LimitableResource type) { | 22 | constexpr 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() { | |||
| 76 | void KSession::PostDestroy(uintptr_t arg) { | 76 | void 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 { | |||
| 14 | KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | 14 | KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} |
| 15 | 15 | ||
| 16 | KSharedMemory::~KSharedMemory() { | 16 | KSharedMemory::~KSharedMemory() { |
| 17 | kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); | 17 | kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, size); |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, | 20 | Result 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 | ||
| 58 | void KSharedMemory::Finalize() { | 58 | void 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 cc88d08f0..21207fe99 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -263,9 +263,9 @@ Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_ | |||
| 263 | R_SUCCEED(); | 263 | R_SUCCEED(); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | Result KThread::InitializeDummyThread(KThread* thread) { | 266 | Result KThread::InitializeDummyThread(KThread* thread, KProcess* owner) { |
| 267 | // Initialize the thread. | 267 | // Initialize the thread. |
| 268 | R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, {}, ThreadType::Dummy)); | 268 | R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy)); |
| 269 | 269 | ||
| 270 | // Initialize emulation parameters. | 270 | // Initialize emulation parameters. |
| 271 | thread->stack_parameters.disable_count = 0; | 271 | thread->stack_parameters.disable_count = 0; |
| @@ -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_thread.h b/src/core/hle/kernel/k_thread.h index 30aa10c9a..f38c92bff 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -415,7 +415,7 @@ public: | |||
| 415 | 415 | ||
| 416 | static void PostDestroy(uintptr_t arg); | 416 | static void PostDestroy(uintptr_t arg); |
| 417 | 417 | ||
| 418 | [[nodiscard]] static Result InitializeDummyThread(KThread* thread); | 418 | [[nodiscard]] static Result InitializeDummyThread(KThread* thread, KProcess* owner); |
| 419 | 419 | ||
| 420 | [[nodiscard]] static Result InitializeMainThread(Core::System& system, KThread* thread, | 420 | [[nodiscard]] static Result InitializeMainThread(Core::System& system, KThread* thread, |
| 421 | s32 virt_core); | 421 | s32 virt_core); |
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 | ||
| 38 | void KTransferMemory::PostDestroy(uintptr_t arg) { | 38 | void 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 abff14079..b77723503 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -91,7 +91,7 @@ struct KernelCore::Impl { | |||
| 91 | pt_heap_region.GetSize()); | 91 | pt_heap_region.GetSize()); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | RegisterHostThread(); | 94 | RegisterHostThread(nullptr); |
| 95 | 95 | ||
| 96 | default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread"); | 96 | default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread"); |
| 97 | } | 97 | } |
| @@ -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 | ||
| @@ -373,15 +377,18 @@ struct KernelCore::Impl { | |||
| 373 | } | 377 | } |
| 374 | 378 | ||
| 375 | // Gets the dummy KThread for the caller, allocating a new one if this is the first time | 379 | // Gets the dummy KThread for the caller, allocating a new one if this is the first time |
| 376 | KThread* GetHostDummyThread() { | 380 | KThread* GetHostDummyThread(KThread* existing_thread) { |
| 377 | auto initialize = [this](KThread* thread) { | 381 | auto initialize = [this](KThread* thread) { |
| 378 | ASSERT(KThread::InitializeDummyThread(thread).IsSuccess()); | 382 | ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess()); |
| 379 | thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); | 383 | thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId())); |
| 380 | return thread; | 384 | return thread; |
| 381 | }; | 385 | }; |
| 382 | 386 | ||
| 383 | thread_local auto raw_thread = KThread(system.Kernel()); | 387 | thread_local KThread raw_thread{system.Kernel()}; |
| 384 | thread_local auto thread = initialize(&raw_thread); | 388 | thread_local KThread* thread = nullptr; |
| 389 | if (thread == nullptr) { | ||
| 390 | thread = (existing_thread == nullptr) ? initialize(&raw_thread) : existing_thread; | ||
| 391 | } | ||
| 385 | 392 | ||
| 386 | return thread; | 393 | return thread; |
| 387 | } | 394 | } |
| @@ -396,9 +403,9 @@ struct KernelCore::Impl { | |||
| 396 | } | 403 | } |
| 397 | 404 | ||
| 398 | /// Registers a new host thread by allocating a host thread ID for it | 405 | /// Registers a new host thread by allocating a host thread ID for it |
| 399 | void RegisterHostThread() { | 406 | void RegisterHostThread(KThread* existing_thread) { |
| 400 | [[maybe_unused]] const auto this_id = GetHostThreadId(); | 407 | [[maybe_unused]] const auto this_id = GetHostThreadId(); |
| 401 | [[maybe_unused]] const auto dummy_thread = GetHostDummyThread(); | 408 | [[maybe_unused]] const auto dummy_thread = GetHostDummyThread(existing_thread); |
| 402 | } | 409 | } |
| 403 | 410 | ||
| 404 | [[nodiscard]] u32 GetCurrentHostThreadID() { | 411 | [[nodiscard]] u32 GetCurrentHostThreadID() { |
| @@ -429,7 +436,7 @@ struct KernelCore::Impl { | |||
| 429 | KThread* GetCurrentEmuThread() { | 436 | KThread* GetCurrentEmuThread() { |
| 430 | const auto thread_id = GetCurrentHostThreadID(); | 437 | const auto thread_id = GetCurrentHostThreadID(); |
| 431 | if (thread_id >= Core::Hardware::NUM_CPU_CORES) { | 438 | if (thread_id >= Core::Hardware::NUM_CPU_CORES) { |
| 432 | return GetHostDummyThread(); | 439 | return GetHostDummyThread(nullptr); |
| 433 | } | 440 | } |
| 434 | 441 | ||
| 435 | return current_thread; | 442 | return current_thread; |
| @@ -1120,8 +1127,12 @@ void KernelCore::RegisterCoreThread(std::size_t core_id) { | |||
| 1120 | impl->RegisterCoreThread(core_id); | 1127 | impl->RegisterCoreThread(core_id); |
| 1121 | } | 1128 | } |
| 1122 | 1129 | ||
| 1123 | void KernelCore::RegisterHostThread() { | 1130 | void KernelCore::RegisterHostThread(KThread* existing_thread) { |
| 1124 | impl->RegisterHostThread(); | 1131 | impl->RegisterHostThread(existing_thread); |
| 1132 | |||
| 1133 | if (existing_thread != nullptr) { | ||
| 1134 | ASSERT(GetCurrentEmuThread() == existing_thread); | ||
| 1135 | } | ||
| 1125 | } | 1136 | } |
| 1126 | 1137 | ||
| 1127 | u32 KernelCore::GetCurrentHostThreadID() const { | 1138 | u32 KernelCore::GetCurrentHostThreadID() const { |
| @@ -1196,16 +1207,28 @@ void KernelCore::Suspend(bool suspended) { | |||
| 1196 | const bool should_suspend{exception_exited || suspended}; | 1207 | const bool should_suspend{exception_exited || suspended}; |
| 1197 | const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable; | 1208 | const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable; |
| 1198 | 1209 | ||
| 1199 | for (auto* process : GetProcessList()) { | 1210 | std::vector<KScopedAutoObject<KThread>> process_threads; |
| 1200 | process->SetActivity(activity); | 1211 | { |
| 1212 | KScopedSchedulerLock sl{*this}; | ||
| 1213 | |||
| 1214 | if (auto* process = CurrentProcess(); process != nullptr) { | ||
| 1215 | process->SetActivity(activity); | ||
| 1216 | |||
| 1217 | if (!should_suspend) { | ||
| 1218 | // Runnable now; no need to wait. | ||
| 1219 | return; | ||
| 1220 | } | ||
| 1201 | 1221 | ||
| 1202 | if (should_suspend) { | ||
| 1203 | // Wait for execution to stop | ||
| 1204 | for (auto* thread : process->GetThreadList()) { | 1222 | for (auto* thread : process->GetThreadList()) { |
| 1205 | thread->WaitUntilSuspended(); | 1223 | process_threads.emplace_back(thread); |
| 1206 | } | 1224 | } |
| 1207 | } | 1225 | } |
| 1208 | } | 1226 | } |
| 1227 | |||
| 1228 | // Wait for execution to stop. | ||
| 1229 | for (auto& thread : process_threads) { | ||
| 1230 | thread->WaitUntilSuspended(); | ||
| 1231 | } | ||
| 1209 | } | 1232 | } |
| 1210 | 1233 | ||
| 1211 | void KernelCore::ShutdownCores() { | 1234 | void KernelCore::ShutdownCores() { |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 29617d736..2e22fe0f6 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -240,7 +240,7 @@ public: | |||
| 240 | void RegisterCoreThread(std::size_t core_id); | 240 | void RegisterCoreThread(std::size_t core_id); |
| 241 | 241 | ||
| 242 | /// Register the current thread as a non CPU core thread. | 242 | /// Register the current thread as a non CPU core thread. |
| 243 | void RegisterHostThread(); | 243 | void RegisterHostThread(KThread* existing_thread = nullptr); |
| 244 | 244 | ||
| 245 | /// Gets the virtual memory manager for the kernel. | 245 | /// Gets the virtual memory manager for the kernel. |
| 246 | KMemoryManager& MemoryManager(); | 246 | KMemoryManager& MemoryManager(); |
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index c8fe42537..f5c2ab23f 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp | |||
| @@ -36,11 +36,12 @@ public: | |||
| 36 | private: | 36 | private: |
| 37 | KernelCore& kernel; | 37 | KernelCore& kernel; |
| 38 | 38 | ||
| 39 | std::jthread m_thread; | 39 | std::jthread m_host_thread; |
| 40 | std::mutex m_session_mutex; | 40 | std::mutex m_session_mutex; |
| 41 | std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions; | 41 | std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions; |
| 42 | KEvent* m_wakeup_event; | 42 | KEvent* m_wakeup_event; |
| 43 | KProcess* m_process; | 43 | KProcess* m_process; |
| 44 | KThread* m_thread; | ||
| 44 | std::atomic<bool> m_shutdown_requested; | 45 | std::atomic<bool> m_shutdown_requested; |
| 45 | const std::string m_service_name; | 46 | const std::string m_service_name; |
| 46 | }; | 47 | }; |
| @@ -132,7 +133,7 @@ void ServiceThread::Impl::SessionClosed(KServerSession* server_session, | |||
| 132 | void ServiceThread::Impl::LoopProcess() { | 133 | void ServiceThread::Impl::LoopProcess() { |
| 133 | Common::SetCurrentThreadName(m_service_name.c_str()); | 134 | Common::SetCurrentThreadName(m_service_name.c_str()); |
| 134 | 135 | ||
| 135 | kernel.RegisterHostThread(); | 136 | kernel.RegisterHostThread(m_thread); |
| 136 | 137 | ||
| 137 | while (!m_shutdown_requested.load()) { | 138 | while (!m_shutdown_requested.load()) { |
| 138 | WaitAndProcessImpl(); | 139 | WaitAndProcessImpl(); |
| @@ -160,7 +161,7 @@ ServiceThread::Impl::~Impl() { | |||
| 160 | // Shut down the processing thread. | 161 | // Shut down the processing thread. |
| 161 | m_shutdown_requested.store(true); | 162 | m_shutdown_requested.store(true); |
| 162 | m_wakeup_event->Signal(); | 163 | m_wakeup_event->Signal(); |
| 163 | m_thread.join(); | 164 | m_host_thread.join(); |
| 164 | 165 | ||
| 165 | // Lock mutex. | 166 | // Lock mutex. |
| 166 | m_session_mutex.lock(); | 167 | m_session_mutex.lock(); |
| @@ -177,6 +178,9 @@ ServiceThread::Impl::~Impl() { | |||
| 177 | m_wakeup_event->GetReadableEvent().Close(); | 178 | m_wakeup_event->GetReadableEvent().Close(); |
| 178 | m_wakeup_event->Close(); | 179 | m_wakeup_event->Close(); |
| 179 | 180 | ||
| 181 | // Close thread. | ||
| 182 | m_thread->Close(); | ||
| 183 | |||
| 180 | // Close process. | 184 | // Close process. |
| 181 | m_process->Close(); | 185 | m_process->Close(); |
| 182 | } | 186 | } |
| @@ -189,7 +193,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name) | |||
| 189 | KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit()); | 193 | KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit()); |
| 190 | 194 | ||
| 191 | // Reserve a new event from the process resource limit | 195 | // Reserve a new event from the process resource limit |
| 192 | KScopedResourceReservation event_reservation(m_process, LimitableResource::Events); | 196 | KScopedResourceReservation event_reservation(m_process, LimitableResource::EventCountMax); |
| 193 | ASSERT(event_reservation.Succeeded()); | 197 | ASSERT(event_reservation.Succeeded()); |
| 194 | 198 | ||
| 195 | // Initialize event. | 199 | // Initialize event. |
| @@ -199,11 +203,19 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name) | |||
| 199 | // Commit the event reservation. | 203 | // Commit the event reservation. |
| 200 | event_reservation.Commit(); | 204 | event_reservation.Commit(); |
| 201 | 205 | ||
| 202 | // Register the event. | 206 | // Reserve a new thread from the process resource limit |
| 203 | KEvent::Register(kernel, m_wakeup_event); | 207 | KScopedResourceReservation thread_reservation(m_process, LimitableResource::ThreadCountMax); |
| 208 | ASSERT(thread_reservation.Succeeded()); | ||
| 209 | |||
| 210 | // Initialize thread. | ||
| 211 | m_thread = KThread::Create(kernel); | ||
| 212 | ASSERT(KThread::InitializeDummyThread(m_thread, m_process).IsSuccess()); | ||
| 213 | |||
| 214 | // Commit the thread reservation. | ||
| 215 | thread_reservation.Commit(); | ||
| 204 | 216 | ||
| 205 | // Start thread. | 217 | // Start thread. |
| 206 | m_thread = std::jthread([this] { LoopProcess(); }); | 218 | m_host_thread = std::jthread([this] { LoopProcess(); }); |
| 207 | } | 219 | } |
| 208 | 220 | ||
| 209 | ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name) | 221 | ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name) |
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 | ||
| 659 | enum 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 | |||
| 669 | struct 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 |
| 678 | static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | 660 | static 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 | |||
| 2539 | static Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { | 2523 | static 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 | ||
| 9 | namespace Kernel::Svc { | 9 | namespace Kernel::Svc { |
| 10 | 10 | ||
| 11 | using Handle = u32; | ||
| 12 | |||
| 11 | enum class MemoryState : u32 { | 13 | enum 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 | }; |
| 56 | DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission); | 58 | DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission); |
| 57 | 59 | ||
| 58 | struct 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 | |||
| 69 | enum class SignalType : u32 { | 60 | enum 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 | ||
| 125 | constexpr inline size_t ThreadLocalRegionSize = 0x200; | 116 | constexpr inline size_t ThreadLocalRegionSize = 0x200; |
| 126 | 117 | ||
| 127 | // Debug types. | 118 | struct PageInfo { |
| 119 | u32 flags; | ||
| 120 | }; | ||
| 121 | |||
| 122 | // Info Types. | ||
| 123 | enum 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 | |||
| 156 | enum 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 | |||
| 128 | enum class DebugEvent : u32 { | 169 | enum 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 | ||
| 177 | enum class DebugThreadParam : u32 { | ||
| 178 | Priority = 0, | ||
| 179 | State = 1, | ||
| 180 | IdealCore = 2, | ||
| 181 | CurrentCore = 3, | ||
| 182 | AffinityMask = 4, | ||
| 183 | }; | ||
| 184 | |||
| 136 | enum class DebugException : u32 { | 185 | enum 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 | ||
| 198 | enum class DebugEventFlag : u32 { | ||
| 199 | Stopped = (1u << 0), | ||
| 200 | }; | ||
| 201 | |||
| 202 | enum class BreakPointType : u32 { | ||
| 203 | HardwareInstruction = 0, | ||
| 204 | HardwareData = 1, | ||
| 205 | }; | ||
| 206 | |||
| 207 | enum 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 | |||
| 242 | namespace lp64 { | ||
| 243 | struct LastThreadContext { | ||
| 244 | u64 fp; | ||
| 245 | u64 sp; | ||
| 246 | u64 lr; | ||
| 247 | u64 pc; | ||
| 248 | }; | ||
| 249 | |||
| 250 | struct PhysicalMemoryInfo { | ||
| 251 | PAddr physical_address; | ||
| 252 | u64 virtual_address; | ||
| 253 | u64 size; | ||
| 254 | }; | ||
| 255 | |||
| 256 | struct 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 | |||
| 264 | struct DebugInfoCreateThread { | ||
| 265 | u64 thread_id; | ||
| 266 | u64 tls_address; | ||
| 267 | // Removed in 11.0.0 u64 entrypoint; | ||
| 268 | }; | ||
| 269 | |||
| 270 | struct DebugInfoExitProcess { | ||
| 271 | ProcessExitReason reason; | ||
| 272 | }; | ||
| 273 | |||
| 274 | struct DebugInfoExitThread { | ||
| 275 | ThreadExitReason reason; | ||
| 276 | }; | ||
| 277 | |||
| 278 | struct DebugInfoUndefinedInstructionException { | ||
| 279 | u32 insn; | ||
| 280 | }; | ||
| 281 | |||
| 282 | struct DebugInfoDataAbortException { | ||
| 283 | u64 address; | ||
| 284 | }; | ||
| 285 | |||
| 286 | struct DebugInfoAlignmentFaultException { | ||
| 287 | u64 address; | ||
| 288 | }; | ||
| 289 | |||
| 290 | struct DebugInfoBreakPointException { | ||
| 291 | BreakPointType type; | ||
| 292 | u64 address; | ||
| 293 | }; | ||
| 294 | |||
| 295 | struct DebugInfoUserBreakException { | ||
| 296 | BreakReason break_reason; | ||
| 297 | u64 address; | ||
| 298 | u64 size; | ||
| 299 | }; | ||
| 300 | |||
| 301 | struct DebugInfoDebuggerBreakException { | ||
| 302 | std::array<u64, 4> active_thread_ids; | ||
| 303 | }; | ||
| 304 | |||
| 305 | struct DebugInfoUndefinedSystemCallException { | ||
| 306 | u32 id; | ||
| 307 | }; | ||
| 308 | |||
| 309 | union 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 | |||
| 320 | struct DebugInfoException { | ||
| 321 | DebugException type; | ||
| 322 | u64 address; | ||
| 323 | DebugInfoSpecificException specific; | ||
| 324 | }; | ||
| 325 | |||
| 326 | union DebugInfo { | ||
| 327 | DebugInfoCreateProcess create_process; | ||
| 328 | DebugInfoCreateThread create_thread; | ||
| 329 | DebugInfoExitProcess exit_process; | ||
| 330 | DebugInfoExitThread exit_thread; | ||
| 331 | DebugInfoException exception; | ||
| 332 | }; | ||
| 333 | |||
| 334 | struct DebugEventInfo { | ||
| 335 | DebugEvent type; | ||
| 336 | u32 flags; | ||
| 337 | u64 thread_id; | ||
| 338 | DebugInfo info; | ||
| 339 | }; | ||
| 340 | static_assert(sizeof(DebugEventInfo) >= 0x40); | ||
| 341 | |||
| 342 | struct SecureMonitorArguments { | ||
| 343 | std::array<u64, 8> r; | ||
| 344 | }; | ||
| 345 | static_assert(sizeof(SecureMonitorArguments) == 0x40); | ||
| 346 | } // namespace lp64 | ||
| 347 | |||
| 348 | namespace ilp32 { | ||
| 349 | struct LastThreadContext { | ||
| 350 | u32 fp; | ||
| 351 | u32 sp; | ||
| 352 | u32 lr; | ||
| 353 | u32 pc; | ||
| 354 | }; | ||
| 355 | |||
| 356 | struct PhysicalMemoryInfo { | ||
| 357 | PAddr physical_address; | ||
| 358 | u32 virtual_address; | ||
| 359 | u32 size; | ||
| 360 | }; | ||
| 361 | |||
| 362 | struct 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 | |||
| 370 | struct DebugInfoCreateThread { | ||
| 371 | u64 thread_id; | ||
| 372 | u32 tls_address; | ||
| 373 | // Removed in 11.0.0 u32 entrypoint; | ||
| 374 | }; | ||
| 375 | |||
| 376 | struct DebugInfoExitProcess { | ||
| 377 | ProcessExitReason reason; | ||
| 378 | }; | ||
| 379 | |||
| 380 | struct DebugInfoExitThread { | ||
| 381 | ThreadExitReason reason; | ||
| 382 | }; | ||
| 383 | |||
| 384 | struct DebugInfoUndefinedInstructionException { | ||
| 385 | u32 insn; | ||
| 386 | }; | ||
| 387 | |||
| 388 | struct DebugInfoDataAbortException { | ||
| 389 | u32 address; | ||
| 390 | }; | ||
| 391 | |||
| 392 | struct DebugInfoAlignmentFaultException { | ||
| 393 | u32 address; | ||
| 394 | }; | ||
| 395 | |||
| 396 | struct DebugInfoBreakPointException { | ||
| 397 | BreakPointType type; | ||
| 398 | u32 address; | ||
| 399 | }; | ||
| 400 | |||
| 401 | struct DebugInfoUserBreakException { | ||
| 402 | BreakReason break_reason; | ||
| 403 | u32 address; | ||
| 404 | u32 size; | ||
| 405 | }; | ||
| 406 | |||
| 407 | struct DebugInfoDebuggerBreakException { | ||
| 408 | std::array<u64, 4> active_thread_ids; | ||
| 409 | }; | ||
| 410 | |||
| 411 | struct DebugInfoUndefinedSystemCallException { | ||
| 412 | u32 id; | ||
| 413 | }; | ||
| 414 | |||
| 415 | union 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 | |||
| 426 | struct DebugInfoException { | ||
| 427 | DebugException type; | ||
| 428 | u32 address; | ||
| 429 | DebugInfoSpecificException specific; | ||
| 430 | }; | ||
| 431 | |||
| 432 | union DebugInfo { | ||
| 433 | DebugInfoCreateProcess create_process; | ||
| 434 | DebugInfoCreateThread create_thread; | ||
| 435 | DebugInfoExitProcess exit_process; | ||
| 436 | DebugInfoExitThread exit_thread; | ||
| 437 | DebugInfoException exception; | ||
| 438 | }; | ||
| 439 | |||
| 440 | struct DebugEventInfo { | ||
| 441 | DebugEvent type; | ||
| 442 | u32 flags; | ||
| 443 | u64 thread_id; | ||
| 444 | DebugInfo info; | ||
| 445 | }; | ||
| 446 | |||
| 447 | struct SecureMonitorArguments { | ||
| 448 | std::array<u32, 8> r; | ||
| 449 | }; | ||
| 450 | static_assert(sizeof(SecureMonitorArguments) == 0x20); | ||
| 451 | } // namespace ilp32 | ||
| 452 | |||
| 453 | struct 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 | }; | ||
| 466 | static_assert(sizeof(ThreadContext) == 0x320); | ||
| 467 | |||
| 468 | struct 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 | |||
| 479 | enum class LimitableResource : u32 { | ||
| 480 | PhysicalMemoryMax = 0, | ||
| 481 | ThreadCountMax = 1, | ||
| 482 | EventCountMax = 2, | ||
| 483 | TransferMemoryCountMax = 3, | ||
| 484 | SessionCountMax = 4, | ||
| 485 | Count, | ||
| 486 | }; | ||
| 487 | |||
| 488 | enum class IoPoolType : u32 { | ||
| 489 | // Not supported. | ||
| 490 | Count = 0, | ||
| 491 | }; | ||
| 492 | |||
| 493 | enum class MemoryMapping : u32 { | ||
| 494 | IoRegister = 0, | ||
| 495 | Uncached = 1, | ||
| 496 | Memory = 2, | ||
| 497 | }; | ||
| 498 | |||
| 499 | enum 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 | |||
| 513 | enum class KernelTraceState : u32 { | ||
| 514 | Disabled = 0, | ||
| 515 | Enabled = 1, | ||
| 516 | }; | ||
| 517 | |||
| 518 | enum class CodeMemoryOperation : u32 { | ||
| 519 | Map = 0, | ||
| 520 | MapToOwner = 1, | ||
| 521 | Unmap = 2, | ||
| 522 | UnmapFromOwner = 3, | ||
| 523 | }; | ||
| 524 | |||
| 525 | enum class InterruptType : u32 { | ||
| 526 | Edge = 0, | ||
| 527 | Level = 1, | ||
| 528 | }; | ||
| 529 | |||
| 530 | enum 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 | |||
| 573 | enum class SystemInfoType : u32 { | ||
| 574 | TotalPhysicalMemorySize = 0, | ||
| 575 | UsedPhysicalMemorySize = 1, | ||
| 576 | InitialProcessIdRange = 2, | ||
| 577 | }; | ||
| 578 | |||
| 579 | enum class ProcessInfoType : u32 { | ||
| 580 | ProcessState = 0, | ||
| 581 | }; | ||
| 582 | |||
| 583 | struct 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 | }; | ||
| 593 | static_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() { | |||
| 31 | Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { | 31 | Kernel::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/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 | ||
| 403 | int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { | 403 | int 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 | ||
| 624 | int GRenderWindow::QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers) { | 527 | int GRenderWindow::QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers) { |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 59e56633a..c27f8196d 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -2018,38 +2018,50 @@ static bool RomFSRawCopy(QProgressDialog& dialog, const FileSys::VirtualDir& src | |||
| 2018 | return true; | 2018 | return true; |
| 2019 | } | 2019 | } |
| 2020 | 2020 | ||
| 2021 | QString GMainWindow::GetGameListErrorRemoving(InstalledEntryType type) const { | ||
| 2022 | switch (type) { | ||
| 2023 | case InstalledEntryType::Game: | ||
| 2024 | return tr("Error Removing Contents"); | ||
| 2025 | case InstalledEntryType::Update: | ||
| 2026 | return tr("Error Removing Update"); | ||
| 2027 | case InstalledEntryType::AddOnContent: | ||
| 2028 | return tr("Error Removing DLC"); | ||
| 2029 | default: | ||
| 2030 | return QStringLiteral("Error Removing <Invalid Type>"); | ||
| 2031 | } | ||
| 2032 | } | ||
| 2021 | void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type) { | 2033 | void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryType type) { |
| 2022 | const QString entry_type = [type] { | 2034 | const QString entry_question = [type] { |
| 2023 | switch (type) { | 2035 | switch (type) { |
| 2024 | case InstalledEntryType::Game: | 2036 | case InstalledEntryType::Game: |
| 2025 | return tr("Contents"); | 2037 | return tr("Remove Installed Game Contents?"); |
| 2026 | case InstalledEntryType::Update: | 2038 | case InstalledEntryType::Update: |
| 2027 | return tr("Update"); | 2039 | return tr("Remove Installed Game Update?"); |
| 2028 | case InstalledEntryType::AddOnContent: | 2040 | case InstalledEntryType::AddOnContent: |
| 2029 | return tr("DLC"); | 2041 | return tr("Remove Installed Game DLC?"); |
| 2030 | default: | 2042 | default: |
| 2031 | return QString{}; | 2043 | return QStringLiteral("Remove Installed Game <Invalid Type>?"); |
| 2032 | } | 2044 | } |
| 2033 | }(); | 2045 | }(); |
| 2034 | 2046 | ||
| 2035 | if (QMessageBox::question( | 2047 | if (QMessageBox::question(this, tr("Remove Entry"), entry_question, |
| 2036 | this, tr("Remove Entry"), tr("Remove Installed Game %1?").arg(entry_type), | 2048 | QMessageBox::Yes | QMessageBox::No, |
| 2037 | QMessageBox::Yes | QMessageBox::No, QMessageBox::No) != QMessageBox::Yes) { | 2049 | QMessageBox::No) != QMessageBox::Yes) { |
| 2038 | return; | 2050 | return; |
| 2039 | } | 2051 | } |
| 2040 | 2052 | ||
| 2041 | switch (type) { | 2053 | switch (type) { |
| 2042 | case InstalledEntryType::Game: | 2054 | case InstalledEntryType::Game: |
| 2043 | RemoveBaseContent(program_id, entry_type); | 2055 | RemoveBaseContent(program_id, type); |
| 2044 | [[fallthrough]]; | 2056 | [[fallthrough]]; |
| 2045 | case InstalledEntryType::Update: | 2057 | case InstalledEntryType::Update: |
| 2046 | RemoveUpdateContent(program_id, entry_type); | 2058 | RemoveUpdateContent(program_id, type); |
| 2047 | if (type != InstalledEntryType::Game) { | 2059 | if (type != InstalledEntryType::Game) { |
| 2048 | break; | 2060 | break; |
| 2049 | } | 2061 | } |
| 2050 | [[fallthrough]]; | 2062 | [[fallthrough]]; |
| 2051 | case InstalledEntryType::AddOnContent: | 2063 | case InstalledEntryType::AddOnContent: |
| 2052 | RemoveAddOnContent(program_id, entry_type); | 2064 | RemoveAddOnContent(program_id, type); |
| 2053 | break; | 2065 | break; |
| 2054 | } | 2066 | } |
| 2055 | Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / | 2067 | Common::FS::RemoveDirRecursively(Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / |
| @@ -2057,7 +2069,7 @@ void GMainWindow::OnGameListRemoveInstalledEntry(u64 program_id, InstalledEntryT | |||
| 2057 | game_list->PopulateAsync(UISettings::values.game_dirs); | 2069 | game_list->PopulateAsync(UISettings::values.game_dirs); |
| 2058 | } | 2070 | } |
| 2059 | 2071 | ||
| 2060 | void GMainWindow::RemoveBaseContent(u64 program_id, const QString& entry_type) { | 2072 | void GMainWindow::RemoveBaseContent(u64 program_id, InstalledEntryType type) { |
| 2061 | const auto& fs_controller = system->GetFileSystemController(); | 2073 | const auto& fs_controller = system->GetFileSystemController(); |
| 2062 | const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) || | 2074 | const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(program_id) || |
| 2063 | fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id); | 2075 | fs_controller.GetSDMCContents()->RemoveExistingEntry(program_id); |
| @@ -2067,12 +2079,12 @@ void GMainWindow::RemoveBaseContent(u64 program_id, const QString& entry_type) { | |||
| 2067 | tr("Successfully removed the installed base game.")); | 2079 | tr("Successfully removed the installed base game.")); |
| 2068 | } else { | 2080 | } else { |
| 2069 | QMessageBox::warning( | 2081 | QMessageBox::warning( |
| 2070 | this, tr("Error Removing %1").arg(entry_type), | 2082 | this, GetGameListErrorRemoving(type), |
| 2071 | tr("The base game is not installed in the NAND and cannot be removed.")); | 2083 | tr("The base game is not installed in the NAND and cannot be removed.")); |
| 2072 | } | 2084 | } |
| 2073 | } | 2085 | } |
| 2074 | 2086 | ||
| 2075 | void GMainWindow::RemoveUpdateContent(u64 program_id, const QString& entry_type) { | 2087 | void GMainWindow::RemoveUpdateContent(u64 program_id, InstalledEntryType type) { |
| 2076 | const auto update_id = program_id | 0x800; | 2088 | const auto update_id = program_id | 0x800; |
| 2077 | const auto& fs_controller = system->GetFileSystemController(); | 2089 | const auto& fs_controller = system->GetFileSystemController(); |
| 2078 | const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) || | 2090 | const auto res = fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) || |
| @@ -2082,12 +2094,12 @@ void GMainWindow::RemoveUpdateContent(u64 program_id, const QString& entry_type) | |||
| 2082 | QMessageBox::information(this, tr("Successfully Removed"), | 2094 | QMessageBox::information(this, tr("Successfully Removed"), |
| 2083 | tr("Successfully removed the installed update.")); | 2095 | tr("Successfully removed the installed update.")); |
| 2084 | } else { | 2096 | } else { |
| 2085 | QMessageBox::warning(this, tr("Error Removing %1").arg(entry_type), | 2097 | QMessageBox::warning(this, GetGameListErrorRemoving(type), |
| 2086 | tr("There is no update installed for this title.")); | 2098 | tr("There is no update installed for this title.")); |
| 2087 | } | 2099 | } |
| 2088 | } | 2100 | } |
| 2089 | 2101 | ||
| 2090 | void GMainWindow::RemoveAddOnContent(u64 program_id, const QString& entry_type) { | 2102 | void GMainWindow::RemoveAddOnContent(u64 program_id, InstalledEntryType type) { |
| 2091 | u32 count{}; | 2103 | u32 count{}; |
| 2092 | const auto& fs_controller = system->GetFileSystemController(); | 2104 | const auto& fs_controller = system->GetFileSystemController(); |
| 2093 | const auto dlc_entries = system->GetContentProvider().ListEntriesFilter( | 2105 | const auto dlc_entries = system->GetContentProvider().ListEntriesFilter( |
| @@ -2105,7 +2117,7 @@ void GMainWindow::RemoveAddOnContent(u64 program_id, const QString& entry_type) | |||
| 2105 | } | 2117 | } |
| 2106 | 2118 | ||
| 2107 | if (count == 0) { | 2119 | if (count == 0) { |
| 2108 | QMessageBox::warning(this, tr("Error Removing %1").arg(entry_type), | 2120 | QMessageBox::warning(this, GetGameListErrorRemoving(type), |
| 2109 | tr("There are no DLC installed for this title.")); | 2121 | tr("There are no DLC installed for this title.")); |
| 2110 | return; | 2122 | return; |
| 2111 | } | 2123 | } |
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 | ||
| 326 | private: | 326 | private: |
| 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); |