mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2026-06-03 14:14:59 -06:00
Refactor pad handles (#4386)
* Set up [userid, type, index] -> pad_handle mapping and hook up currently existing GameControllers backend to it * just use basic oop principles why are we even shoving callee responsibility in caller logic * support special pads * random edge case I thought of * return error if handle is already opened, redirect scePadOpenExt to scePadOpen * scePadClose * error out if trying to close an unopened handle * oof * logging
This commit is contained in:
parent
d3597c7f18
commit
66112bc90a
@ -18,12 +18,38 @@ using Input::GameController;
|
||||
using Input::GameControllers;
|
||||
using namespace Libraries::UserService;
|
||||
|
||||
struct HandleKey {
|
||||
OrbisUserServiceUserId id;
|
||||
s32 device_class;
|
||||
s32 index;
|
||||
|
||||
bool operator==(const HandleKey&) const = default;
|
||||
};
|
||||
struct HandleKeyHash {
|
||||
std::size_t operator()(const HandleKey& k) const {
|
||||
std::size_t h1 = std::hash<OrbisUserServiceUserId>{}(k.id);
|
||||
std::size_t h2 = std::hash<s32>{}(k.device_class);
|
||||
std::size_t h3 = std::hash<s32>{}(k.index);
|
||||
return h1 ^ (h2 << 1) ^ (h3 << 2);
|
||||
}
|
||||
};
|
||||
|
||||
static bool g_initialized = false;
|
||||
static std::unordered_map<OrbisUserServiceUserId, s32> user_id_pad_handle_map{};
|
||||
static constexpr s32 tv_remote_handle = 5;
|
||||
static u64 pad_handle_counter = 1;
|
||||
static std::unordered_map<HandleKey, s32, HandleKeyHash> pad_handle_map{};
|
||||
static std::unordered_map<s32, GameController*> handle_to_controller_map{};
|
||||
|
||||
int PS4_SYSV_ABI scePadClose(s32 handle) {
|
||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
||||
LOG_WARNING(Lib_Pad, "called, handle: {}", handle);
|
||||
if (handle_to_controller_map.erase(handle) == 0) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
for (auto& it : pad_handle_map) {
|
||||
if (it.second == handle) {
|
||||
pad_handle_map.erase(it.first);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@ -34,6 +60,10 @@ int PS4_SYSV_ABI scePadConnectPort() {
|
||||
|
||||
int PS4_SYSV_ABI scePadDeviceClassGetExtendedInformation(
|
||||
s32 handle, OrbisPadDeviceClassExtendedInformation* pExtInfo) {
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
||||
std::memset(pExtInfo, 0, sizeof(OrbisPadDeviceClassExtendedInformation));
|
||||
if (EmulatorSettings.IsUsingSpecialPad()) {
|
||||
@ -100,6 +130,10 @@ int PS4_SYSV_ABI scePadGetCapability() {
|
||||
|
||||
int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerInformation* pInfo) {
|
||||
LOG_DEBUG(Lib_Pad, "called handle = {}", handle);
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
pInfo->touchPadInfo.pixelDensity = 1;
|
||||
pInfo->touchPadInfo.resolution.x = 1920;
|
||||
pInfo->touchPadInfo.resolution.y = 950;
|
||||
@ -108,10 +142,6 @@ int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerIn
|
||||
pInfo->connectionType = ORBIS_PAD_PORT_TYPE_STANDARD;
|
||||
pInfo->connectedCount = 1;
|
||||
pInfo->deviceClass = OrbisPadDeviceClass::Standard;
|
||||
if (handle < 0) {
|
||||
pInfo->connected = false;
|
||||
return ORBIS_OK;
|
||||
}
|
||||
pInfo->connected = true;
|
||||
if (EmulatorSettings.IsUsingSpecialPad()) {
|
||||
pInfo->connectionType = ORBIS_PAD_PORT_TYPE_SPECIAL;
|
||||
@ -168,8 +198,8 @@ int PS4_SYSV_ABI scePadGetHandle(Libraries::UserService::OrbisUserServiceUserId
|
||||
if (userId == -1) {
|
||||
return ORBIS_PAD_ERROR_DEVICE_NO_HANDLE;
|
||||
}
|
||||
auto it = user_id_pad_handle_map.find(userId);
|
||||
if (it == user_id_pad_handle_map.end()) {
|
||||
auto it = pad_handle_map.find({userId, type, index});
|
||||
if (it == pad_handle_map.end()) {
|
||||
return ORBIS_PAD_ERROR_DEVICE_NO_HANDLE;
|
||||
}
|
||||
s32 pad_handle = it->second;
|
||||
@ -281,11 +311,17 @@ int PS4_SYSV_ABI scePadOpen(Libraries::UserService::OrbisUserServiceUserId userI
|
||||
if (userId < 0) {
|
||||
return ORBIS_DEVICE_SERVICE_ERROR_INVALID_USER;
|
||||
}
|
||||
if (pad_handle_map.find({userId, type, index}) != pad_handle_map.end()) {
|
||||
return ORBIS_PAD_ERROR_ALREADY_OPENED;
|
||||
}
|
||||
auto& controllers = *Common::Singleton<GameControllers>::Instance();
|
||||
if (userId == ORBIS_USER_SERVICE_USER_ID_SYSTEM) {
|
||||
if (type == ORBIS_PAD_PORT_TYPE_REMOTE_CONTROL) {
|
||||
LOG_INFO(Lib_Pad, "Opened a TV remote device");
|
||||
user_id_pad_handle_map[ORBIS_USER_SERVICE_USER_ID_SYSTEM] = tv_remote_handle;
|
||||
return tv_remote_handle;
|
||||
s32 new_handle = pad_handle_counter++;
|
||||
pad_handle_map[{userId, type, index}] = new_handle;
|
||||
handle_to_controller_map[new_handle] = controllers[4];
|
||||
LOG_INFO(Lib_Pad, "Opened a TV remote device, out handle: {}", new_handle);
|
||||
return new_handle;
|
||||
}
|
||||
return ORBIS_DEVICE_SERVICE_ERROR_INVALID_USER;
|
||||
}
|
||||
@ -297,28 +333,25 @@ int PS4_SYSV_ABI scePadOpen(Libraries::UserService::OrbisUserServiceUserId userI
|
||||
return ORBIS_DEVICE_SERVICE_ERROR_USER_NOT_LOGIN;
|
||||
}
|
||||
s32 pad_handle = u->player_index;
|
||||
LOG_INFO(Lib_Pad, "called user_id = {} type = {} index = {}, pad_handle = {}", userId, type,
|
||||
LOG_INFO(Lib_Pad, "called user_id = {} type = {} index = {}, player_index = {}", userId, type,
|
||||
index, pad_handle);
|
||||
scePadResetLightBar(pad_handle);
|
||||
scePadResetOrientation(pad_handle);
|
||||
user_id_pad_handle_map[userId] = pad_handle;
|
||||
return pad_handle;
|
||||
s32 new_handle = pad_handle_counter++;
|
||||
pad_handle_map[{userId, type, index}] = new_handle;
|
||||
|
||||
handle_to_controller_map[new_handle] =
|
||||
controllers[type == (EmulatorSettings.IsUsingSpecialPad() ? 2 : 0)
|
||||
? UserManagement.GetUserByID(userId)->player_index - 1
|
||||
: 4];
|
||||
LOG_INFO(Lib_Pad, "Out handle: {}", new_handle);
|
||||
return new_handle;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI scePadOpenExt(Libraries::UserService::OrbisUserServiceUserId userId, s32 type,
|
||||
s32 index, const OrbisPadOpenExtParam* pParam) {
|
||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
||||
auto u = UserManagement.GetUserByID(userId);
|
||||
if (!u) {
|
||||
return ORBIS_DEVICE_SERVICE_ERROR_USER_NOT_LOGIN;
|
||||
}
|
||||
s32 pad_handle = u->player_index;
|
||||
LOG_INFO(Lib_Pad, "called user_id = {} type = {} index = {}, pad_handle = {}", userId, type,
|
||||
index, pad_handle);
|
||||
scePadResetLightBar(pad_handle);
|
||||
scePadResetOrientation(pad_handle);
|
||||
user_id_pad_handle_map[userId] = pad_handle;
|
||||
return pad_handle;
|
||||
LOG_WARNING(Lib_Pad, "Redirect to scePadOpen");
|
||||
return scePadOpen(userId, type, index, nullptr);
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI scePadOpenExt2() {
|
||||
@ -459,12 +492,11 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) {
|
||||
int connected_count = 0;
|
||||
bool connected = false;
|
||||
std::vector<Input::State> states(64);
|
||||
auto controller_id = GameControllers::GetControllerIndexFromControllerID(handle);
|
||||
if (!controller_id) {
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
auto& controllers = *Common::Singleton<GameControllers>::Instance();
|
||||
auto& controller = *controllers[*controller_id];
|
||||
auto& controller = *it->second;
|
||||
int ret_num = controller.ReadStates(states.data(), num, &connected, &connected_count);
|
||||
return ProcessStates(handle, pData, controller, states.data(), ret_num, connected,
|
||||
connected_count);
|
||||
@ -492,12 +524,11 @@ int PS4_SYSV_ABI scePadReadHistory() {
|
||||
|
||||
int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
|
||||
LOG_TRACE(Lib_Pad, "handle: {}", handle);
|
||||
auto controller_id = GameControllers::GetControllerIndexFromControllerID(handle);
|
||||
if (!controller_id) {
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
auto& controllers = *Common::Singleton<GameControllers>::Instance();
|
||||
auto& controller = *controllers[*controller_id];
|
||||
auto& controller = *it->second;
|
||||
int connected_count = 0;
|
||||
bool connected = false;
|
||||
Input::State state;
|
||||
@ -513,12 +544,12 @@ int PS4_SYSV_ABI scePadReadStateExt() {
|
||||
|
||||
int PS4_SYSV_ABI scePadResetLightBar(s32 handle) {
|
||||
LOG_DEBUG(Lib_Pad, "called, handle: {}", handle);
|
||||
auto controller_id = GameControllers::GetControllerIndexFromControllerID(handle);
|
||||
if (!controller_id) {
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
auto& controllers = *Common::Singleton<GameControllers>::Instance();
|
||||
auto u = UserManagement.GetUserByPlayerIndex(handle);
|
||||
auto& controller = *it->second;
|
||||
auto u = UserManagement.GetUserByPlayerIndex(controller.user_id);
|
||||
s32 colour_index = u ? u->user_color - 1 : 0;
|
||||
Input::Colour colour{255, 0, 0};
|
||||
if (colour_index >= 0 && colour_index <= 3) {
|
||||
@ -533,10 +564,7 @@ int PS4_SYSV_ABI scePadResetLightBar(s32 handle) {
|
||||
LOG_ERROR(Lib_Pad, "Invalid user colour value {} for controller {}, falling back to blue",
|
||||
colour_index, handle);
|
||||
}
|
||||
if (auto oc = GameControllers::GetControllerCustomColor(*controller_id)) {
|
||||
colour = *oc;
|
||||
}
|
||||
controllers[*controller_id]->SetLightBarRGB(colour.r, colour.g, colour.b);
|
||||
controller.SetLightBarRGB(colour.r, colour.g, colour.b);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@ -553,15 +581,14 @@ int PS4_SYSV_ABI scePadResetLightBarAllByPortType() {
|
||||
int PS4_SYSV_ABI scePadResetOrientation(s32 handle) {
|
||||
LOG_INFO(Lib_Pad, "scePadResetOrientation called handle = {}", handle);
|
||||
|
||||
auto controller_id = GameControllers::GetControllerIndexFromControllerID(handle);
|
||||
if (!controller_id) {
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
auto& controllers = *Common::Singleton<GameControllers>::Instance();
|
||||
auto& controller = *it->second;
|
||||
Libraries::Pad::OrbisFQuaternion defaultOrientation = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
controllers[*controller_id]->SetLastOrientation(defaultOrientation);
|
||||
controllers[*controller_id]->SetLastUpdate(std::chrono::steady_clock::now());
|
||||
controller.SetLastOrientation(defaultOrientation);
|
||||
controller.SetLastUpdate(std::chrono::steady_clock::now());
|
||||
|
||||
return ORBIS_OK;
|
||||
}
|
||||
@ -612,13 +639,11 @@ int PS4_SYSV_ABI scePadSetForceIntercepted() {
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI scePadSetLightBar(s32 handle, const OrbisPadLightBarParam* pParam) {
|
||||
auto controller_id = GameControllers::GetControllerIndexFromControllerID(handle);
|
||||
if (!controller_id) {
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
if (GameControllers::GetControllerCustomColor(*controller_id)) {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
auto& controller = *it->second;
|
||||
if (pParam != nullptr) {
|
||||
LOG_DEBUG(Lib_Pad, "called handle = {} rgb = {} {} {}", handle, pParam->r, pParam->g,
|
||||
pParam->b);
|
||||
@ -629,7 +654,7 @@ int PS4_SYSV_ABI scePadSetLightBar(s32 handle, const OrbisPadLightBarParam* pPar
|
||||
}
|
||||
|
||||
auto& controllers = *Common::Singleton<GameControllers>::Instance();
|
||||
controllers[*controller_id]->SetLightBarRGB(pParam->r, pParam->g, pParam->b);
|
||||
controller.SetLightBarRGB(pParam->r, pParam->g, pParam->b);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
return ORBIS_PAD_ERROR_INVALID_ARG;
|
||||
@ -647,12 +672,12 @@ int PS4_SYSV_ABI scePadSetLightBarBlinking() {
|
||||
|
||||
int PS4_SYSV_ABI scePadSetLightBarForTracker(s32 handle, const OrbisPadLightBarParam* pParam) {
|
||||
LOG_INFO(Lib_Pad, "called, r: {} g: {} b: {}", pParam->r, pParam->g, pParam->b);
|
||||
auto controller_id = GameControllers::GetControllerIndexFromControllerID(handle);
|
||||
if (!controller_id) {
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
auto& controllers = *Common::Singleton<GameControllers>::Instance();
|
||||
controllers[*controller_id]->SetLightBarRGB(pParam->r, pParam->g, pParam->b);
|
||||
auto& controller = *it->second;
|
||||
controller.SetLightBarRGB(pParam->r, pParam->g, pParam->b);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
@ -699,15 +724,16 @@ int PS4_SYSV_ABI scePadSetUserColor() {
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI scePadSetVibration(s32 handle, const OrbisPadVibrationParam* pParam) {
|
||||
auto controller_id = GameControllers::GetControllerIndexFromControllerID(handle);
|
||||
if (!controller_id) {
|
||||
auto it = handle_to_controller_map.find(handle);
|
||||
if (it == handle_to_controller_map.end()) {
|
||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
auto& controller = *it->second;
|
||||
if (pParam != nullptr) {
|
||||
LOG_DEBUG(Lib_Pad, "scePadSetVibration called handle = {} data = {} , {}", handle,
|
||||
pParam->smallMotor, pParam->largeMotor);
|
||||
auto& controllers = *Common::Singleton<GameControllers>::Instance();
|
||||
controllers[*controller_id]->SetVibration(pParam->smallMotor, pParam->largeMotor);
|
||||
controller.SetVibration(pParam->smallMotor, pParam->largeMotor);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
return ORBIS_PAD_ERROR_INVALID_ARG;
|
||||
|
||||
@ -151,6 +151,9 @@ void GameController::UpdateAxisSmoothing() {
|
||||
}
|
||||
|
||||
void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) {
|
||||
if (override_colour.has_value()) {
|
||||
return;
|
||||
}
|
||||
colour = {r, g, b};
|
||||
if (m_sdl_gamepad != nullptr) {
|
||||
SDL_SetGamepadLED(m_sdl_gamepad, r, g, b);
|
||||
@ -188,9 +191,6 @@ void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, f
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::optional<Colour>, 4> GameControllers::controller_override_colors{
|
||||
std::nullopt, std::nullopt, std::nullopt, std::nullopt};
|
||||
|
||||
void GameControllers::CalculateOrientation(Libraries::Pad::OrbisFVector3& acceleration,
|
||||
Libraries::Pad::OrbisFVector3& angularVelocity,
|
||||
float deltaTime,
|
||||
|
||||
@ -164,6 +164,7 @@ private:
|
||||
std::chrono::steady_clock::time_point m_last_update = {};
|
||||
Libraries::Pad::OrbisFQuaternion m_orientation = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
Colour colour;
|
||||
std::optional<Colour> override_colour{};
|
||||
|
||||
State m_state;
|
||||
|
||||
@ -174,8 +175,6 @@ private:
|
||||
class GameControllers {
|
||||
std::array<GameController*, 5> controllers;
|
||||
|
||||
static std::array<std::optional<Colour>, 4> controller_override_colors;
|
||||
|
||||
public:
|
||||
GameControllers()
|
||||
: controllers({new GameController(), new GameController(), new GameController(),
|
||||
@ -197,14 +196,12 @@ public:
|
||||
float deltaTime,
|
||||
Libraries::Pad::OrbisFQuaternion& lastOrientation,
|
||||
Libraries::Pad::OrbisFQuaternion& orientation);
|
||||
static void SetControllerCustomColor(s32 i, u8 r, u8 g, u8 b) {
|
||||
controller_override_colors[i] = {r, g, b};
|
||||
}
|
||||
static std::optional<Colour> GetControllerCustomColor(s32 i) {
|
||||
if (i >= controller_override_colors.size()) {
|
||||
return {};
|
||||
}
|
||||
return controller_override_colors[i];
|
||||
void SetControllerCustomColor(s32 i, u8 r, u8 g, u8 b) {
|
||||
// reset to ensure the next function always runs, even if there already was a preexisting
|
||||
// override colour before
|
||||
controllers[i]->override_colour = std::nullopt;
|
||||
controllers[i]->SetLightBarRGB(r, g, b);
|
||||
controllers[i]->override_colour = {r, g, b};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -544,7 +544,8 @@ void ParseInputConfig(const std::string game_id = "") {
|
||||
}
|
||||
output_gamepad_id = output_gamepad_id == -1 ? 1 : output_gamepad_id;
|
||||
if (enable == "true") {
|
||||
GameControllers::SetControllerCustomColor(output_gamepad_id - 1, *r, *g, *b);
|
||||
ControllerOutput::controllers.SetControllerCustomColor(output_gamepad_id - 1, *r,
|
||||
*g, *b);
|
||||
}
|
||||
LOG_DEBUG(Input, "Parsed color settings: {} {} - {} {} {}",
|
||||
enable == "true" ? "override" : "no override", output_gamepad_id, *r, *b, *g);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user