From d2f9412cf1717f884855af22793f3a1e5815c967 Mon Sep 17 00:00:00 2001 From: german77 Date: Sat, 8 Jan 2022 23:23:40 -0600 Subject: yuzu: Add custom ringcon configuration --- src/core/hle/service/hid/hidbus/hidbus_base.cpp | 4 +- src/core/hle/service/hid/hidbus/hidbus_base.h | 3 +- src/core/hle/service/hid/hidbus/ringcon.cpp | 78 +++++++++---------------- src/core/hle/service/hid/hidbus/ringcon.h | 29 +++++---- 4 files changed, 51 insertions(+), 63 deletions(-) (limited to 'src/core/hle/service/hid/hidbus') diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.cpp b/src/core/hle/service/hid/hidbus/hidbus_base.cpp index 9cac0be80..09bff10e5 100644 --- a/src/core/hle/service/hid/hidbus/hidbus_base.cpp +++ b/src/core/hle/service/hid/hidbus/hidbus_base.cpp @@ -12,7 +12,7 @@ namespace Service::HID { HidbusBase::HidbusBase(KernelHelpers::ServiceContext& service_context_) : service_context(service_context_) { - send_command_asyc_event = service_context.CreateEvent("hidbus:SendCommandAsycEvent"); + send_command_async_event = service_context.CreateEvent("hidbus:SendCommandAsyncEvent"); } HidbusBase::~HidbusBase() = default; @@ -66,7 +66,7 @@ void HidbusBase::SetTransferMemoryPointer(u8* t_mem) { } Kernel::KReadableEvent& HidbusBase::GetSendCommandAsycEvent() const { - return send_command_asyc_event->GetReadableEvent(); + return send_command_async_event->GetReadableEvent(); } } // namespace Service::HID diff --git a/src/core/hle/service/hid/hidbus/hidbus_base.h b/src/core/hle/service/hid/hidbus/hidbus_base.h index 41e571998..13d073a3d 100644 --- a/src/core/hle/service/hid/hidbus/hidbus_base.h +++ b/src/core/hle/service/hid/hidbus/hidbus_base.h @@ -165,6 +165,7 @@ protected: bool device_enabled{}; bool polling_mode_enabled{}; JoyPollingMode polling_mode = {}; + // TODO(German77): All data accessors need to be replaced with a ring lifo object JoyDisableSixAxisDataAccessor disable_sixaxis_data{}; JoyEnableSixAxisDataAccessor enable_sixaxis_data{}; ButtonOnlyPollingDataAccessor button_only_data{}; @@ -172,7 +173,7 @@ protected: u8* transfer_memory{nullptr}; bool is_transfer_memory_set{}; - Kernel::KEvent* send_command_asyc_event; + Kernel::KEvent* send_command_async_event; KernelHelpers::ServiceContext& service_context; }; } // namespace Service::HID diff --git a/src/core/hle/service/hid/hidbus/ringcon.cpp b/src/core/hle/service/hid/hidbus/ringcon.cpp index 6fe68081f..5ec3cc83c 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.cpp +++ b/src/core/hle/service/hid/hidbus/ringcon.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "core/hid/emulated_controller.h" +#include "core/hid/emulated_devices.h" #include "core/hid/hid_core.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" @@ -13,9 +13,7 @@ namespace Service::HID { RingController::RingController(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_) : HidbusBase(service_context_) { - // Use the horizontal axis of left stick for emulating input - // There is no point on adding a frontend implementation since Ring Fit Adventure doesn't work - input = hid_core_.GetEmulatedController(Core::HID::NpadIdType::Player1); + input = hid_core_.GetEmulatedDevices(); } RingController::~RingController() = default; @@ -41,6 +39,8 @@ void RingController::OnUpdate() { return; } + // TODO: Increment multitasking counters from motion and sensor data + switch (polling_mode) { case JoyPollingMode::SixAxisSensorEnable: { enable_sixaxis_data.header.total_entries = 10; @@ -74,9 +74,8 @@ RingController::RingConData RingController::GetSensorValue() const { .data = 0, }; - const f32 stick_value = static_cast(input->GetSticks().left.x) / 32767.0f; - - ringcon_sensor_value.data = static_cast(stick_value * range) + idle_value; + const f32 force_value = input->GetRingSensorForce().force * range; + ringcon_sensor_value.data = static_cast(force_value) + idle_value; return ringcon_sensor_value; } @@ -105,6 +104,8 @@ std::vector RingController::GetReply() const { return GetReadRepCountReply(); case RingConCommands::ReadTotalPushCount: return GetReadTotalPushCountReply(); + case RingConCommands::ResetRepCount: + return GetResetRepCountReply(); case RingConCommands::SaveCalData: return GetSaveDataReply(); default: @@ -119,36 +120,9 @@ bool RingController::SetCommand(const std::vector& data) { return false; } - // There must be a better way to do this - const u32 command_id = - u32{data[0]} + (u32{data[1]} << 8) + (u32{data[2]} << 16) + (u32{data[3]} << 24); - static constexpr std::array supported_commands = { - RingConCommands::GetFirmwareVersion, - RingConCommands::ReadId, - RingConCommands::c20105, - RingConCommands::ReadUnkCal, - RingConCommands::ReadFactoryCal, - RingConCommands::ReadUserCal, - RingConCommands::ReadRepCount, - RingConCommands::ReadTotalPushCount, - RingConCommands::SaveCalData, - }; - - for (RingConCommands cmd : supported_commands) { - if (command_id == static_cast(cmd)) { - return ExcecuteCommand(cmd, data); - } - } - - LOG_ERROR(Service_HID, "Command not implemented {}", command_id); - command = RingConCommands::Error; - // Signal a reply to avoid softlocking - send_command_asyc_event->GetWritableEvent().Signal(); - return false; -} + std::memcpy(&command, data.data(), sizeof(RingConCommands)); -bool RingController::ExcecuteCommand(RingConCommands cmd, const std::vector& data) { - switch (cmd) { + switch (command) { case RingConCommands::GetFirmwareVersion: case RingConCommands::ReadId: case RingConCommands::c20105: @@ -158,23 +132,27 @@ bool RingController::ExcecuteCommand(RingConCommands cmd, const std::vector& case RingConCommands::ReadRepCount: case RingConCommands::ReadTotalPushCount: ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); - command = cmd; - send_command_asyc_event->GetWritableEvent().Signal(); + send_command_async_event->GetWritableEvent().Signal(); + return true; + case RingConCommands::ResetRepCount: + ASSERT_MSG(data.size() == 0x4, "data.size is not 0x4 bytes"); + total_rep_count = 0; + send_command_async_event->GetWritableEvent().Signal(); return true; case RingConCommands::SaveCalData: { ASSERT_MSG(data.size() == 0x14, "data.size is not 0x14 bytes"); SaveCalData save_info{}; - std::memcpy(&save_info, &data, sizeof(SaveCalData)); + std::memcpy(&save_info, data.data(), sizeof(SaveCalData)); user_calibration = save_info.calibration; - - command = cmd; - send_command_asyc_event->GetWritableEvent().Signal(); + send_command_async_event->GetWritableEvent().Signal(); return true; } default: - LOG_ERROR(Service_HID, "Command not implemented {}", cmd); + LOG_ERROR(Service_HID, "Command not implemented {}", command); command = RingConCommands::Error; + // Signal a reply to avoid softlocking the game + send_command_async_event->GetWritableEvent().Signal(); return false; } } @@ -240,27 +218,29 @@ std::vector RingController::GetReadUserCalReply() const { } std::vector RingController::GetReadRepCountReply() const { - // The values are hardcoded from a real joycon const GetThreeByteReply reply{ .status = DataValid::Valid, - .data = {30, 0, 0}, - .crc = GetCrcValue({30, 0, 0, 0}), + .data = {total_rep_count, 0, 0}, + .crc = GetCrcValue({total_rep_count, 0, 0, 0}), }; return GetDataVector(reply); } std::vector RingController::GetReadTotalPushCountReply() const { - // The values are hardcoded from a real joycon const GetThreeByteReply reply{ .status = DataValid::Valid, - .data = {30, 0, 0}, - .crc = GetCrcValue({30, 0, 0, 0}), + .data = {total_push_count, 0, 0}, + .crc = GetCrcValue({total_push_count, 0, 0, 0}), }; return GetDataVector(reply); } +std::vector RingController::GetResetRepCountReply() const { + return GetReadRepCountReply(); +} + std::vector RingController::GetSaveDataReply() const { const StatusReply reply{ .status = DataValid::Valid, diff --git a/src/core/hle/service/hid/hidbus/ringcon.h b/src/core/hle/service/hid/hidbus/ringcon.h index e8b3d8254..2dbc6150e 100644 --- a/src/core/hle/service/hid/hidbus/ringcon.h +++ b/src/core/hle/service/hid/hidbus/ringcon.h @@ -10,7 +10,7 @@ #include "core/hle/service/hid/hidbus/hidbus_base.h" namespace Core::HID { -class EmulatedController; +class EmulatedDevices; } // namespace Core::HID namespace Service::HID { @@ -43,6 +43,7 @@ private: static constexpr s16 idle_deadzone = 120; static constexpr s16 range = 2500; + // Most missing command names are leftovers from other firmware versions enum class RingConCommands : u32 { GetFirmwareVersion = 0x00020000, ReadId = 0x00020100, @@ -60,10 +61,10 @@ private: ReadUserCal = 0x00021A04, ReadRepCount = 0x00023104, ReadTotalPushCount = 0x00023204, - Unknown9 = 0x04013104, - Unknown10 = 0x04011104, - Unknown11 = 0x04011204, - Unknown12 = 0x04011304, + ResetRepCount = 0x04013104, + Unknown8 = 0x04011104, + Unknown9 = 0x04011204, + Unknown10 = 0x04011304, SaveCalData = 0x10011A04, Error = 0xFFFFFFFF, }; @@ -180,9 +181,6 @@ private: }; static_assert(sizeof(RingConData) == 0x8, "RingConData is an invalid size"); - // Executes the command requested - bool ExcecuteCommand(RingConCommands cmd, const std::vector& data); - // Returns RingConData struct with pressure sensor values RingConData GetSensorValue() const; @@ -204,12 +202,15 @@ private: // Returns 20 byte reply with user calibration values std::vector GetReadUserCalReply() const; - // (STUBBED) Returns 8 byte reply + // Returns 8 byte reply std::vector GetReadRepCountReply() const; - // (STUBBED) Returns 8 byte reply + // Returns 8 byte reply std::vector GetReadTotalPushCountReply() const; + // Returns 8 byte reply + std::vector GetResetRepCountReply() const; + // Returns 4 byte save data reply std::vector GetSaveDataReply() const; @@ -225,6 +226,12 @@ private: RingConCommands command{RingConCommands::Error}; + // These counters are used in multitasking mode while the switch is sleeping + // Total steps taken + u8 total_rep_count = 0; + // Total times the ring was pushed + u8 total_push_count = 0; + const u8 device_id = 0x20; const FirmwareVersion version = { .sub = 0x0, @@ -242,6 +249,6 @@ private: .zero = {.value = idle_value, .crc = 225}, }; - Core::HID::EmulatedController* input; + Core::HID::EmulatedDevices* input; }; } // namespace Service::HID -- cgit v1.2.3