diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index c55d900e27..5136932b15 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp @@ -236,6 +236,8 @@ void Controller_NPad::OnLoadInputDevices() { players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END, sticks[i].begin(), Input::CreateDevice); } + motion_sensors[Settings::values.udp_pad_index] = + Input::CreateDevice(Settings::values.motion_device); } void Controller_NPad::OnRelease() {} @@ -338,6 +340,25 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* cur_entry.timestamp2 = cur_entry.timestamp; } + const std::array controller_sixaxes{&npad.full, &npad._handheld, + &npad._left_dual, &npad._right_dual, + &npad._left, &npad._right}; + + for (auto* sixaxis : controller_sixaxes) { + sixaxis->common.entry_count = 16; + sixaxis->common.total_entry_count = 17; + + const auto& last_entry = sixaxis->sixaxis[sixaxis->common.last_entry_index]; + + sixaxis->common.timestamp = core_timing.GetTicks(); + sixaxis->common.last_entry_index = (sixaxis->common.last_entry_index + 1) % 17; + + auto& cur_entry = sixaxis->sixaxis[sixaxis->common.last_entry_index]; + + cur_entry.timestamp = last_entry.timestamp + 1; + cur_entry.timestamp2 = cur_entry.timestamp; + } + const auto& controller_type = connected_controllers[i].type; if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) { @@ -358,6 +379,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* auto& pokeball_entry = npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index]; auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index]; + auto& sixaxis_entry = npad.full.sixaxis[npad.full.common.last_entry_index]; libnx_entry.connection_status.raw = 0; @@ -434,6 +456,12 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* libnx_entry.pad.l_stick = pad_state.l_stick; libnx_entry.pad.r_stick = pad_state.r_stick; + // Set this entry regardless of the controller type, for now. + if (motion_sensors[i] && sixaxis_sensor_enabled) { + auto& sensor = motion_sensors[i]; + std::tie(sixaxis_entry.accelerometer, sixaxis_entry.gyroscope) = sensor->GetStatus(); + } + press_state |= static_cast(pad_state.pad_states.raw); } std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(), diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h index 931f03430e..f59166d67a 100644 --- a/src/core/hle/service/hid/controllers/npad.h +++ b/src/core/hle/service/hid/controllers/npad.h @@ -7,6 +7,7 @@ #include #include "common/bit_field.h" #include "common/common_types.h" +#include "common/vector_math.h" #include "core/frontend/input.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/writable_event.h" @@ -236,6 +237,24 @@ private: }; static_assert(sizeof(NPadGeneric) == 0x350, "NPadGeneric is an invalid size"); + struct SixAxisState { + s64_le timestamp; + INSERT_PADDING_BYTES(8); // unknown + s64_le timestamp2; + Common::Vec3f accelerometer; + Common::Vec3f gyroscope; + INSERT_PADDING_BYTES(12); // unknown sensor data + std::array orientation; + s64_le _always_one; // always 1 + }; + static_assert(sizeof(SixAxisState) == 0x68, "SixAxisState is an invalid size"); + + struct SixAxisGeneric { + CommonHeader common; + std::array sixaxis; + }; + static_assert(sizeof(SixAxisGeneric) == 0x708, "SixAxisGeneric is an invalid size"); + enum class ColorReadError : u32_le { ReadOk = 0, ColorDoesntExist = 1, @@ -284,9 +303,12 @@ private: NPadGeneric pokeball_states; NPadGeneric libnx; // TODO(ogniK): Find out what this actually is, libnx seems to only be // relying on this for the time being - INSERT_PADDING_BYTES( - 0x708 * - 6); // TODO(ogniK): SixAxis states, require more information before implementation + SixAxisGeneric full; // used + SixAxisGeneric _handheld; // stub + SixAxisGeneric _left_dual; // stub + SixAxisGeneric _right_dual; // stub + SixAxisGeneric _left; // stub + SixAxisGeneric _right; // stub NPadDevice device_type; NPadProperties properties; INSERT_PADDING_WORDS(1); @@ -318,6 +340,8 @@ private: std::array, Settings::NativeAnalog::NUM_STICKS_HID>, 10> sticks; + std::array, 10> motion_sensors; + bool sixaxis_sensor_enabled{true}; std::vector supported_npad_id_types{}; NpadHoldType hold_type{NpadHoldType::Vertical}; // Each controller should have their own styleset changed event diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 5559587e31..a51aef5766 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -31,6 +31,7 @@ #include "core/hle/service/hid/controllers/keyboard.h" #include "core/hle/service/hid/controllers/mouse.h" #include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/controllers/sixaxis.h" #include "core/hle/service/hid/controllers/stubbed.h" #include "core/hle/service/hid/controllers/touchscreen.h" #include "core/hle/service/hid/controllers/xpad.h" @@ -395,9 +396,10 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { const auto handle{rp.Pop()}; const auto applet_resource_user_id{rp.Pop()}; - LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, + LOG_DEBUG(Service_HID, "called, handle={}, applet_resource_user_id={}", handle, applet_resource_user_id); + applet_resource->ActivateController(HidController::SixAxisSensor); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -825,8 +827,9 @@ void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto handle{rp.Pop()}; - LOG_WARNING(Service_HID, "(STUBBED) called, handle={}", handle); + LOG_DEBUG(Service_HID, "called, handle={}", handle); + applet_resource->DeactivateController(HidController::SixAxisSensor); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -1188,4 +1191,4 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system std::make_shared()->InstallAsService(service_manager); } -} // namespace Service::HID +} // namespace Service::HID \ No newline at end of file