diff --git a/src/core/libraries/pad/pad.cpp b/src/core/libraries/pad/pad.cpp index 98f086dd9..3fd1c6e2b 100644 --- a/src/core/libraries/pad/pad.cpp +++ b/src/core/libraries/pad/pad.cpp @@ -285,6 +285,16 @@ int PS4_SYSV_ABI scePadOutputReport() { return ORBIS_OK; } +OrbisFQuaternion UpdateOrientation(const OrbisFVector3& acceleration) { + OrbisFQuaternion orientation; + orientation.x = acceleration.x / 9.8f; // uhh suggestions on this are welcome + orientation.y = acceleration.y / 9.8f; + orientation.z = acceleration.z / 9.8f; + orientation.w = 0; + + return orientation; +} + int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) { int connected_count = 0; bool connected = false; @@ -304,16 +314,13 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) { pData[i].rightStick.y = states[i].axes[static_cast(Input::Axis::RightY)]; pData[i].analogButtons.l2 = states[i].axes[static_cast(Input::Axis::TriggerLeft)]; pData[i].analogButtons.r2 = states[i].axes[static_cast(Input::Axis::TriggerRight)]; - pData[i].orientation.x = 0.0f; - pData[i].orientation.y = 0.0f; - pData[i].orientation.z = 0.0f; - pData[i].orientation.w = 1.0f; - pData[i].acceleration.x = 0.0f; - pData[i].acceleration.y = 0.0f; - pData[i].acceleration.z = 0.0f; - pData[i].angularVelocity.x = 0.0f; - pData[i].angularVelocity.y = 0.0f; - pData[i].angularVelocity.z = 0.0f; + pData[i].acceleration.x = states[i].acceleration[0]; + pData[i].acceleration.y = states[i].acceleration[1]; + pData[i].acceleration.z = states[i].acceleration[2]; + pData[i].angularVelocity.x = states[i].angularVelocity[0]; + pData[i].angularVelocity.y = states[i].angularVelocity[1]; + pData[i].angularVelocity.z = states[i].angularVelocity[2]; + pData[i].orientation = UpdateOrientation(pData[i].acceleration); pData[i].touchData.touchNum = (states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0); pData[i].touchData.touch[0].x = states[i].touchpad[0].x; @@ -367,16 +374,13 @@ int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) { pData->rightStick.y = state.axes[static_cast(Input::Axis::RightY)]; pData->analogButtons.l2 = state.axes[static_cast(Input::Axis::TriggerLeft)]; pData->analogButtons.r2 = state.axes[static_cast(Input::Axis::TriggerRight)]; - pData->orientation.x = 0; - pData->orientation.y = 0; - pData->orientation.z = 0; - pData->orientation.w = 1; - pData->acceleration.x = 0.0f; - pData->acceleration.y = 0.0f; - pData->acceleration.z = 0.0f; - pData->angularVelocity.x = 0.0f; - pData->angularVelocity.y = 0.0f; - pData->angularVelocity.z = 0.0f; + pData->acceleration.x = state.acceleration[0]; + pData->acceleration.y = state.acceleration[1]; + pData->acceleration.z = state.acceleration[2]; + pData->angularVelocity.x = state.angularVelocity[0]; + pData->angularVelocity.y = state.angularVelocity[1]; + pData->angularVelocity.z = state.angularVelocity[2]; + pData->orientation = UpdateOrientation(pData->acceleration); pData->touchData.touchNum = (state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0); pData->touchData.touch[0].x = state.touchpad[0].x; @@ -460,8 +464,8 @@ int PS4_SYSV_ABI scePadSetForceIntercepted() { int PS4_SYSV_ABI scePadSetLightBar(s32 handle, const OrbisPadLightBarParam* pParam) { if (pParam != nullptr) { - LOG_INFO(Lib_Pad, "scePadSetLightBar called handle = {} rgb = {} {} {}", handle, pParam->r, - pParam->g, pParam->b); + //LOG_INFO(Lib_Pad, "scePadSetLightBar called handle = {} rgb = {} {} {}", handle, pParam->r, + // pParam->g, pParam->b); if (pParam->r < 0xD && pParam->g < 0xD && pParam->b < 0xD) { LOG_INFO(Lib_Pad, "Invalid lightbar setting"); @@ -496,8 +500,8 @@ int PS4_SYSV_ABI scePadSetLoginUserNumber() { } int PS4_SYSV_ABI scePadSetMotionSensorState(s32 handle, bool bEnable) { - LOG_ERROR(Lib_Pad, "(STUBBED) called"); - return ORBIS_OK; + LOG_ERROR(Lib_Pad, "(DUMMY) called"); + return 1; // true? } int PS4_SYSV_ABI scePadSetProcessFocus() { @@ -532,8 +536,8 @@ int PS4_SYSV_ABI scePadSetUserColor() { int PS4_SYSV_ABI scePadSetVibration(s32 handle, const OrbisPadVibrationParam* pParam) { if (pParam != nullptr) { - LOG_DEBUG(Lib_Pad, "scePadSetVibration called handle = {} data = {} , {}", handle, - pParam->smallMotor, pParam->largeMotor); + //LOG_DEBUG(Lib_Pad, "scePadSetVibration called handle = {} data = {} , {}", handle, + // pParam->smallMotor, pParam->largeMotor); auto* controller = Common::Singleton::Instance(); controller->SetVibration(pParam->smallMotor, pParam->largeMotor); return ORBIS_OK; diff --git a/src/input/controller.cpp b/src/input/controller.cpp index 3927b096f..a85f80b08 100644 --- a/src/input/controller.cpp +++ b/src/input/controller.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/logging/log.h" #include "core/libraries/kernel/time.h" #include "core/libraries/pad/pad.h" #include "input/controller.h" @@ -116,6 +117,33 @@ void GameController::Axis(int id, Input::Axis axis, int value) { AddState(state); } +void GameController::Gyro(int id, const float gyro[3]) { + //LOG_DEBUG(Lib_Pad, "Gyro update: {} {} {}", gyro[0], gyro[1], gyro[2]); + std::scoped_lock lock{m_mutex}; + auto state = GetLastState(); + state.time = Libraries::Kernel::sceKernelGetProcessTime(); + + // Update the angular velocity (gyro data) + state.angularVelocity[0] = gyro[0]; // X-axis + state.angularVelocity[1] = gyro[1]; // Y-axis + state.angularVelocity[2] = gyro[2]; // Z-axis + + AddState(state); +} +void GameController::Acceleration(int id, const float acceleration[3]) { + //LOG_DEBUG(Lib_Pad, "Accel update: {} {} {}", acceleration[0], acceleration[1], acceleration[2]); + std::scoped_lock lock{m_mutex}; + auto state = GetLastState(); + state.time = Libraries::Kernel::sceKernelGetProcessTime(); + + // Update the acceleration values + state.acceleration[0] = acceleration[0]; // X-axis + state.acceleration[1] = acceleration[1]; // Y-axis + state.acceleration[2] = acceleration[2]; // Z-axis + + AddState(state); +} + void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) { if (m_sdl_gamepad != nullptr) { SDL_SetGamepadLED(m_sdl_gamepad, r, g, b); @@ -149,6 +177,12 @@ void GameController::TryOpenSDLController() { int gamepad_count; SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count); m_sdl_gamepad = gamepad_count > 0 ? SDL_OpenGamepad(gamepads[0]) : nullptr; + if (!SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_GYRO, true)) { + LOG_ERROR(Input, "Failed to initialize gyro controls for gamepad"); + } + if (!SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_ACCEL, true)) { + LOG_ERROR(Input, "Failed to initialize accel controls for gamepad"); + } SDL_free(gamepads); SetLightBarRGB(0, 0, 255); diff --git a/src/input/controller.h b/src/input/controller.h index d425fb46c..8509a65d8 100644 --- a/src/input/controller.h +++ b/src/input/controller.h @@ -33,6 +33,8 @@ struct State { u64 time = 0; int axes[static_cast(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0}; TouchpadEntry touchpad[2] = {{false, 0, 0}, {false, 0, 0}}; + float acceleration[3] = {0.0f, 0.0f, 0.0f}; + float angularVelocity[3] = {0.0f, 0.0f, 0.0f}; }; inline int GetAxis(int min, int max, int value) { @@ -53,6 +55,8 @@ public: void CheckButton(int id, Libraries::Pad::OrbisPadButtonDataOffset button, bool isPressed); void AddState(const State& state); void Axis(int id, Input::Axis axis, int value); + void Gyro(int id, const float gyro[3]); + void Acceleration(int id, const float acceleration[3]); void SetLightBarRGB(u8 r, u8 g, u8 b); bool SetVibration(u8 smallMotor, u8 largeMotor); void SetTouchpadState(int touchIndex, bool touchDown, float x, float y); diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index 50c3e93ee..d694b0939 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -161,6 +161,20 @@ void WindowSDL::WaitEvent() { case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: OnGamepadEvent(&event); break; + // i really would have appreciated ANY KIND OF DOCUMENTATION ON THIS + // AND IT DOESN'T EVEN USE PROPER ENUMS + case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: + switch ((SDL_SensorType)event.gsensor.sensor) { + case SDL_SENSOR_GYRO: + controller->Gyro(0, event.gsensor.data); + break; + case SDL_SENSOR_ACCEL: + controller->Acceleration(0, event.gsensor.data); + break; + default: + break; + } + break; case SDL_EVENT_QUIT: is_open = false; break;