summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp2
-rw-r--r--src/core/hle/kernel/k_device_address_space.cpp150
-rw-r--r--src/core/hle/kernel/k_device_address_space.h60
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/svc_types.h14
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp2
-rw-r--r--src/input_common/helpers/stick_from_buttons.cpp45
-rw-r--r--src/shader_recompiler/frontend/ir/value.h11
-rw-r--r--src/yuzu/multiplayer/lobby.cpp16
-rw-r--r--src/yuzu/multiplayer/lobby.h2
-rw-r--r--src/yuzu/multiplayer/lobby.ui7
-rw-r--r--src/yuzu_cmd/config.cpp3
-rw-r--r--src/yuzu_cmd/default_ini.h13
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.cpp48
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2.h10
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
10namespace Kernel {
11
12KDeviceAddressSpace::KDeviceAddressSpace(KernelCore& kernel_)
13 : KAutoObjectWithSlabHeapAndContainer(kernel_), m_lock(kernel_), m_is_initialized(false) {}
14KDeviceAddressSpace::~KDeviceAddressSpace() = default;
15
16void KDeviceAddressSpace::Initialize() {
17 // This just forwards to the device page table manager.
18 // KDevicePageTable::Initialize();
19}
20
21// Member functions.
22Result 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
34void KDeviceAddressSpace::Finalize() {
35 // Finalize the table.
36 // m_table.Finalize();
37}
38
39Result 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
48Result 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
57Result 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
116Result 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
13namespace Kernel {
14
15class KDeviceAddressSpace final
16 : public KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList> {
17 KERNEL_AUTOOBJECT_TRAITS(KDeviceAddressSpace, KAutoObject);
18
19public:
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
48private:
49 Result Map(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address,
50 u32 option, bool is_aligned);
51
52private:
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;
35class KAutoObjectWithListContainer; 35class KAutoObjectWithListContainer;
36class KClientSession; 36class KClientSession;
37class KDebug; 37class KDebug;
38class KDeviceAddressSpace;
38class KDynamicPageManager; 39class KDynamicPageManager;
39class KEvent; 40class KEvent;
40class KEventInfo; 41class 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
502enum class MapDeviceAddressSpaceFlag : u32 {
503 None = (0U << 0),
504 NotIoRegister = (1U << 0),
505};
506DECLARE_ENUM_FLAG_OPERATORS(MapDeviceAddressSpaceFlag);
507
508union MapDeviceAddressSpaceOption {
509 u32 raw;
510 BitField<0, 16, MemoryPermission> permission;
511 BitField<16, 1, MapDeviceAddressSpaceFlag> flags;
512 BitField<17, 15, u32> reserved;
513};
514
501enum class KernelDebugType : u32 { 515enum 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
1085void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) { 1085void 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
381inline 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
389inline f32 Value::F32() const { 378inline 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
413void LobbyFilterProxyModel::SetFilterEmpty(bool filter) {
414 filter_empty = filter;
415 invalidate();
416}
417
402void LobbyFilterProxyModel::SetFilterFull(bool filter) { 418void 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
131public slots: 131public 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
136private: 137private:
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
17connected= 18connected=
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
95debug_pad_enabled = 96debug_pad_enabled =
96 97
98# Enable sdl raw input. Allows to configure up to 8 xinput controllers.
99# 0 (default): Disabled, 1: Enabled
100enable_raw_input =
101
102# Enable yuzu joycon driver instead of SDL drive.
103# 0: Disabled, 1 (default): Enabled
104enable_joycon_driver =
105
106# Emulates an analog input from buttons. Allowing to dial any angle.
107# 0 (default): Disabled, 1: Enabled
108emulate_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
99vibration_enabled= 112vibration_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
19EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Core::System& system_) 19EmuWindow_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
35void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) {
36 input_subsystem->GetMouse()->MouseMove(x, y, 0, 0, 0, 0);
37}
38
39InputCommon::MouseButton EmuWindow_SDL2::SDLButtonToMouseButton(u32 button) const { 35InputCommon::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
52std::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
56void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { 61void 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
65std::pair<unsigned, unsigned> EmuWindow_SDL2::TouchToPixelPos(float touch_x, float touch_y) const { 71void 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
76void EmuWindow_SDL2::OnFingerDown(float x, float y, std::size_t id) { 76void 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
86void EmuWindow_SDL2::OnFingerMotion(float x, float y, std::size_t id) { 80void 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
96void EmuWindow_SDL2::OnFingerUp() { 84void 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);