mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-04-01 18:40:57 -06:00
Merge 67a0f1c52f into deb8c66ffb
This commit is contained in:
commit
f3bfa02767
@ -233,10 +233,11 @@ find_package(nlohmann_json 3.12 CONFIG)
|
||||
find_package(PNG 1.6 MODULE)
|
||||
find_package(OpenAL CONFIG)
|
||||
find_package(RenderDoc 1.6.0 MODULE)
|
||||
find_package(SDL3_mixer 2.8.1 CONFIG)
|
||||
if (SDL3_mixer_FOUND)
|
||||
find_package(SDL3 3.1.2 CONFIG)
|
||||
endif()
|
||||
|
||||
# find_package(SDL3_mixer 2.8.1 CONFIG)
|
||||
# if (SDL3_mixer_FOUND)
|
||||
# find_package(SDL3 3.1.2 CONFIG)
|
||||
# endif()
|
||||
find_package(stb MODULE)
|
||||
find_package(toml11 4.2.0 CONFIG)
|
||||
find_package(tsl-robin-map 1.3.0 CONFIG)
|
||||
|
||||
2
externals/sdl3
vendored
2
externals/sdl3
vendored
@ -1 +1 @@
|
||||
Subproject commit 4e2fd57e77fb4a28c0eeef0670fc4121cc2cf1f9
|
||||
Subproject commit 9c51f451c67653fc2e73ed734213308ee7db0707
|
||||
@ -1,13 +1,17 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <common/singleton.h>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "core/libraries/move/move.h"
|
||||
#include "core/libraries/move/move_error.h"
|
||||
#include "input/controller.h"
|
||||
#include "move.h"
|
||||
|
||||
auto controllers = *Common::Singleton<Input::GameControllers>::Instance();
|
||||
|
||||
namespace Libraries::Move {
|
||||
|
||||
static bool g_library_initialized = false;
|
||||
@ -44,15 +48,51 @@ s32 PS4_SYSV_ABI sceMoveGetDeviceInfo(s32 handle, OrbisMoveDeviceInfo* info) {
|
||||
return ORBIS_MOVE_ERROR_NO_CONTROLLER_CONNECTED;
|
||||
}
|
||||
|
||||
static OrbisMoveButtonDataOffset PadToMoveOffset(Libraries::Pad::OrbisPadButtonDataOffset p) {
|
||||
OrbisMoveButtonDataOffset m{};
|
||||
using OPBDO = Libraries::Pad::OrbisPadButtonDataOffset;
|
||||
using OMBDO = OrbisMoveButtonDataOffset;
|
||||
#define CONVERT(_pad, _move) \
|
||||
do { \
|
||||
if (True(p & OPBDO::_pad)) \
|
||||
m |= OMBDO::_move; \
|
||||
} while (0)
|
||||
CONVERT(Circle, Circle);
|
||||
CONVERT(Cross, Cross);
|
||||
CONVERT(Square, Square);
|
||||
CONVERT(Triangle, Triangle);
|
||||
CONVERT(Options, Start);
|
||||
CONVERT(R2, T);
|
||||
CONVERT(L1, Move);
|
||||
#undef CONVERT
|
||||
return m;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceMoveReadStateLatest(s32 handle, OrbisMoveData* data) {
|
||||
LOG_TRACE(Lib_Move, "(called");
|
||||
if (!g_library_initialized) {
|
||||
return ORBIS_MOVE_ERROR_NOT_INIT;
|
||||
}
|
||||
if (data == nullptr) {
|
||||
return ORBIS_MOVE_ERROR_INVALID_ARG;
|
||||
}
|
||||
return ORBIS_MOVE_ERROR_NO_CONTROLLER_CONNECTED;
|
||||
if (!controllers.moves(0)->m_sdl_gamepad) {
|
||||
return ORBIS_MOVE_ERROR_NO_CONTROLLER_CONNECTED;
|
||||
}
|
||||
LOG_DEBUG(Lib_Move, "called");
|
||||
auto m = controllers.moves(0);
|
||||
Input::State s{};
|
||||
bool connected;
|
||||
int connected_count;
|
||||
m->ReadState(&s, &connected, &connected_count);
|
||||
data->button_data.trigger_data = u16(s.axes[std::to_underlying(Input::Axis::TriggerRight)]);
|
||||
data->button_data.button_data = std::to_underlying(PadToMoveOffset(s.buttonsState));
|
||||
data->accelerometer[0] = s.acceleration.x;
|
||||
data->accelerometer[1] = s.acceleration.y;
|
||||
data->accelerometer[2] = s.acceleration.z;
|
||||
data->gyro[0] = s.angularVelocity.x;
|
||||
data->gyro[1] = s.angularVelocity.y;
|
||||
data->gyro[2] = s.angularVelocity.z;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceMoveReadStateRecent(s32 handle, s64 timestamp, OrbisMoveData* data,
|
||||
@ -83,15 +123,23 @@ s32 PS4_SYSV_ABI sceMoveSetVibration(s32 handle, u8 intensity) {
|
||||
if (!g_library_initialized) {
|
||||
return ORBIS_MOVE_ERROR_NOT_INIT;
|
||||
}
|
||||
return ORBIS_MOVE_ERROR_NO_CONTROLLER_CONNECTED;
|
||||
if (!controllers.moves(0)->m_sdl_gamepad) {
|
||||
return ORBIS_MOVE_ERROR_NO_CONTROLLER_CONNECTED;
|
||||
}
|
||||
controllers.moves(0)->SetVibration(0, intensity);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceMoveSetLightSphere(s32 handle, u8 red, u8 green, u8 blue) {
|
||||
LOG_TRACE(Lib_Move, "called");
|
||||
LOG_DEBUG(Lib_Move, "called");
|
||||
if (!g_library_initialized) {
|
||||
return ORBIS_MOVE_ERROR_NOT_INIT;
|
||||
}
|
||||
return ORBIS_MOVE_ERROR_NO_CONTROLLER_CONNECTED;
|
||||
if (!controllers.moves(0)->m_sdl_gamepad) {
|
||||
return ORBIS_MOVE_ERROR_NO_CONTROLLER_CONNECTED;
|
||||
}
|
||||
controllers.moves(0)->SetLightBarRGB(red, green, blue);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceMoveResetLightSphere(s32 handle) {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/enum.h"
|
||||
#include "common/types.h"
|
||||
#include "core/libraries/system/userservice.h"
|
||||
|
||||
@ -17,6 +18,19 @@ struct OrbisMoveDeviceInfo {
|
||||
float accelerometer_offset[3];
|
||||
};
|
||||
|
||||
enum class OrbisMoveButtonDataOffset : u16 {
|
||||
Select = (1 << 0),
|
||||
T = (1 << 1),
|
||||
Move = (1 << 2),
|
||||
Start = (1 << 3),
|
||||
Triangle = (1 << 4),
|
||||
Circle = (1 << 5),
|
||||
Cross = (1 << 6),
|
||||
Square = (1 << 7),
|
||||
Intercepted = (1 << 15),
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(OrbisMoveButtonDataOffset)
|
||||
|
||||
struct OrbisMoveButtonData {
|
||||
u16 button_data;
|
||||
u16 trigger_data;
|
||||
|
||||
@ -269,6 +269,41 @@ void GameControllers::TryOpenSDLControllers() {
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_GUID guid = SDL_GetJoystickGUID(SDL_GetJoystickFromID(new_joysticks[j]));
|
||||
Uint16 vendor = 0, product = 0;
|
||||
SDL_GetJoystickGUIDInfo(guid, &vendor, &product, nullptr, nullptr);
|
||||
if (vendor == 0x054C && // Sony
|
||||
(product == 0x03D5 || // PSMove ZCM1
|
||||
product == 0x0C5E)) { // PSMove ZCM2
|
||||
LOG_INFO(Input, "PS Move controller found at slot {}!", j);
|
||||
if (is_first_check) { // ABSOLUTELY HORRIBLE HACK but I just want it hooked up
|
||||
// quickly
|
||||
auto c = move_controllers[move_count];
|
||||
c->m_sdl_gamepad = pad;
|
||||
auto u = UserManagement.GetDefaultUser();
|
||||
c->user_id = u.user_id;
|
||||
c->m_connected = true;
|
||||
move_count++;
|
||||
if (SDL_SetGamepadSensorEnabled(c->m_sdl_gamepad, SDL_SENSOR_GYRO, true)) {
|
||||
c->gyro_poll_rate =
|
||||
SDL_GetGamepadSensorDataRate(c->m_sdl_gamepad, SDL_SENSOR_GYRO);
|
||||
LOG_INFO(Input, "Gyro initialized, poll rate: {}", c->gyro_poll_rate);
|
||||
} else {
|
||||
LOG_ERROR(Input, "Failed to initialize gyro controls for gamepad {}",
|
||||
c->user_id);
|
||||
}
|
||||
if (SDL_SetGamepadSensorEnabled(c->m_sdl_gamepad, SDL_SENSOR_ACCEL, true)) {
|
||||
c->accel_poll_rate =
|
||||
SDL_GetGamepadSensorDataRate(c->m_sdl_gamepad, SDL_SENSOR_ACCEL);
|
||||
LOG_INFO(Input, "Accel initialized, poll rate: {}", c->accel_poll_rate);
|
||||
} else {
|
||||
LOG_ERROR(Input, "Failed to initialize accel controls for gamepad {}",
|
||||
c->user_id);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!slot_taken[i]) {
|
||||
auto u = UserManagement.GetUserByPlayerIndex(i + 1);
|
||||
@ -381,7 +416,16 @@ u8 GameControllers::GetGamepadIndexFromJoystickId(SDL_JoystickID id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// LOG_TRACE(Input, "Gamepad index: {}", index);
|
||||
return -1;
|
||||
}
|
||||
|
||||
u8 GameControllers::GetMoveIndexFromJoystickId(SDL_JoystickID id) {
|
||||
auto g = SDL_GetGamepadFromID(id);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (move_controllers[i]->m_sdl_gamepad == g) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@ namespace Input {
|
||||
|
||||
enum class ControllerType {
|
||||
Standard,
|
||||
Move,
|
||||
};
|
||||
|
||||
enum class Axis {
|
||||
@ -171,13 +172,16 @@ private:
|
||||
|
||||
class GameControllers {
|
||||
std::array<GameController*, 5> controllers;
|
||||
std::array<GameController*, 4> move_controllers;
|
||||
|
||||
static std::array<std::optional<Colour>, 4> controller_override_colors;
|
||||
|
||||
public:
|
||||
GameControllers()
|
||||
: controllers({new GameController(), new GameController(), new GameController(),
|
||||
new GameController(), new GameController()}) {};
|
||||
new GameController(), new GameController()}),
|
||||
move_controllers({new GameController(), new GameController(), new GameController(),
|
||||
new GameController()}) {};
|
||||
virtual ~GameControllers() = default;
|
||||
GameController* operator[](const size_t& i) const {
|
||||
if (i > 4) {
|
||||
@ -185,8 +189,15 @@ public:
|
||||
}
|
||||
return controllers[i];
|
||||
}
|
||||
GameController* moves(const size_t& i) const {
|
||||
if (i > 3) {
|
||||
UNREACHABLE_MSG("Index {} is out of bounds for GameControllers!", i);
|
||||
}
|
||||
return move_controllers[i];
|
||||
}
|
||||
void TryOpenSDLControllers();
|
||||
u8 GetGamepadIndexFromJoystickId(SDL_JoystickID id);
|
||||
u8 GetMoveIndexFromJoystickId(SDL_JoystickID id);
|
||||
static std::optional<u8> GetControllerIndexFromUserID(s32 user_id);
|
||||
static std::optional<u8> GetControllerIndexFromControllerID(s32 controller_id);
|
||||
|
||||
|
||||
@ -208,7 +208,7 @@ std::filesystem::path GetInputConfigFile(const std::string& game_id) {
|
||||
}
|
||||
|
||||
bool leftjoystick_halfmode = false, rightjoystick_halfmode = false;
|
||||
std::array<std::pair<int, int>, 4> leftjoystick_deadzone, rightjoystick_deadzone,
|
||||
std::array<std::pair<int, int>, 9> leftjoystick_deadzone, rightjoystick_deadzone,
|
||||
lefttrigger_deadzone, righttrigger_deadzone;
|
||||
|
||||
std::list<std::pair<InputEvent, bool>> pressed_keys;
|
||||
@ -354,8 +354,8 @@ void ParseInputConfig(const std::string game_id = "") {
|
||||
float mouse_speed_offset = 0.125;
|
||||
|
||||
// me when I'm in a type deduction tournament and my opponent is clang
|
||||
constexpr std::array<std::pair<int, int>, 4> default_deadzone = {
|
||||
std::pair{1, 127}, {1, 127}, {1, 127}, {1, 127}};
|
||||
constexpr std::array<std::pair<int, int>, 9> default_deadzone = {
|
||||
std::pair{1, 127}, {1, 127}, {1, 127}, {1, 127}, {1, 127}, {1, 127}, {1, 127}, {1, 127}};
|
||||
|
||||
leftjoystick_deadzone = default_deadzone;
|
||||
rightjoystick_deadzone = default_deadzone;
|
||||
@ -491,7 +491,7 @@ void ParseInputConfig(const std::string game_id = "") {
|
||||
|
||||
std::pair<int, int> deadzone = {*inner_deadzone, *outer_deadzone};
|
||||
|
||||
static std::unordered_map<std::string, std::array<std::pair<int, int>, 4>&>
|
||||
static std::unordered_map<std::string, std::array<std::pair<int, int>, 9>&>
|
||||
deadzone_map = {
|
||||
{"leftjoystick", leftjoystick_deadzone},
|
||||
{"rightjoystick", rightjoystick_deadzone},
|
||||
@ -644,10 +644,22 @@ InputEvent InputBinding::GetInputEventFromSDLEvent(const SDL_Event& e) {
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
gamepad = ControllerOutput::controllers.GetGamepadIndexFromJoystickId(e.gbutton.which) + 1;
|
||||
if (gamepad == 0) {
|
||||
gamepad = ControllerOutput::controllers.GetMoveIndexFromJoystickId(e.gbutton.which) + 6;
|
||||
if (gamepad < 6) {
|
||||
return InputEvent();
|
||||
}
|
||||
}
|
||||
return InputEvent({InputType::Controller, (u32)e.gbutton.button, gamepad}, e.gbutton.down,
|
||||
0);
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
gamepad = ControllerOutput::controllers.GetGamepadIndexFromJoystickId(e.gaxis.which) + 1;
|
||||
if (gamepad < 1) {
|
||||
gamepad = ControllerOutput::controllers.GetMoveIndexFromJoystickId(e.gaxis.which) + 6;
|
||||
if (gamepad < 6) {
|
||||
return InputEvent();
|
||||
}
|
||||
}
|
||||
return InputEvent({InputType::Axis, (u32)e.gaxis.axis, gamepad}, true, e.gaxis.value / 256);
|
||||
default:
|
||||
return InputEvent();
|
||||
@ -717,6 +729,8 @@ void ControllerOutput::FinalizeUpdate(u8 gamepad_index) {
|
||||
GameController* controller;
|
||||
if (gamepad_index < 5)
|
||||
controller = controllers[gamepad_index];
|
||||
else if (gamepad_index < 9)
|
||||
controller = controllers.moves(gamepad_index - 5); // magic number :(
|
||||
else
|
||||
UNREACHABLE();
|
||||
if (button != SDL_GAMEPAD_BUTTON_INVALID) {
|
||||
|
||||
@ -130,6 +130,7 @@ const std::map<std::string, u32> string_to_cbutton_map = {
|
||||
{"pad_left", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
||||
{"pad_right", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
||||
{"options", SDL_GAMEPAD_BUTTON_START},
|
||||
{"move", SDL_GAMEPAD_BUTTON_MISC1},
|
||||
|
||||
// these are outputs only (touchpad can only be bound to itself)
|
||||
{"touchpad_left", SDL_GAMEPAD_BUTTON_TOUCHPAD_LEFT},
|
||||
@ -175,6 +176,7 @@ const std::map<std::string, AxisMapping> string_to_axis_map = {
|
||||
|
||||
{"l2", {SDL_GAMEPAD_AXIS_LEFT_TRIGGER, 127}},
|
||||
{"r2", {SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 127}},
|
||||
{"move_t", {SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, 127}},
|
||||
|
||||
// should only use these to bind analog inputs to analog outputs
|
||||
{"axis_left_x", {SDL_GAMEPAD_AXIS_LEFTX, 127}},
|
||||
@ -526,7 +528,7 @@ public:
|
||||
|
||||
class ControllerAllOutputs {
|
||||
public:
|
||||
static constexpr u64 output_count = 40;
|
||||
static constexpr u64 output_count = 41;
|
||||
std::array<ControllerOutput, output_count> data = {
|
||||
// Important: these have to be the first, or else they will update in the wrong order
|
||||
ControllerOutput(LEFTJOYSTICK_HALFMODE),
|
||||
@ -551,6 +553,7 @@ public:
|
||||
ControllerOutput(SDL_GAMEPAD_BUTTON_DPAD_DOWN), // Down
|
||||
ControllerOutput(SDL_GAMEPAD_BUTTON_DPAD_LEFT), // Left
|
||||
ControllerOutput(SDL_GAMEPAD_BUTTON_DPAD_RIGHT), // Right
|
||||
ControllerOutput(SDL_GAMEPAD_BUTTON_MISC1), // Move
|
||||
|
||||
// Axis mappings
|
||||
// ControllerOutput(SDL_GAMEPAD_BUTTON_INVALID, SDL_GAMEPAD_AXIS_LEFTX, false),
|
||||
@ -563,7 +566,7 @@ public:
|
||||
ControllerOutput(SDL_GAMEPAD_BUTTON_INVALID, SDL_GAMEPAD_AXIS_RIGHTY),
|
||||
|
||||
ControllerOutput(SDL_GAMEPAD_BUTTON_INVALID, SDL_GAMEPAD_AXIS_LEFT_TRIGGER),
|
||||
ControllerOutput(SDL_GAMEPAD_BUTTON_INVALID, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER),
|
||||
ControllerOutput(SDL_GAMEPAD_BUTTON_INVALID, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER), // R2 / Move T
|
||||
|
||||
ControllerOutput(HOTKEY_FULLSCREEN),
|
||||
ControllerOutput(HOTKEY_PAUSE),
|
||||
|
||||
@ -295,6 +295,9 @@ void WindowSDL::WaitEvent() {
|
||||
void WindowSDL::InitTimers() {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
SDL_AddTimer(4, &PollController, controllers[i]);
|
||||
SDL_AddTimer(13, &PollController, controllers.moves(i));
|
||||
// the move ball resets every 5 seconds, however, for some reason this flickers
|
||||
SDL_AddTimer(500, &PollControllerLightColour, controllers.moves(i));
|
||||
}
|
||||
SDL_AddTimer(33, Input::MousePolling, (void*)controllers[0]);
|
||||
}
|
||||
@ -378,12 +381,22 @@ void WindowSDL::OnGamepadEvent(const SDL_Event* event) {
|
||||
gamepad = controllers.GetGamepadIndexFromJoystickId(event->gsensor.which);
|
||||
if (gamepad < 5) {
|
||||
controllers[gamepad]->UpdateGyro(event->gsensor.data);
|
||||
} else {
|
||||
gamepad = controllers.GetMoveIndexFromJoystickId(event->gsensor.which);
|
||||
if (gamepad < 4) {
|
||||
controllers.moves(gamepad)->UpdateGyro(event->gsensor.data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_SENSOR_ACCEL:
|
||||
gamepad = controllers.GetGamepadIndexFromJoystickId(event->gsensor.which);
|
||||
if (gamepad < 5) {
|
||||
controllers[gamepad]->UpdateAcceleration(event->gsensor.data);
|
||||
} else {
|
||||
gamepad = controllers.GetMoveIndexFromJoystickId(event->gsensor.which);
|
||||
if (gamepad < 4) {
|
||||
controllers.moves(gamepad)->UpdateAcceleration(event->gsensor.data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user