diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/init/init_slab_setup.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_device_address_space.cpp | 150 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_device_address_space.h | 60 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_types.h | 14 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/fsp_srv.cpp | 2 | ||||
| -rw-r--r-- | src/input_common/helpers/stick_from_buttons.cpp | 45 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/value.h | 11 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/lobby.cpp | 16 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/lobby.h | 2 | ||||
| -rw-r--r-- | src/yuzu/multiplayer/lobby.ui | 7 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 3 | ||||
| -rw-r--r-- | src/yuzu_cmd/default_ini.h | 13 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 48 | ||||
| -rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.h | 10 |
16 files changed, 310 insertions, 79 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 3eee1cfbe..112c61b80 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -195,6 +195,8 @@ add_library(core STATIC | |||
| 195 | hle/kernel/k_condition_variable.cpp | 195 | hle/kernel/k_condition_variable.cpp |
| 196 | hle/kernel/k_condition_variable.h | 196 | hle/kernel/k_condition_variable.h |
| 197 | hle/kernel/k_debug.h | 197 | hle/kernel/k_debug.h |
| 198 | hle/kernel/k_device_address_space.cpp | ||
| 199 | hle/kernel/k_device_address_space.h | ||
| 198 | hle/kernel/k_dynamic_page_manager.h | 200 | hle/kernel/k_dynamic_page_manager.h |
| 199 | hle/kernel/k_dynamic_resource_manager.h | 201 | hle/kernel/k_dynamic_resource_manager.h |
| 200 | hle/kernel/k_dynamic_slab_heap.h | 202 | hle/kernel/k_dynamic_slab_heap.h |
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index 7b363eb1e..571acf4b2 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include "core/hle/kernel/init/init_slab_setup.h" | 11 | #include "core/hle/kernel/init/init_slab_setup.h" |
| 12 | #include "core/hle/kernel/k_code_memory.h" | 12 | #include "core/hle/kernel/k_code_memory.h" |
| 13 | #include "core/hle/kernel/k_debug.h" | 13 | #include "core/hle/kernel/k_debug.h" |
| 14 | #include "core/hle/kernel/k_device_address_space.h" | ||
| 14 | #include "core/hle/kernel/k_event.h" | 15 | #include "core/hle/kernel/k_event.h" |
| 15 | #include "core/hle/kernel/k_event_info.h" | 16 | #include "core/hle/kernel/k_event_info.h" |
| 16 | #include "core/hle/kernel/k_memory_layout.h" | 17 | #include "core/hle/kernel/k_memory_layout.h" |
| @@ -43,6 +44,7 @@ namespace Kernel::Init { | |||
| 43 | HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \ | 44 | HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \ |
| 44 | HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ | 45 | HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ |
| 45 | HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__) \ | 46 | HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__) \ |
| 47 | HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ##__VA_ARGS__) \ | ||
| 46 | HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ | 48 | HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ |
| 47 | HANDLER(KThreadLocalPage, \ | 49 | HANDLER(KThreadLocalPage, \ |
| 48 | (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \ | 50 | (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \ |
diff --git a/src/core/hle/kernel/k_device_address_space.cpp b/src/core/hle/kernel/k_device_address_space.cpp new file mode 100644 index 000000000..27659ea3b --- /dev/null +++ b/src/core/hle/kernel/k_device_address_space.cpp | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #include "common/assert.h" | ||
| 5 | #include "core/core.h" | ||
| 6 | #include "core/hle/kernel/k_device_address_space.h" | ||
| 7 | #include "core/hle/kernel/kernel.h" | ||
| 8 | #include "core/hle/kernel/svc_results.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | |||
| 12 | KDeviceAddressSpace::KDeviceAddressSpace(KernelCore& kernel_) | ||
| 13 | : KAutoObjectWithSlabHeapAndContainer(kernel_), m_lock(kernel_), m_is_initialized(false) {} | ||
| 14 | KDeviceAddressSpace::~KDeviceAddressSpace() = default; | ||
| 15 | |||
| 16 | void KDeviceAddressSpace::Initialize() { | ||
| 17 | // This just forwards to the device page table manager. | ||
| 18 | // KDevicePageTable::Initialize(); | ||
| 19 | } | ||
| 20 | |||
| 21 | // Member functions. | ||
| 22 | Result KDeviceAddressSpace::Initialize(u64 address, u64 size) { | ||
| 23 | // Initialize the device page table. | ||
| 24 | // R_TRY(m_table.Initialize(address, size)); | ||
| 25 | |||
| 26 | // Set member variables. | ||
| 27 | m_space_address = address; | ||
| 28 | m_space_size = size; | ||
| 29 | m_is_initialized = true; | ||
| 30 | |||
| 31 | R_SUCCEED(); | ||
| 32 | } | ||
| 33 | |||
| 34 | void KDeviceAddressSpace::Finalize() { | ||
| 35 | // Finalize the table. | ||
| 36 | // m_table.Finalize(); | ||
| 37 | } | ||
| 38 | |||
| 39 | Result KDeviceAddressSpace::Attach(Svc::DeviceName device_name) { | ||
| 40 | // Lock the address space. | ||
| 41 | KScopedLightLock lk(m_lock); | ||
| 42 | |||
| 43 | // Attach. | ||
| 44 | // R_RETURN(m_table.Attach(device_name, m_space_address, m_space_size)); | ||
| 45 | R_SUCCEED(); | ||
| 46 | } | ||
| 47 | |||
| 48 | Result KDeviceAddressSpace::Detach(Svc::DeviceName device_name) { | ||
| 49 | // Lock the address space. | ||
| 50 | KScopedLightLock lk(m_lock); | ||
| 51 | |||
| 52 | // Detach. | ||
| 53 | // R_RETURN(m_table.Detach(device_name)); | ||
| 54 | R_SUCCEED(); | ||
| 55 | } | ||
| 56 | |||
| 57 | Result KDeviceAddressSpace::Map(KPageTable* page_table, VAddr process_address, size_t size, | ||
| 58 | u64 device_address, u32 option, bool is_aligned) { | ||
| 59 | // Check that the address falls within the space. | ||
| 60 | R_UNLESS((m_space_address <= device_address && | ||
| 61 | device_address + size - 1 <= m_space_address + m_space_size - 1), | ||
| 62 | ResultInvalidCurrentMemory); | ||
| 63 | |||
| 64 | // Decode the option. | ||
| 65 | const Svc::MapDeviceAddressSpaceOption option_pack{option}; | ||
| 66 | const auto device_perm = option_pack.permission.Value(); | ||
| 67 | const auto flags = option_pack.flags.Value(); | ||
| 68 | const auto reserved = option_pack.reserved.Value(); | ||
| 69 | |||
| 70 | // Validate the option. | ||
| 71 | // TODO: It is likely that this check for flags == none is only on NX board. | ||
| 72 | R_UNLESS(flags == Svc::MapDeviceAddressSpaceFlag::None, ResultInvalidEnumValue); | ||
| 73 | R_UNLESS(reserved == 0, ResultInvalidEnumValue); | ||
| 74 | |||
| 75 | // Lock the address space. | ||
| 76 | KScopedLightLock lk(m_lock); | ||
| 77 | |||
| 78 | // Lock the page table to prevent concurrent device mapping operations. | ||
| 79 | // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock(); | ||
| 80 | |||
| 81 | // Lock the pages. | ||
| 82 | bool is_io{}; | ||
| 83 | R_TRY(page_table->LockForMapDeviceAddressSpace(std::addressof(is_io), process_address, size, | ||
| 84 | ConvertToKMemoryPermission(device_perm), | ||
| 85 | is_aligned, true)); | ||
| 86 | |||
| 87 | // Ensure that if we fail, we don't keep unmapped pages locked. | ||
| 88 | ON_RESULT_FAILURE { | ||
| 89 | ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess); | ||
| 90 | }; | ||
| 91 | |||
| 92 | // Check that the io status is allowable. | ||
| 93 | if (is_io) { | ||
| 94 | R_UNLESS(static_cast<u32>(flags & Svc::MapDeviceAddressSpaceFlag::NotIoRegister) == 0, | ||
| 95 | ResultInvalidCombination); | ||
| 96 | } | ||
| 97 | |||
| 98 | // Map the pages. | ||
| 99 | { | ||
| 100 | // Perform the mapping. | ||
| 101 | // R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm, | ||
| 102 | // is_aligned, is_io)); | ||
| 103 | |||
| 104 | // Ensure that we unmap the pages if we fail to update the protections. | ||
| 105 | // NOTE: Nintendo does not check the result of this unmap call. | ||
| 106 | // ON_RESULT_FAILURE { m_table.Unmap(device_address, size); }; | ||
| 107 | |||
| 108 | // Update the protections in accordance with how much we mapped. | ||
| 109 | // R_TRY(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size)); | ||
| 110 | } | ||
| 111 | |||
| 112 | // We succeeded. | ||
| 113 | R_SUCCEED(); | ||
| 114 | } | ||
| 115 | |||
| 116 | Result KDeviceAddressSpace::Unmap(KPageTable* page_table, VAddr process_address, size_t size, | ||
| 117 | u64 device_address) { | ||
| 118 | // Check that the address falls within the space. | ||
| 119 | R_UNLESS((m_space_address <= device_address && | ||
| 120 | device_address + size - 1 <= m_space_address + m_space_size - 1), | ||
| 121 | ResultInvalidCurrentMemory); | ||
| 122 | |||
| 123 | // Lock the address space. | ||
| 124 | KScopedLightLock lk(m_lock); | ||
| 125 | |||
| 126 | // Lock the page table to prevent concurrent device mapping operations. | ||
| 127 | // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock(); | ||
| 128 | |||
| 129 | // Lock the pages. | ||
| 130 | R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size, true)); | ||
| 131 | |||
| 132 | // Unmap the pages. | ||
| 133 | { | ||
| 134 | // If we fail to unmap, we want to do a partial unlock. | ||
| 135 | // ON_RESULT_FAILURE { | ||
| 136 | // ASSERT(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size) == | ||
| 137 | // ResultSuccess); | ||
| 138 | // }; | ||
| 139 | |||
| 140 | // Perform the unmap. | ||
| 141 | // R_TRY(m_table.Unmap(page_table, process_address, size, device_address)); | ||
| 142 | } | ||
| 143 | |||
| 144 | // Unlock the pages. | ||
| 145 | ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess); | ||
| 146 | |||
| 147 | R_SUCCEED(); | ||
| 148 | } | ||
| 149 | |||
| 150 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h new file mode 100644 index 000000000..4709df995 --- /dev/null +++ b/src/core/hle/kernel/k_device_address_space.h | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include <string> | ||
| 7 | |||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/kernel/k_page_table.h" | ||
| 10 | #include "core/hle/kernel/slab_helpers.h" | ||
| 11 | #include "core/hle/result.h" | ||
| 12 | |||
| 13 | namespace Kernel { | ||
| 14 | |||
| 15 | class KDeviceAddressSpace final | ||
| 16 | : public KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList> { | ||
| 17 | KERNEL_AUTOOBJECT_TRAITS(KDeviceAddressSpace, KAutoObject); | ||
| 18 | |||
| 19 | public: | ||
| 20 | explicit KDeviceAddressSpace(KernelCore& kernel); | ||
| 21 | ~KDeviceAddressSpace(); | ||
| 22 | |||
| 23 | Result Initialize(u64 address, u64 size); | ||
| 24 | void Finalize(); | ||
| 25 | |||
| 26 | bool IsInitialized() const { | ||
| 27 | return m_is_initialized; | ||
| 28 | } | ||
| 29 | static void PostDestroy(uintptr_t arg) {} | ||
| 30 | |||
| 31 | Result Attach(Svc::DeviceName device_name); | ||
| 32 | Result Detach(Svc::DeviceName device_name); | ||
| 33 | |||
| 34 | Result MapByForce(KPageTable* page_table, VAddr process_address, size_t size, | ||
| 35 | u64 device_address, u32 option) { | ||
| 36 | R_RETURN(this->Map(page_table, process_address, size, device_address, option, false)); | ||
| 37 | } | ||
| 38 | |||
| 39 | Result MapAligned(KPageTable* page_table, VAddr process_address, size_t size, | ||
| 40 | u64 device_address, u32 option) { | ||
| 41 | R_RETURN(this->Map(page_table, process_address, size, device_address, option, true)); | ||
| 42 | } | ||
| 43 | |||
| 44 | Result Unmap(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address); | ||
| 45 | |||
| 46 | static void Initialize(); | ||
| 47 | |||
| 48 | private: | ||
| 49 | Result Map(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address, | ||
| 50 | u32 option, bool is_aligned); | ||
| 51 | |||
| 52 | private: | ||
| 53 | KLightLock m_lock; | ||
| 54 | // KDevicePageTable m_table; | ||
| 55 | u64 m_space_address{}; | ||
| 56 | u64 m_space_size{}; | ||
| 57 | bool m_is_initialized{}; | ||
| 58 | }; | ||
| 59 | |||
| 60 | } // namespace Kernel | ||
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 8d22f8d2c..5f52e1e95 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -35,6 +35,7 @@ class GlobalSchedulerContext; | |||
| 35 | class KAutoObjectWithListContainer; | 35 | class KAutoObjectWithListContainer; |
| 36 | class KClientSession; | 36 | class KClientSession; |
| 37 | class KDebug; | 37 | class KDebug; |
| 38 | class KDeviceAddressSpace; | ||
| 38 | class KDynamicPageManager; | 39 | class KDynamicPageManager; |
| 39 | class KEvent; | 40 | class KEvent; |
| 40 | class KEventInfo; | 41 | class KEventInfo; |
| @@ -359,6 +360,8 @@ public: | |||
| 359 | return slab_heap_container->transfer_memory; | 360 | return slab_heap_container->transfer_memory; |
| 360 | } else if constexpr (std::is_same_v<T, KCodeMemory>) { | 361 | } else if constexpr (std::is_same_v<T, KCodeMemory>) { |
| 361 | return slab_heap_container->code_memory; | 362 | return slab_heap_container->code_memory; |
| 363 | } else if constexpr (std::is_same_v<T, KDeviceAddressSpace>) { | ||
| 364 | return slab_heap_container->device_address_space; | ||
| 362 | } else if constexpr (std::is_same_v<T, KPageBuffer>) { | 365 | } else if constexpr (std::is_same_v<T, KPageBuffer>) { |
| 363 | return slab_heap_container->page_buffer; | 366 | return slab_heap_container->page_buffer; |
| 364 | } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { | 367 | } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { |
| @@ -431,6 +434,7 @@ private: | |||
| 431 | KSlabHeap<KThread> thread; | 434 | KSlabHeap<KThread> thread; |
| 432 | KSlabHeap<KTransferMemory> transfer_memory; | 435 | KSlabHeap<KTransferMemory> transfer_memory; |
| 433 | KSlabHeap<KCodeMemory> code_memory; | 436 | KSlabHeap<KCodeMemory> code_memory; |
| 437 | KSlabHeap<KDeviceAddressSpace> device_address_space; | ||
| 434 | KSlabHeap<KPageBuffer> page_buffer; | 438 | KSlabHeap<KPageBuffer> page_buffer; |
| 435 | KSlabHeap<KThreadLocalPage> thread_local_page; | 439 | KSlabHeap<KThreadLocalPage> thread_local_page; |
| 436 | KSlabHeap<KSessionRequest> session_request; | 440 | KSlabHeap<KSessionRequest> session_request; |
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index 9c2f9998a..e90c35601 100644 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <bitset> | 6 | #include <bitset> |
| 7 | 7 | ||
| 8 | #include "common/bit_field.h" | ||
| 8 | #include "common/common_funcs.h" | 9 | #include "common/common_funcs.h" |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | 11 | ||
| @@ -498,6 +499,19 @@ enum class MemoryMapping : u32 { | |||
| 498 | Memory = 2, | 499 | Memory = 2, |
| 499 | }; | 500 | }; |
| 500 | 501 | ||
| 502 | enum class MapDeviceAddressSpaceFlag : u32 { | ||
| 503 | None = (0U << 0), | ||
| 504 | NotIoRegister = (1U << 0), | ||
| 505 | }; | ||
| 506 | DECLARE_ENUM_FLAG_OPERATORS(MapDeviceAddressSpaceFlag); | ||
| 507 | |||
| 508 | union MapDeviceAddressSpaceOption { | ||
| 509 | u32 raw; | ||
| 510 | BitField<0, 16, MemoryPermission> permission; | ||
| 511 | BitField<16, 1, MapDeviceAddressSpaceFlag> flags; | ||
| 512 | BitField<17, 15, u32> reserved; | ||
| 513 | }; | ||
| 514 | |||
| 501 | enum class KernelDebugType : u32 { | 515 | enum class KernelDebugType : u32 { |
| 502 | Thread = 0, | 516 | Thread = 0, |
| 503 | ThreadCallStack = 1, | 517 | ThreadCallStack = 1, |
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index cab44bf9c..447d624e1 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp | |||
| @@ -1083,7 +1083,7 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) { | |||
| 1083 | } | 1083 | } |
| 1084 | 1084 | ||
| 1085 | void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { | 1085 | void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { |
| 1086 | const auto raw = ctx.ReadBuffer(); | 1086 | const auto raw = ctx.ReadBufferCopy(); |
| 1087 | auto log = Common::StringFromFixedZeroTerminatedBuffer( | 1087 | auto log = Common::StringFromFixedZeroTerminatedBuffer( |
| 1088 | reinterpret_cast<const char*>(raw.data()), raw.size()); | 1088 | reinterpret_cast<const char*>(raw.data()), raw.size()); |
| 1089 | 1089 | ||
diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 096c23b07..a6be6dac1 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp | |||
| @@ -15,6 +15,9 @@ public: | |||
| 15 | // do not play nicely with the theoretical maximum range. | 15 | // do not play nicely with the theoretical maximum range. |
| 16 | // Using a value one lower from the maximum emulates real stick behavior. | 16 | // Using a value one lower from the maximum emulates real stick behavior. |
| 17 | static constexpr float MAX_RANGE = 32766.0f / 32767.0f; | 17 | static constexpr float MAX_RANGE = 32766.0f / 32767.0f; |
| 18 | static constexpr float TAU = Common::PI * 2.0f; | ||
| 19 | // Use wider angle to ease the transition. | ||
| 20 | static constexpr float APERTURE = TAU * 0.15f; | ||
| 18 | 21 | ||
| 19 | using Button = std::unique_ptr<Common::Input::InputDevice>; | 22 | using Button = std::unique_ptr<Common::Input::InputDevice>; |
| 20 | 23 | ||
| @@ -61,30 +64,23 @@ public: | |||
| 61 | } | 64 | } |
| 62 | 65 | ||
| 63 | bool IsAngleGreater(float old_angle, float new_angle) const { | 66 | bool IsAngleGreater(float old_angle, float new_angle) const { |
| 64 | constexpr float TAU = Common::PI * 2.0f; | 67 | const float top_limit = new_angle + APERTURE; |
| 65 | // Use wider angle to ease the transition. | ||
| 66 | constexpr float aperture = TAU * 0.15f; | ||
| 67 | const float top_limit = new_angle + aperture; | ||
| 68 | return (old_angle > new_angle && old_angle <= top_limit) || | 68 | return (old_angle > new_angle && old_angle <= top_limit) || |
| 69 | (old_angle + TAU > new_angle && old_angle + TAU <= top_limit); | 69 | (old_angle + TAU > new_angle && old_angle + TAU <= top_limit); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | bool IsAngleSmaller(float old_angle, float new_angle) const { | 72 | bool IsAngleSmaller(float old_angle, float new_angle) const { |
| 73 | constexpr float TAU = Common::PI * 2.0f; | 73 | const float bottom_limit = new_angle - APERTURE; |
| 74 | // Use wider angle to ease the transition. | ||
| 75 | constexpr float aperture = TAU * 0.15f; | ||
| 76 | const float bottom_limit = new_angle - aperture; | ||
| 77 | return (old_angle >= bottom_limit && old_angle < new_angle) || | 74 | return (old_angle >= bottom_limit && old_angle < new_angle) || |
| 78 | (old_angle - TAU >= bottom_limit && old_angle - TAU < new_angle); | 75 | (old_angle - TAU >= bottom_limit && old_angle - TAU < new_angle); |
| 79 | } | 76 | } |
| 80 | 77 | ||
| 81 | float GetAngle(std::chrono::time_point<std::chrono::steady_clock> now) const { | 78 | float GetAngle(std::chrono::time_point<std::chrono::steady_clock> now) const { |
| 82 | constexpr float TAU = Common::PI * 2.0f; | ||
| 83 | float new_angle = angle; | 79 | float new_angle = angle; |
| 84 | 80 | ||
| 85 | auto time_difference = static_cast<float>( | 81 | auto time_difference = static_cast<float>( |
| 86 | std::chrono::duration_cast<std::chrono::microseconds>(now - last_update).count()); | 82 | std::chrono::duration_cast<std::chrono::milliseconds>(now - last_update).count()); |
| 87 | time_difference /= 1000.0f * 1000.0f; | 83 | time_difference /= 1000.0f; |
| 88 | if (time_difference > 0.5f) { | 84 | if (time_difference > 0.5f) { |
| 89 | time_difference = 0.5f; | 85 | time_difference = 0.5f; |
| 90 | } | 86 | } |
| @@ -201,8 +197,6 @@ public: | |||
| 201 | } | 197 | } |
| 202 | 198 | ||
| 203 | void UpdateStatus() { | 199 | void UpdateStatus() { |
| 204 | const float coef = modifier_status.value ? modifier_scale : MAX_RANGE; | ||
| 205 | |||
| 206 | bool r = right_status; | 200 | bool r = right_status; |
| 207 | bool l = left_status; | 201 | bool l = left_status; |
| 208 | bool u = up_status; | 202 | bool u = up_status; |
| @@ -220,7 +214,7 @@ public: | |||
| 220 | 214 | ||
| 221 | // Move if a key is pressed | 215 | // Move if a key is pressed |
| 222 | if (r || l || u || d) { | 216 | if (r || l || u || d) { |
| 223 | amplitude = coef; | 217 | amplitude = modifier_status.value ? modifier_scale : MAX_RANGE; |
| 224 | } else { | 218 | } else { |
| 225 | amplitude = 0; | 219 | amplitude = 0; |
| 226 | } | 220 | } |
| @@ -274,30 +268,17 @@ public: | |||
| 274 | Common::Input::StickStatus status{}; | 268 | Common::Input::StickStatus status{}; |
| 275 | status.x.properties = properties; | 269 | status.x.properties = properties; |
| 276 | status.y.properties = properties; | 270 | status.y.properties = properties; |
| 271 | |||
| 277 | if (Settings::values.emulate_analog_keyboard) { | 272 | if (Settings::values.emulate_analog_keyboard) { |
| 278 | const auto now = std::chrono::steady_clock::now(); | 273 | const auto now = std::chrono::steady_clock::now(); |
| 279 | float angle_ = GetAngle(now); | 274 | const float angle_ = GetAngle(now); |
| 280 | status.x.raw_value = std::cos(angle_) * amplitude; | 275 | status.x.raw_value = std::cos(angle_) * amplitude; |
| 281 | status.y.raw_value = std::sin(angle_) * amplitude; | 276 | status.y.raw_value = std::sin(angle_) * amplitude; |
| 282 | return status; | 277 | return status; |
| 283 | } | 278 | } |
| 284 | constexpr float SQRT_HALF = 0.707106781f; | 279 | |
| 285 | int x = 0, y = 0; | 280 | status.x.raw_value = std::cos(goal_angle) * amplitude; |
| 286 | if (right_status) { | 281 | status.y.raw_value = std::sin(goal_angle) * amplitude; |
| 287 | ++x; | ||
| 288 | } | ||
| 289 | if (left_status) { | ||
| 290 | --x; | ||
| 291 | } | ||
| 292 | if (up_status) { | ||
| 293 | ++y; | ||
| 294 | } | ||
| 295 | if (down_status) { | ||
| 296 | --y; | ||
| 297 | } | ||
| 298 | const float coef = modifier_status.value ? modifier_scale : MAX_RANGE; | ||
| 299 | status.x.raw_value = static_cast<float>(x) * coef * (y == 0 ? 1.0f : SQRT_HALF); | ||
| 300 | status.y.raw_value = static_cast<float>(y) * coef * (x == 0 ? 1.0f : SQRT_HALF); | ||
| 301 | return status; | 282 | return status; |
| 302 | } | 283 | } |
| 303 | 284 | ||
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index 22e89dd1b..c27546b0e 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -43,7 +43,6 @@ public: | |||
| 43 | explicit Value(u8 value) noexcept; | 43 | explicit Value(u8 value) noexcept; |
| 44 | explicit Value(u16 value) noexcept; | 44 | explicit Value(u16 value) noexcept; |
| 45 | explicit Value(u32 value) noexcept; | 45 | explicit Value(u32 value) noexcept; |
| 46 | explicit Value(s32 value) noexcept; | ||
| 47 | explicit Value(f32 value) noexcept; | 46 | explicit Value(f32 value) noexcept; |
| 48 | explicit Value(u64 value) noexcept; | 47 | explicit Value(u64 value) noexcept; |
| 49 | explicit Value(f64 value) noexcept; | 48 | explicit Value(f64 value) noexcept; |
| @@ -66,7 +65,6 @@ public: | |||
| 66 | [[nodiscard]] u8 U8() const; | 65 | [[nodiscard]] u8 U8() const; |
| 67 | [[nodiscard]] u16 U16() const; | 66 | [[nodiscard]] u16 U16() const; |
| 68 | [[nodiscard]] u32 U32() const; | 67 | [[nodiscard]] u32 U32() const; |
| 69 | [[nodiscard]] s32 S32() const; | ||
| 70 | [[nodiscard]] f32 F32() const; | 68 | [[nodiscard]] f32 F32() const; |
| 71 | [[nodiscard]] u64 U64() const; | 69 | [[nodiscard]] u64 U64() const; |
| 72 | [[nodiscard]] f64 F64() const; | 70 | [[nodiscard]] f64 F64() const; |
| @@ -86,7 +84,6 @@ private: | |||
| 86 | u8 imm_u8; | 84 | u8 imm_u8; |
| 87 | u16 imm_u16; | 85 | u16 imm_u16; |
| 88 | u32 imm_u32; | 86 | u32 imm_u32; |
| 89 | s32 imm_s32; | ||
| 90 | f32 imm_f32; | 87 | f32 imm_f32; |
| 91 | u64 imm_u64; | 88 | u64 imm_u64; |
| 92 | f64 imm_f64; | 89 | f64 imm_f64; |
| @@ -378,14 +375,6 @@ inline u32 Value::U32() const { | |||
| 378 | return imm_u32; | 375 | return imm_u32; |
| 379 | } | 376 | } |
| 380 | 377 | ||
| 381 | inline s32 Value::S32() const { | ||
| 382 | if (IsIdentity()) { | ||
| 383 | return inst->Arg(0).S32(); | ||
| 384 | } | ||
| 385 | DEBUG_ASSERT(type == Type::S32); | ||
| 386 | return imm_s32; | ||
| 387 | } | ||
| 388 | |||
| 389 | inline f32 Value::F32() const { | 378 | inline f32 Value::F32() const { |
| 390 | if (IsIdentity()) { | 379 | if (IsIdentity()) { |
| 391 | return inst->Arg(0).F32(); | 380 | return inst->Arg(0).F32(); |
diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp index 08c275696..6c93e3511 100644 --- a/src/yuzu/multiplayer/lobby.cpp +++ b/src/yuzu/multiplayer/lobby.cpp | |||
| @@ -77,6 +77,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, | |||
| 77 | // UI Buttons | 77 | // UI Buttons |
| 78 | connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby); | 78 | connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby); |
| 79 | connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned); | 79 | connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned); |
| 80 | connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty); | ||
| 80 | connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull); | 81 | connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull); |
| 81 | connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch); | 82 | connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch); |
| 82 | connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom); | 83 | connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom); |
| @@ -329,6 +330,16 @@ bool LobbyFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s | |||
| 329 | return true; | 330 | return true; |
| 330 | } | 331 | } |
| 331 | 332 | ||
| 333 | // filter by empty rooms | ||
| 334 | if (filter_empty) { | ||
| 335 | QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent); | ||
| 336 | int player_count = | ||
| 337 | sourceModel()->data(member_list, LobbyItemMemberList::MemberListRole).toList().size(); | ||
| 338 | if (player_count == 0) { | ||
| 339 | return false; | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 332 | // filter by filled rooms | 343 | // filter by filled rooms |
| 333 | if (filter_full) { | 344 | if (filter_full) { |
| 334 | QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent); | 345 | QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent); |
| @@ -399,6 +410,11 @@ void LobbyFilterProxyModel::SetFilterOwned(bool filter) { | |||
| 399 | invalidate(); | 410 | invalidate(); |
| 400 | } | 411 | } |
| 401 | 412 | ||
| 413 | void LobbyFilterProxyModel::SetFilterEmpty(bool filter) { | ||
| 414 | filter_empty = filter; | ||
| 415 | invalidate(); | ||
| 416 | } | ||
| 417 | |||
| 402 | void LobbyFilterProxyModel::SetFilterFull(bool filter) { | 418 | void LobbyFilterProxyModel::SetFilterFull(bool filter) { |
| 403 | filter_full = filter; | 419 | filter_full = filter; |
| 404 | invalidate(); | 420 | invalidate(); |
diff --git a/src/yuzu/multiplayer/lobby.h b/src/yuzu/multiplayer/lobby.h index 300dad13e..2674ae7c3 100644 --- a/src/yuzu/multiplayer/lobby.h +++ b/src/yuzu/multiplayer/lobby.h | |||
| @@ -130,12 +130,14 @@ public: | |||
| 130 | 130 | ||
| 131 | public slots: | 131 | public slots: |
| 132 | void SetFilterOwned(bool); | 132 | void SetFilterOwned(bool); |
| 133 | void SetFilterEmpty(bool); | ||
| 133 | void SetFilterFull(bool); | 134 | void SetFilterFull(bool); |
| 134 | void SetFilterSearch(const QString&); | 135 | void SetFilterSearch(const QString&); |
| 135 | 136 | ||
| 136 | private: | 137 | private: |
| 137 | QStandardItemModel* game_list; | 138 | QStandardItemModel* game_list; |
| 138 | bool filter_owned = false; | 139 | bool filter_owned = false; |
| 140 | bool filter_empty = false; | ||
| 139 | bool filter_full = false; | 141 | bool filter_full = false; |
| 140 | QString filter_search; | 142 | QString filter_search; |
| 141 | }; | 143 | }; |
diff --git a/src/yuzu/multiplayer/lobby.ui b/src/yuzu/multiplayer/lobby.ui index 4c9901c9a..0ef0ef762 100644 --- a/src/yuzu/multiplayer/lobby.ui +++ b/src/yuzu/multiplayer/lobby.ui | |||
| @@ -78,6 +78,13 @@ | |||
| 78 | </widget> | 78 | </widget> |
| 79 | </item> | 79 | </item> |
| 80 | <item> | 80 | <item> |
| 81 | <widget class="QCheckBox" name="hide_empty"> | ||
| 82 | <property name="text"> | ||
| 83 | <string>Hide Empty Rooms</string> | ||
| 84 | </property> | ||
| 85 | </widget> | ||
| 86 | </item> | ||
| 87 | <item> | ||
| 81 | <widget class="QCheckBox" name="hide_full"> | 88 | <widget class="QCheckBox" name="hide_full"> |
| 82 | <property name="text"> | 89 | <property name="text"> |
| 83 | <string>Hide Full Rooms</string> | 90 | <string>Hide Full Rooms</string> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 527017282..9c34cdc6e 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -176,6 +176,9 @@ void Config::ReadValues() { | |||
| 176 | Settings::values.debug_pad_analogs[i] = default_param; | 176 | Settings::values.debug_pad_analogs[i] = default_param; |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | ReadSetting("ControlsGeneral", Settings::values.enable_raw_input); | ||
| 180 | ReadSetting("ControlsGeneral", Settings::values.enable_joycon_driver); | ||
| 181 | ReadSetting("ControlsGeneral", Settings::values.emulate_analog_keyboard); | ||
| 179 | ReadSetting("ControlsGeneral", Settings::values.vibration_enabled); | 182 | ReadSetting("ControlsGeneral", Settings::values.vibration_enabled); |
| 180 | ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations); | 183 | ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations); |
| 181 | ReadSetting("ControlsGeneral", Settings::values.motion_enabled); | 184 | ReadSetting("ControlsGeneral", Settings::values.motion_enabled); |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 67d230462..3f3651dbe 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -14,6 +14,7 @@ const char* sdl2_config_file = | |||
| 14 | # Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values | 14 | # Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values |
| 15 | 15 | ||
| 16 | # Indicates if this player should be connected at boot | 16 | # Indicates if this player should be connected at boot |
| 17 | # 0 (default): Disabled, 1: Enabled | ||
| 17 | connected= | 18 | connected= |
| 18 | 19 | ||
| 19 | # for button input, the following devices are available: | 20 | # for button input, the following devices are available: |
| @@ -94,6 +95,18 @@ motionright= | |||
| 94 | # 0 (default): Disabled, 1: Enabled | 95 | # 0 (default): Disabled, 1: Enabled |
| 95 | debug_pad_enabled = | 96 | debug_pad_enabled = |
| 96 | 97 | ||
| 98 | # Enable sdl raw input. Allows to configure up to 8 xinput controllers. | ||
| 99 | # 0 (default): Disabled, 1: Enabled | ||
| 100 | enable_raw_input = | ||
| 101 | |||
| 102 | # Enable yuzu joycon driver instead of SDL drive. | ||
| 103 | # 0: Disabled, 1 (default): Enabled | ||
| 104 | enable_joycon_driver = | ||
| 105 | |||
| 106 | # Emulates an analog input from buttons. Allowing to dial any angle. | ||
| 107 | # 0 (default): Disabled, 1: Enabled | ||
| 108 | emulate_analog_keyboard = | ||
| 109 | |||
| 97 | # Whether to enable or disable vibration | 110 | # Whether to enable or disable vibration |
| 98 | # 0: Disabled, 1 (default): Enabled | 111 | # 0: Disabled, 1 (default): Enabled |
| 99 | vibration_enabled= | 112 | vibration_enabled= |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 31f28a507..5450b8c38 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -18,11 +18,11 @@ | |||
| 18 | 18 | ||
| 19 | EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) | 19 | EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) |
| 20 | : input_subsystem{input_subsystem_}, system{system_} { | 20 | : input_subsystem{input_subsystem_}, system{system_} { |
| 21 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) { | 21 | input_subsystem->Initialize(); |
| 22 | if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER) < 0) { | ||
| 22 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); | 23 | LOG_CRITICAL(Frontend, "Failed to initialize SDL2! Exiting..."); |
| 23 | exit(1); | 24 | exit(1); |
| 24 | } | 25 | } |
| 25 | input_subsystem->Initialize(); | ||
| 26 | SDL_SetMainReady(); | 26 | SDL_SetMainReady(); |
| 27 | } | 27 | } |
| 28 | 28 | ||
| @@ -32,10 +32,6 @@ EmuWindow_SDL2::~EmuWindow_SDL2() { | |||
| 32 | SDL_Quit(); | 32 | SDL_Quit(); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { | ||
| 36 | input_subsystem->GetMouse()->MouseMove(x, y, 0, 0, 0, 0); | ||
| 37 | } | ||
| 38 | |||
| 39 | InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const { | 35 | InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const { |
| 40 | switch (button) { | 36 | switch (button) { |
| 41 | case SDL_BUTTON_LEFT: | 37 | case SDL_BUTTON_LEFT: |
| @@ -53,44 +49,36 @@ InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) cons | |||
| 53 | } | 49 | } |
| 54 | } | 50 | } |
| 55 | 51 | ||
| 52 | std::pair<float, float> EmuWindow_SDL2::MouseToTouchPos(s32 touch_x, s32 touch_y) const { | ||
| 53 | int w, h; | ||
| 54 | SDL_GetWindowSize(render_window, &w, &h); | ||
| 55 | const float fx = static_cast<float>(touch_x) / w; | ||
| 56 | const float fy = static_cast<float>(touch_y) / h; | ||
| 57 | |||
| 58 | return {std::clamp<float>(fx, 0.0f, 1.0f), std::clamp<float>(fy, 0.0f, 1.0f)}; | ||
| 59 | } | ||
| 60 | |||
| 56 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | 61 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { |
| 57 | const auto mouse_button = SDLButtonToMouseButton(button); | 62 | const auto mouse_button = SDLButtonToMouseButton(button); |
| 58 | if (state == SDL_PRESSED) { | 63 | if (state == SDL_PRESSED) { |
| 59 | input_subsystem->GetMouse()->PressButton(x, y, 0, 0, mouse_button); | 64 | const auto [touch_x, touch_y] = MouseToTouchPos(x, y); |
| 65 | input_subsystem->GetMouse()->PressButton(x, y, touch_x, touch_y, mouse_button); | ||
| 60 | } else { | 66 | } else { |
| 61 | input_subsystem->GetMouse()->ReleaseButton(mouse_button); | 67 | input_subsystem->GetMouse()->ReleaseButton(mouse_button); |
| 62 | } | 68 | } |
| 63 | } | 69 | } |
| 64 | 70 | ||
| 65 | std::pair<unsigned, unsigned> EmuWindow_SDL2::TouchToPixelPos(float touch_x, float touch_y) const { | 71 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { |
| 66 | int w, h; | 72 | const auto [touch_x, touch_y] = MouseToTouchPos(x, y); |
| 67 | SDL_GetWindowSize(render_window, &w, &h); | 73 | input_subsystem->GetMouse()->MouseMove(x, y, touch_x, touch_y, 0, 0); |
| 68 | |||
| 69 | touch_x *= w; | ||
| 70 | touch_y *= h; | ||
| 71 | |||
| 72 | return {static_cast<unsigned>(std::max(std::round(touch_x), 0.0f)), | ||
| 73 | static_cast<unsigned>(std::max(std::round(touch_y), 0.0f))}; | ||
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) { | 76 | void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) { |
| 77 | int width, height; | 77 | input_subsystem->GetTouchScreen()->TouchPressed(x, y, id); |
| 78 | SDL_GetWindowSize(render_window, &width, &height); | ||
| 79 | const auto [px, py] = TouchToPixelPos(x, y); | ||
| 80 | const float fx = px * 1.0f / width; | ||
| 81 | const float fy = py * 1.0f / height; | ||
| 82 | |||
| 83 | input_subsystem->GetTouchScreen()->TouchPressed(fx, fy, id); | ||
| 84 | } | 78 | } |
| 85 | 79 | ||
| 86 | void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) { | 80 | void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) { |
| 87 | int width, height; | 81 | input_subsystem->GetTouchScreen()->TouchMoved(x, y, id); |
| 88 | SDL_GetWindowSize(render_window, &width, &height); | ||
| 89 | const auto [px, py] = TouchToPixelPos(x, y); | ||
| 90 | const float fx = px * 1.0f / width; | ||
| 91 | const float fy = py * 1.0f / height; | ||
| 92 | |||
| 93 | input_subsystem->GetTouchScreen()->TouchMoved(fx, fy, id); | ||
| 94 | } | 82 | } |
| 95 | 83 | ||
| 96 | void EmuWindow_SDL2::OnFingerUp() { | 84 | void EmuWindow_SDL2::OnFingerUp() { |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.h b/src/yuzu_cmd/emu_window/emu_window_sdl2.h index 25c23e2a5..d9b453dee 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.h +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.h | |||
| @@ -38,17 +38,17 @@ protected: | |||
| 38 | /// Called by WaitEvent when a key is pressed or released. | 38 | /// Called by WaitEvent when a key is pressed or released. |
| 39 | void OnKeyEvent(int key, u8 state); | 39 | void OnKeyEvent(int key, u8 state); |
| 40 | 40 | ||
| 41 | /// Called by WaitEvent when the mouse moves. | ||
| 42 | void OnMouseMotion(s32 x, s32 y); | ||
| 43 | |||
| 44 | /// Converts a SDL mouse button into MouseInput mouse button | 41 | /// Converts a SDL mouse button into MouseInput mouse button |
| 45 | InputCommon::MouseButton SDLButtonToMouseButton(u32 button) const; | 42 | InputCommon::MouseButton SDLButtonToMouseButton(u32 button) const; |
| 46 | 43 | ||
| 44 | /// Translates pixel position to float position | ||
| 45 | std::pair<float, float> MouseToTouchPos(s32 touch_x, s32 touch_y) const; | ||
| 46 | |||
| 47 | /// Called by WaitEvent when a mouse button is pressed or released | 47 | /// Called by WaitEvent when a mouse button is pressed or released |
| 48 | void OnMouseButton(u32 button, u8 state, s32 x, s32 y); | 48 | void OnMouseButton(u32 button, u8 state, s32 x, s32 y); |
| 49 | 49 | ||
| 50 | /// Translates pixel position (0..1) to pixel positions | 50 | /// Called by WaitEvent when the mouse moves. |
| 51 | std::pair<unsigned, unsigned> TouchToPixelPos(float touch_x, float touch_y) const; | 51 | void OnMouseMotion(s32 x, s32 y); |
| 52 | 52 | ||
| 53 | /// Called by WaitEvent when a finger starts touching the touchscreen | 53 | /// Called by WaitEvent when a finger starts touching the touchscreen |
| 54 | void OnFingerDown(float x, float y, std::size_t id); | 54 | void OnFingerDown(float x, float y, std::size_t id); |