SDL: Add sensor support for controllers with SDL 2.0.14+

This commit is contained in:
Vicki Pfau 2021-09-10 18:23:32 -07:00
parent 9430913ba3
commit c1c931c61f
3 changed files with 79 additions and 45 deletions

View File

@ -5,6 +5,7 @@ Features:
- Tool for converting scanned pictures of e-Reader cards to raw dotcode data - Tool for converting scanned pictures of e-Reader cards to raw dotcode data
- Options for muting when inactive, minimized, or for different players in multiplayer - Options for muting when inactive, minimized, or for different players in multiplayer
- Cheat code support in homebrew ports - Cheat code support in homebrew ports
- Acclerometer and gyro support for controllers on PC
- Support for combo "Super Game Boy Color" SGB + GBC ROM hacks - Support for combo "Super Game Boy Color" SGB + GBC ROM hacks
- Support for 64 kiB SRAM saves used in some bootlegs - Support for 64 kiB SRAM saves used in some bootlegs
- Discord Rich Presence now supports time elapsed - Discord Rich Presence now supports time elapsed

View File

@ -37,6 +37,34 @@ static int32_t _mSDLReadTiltY(struct mRotationSource* rumble);
static int32_t _mSDLReadGyroZ(struct mRotationSource* rumble); static int32_t _mSDLReadGyroZ(struct mRotationSource* rumble);
static void _mSDLRotationSample(struct mRotationSource* source); static void _mSDLRotationSample(struct mRotationSource* source);
static struct SDL_JoystickCombo* _mSDLOpenJoystick(struct mSDLEvents* events, int i) {
SDL_Joystick* sdlJoystick = SDL_JoystickOpen(i);
if (!sdlJoystick) {
return NULL;
}
struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&events->joysticks);
joystick->index = SDL_JoystickListSize(&events->joysticks) - 1;
joystick->joystick = sdlJoystick;
#if SDL_VERSION_ATLEAST(2, 0, 0)
joystick->id = SDL_JoystickInstanceID(joystick->joystick);
joystick->haptic = SDL_HapticOpenFromJoystick(joystick->joystick);
joystick->controller = SDL_GameControllerOpen(i);
#if SDL_VERSION_ATLEAST(2, 0, 14)
if (joystick->controller) {
if (SDL_GameControllerHasSensor(joystick->controller, SDL_SENSOR_GYRO) && !SDL_GameControllerIsSensorEnabled(joystick->controller, SDL_SENSOR_GYRO)) {
SDL_GameControllerSetSensorEnabled(joystick->controller, SDL_SENSOR_GYRO, SDL_TRUE);
}
if (SDL_GameControllerHasSensor(joystick->controller, SDL_SENSOR_ACCEL) && !SDL_GameControllerIsSensorEnabled(joystick->controller, SDL_SENSOR_ACCEL)) {
SDL_GameControllerSetSensorEnabled(joystick->controller, SDL_SENSOR_ACCEL, SDL_TRUE);
}
}
#endif
#else
joystick->id = SDL_JoystickIndex(joystick->joystick);
#endif
return joystick;
}
bool mSDLInitEvents(struct mSDLEvents* context) { bool mSDLInitEvents(struct mSDLEvents* context) {
#if SDL_VERSION_ATLEAST(2, 0, 4) #if SDL_VERSION_ATLEAST(2, 0, 4)
SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1"); SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, "1");
@ -50,6 +78,9 @@ bool mSDLInitEvents(struct mSDLEvents* context) {
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) { if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) {
mLOG(SDL_EVENTS, ERROR, "SDL haptic initialization failed: %s", SDL_GetError()); mLOG(SDL_EVENTS, ERROR, "SDL haptic initialization failed: %s", SDL_GetError());
} }
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) {
mLOG(SDL_EVENTS, ERROR, "SDL game controller initialization failed: %s", SDL_GetError());
}
if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) { if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
mLOG(SDL_EVENTS, ERROR, "SDL video initialization failed: %s", SDL_GetError()); mLOG(SDL_EVENTS, ERROR, "SDL video initialization failed: %s", SDL_GetError());
} }
@ -64,19 +95,7 @@ bool mSDLInitEvents(struct mSDLEvents* context) {
if (!SDL_JoystickListSize(&context->joysticks)) { if (!SDL_JoystickListSize(&context->joysticks)) {
int i; int i;
for (i = 0; i < nJoysticks; ++i) { for (i = 0; i < nJoysticks; ++i) {
SDL_Joystick* sdlJoystick = SDL_JoystickOpen(i); _mSDLOpenJoystick(context, i);
if (!sdlJoystick) {
continue;
}
struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&context->joysticks);
joystick->joystick = sdlJoystick;
joystick->index = SDL_JoystickListSize(&context->joysticks) - 1;
#if SDL_VERSION_ATLEAST(2, 0, 0)
joystick->id = SDL_JoystickInstanceID(joystick->joystick);
joystick->haptic = SDL_HapticOpenFromJoystick(joystick->joystick);
#else
joystick->id = SDL_JoystickIndex(joystick->joystick);
#endif
} }
} }
} }
@ -101,6 +120,7 @@ void mSDLDeinitEvents(struct mSDLEvents* context) {
for (i = 0; i < SDL_JoystickListSize(&context->joysticks); ++i) { for (i = 0; i < SDL_JoystickListSize(&context->joysticks); ++i) {
struct SDL_JoystickCombo* joystick = SDL_JoystickListGetPointer(&context->joysticks, i); struct SDL_JoystickCombo* joystick = SDL_JoystickListGetPointer(&context->joysticks, i);
#if SDL_VERSION_ATLEAST(2, 0, 0) #if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_GameControllerClose(joystick->controller);
SDL_HapticClose(joystick->haptic); SDL_HapticClose(joystick->haptic);
#endif #endif
SDL_JoystickClose(joystick->joystick); SDL_JoystickClose(joystick->joystick);
@ -350,10 +370,6 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration*
SDL_Event event; SDL_Event event;
while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED) > 0) { while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED) > 0) {
if (event.type == SDL_JOYDEVICEADDED) { if (event.type == SDL_JOYDEVICEADDED) {
SDL_Joystick* sdlJoystick = SDL_JoystickOpen(event.jdevice.which);
if (!sdlJoystick) {
continue;
}
ssize_t joysticks[MAX_PLAYERS]; ssize_t joysticks[MAX_PLAYERS];
ssize_t i; ssize_t i;
// Pointers can get invalidated, so we'll need to refresh them // Pointers can get invalidated, so we'll need to refresh them
@ -361,38 +377,26 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration*
joysticks[i] = events->players[i]->joystick ? (ssize_t) SDL_JoystickListIndex(&events->joysticks, events->players[i]->joystick) : -1; joysticks[i] = events->players[i]->joystick ? (ssize_t) SDL_JoystickListIndex(&events->joysticks, events->players[i]->joystick) : -1;
events->players[i]->joystick = NULL; events->players[i]->joystick = NULL;
} }
struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&events->joysticks); struct SDL_JoystickCombo* joystick = _mSDLOpenJoystick(events, event.jdevice.which);
joystick->joystick = sdlJoystick;
joystick->id = SDL_JoystickInstanceID(joystick->joystick);
joystick->index = SDL_JoystickListSize(&events->joysticks) - 1;
#if SDL_VERSION_ATLEAST(2, 0, 0)
joystick->haptic = SDL_HapticOpenFromJoystick(joystick->joystick);
#endif
for (i = 0; i < events->playersAttached && i < MAX_PLAYERS; ++i) { for (i = 0; i < events->playersAttached && i < MAX_PLAYERS; ++i) {
if (joysticks[i] != -1) { if (joysticks[i] != -1) {
events->players[i]->joystick = SDL_JoystickListGetPointer(&events->joysticks, joysticks[i]); events->players[i]->joystick = SDL_JoystickListGetPointer(&events->joysticks, joysticks[i]);
} }
} }
#if SDL_VERSION_ATLEAST(2, 0, 0)
char joystickName[34] = {0}; char joystickName[34] = {0};
SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick->joystick), joystickName, sizeof(joystickName)); SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick->joystick), joystickName, sizeof(joystickName));
#else for (i = 0; (int) i < events->playersAttached; ++i) {
const char* joystickName = SDL_JoystickName(SDL_JoystickIndex(joystick->joystick)); if (events->players[i]->joystick) {
if (joystickName) continue;
#endif }
{ if (events->preferredJoysticks[i] && strcmp(events->preferredJoysticks[i], joystickName) == 0) {
for (i = 0; (int) i < events->playersAttached; ++i) { events->players[i]->joystick = joystick;
if (events->players[i]->joystick) { if (config) {
continue; mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName);
}
if (events->preferredJoysticks[i] && strcmp(events->preferredJoysticks[i], joystickName) == 0) {
events->players[i]->joystick = joystick;
if (config) {
mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName);
}
return;
} }
return;
} }
} }
for (i = 0; (int) i < events->playersAttached; ++i) { for (i = 0; (int) i < events->playersAttached; ++i) {
@ -400,11 +404,7 @@ void mSDLUpdateJoysticks(struct mSDLEvents* events, const struct Configuration*
continue; continue;
} }
events->players[i]->joystick = joystick; events->players[i]->joystick = joystick;
if (config if (config && joystickName[0]) {
#if !SDL_VERSION_ATLEAST(2, 0, 0)
&& joystickName
#endif
) {
mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName); mInputProfileLoad(events->players[i]->bindings, SDL_BINDING_BUTTON, config, joystickName);
} }
break; break;
@ -686,11 +686,17 @@ static int32_t _readTilt(struct mSDLPlayer* player, int axis) {
static int32_t _mSDLReadTiltX(struct mRotationSource* source) { static int32_t _mSDLReadTiltX(struct mRotationSource* source) {
struct mSDLRotation* rotation = (struct mSDLRotation*) source; struct mSDLRotation* rotation = (struct mSDLRotation*) source;
if (rotation->axisX < 0) {
return rotation->accelX * -0x2000000;
}
return _readTilt(rotation->p, rotation->axisX); return _readTilt(rotation->p, rotation->axisX);
} }
static int32_t _mSDLReadTiltY(struct mRotationSource* source) { static int32_t _mSDLReadTiltY(struct mRotationSource* source) {
struct mSDLRotation* rotation = (struct mSDLRotation*) source; struct mSDLRotation* rotation = (struct mSDLRotation*) source;
if (rotation->axisY < 0) {
return rotation->accelY * -0x2000000;
}
return _readTilt(rotation->p, rotation->axisY); return _readTilt(rotation->p, rotation->axisY);
} }
@ -707,6 +713,30 @@ static void _mSDLRotationSample(struct mRotationSource* source) {
return; return;
} }
#if SDL_VERSION_ATLEAST(2, 0, 14)
if (rotation->p->joystick->controller) {
SDL_GameController* controller = rotation->p->joystick->controller;
if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_ACCEL)) {
float accel[3];
int count = SDL_GameControllerGetSensorData(controller, SDL_SENSOR_ACCEL, accel, 3);
if (count >= 0) {
rotation->accelX = accel[0];
rotation->accelY = accel[2];
rotation->axisX = -1;
rotation->axisY = -1;
}
}
if (SDL_GameControllerHasSensor(controller, SDL_SENSOR_GYRO)) {
float theta[3];
int count = SDL_GameControllerGetSensorData(controller, SDL_SENSOR_GYRO, theta, 3);
if (count >= 0) {
rotation->zDelta = theta[1] / -10.f;
}
return;
}
}
#endif
int x = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroX); int x = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroX);
int y = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroY); int y = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroY);
union { union {

View File

@ -38,6 +38,7 @@ struct SDL_JoystickCombo {
size_t index; size_t index;
SDL_Joystick* joystick; SDL_Joystick* joystick;
#if SDL_VERSION_ATLEAST(2, 0, 0) #if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_GameController* controller;
SDL_Haptic* haptic; SDL_Haptic* haptic;
SDL_JoystickID id; SDL_JoystickID id;
#else #else
@ -88,6 +89,8 @@ struct mSDLPlayer {
// Tilt // Tilt
int axisX; int axisX;
int axisY; int axisY;
float accelX;
float accelY;
// Gyro // Gyro
int gyroX; int gyroX;