From 70420272ca63425b52844632c6be3d3691446468 Mon Sep 17 00:00:00 2001
From: wwylele <wwylele@gmail.com>
Date: Fri, 20 Jan 2017 23:58:03 +0200
Subject: [PATCH] HID: use AnalogDevice

---
 src/core/frontend/input.h        |  7 +++++++
 src/core/hle/service/hid/hid.cpp | 11 +++++++++--
 src/core/settings.h              | 14 ++++++++++++++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h
index 63e64ac67..0a5713dc0 100644
--- a/src/core/frontend/input.h
+++ b/src/core/frontend/input.h
@@ -100,4 +100,11 @@ std::unique_ptr<InputDeviceType> CreateDevice(const std::string& params) {
  */
 using ButtonDevice = InputDevice<bool>;
 
+/**
+ * An analog device is an input device that returns a tuple of x and y coordinates as status. The
+ * coordinates are within the unit circle. x+ is defined as right direction, and y+ is defined as up
+ * direction
+ */
+using AnalogDevice = InputDevice<std::tuple<float, float>>;
+
 } // namespace Input
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 0da731418..b19e831fe 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -51,6 +51,7 @@ constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE_ARM11 / 101;
 static std::atomic<bool> is_device_reload_pending;
 static std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
     buttons;
+static std::unique_ptr<Input::AnalogDevice> circle_pad;
 
 static PadState GetCirclePadDirectionState(s16 circle_pad_x, s16 circle_pad_y) {
     // 30 degree and 60 degree are angular thresholds for directions
@@ -86,12 +87,15 @@ static void LoadInputDevices() {
     std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
                    Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
                    buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
+    circle_pad = Input::CreateDevice<Input::AnalogDevice>(
+        Settings::values.analogs[Settings::NativeAnalog::CirclePad]);
 }
 
 static void UnloadInputDevices() {
     for (auto& button : buttons) {
         button.reset();
     }
+    circle_pad.reset();
 }
 
 static void UpdatePadCallback(u64 userdata, int cycles_late) {
@@ -116,8 +120,11 @@ static void UpdatePadCallback(u64 userdata, int cycles_late) {
     state.select.Assign(buttons[Select - BUTTON_HID_BEGIN]->GetStatus());
 
     // Get current circle pad position and update circle pad direction
-    s16 circle_pad_x, circle_pad_y;
-    std::tie(circle_pad_x, circle_pad_y) = VideoCore::g_emu_window->GetCirclePadState();
+    float circle_pad_x_f, circle_pad_y_f;
+    std::tie(circle_pad_x_f, circle_pad_y_f) = circle_pad->GetStatus();
+    constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position
+    s16 circle_pad_x = static_cast<s16>(circle_pad_x_f * MAX_CIRCLEPAD_POS);
+    s16 circle_pad_y = static_cast<s16>(circle_pad_y_f * MAX_CIRCLEPAD_POS);
     state.hex |= GetCirclePadDirectionState(circle_pad_x, circle_pad_y).hex;
 
     mem->pad.current_state.hex = state.hex;
diff --git a/src/core/settings.h b/src/core/settings.h
index dba57bd6c..4f83d285c 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -111,6 +111,19 @@ static const std::array<const char*, NumButtons> mapping = {{
 }};
 } // namespace NativeButton
 
+namespace NativeAnalog {
+enum Values {
+    CirclePad,
+    CStick,
+
+    NumAnalogs,
+};
+
+static const std::array<const char*, NumAnalogs> mapping = {{
+    "circle_pad", "c_stick",
+}};
+} // namespace NumAnalog
+
 struct Values {
     // CheckNew3DS
     bool is_new_3ds;
@@ -120,6 +133,7 @@ struct Values {
     float pad_circle_modifier_scale;
 
     std::array<std::string, NativeButton::NumButtons> buttons;
+    std::array<std::string, NativeAnalog::NumAnalogs> analogs;
 
     // Core
     bool use_cpu_jit;