Cleanup + add ability to connect/disconnect controllers at runtime

This commit is contained in:
kalaposfos13 2025-04-15 14:32:27 +02:00
parent e92481770c
commit fa27744588
4 changed files with 56 additions and 23 deletions

View File

@ -6,10 +6,12 @@
#include "common/config.h" #include "common/config.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/singleton.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "core/libraries/system/userservice.h" #include "core/libraries/system/userservice.h"
#include "core/libraries/system/userservice_error.h" #include "core/libraries/system/userservice_error.h"
#include "core/tls.h" #include "core/tls.h"
#include "input/controller.h"
namespace Libraries::UserService { namespace Libraries::UserService {
@ -584,13 +586,9 @@ s32 PS4_SYSV_ABI sceUserServiceGetLoginUserIdList(OrbisUserServiceLoginUserIdLis
return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT; return ORBIS_USER_SERVICE_ERROR_INVALID_ARGUMENT;
} }
// TODO only first user, do the others as well // TODO only first user, do the others as well
int player_count = Config::GetNumberOfPlayers();
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (i < player_count) { auto controllers = *Common::Singleton<Input::GameControllers>::Instance();
userIdList->user_id[i] = i + 1; userIdList->user_id[i] = controllers[i]->GetUserId();
} else {
userIdList->user_id[i] = ORBIS_USER_SERVICE_USER_ID_INVALID;
}
} }
return ORBIS_OK; return ORBIS_OK;
} }

View File

@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <unordered_set>
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include "common/config.h" #include "common/config.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -242,21 +243,52 @@ void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, f
void GameControllers::TryOpenSDLControllers(GameControllers& controllers) { void GameControllers::TryOpenSDLControllers(GameControllers& controllers) {
using namespace Libraries::UserService; using namespace Libraries::UserService;
int controller_count; int controller_count;
SDL_JoystickID* joysticks = SDL_GetGamepads(&controller_count); SDL_JoystickID* new_joysticks = SDL_GetGamepads(&controller_count);
std::unordered_set<SDL_JoystickID> assigned_ids;
std::array<bool, 4> slot_taken{false, false, false, false};
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
if (i < controller_count) { SDL_Gamepad* pad = controllers[i]->m_sdl_gamepad;
SDL_Gamepad** temp = &(controllers[i]->m_sdl_gamepad); if (pad) {
controllers[i]->m_sdl_gamepad = SDL_OpenGamepad(joysticks[i]); SDL_JoystickID id = SDL_GetGamepadID(pad);
if (*temp == 0) { bool still_connected = false;
AddUserServiceEvent({OrbisUserServiceEventType::Login, for (int j = 0; j < controller_count; j++) {
SDL_GetGamepadPlayerIndex(controllers[i]->m_sdl_gamepad) + 2}); if (new_joysticks[j] == id) {
still_connected = true;
assigned_ids.insert(id);
slot_taken[i] = true;
break;
}
} }
} else { if (!still_connected) {
SDL_Gamepad** temp = &(controllers[i]->m_sdl_gamepad);
controllers[i]->m_sdl_gamepad = nullptr;
if (*temp != 0) {
AddUserServiceEvent( AddUserServiceEvent(
{OrbisUserServiceEventType::Logout, SDL_GetGamepadPlayerIndex(*temp) + 2}); {OrbisUserServiceEventType::Logout, SDL_GetGamepadPlayerIndex(pad) + 1});
SDL_CloseGamepad(pad);
controllers[i]->m_sdl_gamepad = nullptr;
controllers[i]->user_id = -1;
}
}
}
// Now, add any new controllers not already assigned
for (int j = 0; j < controller_count; j++) {
SDL_JoystickID id = new_joysticks[j];
if (assigned_ids.contains(id))
continue; // already handled
SDL_Gamepad* pad = SDL_OpenGamepad(id);
if (!pad)
continue;
for (int i = 0; i < 4; i++) {
if (!slot_taken[i]) {
controllers[i]->m_sdl_gamepad = pad;
controllers[i]->user_id = i + 1;
slot_taken[i] = true;
AddUserServiceEvent(
{OrbisUserServiceEventType::Login, SDL_GetGamepadPlayerIndex(pad) + 1});
break;
} }
} }
} }

View File

@ -65,6 +65,9 @@ public:
bool SetVibration(u8 smallMotor, u8 largeMotor); bool SetVibration(u8 smallMotor, u8 largeMotor);
void SetTouchpadState(int touchIndex, bool touchDown, float x, float y); void SetTouchpadState(int touchIndex, bool touchDown, float x, float y);
u32 Poll(); u32 Poll();
u32 GetUserId() {
return user_id;
}
float gyro_poll_rate; float gyro_poll_rate;
float accel_poll_rate; float accel_poll_rate;
@ -86,6 +89,7 @@ private:
u32 m_first_state = 0; u32 m_first_state = 0;
std::array<State, MAX_STATES> m_states; std::array<State, MAX_STATES> m_states;
std::array<StateInternal, MAX_STATES> m_private; std::array<StateInternal, MAX_STATES> m_private;
u32 user_id = -1; // ORBIS_USER_SERVICE_USER_ID_INVALID
SDL_Gamepad* m_sdl_gamepad = nullptr; SDL_Gamepad* m_sdl_gamepad = nullptr;
}; };

View File

@ -117,7 +117,6 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameControllers* controller
SDL_SetWindowFullscreen(window, Config::getIsFullscreen()); SDL_SetWindowFullscreen(window, Config::getIsFullscreen());
SDL_InitSubSystem(SDL_INIT_GAMEPAD); SDL_InitSubSystem(SDL_INIT_GAMEPAD);
Input::GameControllers::TryOpenSDLControllers(controllers);
#if defined(SDL_PLATFORM_WIN32) #if defined(SDL_PLATFORM_WIN32)
window_info.type = WindowSystemType::Windows; window_info.type = WindowSystemType::Windows;
@ -146,10 +145,10 @@ WindowSDL::WindowSDL(s32 width_, s32 height_, Input::GameControllers* controller
Input::ParseInputConfig(std::string(Common::ElfInfo::Instance().GameSerial())); Input::ParseInputConfig(std::string(Common::ElfInfo::Instance().GameSerial()));
// default login // default login
using namespace Libraries::UserService; using namespace Libraries::UserService;
int player_count = Config::GetNumberOfPlayers(); // int player_count = Config::GetNumberOfPlayers();
for (int i = 0; i < player_count; i++) { // for (int i = 0; i < player_count; i++) {
AddUserServiceEvent({OrbisUserServiceEventType::Login, i + 1}); // AddUserServiceEvent({OrbisUserServiceEventType::Login, i + 1});
} // }
} }
WindowSDL::~WindowSDL() = default; WindowSDL::~WindowSDL() = default;