summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt7
-rw-r--r--src/core/file_sys/submission_package.cpp25
-rw-r--r--src/core/hle/service/caps/caps_c.cpp16
-rw-r--r--src/core/hle/service/caps/caps_c.h3
-rw-r--r--src/core/hle/service/caps/caps_su.cpp7
-rw-r--r--src/core/hle/service/caps/caps_u.cpp15
-rw-r--r--src/core/hle/service/caps/caps_u.h1
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp116
-rw-r--r--src/core/hle/service/hid/controllers/npad.h3
-rw-r--r--src/core/hle/service/hid/hid.cpp53
-rw-r--r--src/core/hle/service/hid/hid.h3
-rw-r--r--src/input_common/CMakeLists.txt2
-rw-r--r--src/input_common/main.cpp4
-rw-r--r--src/input_common/motion_from_button.cpp34
-rw-r--r--src/input_common/motion_from_button.h25
-rw-r--r--src/input_common/motion_input.cpp32
-rw-r--r--src/input_common/motion_input.h3
-rw-r--r--src/input_common/sdl/sdl_impl.cpp190
-rw-r--r--src/input_common/sdl/sdl_impl.h2
-rw-r--r--src/input_common/udp/client.cpp16
-rw-r--r--src/video_core/CMakeLists.txt8
-rw-r--r--src/video_core/engines/maxwell_dma.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_device.cpp1
-rw-r--r--src/video_core/renderer_vulkan/wrapper.cpp48
24 files changed, 532 insertions, 84 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 5d54516eb..0fb5d9708 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -192,4 +192,9 @@ create_target_directory_groups(common)
192find_package(Boost 1.71 COMPONENTS context headers REQUIRED) 192find_package(Boost 1.71 COMPONENTS context headers REQUIRED)
193 193
194target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile) 194target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile)
195target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd xbyak) 195target_link_libraries(common PRIVATE lz4::lz4 xbyak)
196if (MSVC)
197 target_link_libraries(common PRIVATE zstd::zstd)
198else()
199 target_link_libraries(common PRIVATE zstd)
200endif()
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp
index aab957bf2..07ae90819 100644
--- a/src/core/file_sys/submission_package.cpp
+++ b/src/core/file_sys/submission_package.cpp
@@ -286,12 +286,31 @@ void NSP::ReadNCAs(const std::vector<VirtualFile>& files) {
286 } 286 }
287 287
288 auto next_nca = std::make_shared<NCA>(std::move(next_file), nullptr, 0); 288 auto next_nca = std::make_shared<NCA>(std::move(next_file), nullptr, 0);
289
289 if (next_nca->GetType() == NCAContentType::Program) { 290 if (next_nca->GetType() == NCAContentType::Program) {
290 program_status[next_nca->GetTitleId()] = next_nca->GetStatus(); 291 program_status[next_nca->GetTitleId()] = next_nca->GetStatus();
291 } 292 }
292 if (next_nca->GetStatus() == Loader::ResultStatus::Success || 293
293 (next_nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS && 294 if (next_nca->GetStatus() != Loader::ResultStatus::Success &&
294 (next_nca->GetTitleId() & 0x800) != 0)) { 295 next_nca->GetStatus() != Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
296 continue;
297 }
298
299 // If the last 3 hexadecimal digits of the CNMT TitleID is 0x800 or is missing the
300 // BKTRBaseRomFS, this is an update NCA. Otherwise, this is a base NCA.
301 if ((cnmt.GetTitleID() & 0x800) != 0 ||
302 next_nca->GetStatus() == Loader::ResultStatus::ErrorMissingBKTRBaseRomFS) {
303 // If the last 3 hexadecimal digits of the NCA's TitleID is between 0x1 and
304 // 0x7FF, this is a multi-program update NCA. Otherwise, this is a regular
305 // update NCA.
306 if ((next_nca->GetTitleId() & 0x7FF) != 0 &&
307 (next_nca->GetTitleId() & 0x800) == 0) {
308 ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] =
309 std::move(next_nca);
310 } else {
311 ncas[cnmt.GetTitleID()][{cnmt.GetType(), rec.type}] = std::move(next_nca);
312 }
313 } else {
295 ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] = std::move(next_nca); 314 ncas[next_nca->GetTitleId()][{cnmt.GetType(), rec.type}] = std::move(next_nca);
296 } 315 }
297 } 316 }
diff --git a/src/core/hle/service/caps/caps_c.cpp b/src/core/hle/service/caps/caps_c.cpp
index ab17a187e..a0ee116fa 100644
--- a/src/core/hle/service/caps/caps_c.cpp
+++ b/src/core/hle/service/caps/caps_c.cpp
@@ -2,6 +2,8 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/logging/log.h"
6#include "core/hle/ipc_helpers.h"
5#include "core/hle/service/caps/caps_c.h" 7#include "core/hle/service/caps/caps_c.h"
6 8
7namespace Service::Capture { 9namespace Service::Capture {
@@ -47,7 +49,7 @@ CAPS_C::CAPS_C() : ServiceFramework("caps:c") {
47 static const FunctionInfo functions[] = { 49 static const FunctionInfo functions[] = {
48 {1, nullptr, "CaptureRawImage"}, 50 {1, nullptr, "CaptureRawImage"},
49 {2, nullptr, "CaptureRawImageWithTimeout"}, 51 {2, nullptr, "CaptureRawImageWithTimeout"},
50 {33, nullptr, "Unknown33"}, 52 {33, &CAPS_C::SetShimLibraryVersion, "SetShimLibraryVersion"},
51 {1001, nullptr, "RequestTakingScreenShot"}, 53 {1001, nullptr, "RequestTakingScreenShot"},
52 {1002, nullptr, "RequestTakingScreenShotWithTimeout"}, 54 {1002, nullptr, "RequestTakingScreenShotWithTimeout"},
53 {1011, nullptr, "NotifyTakingScreenShotRefused"}, 55 {1011, nullptr, "NotifyTakingScreenShotRefused"},
@@ -72,4 +74,16 @@ CAPS_C::CAPS_C() : ServiceFramework("caps:c") {
72 74
73CAPS_C::~CAPS_C() = default; 75CAPS_C::~CAPS_C() = default;
74 76
77void CAPS_C::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) {
78 IPC::RequestParser rp{ctx};
79 const auto library_version{rp.Pop<u64>()};
80 const auto applet_resource_user_id{rp.Pop<u64>()};
81
82 LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
83 library_version, applet_resource_user_id);
84
85 IPC::ResponseBuilder rb{ctx, 2};
86 rb.Push(RESULT_SUCCESS);
87}
88
75} // namespace Service::Capture 89} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_c.h b/src/core/hle/service/caps/caps_c.h
index a9d028689..b110301d4 100644
--- a/src/core/hle/service/caps/caps_c.h
+++ b/src/core/hle/service/caps/caps_c.h
@@ -16,6 +16,9 @@ class CAPS_C final : public ServiceFramework<CAPS_C> {
16public: 16public:
17 explicit CAPS_C(); 17 explicit CAPS_C();
18 ~CAPS_C() override; 18 ~CAPS_C() override;
19
20private:
21 void SetShimLibraryVersion(Kernel::HLERequestContext& ctx);
19}; 22};
20 23
21} // namespace Service::Capture 24} // namespace Service::Capture
diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp
index fffb2ecf9..e386470f7 100644
--- a/src/core/hle/service/caps/caps_su.cpp
+++ b/src/core/hle/service/caps/caps_su.cpp
@@ -25,7 +25,12 @@ CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") {
25CAPS_SU::~CAPS_SU() = default; 25CAPS_SU::~CAPS_SU() = default;
26 26
27void CAPS_SU::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) { 27void CAPS_SU::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) {
28 LOG_WARNING(Service_Capture, "(STUBBED) called"); 28 IPC::RequestParser rp{ctx};
29 const auto library_version{rp.Pop<u64>()};
30 const auto applet_resource_user_id{rp.Pop<u64>()};
31
32 LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
33 library_version, applet_resource_user_id);
29 34
30 IPC::ResponseBuilder rb{ctx, 2}; 35 IPC::ResponseBuilder rb{ctx, 2};
31 rb.Push(RESULT_SUCCESS); 36 rb.Push(RESULT_SUCCESS);
diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp
index f36d8de2d..8e2b83629 100644
--- a/src/core/hle/service/caps/caps_u.cpp
+++ b/src/core/hle/service/caps/caps_u.cpp
@@ -31,8 +31,7 @@ public:
31CAPS_U::CAPS_U() : ServiceFramework("caps:u") { 31CAPS_U::CAPS_U() : ServiceFramework("caps:u") {
32 // clang-format off 32 // clang-format off
33 static const FunctionInfo functions[] = { 33 static const FunctionInfo functions[] = {
34 {31, nullptr, "GetShimLibraryVersion"}, 34 {32, &CAPS_U::SetShimLibraryVersion, "SetShimLibraryVersion"},
35 {32, nullptr, "SetShimLibraryVersion"},
36 {102, &CAPS_U::GetAlbumContentsFileListForApplication, "GetAlbumContentsFileListForApplication"}, 35 {102, &CAPS_U::GetAlbumContentsFileListForApplication, "GetAlbumContentsFileListForApplication"},
37 {103, nullptr, "DeleteAlbumContentsFileForApplication"}, 36 {103, nullptr, "DeleteAlbumContentsFileForApplication"},
38 {104, nullptr, "GetAlbumContentsFileSizeForApplication"}, 37 {104, nullptr, "GetAlbumContentsFileSizeForApplication"},
@@ -53,6 +52,18 @@ CAPS_U::CAPS_U() : ServiceFramework("caps:u") {
53 52
54CAPS_U::~CAPS_U() = default; 53CAPS_U::~CAPS_U() = default;
55 54
55void CAPS_U::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) {
56 IPC::RequestParser rp{ctx};
57 const auto library_version{rp.Pop<u64>()};
58 const auto applet_resource_user_id{rp.Pop<u64>()};
59
60 LOG_WARNING(Service_Capture, "(STUBBED) called. library_version={}, applet_resource_user_id={}",
61 library_version, applet_resource_user_id);
62
63 IPC::ResponseBuilder rb{ctx, 2};
64 rb.Push(RESULT_SUCCESS);
65}
66
56void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx) { 67void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx) {
57 // Takes a type-0x6 output buffer containing an array of ApplicationAlbumFileEntry, a PID, an 68 // Takes a type-0x6 output buffer containing an array of ApplicationAlbumFileEntry, a PID, an
58 // u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total 69 // u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total
diff --git a/src/core/hle/service/caps/caps_u.h b/src/core/hle/service/caps/caps_u.h
index 689364de4..e04e56bbc 100644
--- a/src/core/hle/service/caps/caps_u.h
+++ b/src/core/hle/service/caps/caps_u.h
@@ -18,6 +18,7 @@ public:
18 ~CAPS_U() override; 18 ~CAPS_U() override;
19 19
20private: 20private:
21 void SetShimLibraryVersion(Kernel::HLERequestContext& ctx);
21 void GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx); 22 void GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx);
22}; 23};
23 24
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index fb007767d..2de4ed348 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -260,7 +260,7 @@ void Controller_NPad::OnRelease() {}
260 260
261void Controller_NPad::RequestPadStateUpdate(u32 npad_id) { 261void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
262 const auto controller_idx = NPadIdToIndex(npad_id); 262 const auto controller_idx = NPadIdToIndex(npad_id);
263 [[maybe_unused]] const auto controller_type = connected_controllers[controller_idx].type; 263 const auto controller_type = connected_controllers[controller_idx].type;
264 if (!connected_controllers[controller_idx].is_connected) { 264 if (!connected_controllers[controller_idx].is_connected) {
265 return; 265 return;
266 } 266 }
@@ -276,54 +276,63 @@ void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
276 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus(); 276 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
277 277
278 using namespace Settings::NativeButton; 278 using namespace Settings::NativeButton;
279 pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus()); 279 if (controller_type != NPadControllerType::JoyLeft) {
280 pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus()); 280 pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
281 pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus()); 281 pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
282 pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus()); 282 pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
283 pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus()); 283 pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
284 pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus()); 284 pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
285 pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus()); 285 pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
286 pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus()); 286 pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
287 pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus()); 287 pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
288 pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus()); 288
289 pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus()); 289 pad_state.r_stick_right.Assign(
290 pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus()); 290 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
291 291 ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
292 pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus()); 292 pad_state.r_stick_left.Assign(
293 pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus()); 293 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
294 pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus()); 294 ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
295 pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus()); 295 pad_state.r_stick_up.Assign(
296 296 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
297 pad_state.l_stick_right.Assign( 297 ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
298 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( 298 pad_state.r_stick_down.Assign(
299 Input::AnalogDirection::RIGHT)); 299 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
300 pad_state.l_stick_left.Assign( 300 ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
301 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( 301 rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
302 Input::AnalogDirection::LEFT)); 302 rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
303 pad_state.l_stick_up.Assign( 303 }
304 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( 304
305 Input::AnalogDirection::UP)); 305 if (controller_type != NPadControllerType::JoyRight) {
306 pad_state.l_stick_down.Assign( 306 pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
307 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus( 307 pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
308 Input::AnalogDirection::DOWN)); 308 pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
309 309 pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
310 pad_state.r_stick_right.Assign( 310 pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
311 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] 311 pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
312 ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT)); 312 pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
313 pad_state.r_stick_left.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] 313 pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
314 ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT)); 314
315 pad_state.r_stick_up.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] 315 pad_state.l_stick_right.Assign(
316 ->GetAnalogDirectionStatus(Input::AnalogDirection::UP)); 316 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
317 pad_state.r_stick_down.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)] 317 ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
318 ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN)); 318 pad_state.l_stick_left.Assign(
319 319 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
320 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus()); 320 ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
321 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus()); 321 pad_state.l_stick_up.Assign(
322 322 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
323 lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX); 323 ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
324 lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX); 324 pad_state.l_stick_down.Assign(
325 rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX); 325 analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
326 rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX); 326 ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
327 lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
328 lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
329 }
330
331 if (controller_type == NPadControllerType::JoyLeft ||
332 controller_type == NPadControllerType::JoyRight) {
333 pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
334 pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
335 }
327} 336}
328 337
329void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data, 338void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
@@ -837,6 +846,15 @@ Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
837 } 846 }
838} 847}
839 848
849bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
850 return unintended_home_button_input_protection[NPadIdToIndex(npad_id)];
851}
852
853void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
854 u32 npad_id) {
855 unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
856}
857
840void Controller_NPad::SetVibrationEnabled(bool can_vibrate) { 858void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
841 can_controllers_vibrate = can_vibrate; 859 can_controllers_vibrate = can_vibrate;
842} 860}
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index e65277c7b..fd5c5a6eb 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -146,6 +146,8 @@ public:
146 bool IsSixAxisSensorAtRest() const; 146 bool IsSixAxisSensorAtRest() const;
147 void SetSixAxisEnabled(bool six_axis_status); 147 void SetSixAxisEnabled(bool six_axis_status);
148 LedPattern GetLedPattern(u32 npad_id); 148 LedPattern GetLedPattern(u32 npad_id);
149 bool IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const;
150 void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled, u32 npad_id);
149 void SetVibrationEnabled(bool can_vibrate); 151 void SetVibrationEnabled(bool can_vibrate);
150 bool IsVibrationEnabled() const; 152 bool IsVibrationEnabled() const;
151 void ClearAllConnectedControllers(); 153 void ClearAllConnectedControllers();
@@ -387,6 +389,7 @@ private:
387 std::array<Kernel::EventPair, 10> styleset_changed_events; 389 std::array<Kernel::EventPair, 10> styleset_changed_events;
388 Vibration last_processed_vibration{}; 390 Vibration last_processed_vibration{};
389 std::array<ControllerHolder, 10> connected_controllers{}; 391 std::array<ControllerHolder, 10> connected_controllers{};
392 std::array<bool, 10> unintended_home_button_input_protection{};
390 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard}; 393 GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
391 bool can_controllers_vibrate{true}; 394 bool can_controllers_vibrate{true};
392 bool sixaxis_sensors_enabled{true}; 395 bool sixaxis_sensors_enabled{true};
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 90a71ab1c..71dbaba7f 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -188,7 +188,7 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
188 {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"}, 188 {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
189 {67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"}, 189 {67, &Hid::StopSixAxisSensor, "StopSixAxisSensor"},
190 {68, nullptr, "IsSixAxisSensorFusionEnabled"}, 190 {68, nullptr, "IsSixAxisSensorFusionEnabled"},
191 {69, nullptr, "EnableSixAxisSensorFusion"}, 191 {69, &Hid::EnableSixAxisSensorFusion, "EnableSixAxisSensorFusion"},
192 {70, nullptr, "SetSixAxisSensorFusionParameters"}, 192 {70, nullptr, "SetSixAxisSensorFusionParameters"},
193 {71, nullptr, "GetSixAxisSensorFusionParameters"}, 193 {71, nullptr, "GetSixAxisSensorFusionParameters"},
194 {72, nullptr, "ResetSixAxisSensorFusionParameters"}, 194 {72, nullptr, "ResetSixAxisSensorFusionParameters"},
@@ -224,8 +224,8 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) {
224 {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"}, 224 {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
225 {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"}, 225 {129, &Hid::GetNpadHandheldActivationMode, "GetNpadHandheldActivationMode"},
226 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"}, 226 {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
227 {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"}, 227 {131, &Hid::IsUnintendedHomeButtonInputProtectionEnabled, "IsUnintendedHomeButtonInputProtectionEnabled"},
228 {132, nullptr, "EnableUnintendedHomeButtonInputProtection"}, 228 {132, &Hid::EnableUnintendedHomeButtonInputProtection, "EnableUnintendedHomeButtonInputProtection"},
229 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"}, 229 {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
230 {134, nullptr, "SetNpadAnalogStickUseCenterClamp"}, 230 {134, nullptr, "SetNpadAnalogStickUseCenterClamp"},
231 {135, nullptr, "SetNpadCaptureButtonAssignment"}, 231 {135, nullptr, "SetNpadCaptureButtonAssignment"},
@@ -473,6 +473,19 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) {
473 rb.Push(RESULT_SUCCESS); 473 rb.Push(RESULT_SUCCESS);
474} 474}
475 475
476void Hid::EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx) {
477 IPC::RequestParser rp{ctx};
478 const auto enable{rp.Pop<bool>()};
479 const auto handle{rp.Pop<u32>()};
480 const auto applet_resource_user_id{rp.Pop<u64>()};
481
482 LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle,
483 applet_resource_user_id);
484
485 IPC::ResponseBuilder rb{ctx, 2};
486 rb.Push(RESULT_SUCCESS);
487}
488
476void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { 489void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
477 IPC::RequestParser rp{ctx}; 490 IPC::RequestParser rp{ctx};
478 const auto handle{rp.Pop<u32>()}; 491 const auto handle{rp.Pop<u32>()};
@@ -796,6 +809,40 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
796 } 809 }
797} 810}
798 811
812void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) {
813 IPC::RequestParser rp{ctx};
814 const auto npad_id{rp.Pop<u32>()};
815 const auto applet_resource_user_id{rp.Pop<u64>()};
816
817 LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}", npad_id,
818 applet_resource_user_id);
819
820 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
821
822 IPC::ResponseBuilder rb{ctx, 3};
823 rb.Push(RESULT_SUCCESS);
824 rb.Push<bool>(controller.IsUnintendedHomeButtonInputProtectionEnabled(npad_id));
825}
826
827void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) {
828 IPC::RequestParser rp{ctx};
829 const auto unintended_home_button_input_protection{rp.Pop<bool>()};
830 const auto npad_id{rp.Pop<u32>()};
831 const auto applet_resource_user_id{rp.Pop<u64>()};
832
833 LOG_WARNING(Service_HID,
834 "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={},"
835 "applet_resource_user_id={}",
836 npad_id, unintended_home_button_input_protection, applet_resource_user_id);
837
838 auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
839 controller.SetUnintendedHomeButtonInputProtectionEnabled(
840 unintended_home_button_input_protection, npad_id);
841
842 IPC::ResponseBuilder rb{ctx, 2};
843 rb.Push(RESULT_SUCCESS);
844}
845
799void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { 846void Hid::BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) {
800 IPC::RequestParser rp{ctx}; 847 IPC::RequestParser rp{ctx};
801 const auto applet_resource_user_id{rp.Pop<u64>()}; 848 const auto applet_resource_user_id{rp.Pop<u64>()};
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index 3cfd72a51..fd0372b18 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -99,6 +99,7 @@ private:
99 void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); 99 void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx);
100 void StartSixAxisSensor(Kernel::HLERequestContext& ctx); 100 void StartSixAxisSensor(Kernel::HLERequestContext& ctx);
101 void StopSixAxisSensor(Kernel::HLERequestContext& ctx); 101 void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
102 void EnableSixAxisSensorFusion(Kernel::HLERequestContext& ctx);
102 void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); 103 void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
103 void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); 104 void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
104 void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); 105 void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
@@ -122,6 +123,8 @@ private:
122 void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); 123 void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
123 void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx); 124 void GetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx);
124 void SwapNpadAssignment(Kernel::HLERequestContext& ctx); 125 void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
126 void IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx);
127 void EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx);
125 void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx); 128 void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx);
126 void EndPermitVibrationSession(Kernel::HLERequestContext& ctx); 129 void EndPermitVibrationSession(Kernel::HLERequestContext& ctx);
127 void SendVibrationValue(Kernel::HLERequestContext& ctx); 130 void SendVibrationValue(Kernel::HLERequestContext& ctx);
diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt
index 09361e37e..c84685214 100644
--- a/src/input_common/CMakeLists.txt
+++ b/src/input_common/CMakeLists.txt
@@ -7,6 +7,8 @@ add_library(input_common STATIC
7 main.h 7 main.h
8 motion_emu.cpp 8 motion_emu.cpp
9 motion_emu.h 9 motion_emu.h
10 motion_from_button.cpp
11 motion_from_button.h
10 motion_input.cpp 12 motion_input.cpp
11 motion_input.h 13 motion_input.h
12 settings.cpp 14 settings.cpp
diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp
index 8da829132..3d97d95f7 100644
--- a/src/input_common/main.cpp
+++ b/src/input_common/main.cpp
@@ -11,6 +11,7 @@
11#include "input_common/keyboard.h" 11#include "input_common/keyboard.h"
12#include "input_common/main.h" 12#include "input_common/main.h"
13#include "input_common/motion_emu.h" 13#include "input_common/motion_emu.h"
14#include "input_common/motion_from_button.h"
14#include "input_common/touch_from_button.h" 15#include "input_common/touch_from_button.h"
15#include "input_common/udp/client.h" 16#include "input_common/udp/client.h"
16#include "input_common/udp/udp.h" 17#include "input_common/udp/udp.h"
@@ -32,6 +33,8 @@ struct InputSubsystem::Impl {
32 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard); 33 Input::RegisterFactory<Input::ButtonDevice>("keyboard", keyboard);
33 Input::RegisterFactory<Input::AnalogDevice>("analog_from_button", 34 Input::RegisterFactory<Input::AnalogDevice>("analog_from_button",
34 std::make_shared<AnalogFromButton>()); 35 std::make_shared<AnalogFromButton>());
36 Input::RegisterFactory<Input::MotionDevice>("keyboard",
37 std::make_shared<MotionFromButton>());
35 motion_emu = std::make_shared<MotionEmu>(); 38 motion_emu = std::make_shared<MotionEmu>();
36 Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu); 39 Input::RegisterFactory<Input::MotionDevice>("motion_emu", motion_emu);
37 Input::RegisterFactory<Input::TouchDevice>("touch_from_button", 40 Input::RegisterFactory<Input::TouchDevice>("touch_from_button",
@@ -50,6 +53,7 @@ struct InputSubsystem::Impl {
50 53
51 void Shutdown() { 54 void Shutdown() {
52 Input::UnregisterFactory<Input::ButtonDevice>("keyboard"); 55 Input::UnregisterFactory<Input::ButtonDevice>("keyboard");
56 Input::UnregisterFactory<Input::MotionDevice>("keyboard");
53 keyboard.reset(); 57 keyboard.reset();
54 Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button"); 58 Input::UnregisterFactory<Input::AnalogDevice>("analog_from_button");
55 Input::UnregisterFactory<Input::MotionDevice>("motion_emu"); 59 Input::UnregisterFactory<Input::MotionDevice>("motion_emu");
diff --git a/src/input_common/motion_from_button.cpp b/src/input_common/motion_from_button.cpp
new file mode 100644
index 000000000..9d459f963
--- /dev/null
+++ b/src/input_common/motion_from_button.cpp
@@ -0,0 +1,34 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "input_common/motion_from_button.h"
6#include "input_common/motion_input.h"
7
8namespace InputCommon {
9
10class MotionKey final : public Input::MotionDevice {
11public:
12 using Button = std::unique_ptr<Input::ButtonDevice>;
13
14 MotionKey(Button key_) : key(std::move(key_)) {}
15
16 Input::MotionStatus GetStatus() const override {
17
18 if (key->GetStatus()) {
19 return motion.GetRandomMotion(2, 6);
20 }
21 return motion.GetRandomMotion(0, 0);
22 }
23
24private:
25 Button key;
26 InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
27};
28
29std::unique_ptr<Input::MotionDevice> MotionFromButton::Create(const Common::ParamPackage& params) {
30 auto key = Input::CreateDevice<Input::ButtonDevice>(params.Serialize());
31 return std::make_unique<MotionKey>(std::move(key));
32}
33
34} // namespace InputCommon
diff --git a/src/input_common/motion_from_button.h b/src/input_common/motion_from_button.h
new file mode 100644
index 000000000..a959046fb
--- /dev/null
+++ b/src/input_common/motion_from_button.h
@@ -0,0 +1,25 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/frontend/input.h"
8
9namespace InputCommon {
10
11/**
12 * An motion device factory that takes a keyboard button and uses it as a random
13 * motion device.
14 */
15class MotionFromButton final : public Input::Factory<Input::MotionDevice> {
16public:
17 /**
18 * Creates an motion device from button devices
19 * @param params contains parameters for creating the device:
20 * - "key": a serialized ParamPackage for creating a button device
21 */
22 std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override;
23};
24
25} // namespace InputCommon
diff --git a/src/input_common/motion_input.cpp b/src/input_common/motion_input.cpp
index 182a2869a..e89019723 100644
--- a/src/input_common/motion_input.cpp
+++ b/src/input_common/motion_input.cpp
@@ -2,6 +2,7 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included 3// Refer to the license.txt file included
4 4
5#include <random>
5#include "common/math_util.h" 6#include "common/math_util.h"
6#include "input_common/motion_input.h" 7#include "input_common/motion_input.h"
7 8
@@ -190,6 +191,37 @@ Common::Vec3f MotionInput::GetRotations() const {
190 return rotations; 191 return rotations;
191} 192}
192 193
194Input::MotionStatus MotionInput::GetMotion() const {
195 const Common::Vec3f gyroscope = GetGyroscope();
196 const Common::Vec3f accelerometer = GetAcceleration();
197 const Common::Vec3f rotation = GetRotations();
198 const std::array<Common::Vec3f, 3> orientation = GetOrientation();
199 return {accelerometer, gyroscope, rotation, orientation};
200}
201
202Input::MotionStatus MotionInput::GetRandomMotion(int accel_magnitude, int gyro_magnitude) const {
203 std::random_device device;
204 std::mt19937 gen(device());
205 std::uniform_int_distribution<s16> distribution(-1000, 1000);
206 const Common::Vec3f gyroscope = {
207 distribution(gen) * 0.001f,
208 distribution(gen) * 0.001f,
209 distribution(gen) * 0.001f,
210 };
211 const Common::Vec3f accelerometer = {
212 distribution(gen) * 0.001f,
213 distribution(gen) * 0.001f,
214 distribution(gen) * 0.001f,
215 };
216 const Common::Vec3f rotation = {};
217 const std::array<Common::Vec3f, 3> orientation = {
218 Common::Vec3f{1.0f, 0, 0},
219 Common::Vec3f{0, 1.0f, 0},
220 Common::Vec3f{0, 0, 1.0f},
221 };
222 return {accelerometer * accel_magnitude, gyroscope * gyro_magnitude, rotation, orientation};
223}
224
193void MotionInput::ResetOrientation() { 225void MotionInput::ResetOrientation() {
194 if (!reset_enabled || only_accelerometer) { 226 if (!reset_enabled || only_accelerometer) {
195 return; 227 return;
diff --git a/src/input_common/motion_input.h b/src/input_common/motion_input.h
index c90ee64e5..6342d0318 100644
--- a/src/input_common/motion_input.h
+++ b/src/input_common/motion_input.h
@@ -7,6 +7,7 @@
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/quaternion.h" 8#include "common/quaternion.h"
9#include "common/vector_math.h" 9#include "common/vector_math.h"
10#include "core/frontend/input.h"
10 11
11namespace InputCommon { 12namespace InputCommon {
12 13
@@ -37,6 +38,8 @@ public:
37 Common::Vec3f GetGyroscope() const; 38 Common::Vec3f GetGyroscope() const;
38 Common::Vec3f GetRotations() const; 39 Common::Vec3f GetRotations() const;
39 Common::Quaternion<f32> GetQuaternion() const; 40 Common::Quaternion<f32> GetQuaternion() const;
41 Input::MotionStatus GetMotion() const;
42 Input::MotionStatus GetRandomMotion(int accel_magnitude, int gyro_magnitude) const;
40 43
41 bool IsMoving(f32 sensitivity) const; 44 bool IsMoving(f32 sensitivity) const;
42 bool IsCalibrated(f32 sensitivity) const; 45 bool IsCalibrated(f32 sensitivity) const;
diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp
index 27a96c18b..bd480570a 100644
--- a/src/input_common/sdl/sdl_impl.cpp
+++ b/src/input_common/sdl/sdl_impl.cpp
@@ -22,6 +22,7 @@
22#include "common/param_package.h" 22#include "common/param_package.h"
23#include "common/threadsafe_queue.h" 23#include "common/threadsafe_queue.h"
24#include "core/frontend/input.h" 24#include "core/frontend/input.h"
25#include "input_common/motion_input.h"
25#include "input_common/sdl/sdl_impl.h" 26#include "input_common/sdl/sdl_impl.h"
26#include "input_common/settings.h" 27#include "input_common/settings.h"
27 28
@@ -123,6 +124,10 @@ public:
123 return std::make_tuple(x, y); 124 return std::make_tuple(x, y);
124 } 125 }
125 126
127 const InputCommon::MotionInput& GetMotion() const {
128 return motion;
129 }
130
126 void SetHat(int hat, Uint8 direction) { 131 void SetHat(int hat, Uint8 direction) {
127 std::lock_guard lock{mutex}; 132 std::lock_guard lock{mutex};
128 state.hats.insert_or_assign(hat, direction); 133 state.hats.insert_or_assign(hat, direction);
@@ -173,6 +178,9 @@ private:
173 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick; 178 std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)> sdl_joystick;
174 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller; 179 std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> sdl_controller;
175 mutable std::mutex mutex; 180 mutable std::mutex mutex;
181
182 // motion is initalized without PID values as motion input is not aviable for SDL2
183 InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f};
176}; 184};
177 185
178std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) { 186std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) {
@@ -423,6 +431,68 @@ private:
423 const float range; 431 const float range;
424}; 432};
425 433
434class SDLDirectionMotion final : public Input::MotionDevice {
435public:
436 explicit SDLDirectionMotion(std::shared_ptr<SDLJoystick> joystick_, int hat_, Uint8 direction_)
437 : joystick(std::move(joystick_)), hat(hat_), direction(direction_) {}
438
439 Input::MotionStatus GetStatus() const override {
440 if (joystick->GetHatDirection(hat, direction)) {
441 return joystick->GetMotion().GetRandomMotion(2, 6);
442 }
443 return joystick->GetMotion().GetRandomMotion(0, 0);
444 }
445
446private:
447 std::shared_ptr<SDLJoystick> joystick;
448 int hat;
449 Uint8 direction;
450};
451
452class SDLAxisMotion final : public Input::MotionDevice {
453public:
454 explicit SDLAxisMotion(std::shared_ptr<SDLJoystick> joystick_, int axis_, float threshold_,
455 bool trigger_if_greater_)
456 : joystick(std::move(joystick_)), axis(axis_), threshold(threshold_),
457 trigger_if_greater(trigger_if_greater_) {}
458
459 Input::MotionStatus GetStatus() const override {
460 const float axis_value = joystick->GetAxis(axis, 1.0f);
461 bool trigger = axis_value < threshold;
462 if (trigger_if_greater) {
463 trigger = axis_value > threshold;
464 }
465
466 if (trigger) {
467 return joystick->GetMotion().GetRandomMotion(2, 6);
468 }
469 return joystick->GetMotion().GetRandomMotion(0, 0);
470 }
471
472private:
473 std::shared_ptr<SDLJoystick> joystick;
474 int axis;
475 float threshold;
476 bool trigger_if_greater;
477};
478
479class SDLButtonMotion final : public Input::MotionDevice {
480public:
481 explicit SDLButtonMotion(std::shared_ptr<SDLJoystick> joystick_, int button_)
482 : joystick(std::move(joystick_)), button(button_) {}
483
484 Input::MotionStatus GetStatus() const override {
485 if (joystick->GetButton(button)) {
486 return joystick->GetMotion().GetRandomMotion(2, 6);
487 }
488 return joystick->GetMotion().GetRandomMotion(0, 0);
489 }
490
491private:
492 std::shared_ptr<SDLJoystick> joystick;
493 int button;
494};
495
426/// A button device factory that creates button devices from SDL joystick 496/// A button device factory that creates button devices from SDL joystick
427class SDLButtonFactory final : public Input::Factory<Input::ButtonDevice> { 497class SDLButtonFactory final : public Input::Factory<Input::ButtonDevice> {
428public: 498public:
@@ -529,12 +599,78 @@ private:
529 SDLState& state; 599 SDLState& state;
530}; 600};
531 601
602/// A motion device factory that creates motion devices from SDL joystick
603class SDLMotionFactory final : public Input::Factory<Input::MotionDevice> {
604public:
605 explicit SDLMotionFactory(SDLState& state_) : state(state_) {}
606 /**
607 * Creates motion device from joystick axes
608 * @param params contains parameters for creating the device:
609 * - "guid": the guid of the joystick to bind
610 * - "port": the nth joystick of the same type
611 */
612 std::unique_ptr<Input::MotionDevice> Create(const Common::ParamPackage& params) override {
613 const std::string guid = params.Get("guid", "0");
614 const int port = params.Get("port", 0);
615
616 auto joystick = state.GetSDLJoystickByGUID(guid, port);
617
618 if (params.Has("hat")) {
619 const int hat = params.Get("hat", 0);
620 const std::string direction_name = params.Get("direction", "");
621 Uint8 direction;
622 if (direction_name == "up") {
623 direction = SDL_HAT_UP;
624 } else if (direction_name == "down") {
625 direction = SDL_HAT_DOWN;
626 } else if (direction_name == "left") {
627 direction = SDL_HAT_LEFT;
628 } else if (direction_name == "right") {
629 direction = SDL_HAT_RIGHT;
630 } else {
631 direction = 0;
632 }
633 // This is necessary so accessing GetHat with hat won't crash
634 joystick->SetHat(hat, SDL_HAT_CENTERED);
635 return std::make_unique<SDLDirectionMotion>(joystick, hat, direction);
636 }
637
638 if (params.Has("axis")) {
639 const int axis = params.Get("axis", 0);
640 const float threshold = params.Get("threshold", 0.5f);
641 const std::string direction_name = params.Get("direction", "");
642 bool trigger_if_greater;
643 if (direction_name == "+") {
644 trigger_if_greater = true;
645 } else if (direction_name == "-") {
646 trigger_if_greater = false;
647 } else {
648 trigger_if_greater = true;
649 LOG_ERROR(Input, "Unknown direction {}", direction_name);
650 }
651 // This is necessary so accessing GetAxis with axis won't crash
652 joystick->SetAxis(axis, 0);
653 return std::make_unique<SDLAxisMotion>(joystick, axis, threshold, trigger_if_greater);
654 }
655
656 const int button = params.Get("button", 0);
657 // This is necessary so accessing GetButton with button won't crash
658 joystick->SetButton(button, false);
659 return std::make_unique<SDLButtonMotion>(joystick, button);
660 }
661
662private:
663 SDLState& state;
664};
665
532SDLState::SDLState() { 666SDLState::SDLState() {
533 using namespace Input; 667 using namespace Input;
534 analog_factory = std::make_shared<SDLAnalogFactory>(*this); 668 analog_factory = std::make_shared<SDLAnalogFactory>(*this);
535 button_factory = std::make_shared<SDLButtonFactory>(*this); 669 button_factory = std::make_shared<SDLButtonFactory>(*this);
670 motion_factory = std::make_shared<SDLMotionFactory>(*this);
536 RegisterFactory<AnalogDevice>("sdl", analog_factory); 671 RegisterFactory<AnalogDevice>("sdl", analog_factory);
537 RegisterFactory<ButtonDevice>("sdl", button_factory); 672 RegisterFactory<ButtonDevice>("sdl", button_factory);
673 RegisterFactory<MotionDevice>("sdl", motion_factory);
538 674
539 // If the frontend is going to manage the event loop, then we dont start one here 675 // If the frontend is going to manage the event loop, then we dont start one here
540 start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK); 676 start_thread = !SDL_WasInit(SDL_INIT_JOYSTICK);
@@ -570,6 +706,7 @@ SDLState::~SDLState() {
570 using namespace Input; 706 using namespace Input;
571 UnregisterFactory<ButtonDevice>("sdl"); 707 UnregisterFactory<ButtonDevice>("sdl");
572 UnregisterFactory<AnalogDevice>("sdl"); 708 UnregisterFactory<AnalogDevice>("sdl");
709 UnregisterFactory<MotionDevice>("sdl");
573 710
574 CloseJoysticks(); 711 CloseJoysticks();
575 SDL_DelEventWatch(&SDLEventWatcher, this); 712 SDL_DelEventWatch(&SDLEventWatcher, this);
@@ -681,6 +818,27 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve
681 return {}; 818 return {};
682} 819}
683 820
821Common::ParamPackage SDLEventToMotionParamPackage(SDLState& state, const SDL_Event& event) {
822 switch (event.type) {
823 case SDL_JOYAXISMOTION: {
824 const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);
825 return BuildAnalogParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
826 event.jaxis.axis, event.jaxis.value);
827 }
828 case SDL_JOYBUTTONUP: {
829 const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);
830 return BuildButtonParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
831 event.jbutton.button);
832 }
833 case SDL_JOYHATMOTION: {
834 const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);
835 return BuildHatParamPackageForButton(joystick->GetPort(), joystick->GetGUID(),
836 event.jhat.hat, event.jhat.value);
837 }
838 }
839 return {};
840}
841
684Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid, 842Common::ParamPackage BuildParamPackageForBinding(int port, const std::string& guid,
685 const SDL_GameControllerButtonBind& binding) { 843 const SDL_GameControllerButtonBind& binding) {
686 switch (binding.bindType) { 844 switch (binding.bindType) {
@@ -846,6 +1004,35 @@ public:
846 } 1004 }
847}; 1005};
848 1006
1007class SDLMotionPoller final : public SDLPoller {
1008public:
1009 explicit SDLMotionPoller(SDLState& state_) : SDLPoller(state_) {}
1010
1011 Common::ParamPackage GetNextInput() override {
1012 SDL_Event event;
1013 while (state.event_queue.Pop(event)) {
1014 const auto package = FromEvent(event);
1015 if (package) {
1016 return *package;
1017 }
1018 }
1019 return {};
1020 }
1021 [[nodiscard]] std::optional<Common::ParamPackage> FromEvent(const SDL_Event& event) const {
1022 switch (event.type) {
1023 case SDL_JOYAXISMOTION:
1024 if (std::abs(event.jaxis.value / 32767.0) < 0.5) {
1025 break;
1026 }
1027 [[fallthrough]];
1028 case SDL_JOYBUTTONUP:
1029 case SDL_JOYHATMOTION:
1030 return {SDLEventToMotionParamPackage(state, event)};
1031 }
1032 return std::nullopt;
1033 }
1034};
1035
849/** 1036/**
850 * Attempts to match the press to a controller joy axis (left/right stick) and if a match 1037 * Attempts to match the press to a controller joy axis (left/right stick) and if a match
851 * isn't found, checks if the event matches anything from SDLButtonPoller and uses that 1038 * isn't found, checks if the event matches anything from SDLButtonPoller and uses that
@@ -937,6 +1124,9 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) {
937 case InputCommon::Polling::DeviceType::Button: 1124 case InputCommon::Polling::DeviceType::Button:
938 pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this)); 1125 pollers.emplace_back(std::make_unique<Polling::SDLButtonPoller>(*this));
939 break; 1126 break;
1127 case InputCommon::Polling::DeviceType::Motion:
1128 pollers.emplace_back(std::make_unique<Polling::SDLMotionPoller>(*this));
1129 break;
940 } 1130 }
941 1131
942 return pollers; 1132 return pollers;
diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h
index bd19ba61d..b9bb4dc56 100644
--- a/src/input_common/sdl/sdl_impl.h
+++ b/src/input_common/sdl/sdl_impl.h
@@ -21,6 +21,7 @@ namespace InputCommon::SDL {
21 21
22class SDLAnalogFactory; 22class SDLAnalogFactory;
23class SDLButtonFactory; 23class SDLButtonFactory;
24class SDLMotionFactory;
24class SDLJoystick; 25class SDLJoystick;
25 26
26class SDLState : public State { 27class SDLState : public State {
@@ -71,6 +72,7 @@ private:
71 72
72 std::shared_ptr<SDLButtonFactory> button_factory; 73 std::shared_ptr<SDLButtonFactory> button_factory;
73 std::shared_ptr<SDLAnalogFactory> analog_factory; 74 std::shared_ptr<SDLAnalogFactory> analog_factory;
75 std::shared_ptr<SDLMotionFactory> motion_factory;
74 76
75 bool start_thread = false; 77 bool start_thread = false;
76 std::atomic<bool> initialized = false; 78 std::atomic<bool> initialized = false;
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp
index 2b6a68d4b..9d0b9f31d 100644
--- a/src/input_common/udp/client.cpp
+++ b/src/input_common/udp/client.cpp
@@ -219,14 +219,10 @@ void Client::OnPadData(Response::PadData data) {
219 clients[client].motion.SetGyroscope(raw_gyroscope / 312.0f); 219 clients[client].motion.SetGyroscope(raw_gyroscope / 312.0f);
220 clients[client].motion.UpdateRotation(time_difference); 220 clients[client].motion.UpdateRotation(time_difference);
221 clients[client].motion.UpdateOrientation(time_difference); 221 clients[client].motion.UpdateOrientation(time_difference);
222 Common::Vec3f gyroscope = clients[client].motion.GetGyroscope();
223 Common::Vec3f accelerometer = clients[client].motion.GetAcceleration();
224 Common::Vec3f rotation = clients[client].motion.GetRotations();
225 std::array<Common::Vec3f, 3> orientation = clients[client].motion.GetOrientation();
226 222
227 { 223 {
228 std::lock_guard guard(clients[client].status.update_mutex); 224 std::lock_guard guard(clients[client].status.update_mutex);
229 clients[client].status.motion_status = {accelerometer, gyroscope, rotation, orientation}; 225 clients[client].status.motion_status = clients[client].motion.GetMotion();
230 226
231 // TODO: add a setting for "click" touch. Click touch refers to a device that differentiates 227 // TODO: add a setting for "click" touch. Click touch refers to a device that differentiates
232 // between a simple "tap" and a hard press that causes the touch screen to click. 228 // between a simple "tap" and a hard press that causes the touch screen to click.
@@ -250,6 +246,8 @@ void Client::OnPadData(Response::PadData data) {
250 clients[client].status.touch_status = {x, y, is_active}; 246 clients[client].status.touch_status = {x, y, is_active};
251 247
252 if (configuring) { 248 if (configuring) {
249 const Common::Vec3f gyroscope = clients[client].motion.GetGyroscope();
250 const Common::Vec3f accelerometer = clients[client].motion.GetAcceleration();
253 UpdateYuzuSettings(client, accelerometer, gyroscope, is_active); 251 UpdateYuzuSettings(client, accelerometer, gyroscope, is_active);
254 } 252 }
255 } 253 }
@@ -274,18 +272,22 @@ void Client::Reset() {
274 272
275void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, 273void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc,
276 const Common::Vec3<float>& gyro, bool touch) { 274 const Common::Vec3<float>& gyro, bool touch) {
275 if (gyro.Length() > 0.2f) {
276 LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {}), touch={}",
277 client, gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2], touch);
278 }
277 UDPPadStatus pad; 279 UDPPadStatus pad;
278 if (touch) { 280 if (touch) {
279 pad.touch = PadTouch::Click; 281 pad.touch = PadTouch::Click;
280 pad_queue[client].Push(pad); 282 pad_queue[client].Push(pad);
281 } 283 }
282 for (size_t i = 0; i < 3; ++i) { 284 for (size_t i = 0; i < 3; ++i) {
283 if (gyro[i] > 6.0f || gyro[i] < -6.0f) { 285 if (gyro[i] > 5.0f || gyro[i] < -5.0f) {
284 pad.motion = static_cast<PadMotion>(i); 286 pad.motion = static_cast<PadMotion>(i);
285 pad.motion_value = gyro[i]; 287 pad.motion_value = gyro[i];
286 pad_queue[client].Push(pad); 288 pad_queue[client].Push(pad);
287 } 289 }
288 if (acc[i] > 2.0f || acc[i] < -2.0f) { 290 if (acc[i] > 1.75f || acc[i] < -1.75f) {
289 pad.motion = static_cast<PadMotion>(i + 3); 291 pad.motion = static_cast<PadMotion>(i + 3);
290 pad.motion_value = acc[i]; 292 pad.motion_value = acc[i];
291 pad_queue[client].Push(pad); 293 pad_queue[client].Push(pad);
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index da9e9fdda..2be455679 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -273,5 +273,11 @@ endif()
273if (MSVC) 273if (MSVC)
274 target_compile_options(video_core PRIVATE /we4267) 274 target_compile_options(video_core PRIVATE /we4267)
275else() 275else()
276 target_compile_options(video_core PRIVATE -Werror=conversion -Wno-error=sign-conversion -Werror=switch) 276 target_compile_options(video_core PRIVATE
277 -Werror=conversion
278 -Wno-error=sign-conversion
279 -Werror=switch
280 -Werror=unused-variable
281 -Werror=unused-but-set-variable
282 )
277endif() 283endif()
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp
index e88290754..8fa359d0a 100644
--- a/src/video_core/engines/maxwell_dma.cpp
+++ b/src/video_core/engines/maxwell_dma.cpp
@@ -114,8 +114,6 @@ void MaxwellDMA::CopyBlockLinearToPitch() {
114 const u32 block_depth = src_params.block_size.depth; 114 const u32 block_depth = src_params.block_size.depth;
115 const size_t src_size = 115 const size_t src_size =
116 CalculateSize(true, bytes_per_pixel, width, height, depth, block_height, block_depth); 116 CalculateSize(true, bytes_per_pixel, width, height, depth, block_height, block_depth);
117 const size_t src_layer_size =
118 CalculateSize(true, bytes_per_pixel, width, height, 1, block_height, block_depth);
119 117
120 if (read_buffer.size() < src_size) { 118 if (read_buffer.size() < src_size) {
121 read_buffer.resize(src_size); 119 read_buffer.resize(src_size);
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp
index e7d95149f..a94e4f72e 100644
--- a/src/video_core/renderer_opengl/gl_device.cpp
+++ b/src/video_core/renderer_opengl/gl_device.cpp
@@ -193,7 +193,6 @@ bool IsASTCSupported() {
193Device::Device() 193Device::Device()
194 : max_uniform_buffers{BuildMaxUniformBuffers()}, base_bindings{BuildBaseBindings()} { 194 : max_uniform_buffers{BuildMaxUniformBuffers()}, base_bindings{BuildBaseBindings()} {
195 const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); 195 const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
196 const std::string_view renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
197 const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); 196 const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
198 const std::vector extensions = GetExtensions(); 197 const std::vector extensions = GetExtensions();
199 198
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp
index 1fb14e190..2598440fb 100644
--- a/src/video_core/renderer_vulkan/wrapper.cpp
+++ b/src/video_core/renderer_vulkan/wrapper.cpp
@@ -6,6 +6,7 @@
6#include <exception> 6#include <exception>
7#include <memory> 7#include <memory>
8#include <optional> 8#include <optional>
9#include <string_view>
9#include <utility> 10#include <utility>
10#include <vector> 11#include <vector>
11 12
@@ -17,21 +18,42 @@ namespace Vulkan::vk {
17 18
18namespace { 19namespace {
19 20
21template <typename Func>
22void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld,
23 Func&& func) {
24 // Calling GetProperties calls Vulkan more than needed. But they are supposed to be cheap
25 // functions.
26 std::stable_sort(devices.begin(), devices.end(),
27 [&dld, &func](VkPhysicalDevice lhs, VkPhysicalDevice rhs) {
28 return func(vk::PhysicalDevice(lhs, dld).GetProperties(),
29 vk::PhysicalDevice(rhs, dld).GetProperties());
30 });
31}
32
33void SortPhysicalDevicesPerVendor(std::vector<VkPhysicalDevice>& devices,
34 const InstanceDispatch& dld,
35 std::initializer_list<u32> vendor_ids) {
36 for (auto it = vendor_ids.end(); it != vendor_ids.begin();) {
37 --it;
38 SortPhysicalDevices(devices, dld, [id = *it](const auto& lhs, const auto& rhs) {
39 return lhs.vendorID == id && rhs.vendorID != id;
40 });
41 }
42}
43
20void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) { 44void SortPhysicalDevices(std::vector<VkPhysicalDevice>& devices, const InstanceDispatch& dld) {
21 std::stable_sort(devices.begin(), devices.end(), [&](auto lhs, auto rhs) { 45 // Sort by name, this will set a base and make GPUs with higher numbers appear first
22 // This will call Vulkan more than needed, but these calls are cheap. 46 // (e.g. GTX 1650 will intentionally be listed before a GTX 1080).
23 const auto lhs_properties = vk::PhysicalDevice(lhs, dld).GetProperties(); 47 SortPhysicalDevices(devices, dld, [](const auto& lhs, const auto& rhs) {
24 const auto rhs_properties = vk::PhysicalDevice(rhs, dld).GetProperties(); 48 return std::string_view{lhs.deviceName} > std::string_view{rhs.deviceName};
25 49 });
26 // Prefer discrete GPUs, Nvidia over AMD, AMD over Intel, Intel over the rest. 50 // Prefer discrete over non-discrete
27 const bool preferred = 51 SortPhysicalDevices(devices, dld, [](const auto& lhs, const auto& rhs) {
28 (lhs_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && 52 return lhs.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU &&
29 rhs_properties.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) || 53 rhs.deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
30 (lhs_properties.vendorID == 0x10DE && rhs_properties.vendorID != 0x10DE) ||
31 (lhs_properties.vendorID == 0x1002 && rhs_properties.vendorID != 0x1002) ||
32 (lhs_properties.vendorID == 0x8086 && rhs_properties.vendorID != 0x8086);
33 return !preferred;
34 }); 54 });
55 // Prefer Nvidia over AMD, AMD over Intel, Intel over the rest.
56 SortPhysicalDevicesPerVendor(devices, dld, {0x10DE, 0x1002, 0x8086});
35} 57}
36 58
37template <typename T> 59template <typename T>