From 06cf050c0a541bc0bf9b4ca41fdec75f133c91d3 Mon Sep 17 00:00:00 2001
From: Zach Hilman <zachhilman@gmail.com>
Date: Thu, 1 Nov 2018 22:01:11 -0400
Subject: [PATCH] hid: Add controller bindings for DebugPad controller Used by
 developers to test games, not present on retail systems. Some games are known
 to respond to DebugPad input though, for example Kirby Star Allies.

---
 .../hle/service/hid/controllers/debug_pad.cpp | 57 ++++++++++++-------
 .../hle/service/hid/controllers/debug_pad.h   |  7 +++
 2 files changed, 43 insertions(+), 21 deletions(-)

diff --git a/src/core/hle/service/hid/controllers/debug_pad.cpp b/src/core/hle/service/hid/controllers/debug_pad.cpp
index ac9b23bb8b..e76c83aeef 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.cpp
+++ b/src/core/hle/service/hid/controllers/debug_pad.cpp
@@ -6,9 +6,14 @@
 #include "common/common_types.h"
 #include "core/core_timing.h"
 #include "core/hle/service/hid/controllers/debug_pad.h"
+#include "core/settings.h"
 
 namespace Service::HID {
 
+constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
+constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
+enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right };
+
 Controller_DebugPad::Controller_DebugPad() = default;
 Controller_DebugPad::~Controller_DebugPad() = default;
 
@@ -33,33 +38,43 @@ void Controller_DebugPad::OnUpdate(u8* data, std::size_t size) {
 
     cur_entry.sampling_number = last_entry.sampling_number + 1;
     cur_entry.sampling_number2 = cur_entry.sampling_number;
-    // TODO(ogniK): Update debug pad states
     cur_entry.attribute.connected.Assign(1);
     auto& pad = cur_entry.pad_state;
 
-    pad.a.Assign(0);
-    pad.b.Assign(0);
-    pad.x.Assign(0);
-    pad.y.Assign(0);
-    pad.l.Assign(0);
-    pad.r.Assign(0);
-    pad.zl.Assign(0);
-    pad.zr.Assign(0);
-    pad.plus.Assign(0);
-    pad.minus.Assign(0);
-    pad.d_left.Assign(0);
-    pad.d_up.Assign(0);
-    pad.d_right.Assign(0);
-    pad.d_down.Assign(0);
+    using namespace Settings::NativeButton;
+    pad.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
+    pad.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
+    pad.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
+    pad.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
+    pad.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
+    pad.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
+    pad.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
+    pad.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
+    pad.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
+    pad.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
+    pad.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
+    pad.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
+    pad.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
+    pad.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
 
-    cur_entry.l_stick.x = 0;
-    cur_entry.l_stick.y = 0;
-
-    cur_entry.r_stick.x = 0;
-    cur_entry.r_stick.y = 0;
+    const auto [stick_l_x_f, stick_l_y_f] =
+        analogs[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
+    const auto [stick_r_x_f, stick_r_y_f] =
+        analogs[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
+    cur_entry.l_stick.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
+    cur_entry.l_stick.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
+    cur_entry.r_stick.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
+    cur_entry.r_stick.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
 
     std::memcpy(data, &shared_memory, sizeof(SharedMemory));
 }
 
-void Controller_DebugPad::OnLoadInputDevices() {}
+void Controller_DebugPad::OnLoadInputDevices() {
+    std::transform(Settings::values.debug_pad_buttons.begin(),
+                   Settings::values.debug_pad_buttons.end(), buttons.begin(),
+                   Input::CreateDevice<Input::ButtonDevice>);
+    std::transform(Settings::values.debug_pad_analogs.begin(),
+                   Settings::values.debug_pad_analogs.end(), analogs.begin(),
+                   Input::CreateDevice<Input::AnalogDevice>);
+}
 } // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/debug_pad.h b/src/core/hle/service/hid/controllers/debug_pad.h
index a41564b4d4..68b734248e 100644
--- a/src/core/hle/service/hid/controllers/debug_pad.h
+++ b/src/core/hle/service/hid/controllers/debug_pad.h
@@ -9,7 +9,9 @@
 #include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/swap.h"
+#include "core/frontend/input.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
+#include "core/settings.h"
 
 namespace Service::HID {
 class Controller_DebugPad final : public ControllerBase {
@@ -82,5 +84,10 @@ private:
     };
     static_assert(sizeof(SharedMemory) == 0x400, "SharedMemory is an invalid size");
     SharedMemory shared_memory{};
+
+    std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
+        buttons;
+    std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>
+        analogs;
 };
 } // namespace Service::HID