mirror of https://github.com/mgba-emu/mgba.git
SDL: Hotplugging for joysticks. Still needs work.
This commit is contained in:
parent
f6590de2ce
commit
13dfb144e8
1
CHANGES
1
CHANGES
|
@ -18,6 +18,7 @@ Features:
|
||||||
- Cleaner, unified settings window
|
- Cleaner, unified settings window
|
||||||
- Added a setting for pausing when the emulator is not in focus
|
- Added a setting for pausing when the emulator is not in focus
|
||||||
- Customizable paths for save games, save states, screenshots and patches
|
- Customizable paths for save games, save states, screenshots and patches
|
||||||
|
- Controller hotplugging
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
- Util: Fix PowerPC PNG read/write pixel order
|
- Util: Fix PowerPC PNG read/write pixel order
|
||||||
- VFS: Fix VFileReadline and remove _vfdReadline
|
- VFS: Fix VFileReadline and remove _vfdReadline
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
#include "InputController.h"
|
#include "InputController.h"
|
||||||
#include "KeyEditor.h"
|
#include "KeyEditor.h"
|
||||||
|
|
||||||
|
#ifdef BUILD_SDL
|
||||||
|
extern "C" {
|
||||||
|
#include "platform/sdl/sdl-events.h"
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace QGBA;
|
using namespace QGBA;
|
||||||
|
|
||||||
const qreal GBAKeyEditor::DPAD_CENTER_X = 0.247;
|
const qreal GBAKeyEditor::DPAD_CENTER_X = 0.247;
|
||||||
|
@ -51,22 +57,19 @@ GBAKeyEditor::GBAKeyEditor(InputController* controller, int type, const QString&
|
||||||
|
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (type == SDL_BINDING_BUTTON) {
|
if (type == SDL_BINDING_BUTTON) {
|
||||||
|
controller->updateJoysticks();
|
||||||
controller->recalibrateAxes();
|
controller->recalibrateAxes();
|
||||||
lookupAxes(map);
|
lookupAxes(map);
|
||||||
|
|
||||||
m_profileSelect = new QComboBox(this);
|
m_profileSelect = new QComboBox(this);
|
||||||
m_profileSelect->addItems(controller->connectedGamepads(type));
|
m_profileSelect->addItems(controller->connectedGamepads(type));
|
||||||
int activeGamepad = controller->gamepad(type);
|
int activeGamepad = controller->gamepad(type);
|
||||||
|
selectGamepad(activeGamepad);
|
||||||
if (activeGamepad > 0) {
|
if (activeGamepad > 0) {
|
||||||
m_profileSelect->setCurrentIndex(activeGamepad);
|
m_profileSelect->setCurrentIndex(activeGamepad);
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(m_profileSelect, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [this] (int i) {
|
connect(m_profileSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGamepad(int)));
|
||||||
m_controller->setGamepad(m_type, i);
|
|
||||||
m_profile = m_profileSelect->currentText();
|
|
||||||
m_controller->loadProfile(m_type, m_profile);
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
m_clear = new QWidget(this);
|
m_clear = new QWidget(this);
|
||||||
QHBoxLayout* layout = new QHBoxLayout;
|
QHBoxLayout* layout = new QHBoxLayout;
|
||||||
|
@ -311,6 +314,13 @@ void GBAKeyEditor::setAxisValue(int axis, int32_t value) {
|
||||||
KeyEditor* focused = *m_currentKey;
|
KeyEditor* focused = *m_currentKey;
|
||||||
focused->setValueAxis(axis, value);
|
focused->setValueAxis(axis, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GBAKeyEditor::selectGamepad(int index) {
|
||||||
|
m_controller->setGamepad(m_type, index);
|
||||||
|
m_profile = m_profileSelect->currentText();
|
||||||
|
m_controller->loadProfile(m_type, m_profile);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
KeyEditor* GBAKeyEditor::keyById(GBAKey key) {
|
KeyEditor* GBAKeyEditor::keyById(GBAKey key) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ private slots:
|
||||||
void refresh();
|
void refresh();
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
void setAxisValue(int axis, int32_t value);
|
void setAxisValue(int axis, int32_t value);
|
||||||
|
void selectGamepad(int index);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -46,6 +46,7 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
|
||||||
++s_sdlInited;
|
++s_sdlInited;
|
||||||
m_sdlPlayer.bindings = &m_inputMap;
|
m_sdlPlayer.bindings = &m_inputMap;
|
||||||
GBASDLInitBindings(&m_inputMap);
|
GBASDLInitBindings(&m_inputMap);
|
||||||
|
updateJoysticks();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_gamepadTimer = new QTimer(this);
|
m_gamepadTimer = new QTimer(this);
|
||||||
|
@ -146,9 +147,9 @@ const char* InputController::profileForType(uint32_t type) {
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) {
|
if (type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) {
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
return SDL_JoystickName(m_sdlPlayer.joystick);
|
return SDL_JoystickName(m_sdlPlayer.joystick->joystick);
|
||||||
#else
|
#else
|
||||||
return SDL_JoystickName(SDL_JoystickIndex(m_sdlPlayer.joystick));
|
return SDL_JoystickName(SDL_JoystickIndex(m_sdlPlayer.joystick->joystick));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -161,12 +162,12 @@ QStringList InputController::connectedGamepads(uint32_t type) const {
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (type == SDL_BINDING_BUTTON) {
|
if (type == SDL_BINDING_BUTTON) {
|
||||||
QStringList pads;
|
QStringList pads;
|
||||||
for (size_t i = 0; i < s_sdlEvents.nJoysticks; ++i) {
|
for (size_t i = 0; i < SDL_JoystickListSize(&s_sdlEvents.joysticks); ++i) {
|
||||||
const char* name;
|
const char* name;
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
name = SDL_JoystickName(s_sdlEvents.joysticks[i]);
|
name = SDL_JoystickName(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, i)->joystick);
|
||||||
#else
|
#else
|
||||||
name = SDL_JoystickName(SDL_JoystickIndex(s_sdlEvents.joysticks[i]));
|
name = SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&s_sdlEvents.joysticks, i)->joystick));
|
||||||
#endif
|
#endif
|
||||||
if (name) {
|
if (name) {
|
||||||
pads.append(QString(name));
|
pads.append(QString(name));
|
||||||
|
@ -184,7 +185,7 @@ QStringList InputController::connectedGamepads(uint32_t type) const {
|
||||||
int InputController::gamepad(uint32_t type) const {
|
int InputController::gamepad(uint32_t type) const {
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (type == SDL_BINDING_BUTTON) {
|
if (type == SDL_BINDING_BUTTON) {
|
||||||
return m_sdlPlayer.joystickIndex;
|
return m_sdlPlayer.joystick ? m_sdlPlayer.joystick->index : 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -282,11 +283,17 @@ void InputController::bindKey(uint32_t type, int key, GBAKey gbaKey) {
|
||||||
return GBAInputBindKey(&m_inputMap, type, key, gbaKey);
|
return GBAInputBindKey(&m_inputMap, type, key, gbaKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputController::updateJoysticks() {
|
||||||
|
#ifdef BUILD_SDL
|
||||||
|
GBASDLUpdateJoysticks(&s_sdlEvents);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int InputController::pollEvents() {
|
int InputController::pollEvents() {
|
||||||
int activeButtons = 0;
|
int activeButtons = 0;
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (m_playerAttached) {
|
if (m_playerAttached && m_sdlPlayer.joystick) {
|
||||||
SDL_Joystick* joystick = m_sdlPlayer.joystick;
|
SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick;
|
||||||
SDL_JoystickUpdate();
|
SDL_JoystickUpdate();
|
||||||
int numButtons = SDL_JoystickNumButtons(joystick);
|
int numButtons = SDL_JoystickNumButtons(joystick);
|
||||||
int i;
|
int i;
|
||||||
|
@ -336,8 +343,8 @@ int InputController::pollEvents() {
|
||||||
QSet<int> InputController::activeGamepadButtons(int type) {
|
QSet<int> InputController::activeGamepadButtons(int type) {
|
||||||
QSet<int> activeButtons;
|
QSet<int> activeButtons;
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (m_playerAttached && type == SDL_BINDING_BUTTON) {
|
if (m_playerAttached && type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) {
|
||||||
SDL_Joystick* joystick = m_sdlPlayer.joystick;
|
SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick;
|
||||||
SDL_JoystickUpdate();
|
SDL_JoystickUpdate();
|
||||||
int numButtons = SDL_JoystickNumButtons(joystick);
|
int numButtons = SDL_JoystickNumButtons(joystick);
|
||||||
int i;
|
int i;
|
||||||
|
@ -353,8 +360,8 @@ QSet<int> InputController::activeGamepadButtons(int type) {
|
||||||
|
|
||||||
void InputController::recalibrateAxes() {
|
void InputController::recalibrateAxes() {
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (m_playerAttached) {
|
if (m_playerAttached && m_sdlPlayer.joystick) {
|
||||||
SDL_Joystick* joystick = m_sdlPlayer.joystick;
|
SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick;
|
||||||
SDL_JoystickUpdate();
|
SDL_JoystickUpdate();
|
||||||
int numAxes = SDL_JoystickNumAxes(joystick);
|
int numAxes = SDL_JoystickNumAxes(joystick);
|
||||||
if (numAxes < 1) {
|
if (numAxes < 1) {
|
||||||
|
@ -372,8 +379,8 @@ void InputController::recalibrateAxes() {
|
||||||
QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes(int type) {
|
QSet<QPair<int, GamepadAxisEvent::Direction>> InputController::activeGamepadAxes(int type) {
|
||||||
QSet<QPair<int, GamepadAxisEvent::Direction>> activeAxes;
|
QSet<QPair<int, GamepadAxisEvent::Direction>> activeAxes;
|
||||||
#ifdef BUILD_SDL
|
#ifdef BUILD_SDL
|
||||||
if (m_playerAttached && type == SDL_BINDING_BUTTON) {
|
if (m_playerAttached && type == SDL_BINDING_BUTTON && m_sdlPlayer.joystick) {
|
||||||
SDL_Joystick* joystick = m_sdlPlayer.joystick;
|
SDL_Joystick* joystick = m_sdlPlayer.joystick->joystick;
|
||||||
SDL_JoystickUpdate();
|
SDL_JoystickUpdate();
|
||||||
int numAxes = SDL_JoystickNumAxes(joystick);
|
int numAxes = SDL_JoystickNumAxes(joystick);
|
||||||
if (numAxes < 1) {
|
if (numAxes < 1) {
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
|
|
||||||
const GBAInputMap* map() const { return &m_inputMap; }
|
const GBAInputMap* map() const { return &m_inputMap; }
|
||||||
|
|
||||||
|
void updateJoysticks();
|
||||||
int pollEvents();
|
int pollEvents();
|
||||||
|
|
||||||
static const int32_t AXIS_THRESHOLD = 0x3000;
|
static const int32_t AXIS_THRESHOLD = 0x3000;
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
#define GYRO_STEPS 100
|
#define GYRO_STEPS 100
|
||||||
#define RUMBLE_PWM 20
|
#define RUMBLE_PWM 20
|
||||||
|
|
||||||
|
DEFINE_VECTOR(SDL_JoystickList, struct SDL_JoystickCombo);
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
static void _GBASDLSetRumble(struct GBARumble* rumble, int enable);
|
static void _GBASDLSetRumble(struct GBARumble* rumble, int enable);
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,22 +54,9 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) {
|
||||||
|
|
||||||
SDL_JoystickEventState(SDL_ENABLE);
|
SDL_JoystickEventState(SDL_ENABLE);
|
||||||
int nJoysticks = SDL_NumJoysticks();
|
int nJoysticks = SDL_NumJoysticks();
|
||||||
|
SDL_JoystickListInit(&context->joysticks, nJoysticks);
|
||||||
if (nJoysticks > 0) {
|
if (nJoysticks > 0) {
|
||||||
context->nJoysticks = nJoysticks;
|
GBASDLUpdateJoysticks(context);
|
||||||
context->joysticks = calloc(context->nJoysticks, sizeof(SDL_Joystick*));
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
context->haptic = calloc(context->nJoysticks, sizeof(SDL_Haptic*));
|
|
||||||
#endif
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < context->nJoysticks; ++i) {
|
|
||||||
context->joysticks[i] = SDL_JoystickOpen(i);
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
|
||||||
context->haptic[i] = SDL_HapticOpenFromJoystick(context->joysticks[i]);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
context->nJoysticks = 0;
|
|
||||||
context->joysticks = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
context->playersAttached = 0;
|
context->playersAttached = 0;
|
||||||
|
@ -75,7 +64,6 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < MAX_PLAYERS; ++i) {
|
for (i = 0; i < MAX_PLAYERS; ++i) {
|
||||||
context->preferredJoysticks[i] = 0;
|
context->preferredJoysticks[i] = 0;
|
||||||
context->joysticksClaimed[i] = SIZE_MAX;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
#if !SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
@ -88,13 +76,14 @@ bool GBASDLInitEvents(struct GBASDLEvents* context) {
|
||||||
|
|
||||||
void GBASDLDeinitEvents(struct GBASDLEvents* context) {
|
void GBASDLDeinitEvents(struct GBASDLEvents* context) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < context->nJoysticks; ++i) {
|
for (i = 0; i < SDL_JoystickListSize(&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_HapticClose(context->haptic[i]);
|
SDL_HapticClose(joystick->haptic);
|
||||||
#endif
|
#endif
|
||||||
SDL_JoystickClose(context->joysticks[i]);
|
SDL_JoystickClose(joystick->joystick);
|
||||||
}
|
}
|
||||||
|
SDL_JoystickListDeinit(&context->joysticks);
|
||||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +149,6 @@ void GBASDLInitBindings(struct GBAInputMap* inputMap) {
|
||||||
|
|
||||||
bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player) {
|
bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player) {
|
||||||
player->joystick = 0;
|
player->joystick = 0;
|
||||||
player->joystickIndex = SIZE_MAX;
|
|
||||||
|
|
||||||
if (events->playersAttached >= MAX_PLAYERS) {
|
if (events->playersAttached >= MAX_PLAYERS) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -187,15 +175,17 @@ bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player
|
||||||
player->rotation.p = player;
|
player->rotation.p = player;
|
||||||
|
|
||||||
player->playerId = events->playersAttached;
|
player->playerId = events->playersAttached;
|
||||||
|
events->players[player->playerId] = player;
|
||||||
size_t firstUnclaimed = SIZE_MAX;
|
size_t firstUnclaimed = SIZE_MAX;
|
||||||
|
size_t index = SIZE_MAX;
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < events->nJoysticks; ++i) {
|
for (i = 0; i < SDL_JoystickListSize(&events->joysticks); ++i) {
|
||||||
bool claimed = false;
|
bool claimed = false;
|
||||||
|
|
||||||
int p;
|
int p;
|
||||||
for (p = 0; p < events->playersAttached; ++p) {
|
for (p = 0; p < events->playersAttached; ++p) {
|
||||||
if (events->joysticksClaimed[p] == i) {
|
if (events->players[p]->joystick == SDL_JoystickListGetPointer(&events->joysticks, i)) {
|
||||||
claimed = true;
|
claimed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -210,28 +200,26 @@ bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player
|
||||||
|
|
||||||
const char* joystickName;
|
const char* joystickName;
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
joystickName = SDL_JoystickName(events->joysticks[i]);
|
joystickName = SDL_JoystickName(SDL_JoystickListGetPointer(&events->joysticks, i)->joystick);
|
||||||
#else
|
#else
|
||||||
joystickName = SDL_JoystickName(SDL_JoystickIndex(events->joysticks[i]));
|
joystickName = SDL_JoystickName(SDL_JoystickIndex(SDL_JoystickListGetPointer(&events->joysticks, i)->joystick));
|
||||||
#endif
|
#endif
|
||||||
if (events->preferredJoysticks[player->playerId] && strcmp(events->preferredJoysticks[player->playerId], joystickName) == 0) {
|
if (events->preferredJoysticks[player->playerId] && strcmp(events->preferredJoysticks[player->playerId], joystickName) == 0) {
|
||||||
player->joystickIndex = i;
|
index = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->joystickIndex == SIZE_MAX && firstUnclaimed != SIZE_MAX) {
|
if (index == SIZE_MAX && firstUnclaimed != SIZE_MAX) {
|
||||||
player->joystickIndex = firstUnclaimed;
|
index = firstUnclaimed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player->joystickIndex != SIZE_MAX) {
|
if (index != SIZE_MAX) {
|
||||||
player->joystick = events->joysticks[player->joystickIndex];
|
player->joystick = SDL_JoystickListGetPointer(&events->joysticks, index);
|
||||||
events->joysticksClaimed[player->playerId] = player->joystickIndex;
|
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
player->haptic = events->haptic[player->joystickIndex];
|
if (player->joystick->haptic) {
|
||||||
if (player->haptic) {
|
SDL_HapticRumbleInit(player->joystick->haptic);
|
||||||
SDL_HapticRumbleInit(player->haptic);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -241,7 +229,19 @@ bool GBASDLAttachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBASDLDetachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player) {
|
void GBASDLDetachPlayer(struct GBASDLEvents* events, struct GBASDLPlayer* player) {
|
||||||
events->joysticksClaimed[player->playerId] = SIZE_MAX;
|
if (player != events->players[player->playerId]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int i;
|
||||||
|
for (i = player->playerId; i < events->playersAttached; ++i) {
|
||||||
|
if (i + 1 < MAX_PLAYERS) {
|
||||||
|
events->players[i] = events->players[i + 1];
|
||||||
|
}
|
||||||
|
if (i < events->playersAttached - 1) {
|
||||||
|
events->players[i]->playerId = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--events->playersAttached;
|
||||||
CircleBufferDeinit(&player->rotation.zHistory);
|
CircleBufferDeinit(&player->rotation.zHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,15 +250,15 @@ void GBASDLPlayerLoadConfig(struct GBASDLPlayer* context, const struct Configura
|
||||||
if (context->joystick) {
|
if (context->joystick) {
|
||||||
GBAInputMapLoad(context->bindings, SDL_BINDING_BUTTON, config);
|
GBAInputMapLoad(context->bindings, SDL_BINDING_BUTTON, config);
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
const char* name = SDL_JoystickName(context->joystick);
|
const char* name = SDL_JoystickName(context->joystick->joystick);
|
||||||
#else
|
#else
|
||||||
const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick));
|
const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick->joystick));
|
||||||
#endif
|
#endif
|
||||||
GBAInputProfileLoad(context->bindings, SDL_BINDING_BUTTON, config, name);
|
GBAInputProfileLoad(context->bindings, SDL_BINDING_BUTTON, config, name);
|
||||||
|
|
||||||
const char* value;
|
const char* value;
|
||||||
char* end;
|
char* end;
|
||||||
int numAxes = SDL_JoystickNumAxes(context->joystick);
|
int numAxes = SDL_JoystickNumAxes(context->joystick->joystick);
|
||||||
int axis;
|
int axis;
|
||||||
value = GBAInputGetCustomValue(config, SDL_BINDING_BUTTON, "tiltAxisX", name);
|
value = GBAInputGetCustomValue(config, SDL_BINDING_BUTTON, "tiltAxisX", name);
|
||||||
if (value) {
|
if (value) {
|
||||||
|
@ -301,9 +301,9 @@ void GBASDLPlayerLoadConfig(struct GBASDLPlayer* context, const struct Configura
|
||||||
void GBASDLPlayerSaveConfig(const struct GBASDLPlayer* context, struct Configuration* config) {
|
void GBASDLPlayerSaveConfig(const struct GBASDLPlayer* context, struct Configuration* config) {
|
||||||
if (context->joystick) {
|
if (context->joystick) {
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
const char* name = SDL_JoystickName(context->joystick);
|
const char* name = SDL_JoystickName(context->joystick->joystick);
|
||||||
#else
|
#else
|
||||||
const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick));
|
const char* name = SDL_JoystickName(SDL_JoystickIndex(context->joystick->joystick));
|
||||||
#endif
|
#endif
|
||||||
char value[12];
|
char value[12];
|
||||||
snprintf(value, sizeof(value), "%i", context->rotation.axisX);
|
snprintf(value, sizeof(value), "%i", context->rotation.axisX);
|
||||||
|
@ -320,14 +320,54 @@ void GBASDLPlayerSaveConfig(const struct GBASDLPlayer* context, struct Configura
|
||||||
}
|
}
|
||||||
|
|
||||||
void GBASDLPlayerChangeJoystick(struct GBASDLEvents* events, struct GBASDLPlayer* player, size_t index) {
|
void GBASDLPlayerChangeJoystick(struct GBASDLEvents* events, struct GBASDLPlayer* player, size_t index) {
|
||||||
if (player->playerId >= MAX_PLAYERS || index >= events->nJoysticks) {
|
if (player->playerId >= MAX_PLAYERS || index >= SDL_JoystickListSize(&events->joysticks)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
events->joysticksClaimed[player->playerId] = index;
|
player->joystick = SDL_JoystickListGetPointer(&events->joysticks, index);
|
||||||
player->joystickIndex = index;
|
}
|
||||||
player->joystick = events->joysticks[index];
|
|
||||||
|
void GBASDLUpdateJoysticks(struct GBASDLEvents* events) {
|
||||||
|
// Pump SDL joystick events without eating the rest of the events
|
||||||
|
SDL_JoystickUpdate();
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
player->haptic = events->haptic[index];
|
SDL_Event event;
|
||||||
|
while (SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED) > 0) {
|
||||||
|
if (event.type == SDL_JOYDEVICEADDED) {
|
||||||
|
struct SDL_JoystickCombo* joystick = SDL_JoystickListAppend(&events->joysticks);
|
||||||
|
joystick->joystick = SDL_JoystickOpen(event.jdevice.which);
|
||||||
|
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
|
||||||
|
} else if (event.type == SDL_JOYDEVICEREMOVED) {
|
||||||
|
SDL_JoystickID ids[MAX_PLAYERS];
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; (int) i < events->playersAttached; ++i) {
|
||||||
|
if (events->players[i]->joystick) {
|
||||||
|
ids[i] = events->players[i]->joystick->id;
|
||||||
|
events->players[i]->joystick = 0;
|
||||||
|
} else {
|
||||||
|
ids[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < SDL_JoystickListSize(&events->joysticks);) {
|
||||||
|
struct SDL_JoystickCombo* joystick = SDL_JoystickListGetPointer(&events->joysticks, i);
|
||||||
|
if (joystick->id == event.jdevice.which) {
|
||||||
|
SDL_JoystickListShift(&events->joysticks, i, 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
SDL_JoystickListGetPointer(&events->joysticks, i)->index = i;
|
||||||
|
int p;
|
||||||
|
for (p = 0; p < events->playersAttached; ++p) {
|
||||||
|
if (joystick->id == ids[p]) {
|
||||||
|
events->players[p]->joystick = SDL_JoystickListGetPointer(&events->joysticks, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -540,7 +580,7 @@ void GBASDLHandleEvent(struct GBAThread* context, struct GBASDLPlayer* sdlContex
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
static void _GBASDLSetRumble(struct GBARumble* rumble, int enable) {
|
static void _GBASDLSetRumble(struct GBARumble* rumble, int enable) {
|
||||||
struct GBASDLRumble* sdlRumble = (struct GBASDLRumble*) rumble;
|
struct GBASDLRumble* sdlRumble = (struct GBASDLRumble*) rumble;
|
||||||
if (!sdlRumble->p->haptic || !SDL_HapticRumbleSupported(sdlRumble->p->haptic)) {
|
if (!sdlRumble->p->joystick->haptic || !SDL_HapticRumbleSupported(sdlRumble->p->joystick->haptic)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sdlRumble->level += enable;
|
sdlRumble->level += enable;
|
||||||
|
@ -551,15 +591,15 @@ static void _GBASDLSetRumble(struct GBARumble* rumble, int enable) {
|
||||||
}
|
}
|
||||||
CircleBufferWrite8(&sdlRumble->history, enable);
|
CircleBufferWrite8(&sdlRumble->history, enable);
|
||||||
if (sdlRumble->level) {
|
if (sdlRumble->level) {
|
||||||
SDL_HapticRumblePlay(sdlRumble->p->haptic, sdlRumble->level / (float) RUMBLE_PWM, 20);
|
SDL_HapticRumblePlay(sdlRumble->p->joystick->haptic, sdlRumble->level / (float) RUMBLE_PWM, 20);
|
||||||
} else {
|
} else {
|
||||||
SDL_HapticRumbleStop(sdlRumble->p->haptic);
|
SDL_HapticRumbleStop(sdlRumble->p->joystick->haptic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int32_t _readTilt(struct GBASDLPlayer* player, int axis) {
|
static int32_t _readTilt(struct GBASDLPlayer* player, int axis) {
|
||||||
return SDL_JoystickGetAxis(player->joystick, axis) * 0x3800;
|
return SDL_JoystickGetAxis(player->joystick->joystick, axis) * 0x3800;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t _GBASDLReadTiltX(struct GBARotationSource* source) {
|
static int32_t _GBASDLReadTiltX(struct GBARotationSource* source) {
|
||||||
|
@ -582,8 +622,8 @@ static void _GBASDLRotationSample(struct GBARotationSource* source) {
|
||||||
struct GBASDLRotation* rotation = (struct GBASDLRotation*) source;
|
struct GBASDLRotation* rotation = (struct GBASDLRotation*) source;
|
||||||
SDL_JoystickUpdate();
|
SDL_JoystickUpdate();
|
||||||
|
|
||||||
int x = SDL_JoystickGetAxis(rotation->p->joystick, rotation->gyroX);
|
int x = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroX);
|
||||||
int y = SDL_JoystickGetAxis(rotation->p->joystick, rotation->gyroY);
|
int y = SDL_JoystickGetAxis(rotation->p->joystick->joystick, rotation->gyroY);
|
||||||
union {
|
union {
|
||||||
float f;
|
float f;
|
||||||
int32_t i;
|
int32_t i;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "util/common.h"
|
#include "util/common.h"
|
||||||
#include "util/circle-buffer.h"
|
#include "util/circle-buffer.h"
|
||||||
|
#include "util/vector.h"
|
||||||
|
|
||||||
#include "gba/supervisor/thread.h"
|
#include "gba/supervisor/thread.h"
|
||||||
|
|
||||||
|
@ -21,14 +22,25 @@
|
||||||
struct GBAVideoSoftwareRenderer;
|
struct GBAVideoSoftwareRenderer;
|
||||||
struct Configuration;
|
struct Configuration;
|
||||||
|
|
||||||
|
struct SDL_JoystickCombo {
|
||||||
|
SDL_JoystickID id;
|
||||||
|
size_t index;
|
||||||
|
SDL_Joystick* joystick;
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
SDL_Haptic* haptic;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
DECLARE_VECTOR(SDL_JoystickList, struct SDL_JoystickCombo);
|
||||||
|
|
||||||
|
struct GBASDLPlayer;
|
||||||
|
|
||||||
struct GBASDLEvents {
|
struct GBASDLEvents {
|
||||||
SDL_Joystick** joysticks;
|
struct SDL_JoystickList joysticks;
|
||||||
size_t nJoysticks;
|
|
||||||
const char* preferredJoysticks[MAX_PLAYERS];
|
const char* preferredJoysticks[MAX_PLAYERS];
|
||||||
int playersAttached;
|
int playersAttached;
|
||||||
size_t joysticksClaimed[MAX_PLAYERS];
|
struct GBASDLPlayer* players[MAX_PLAYERS];
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_Haptic** haptic;
|
|
||||||
int screensaverSuspendDepth;
|
int screensaverSuspendDepth;
|
||||||
bool screensaverSuspendable;
|
bool screensaverSuspendable;
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,13 +49,11 @@ struct GBASDLEvents {
|
||||||
struct GBASDLPlayer {
|
struct GBASDLPlayer {
|
||||||
size_t playerId;
|
size_t playerId;
|
||||||
struct GBAInputMap* bindings;
|
struct GBAInputMap* bindings;
|
||||||
SDL_Joystick* joystick;
|
struct SDL_JoystickCombo* joystick;
|
||||||
size_t joystickIndex;
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
int fullscreen;
|
int fullscreen;
|
||||||
int windowUpdated;
|
int windowUpdated;
|
||||||
SDL_Haptic* haptic;
|
|
||||||
|
|
||||||
struct GBASDLRumble {
|
struct GBASDLRumble {
|
||||||
struct GBARumble d;
|
struct GBARumble d;
|
||||||
|
@ -80,6 +90,7 @@ bool GBASDLAttachPlayer(struct GBASDLEvents*, struct GBASDLPlayer*);
|
||||||
void GBASDLDetachPlayer(struct GBASDLEvents*, struct GBASDLPlayer*);
|
void GBASDLDetachPlayer(struct GBASDLEvents*, struct GBASDLPlayer*);
|
||||||
void GBASDLEventsLoadConfig(struct GBASDLEvents*, const struct Configuration*);
|
void GBASDLEventsLoadConfig(struct GBASDLEvents*, const struct Configuration*);
|
||||||
void GBASDLPlayerChangeJoystick(struct GBASDLEvents*, struct GBASDLPlayer*, size_t index);
|
void GBASDLPlayerChangeJoystick(struct GBASDLEvents*, struct GBASDLPlayer*, size_t index);
|
||||||
|
void GBASDLUpdateJoysticks(struct GBASDLEvents* events);
|
||||||
|
|
||||||
void GBASDLInitBindings(struct GBAInputMap* inputMap);
|
void GBASDLInitBindings(struct GBAInputMap* inputMap);
|
||||||
void GBASDLPlayerLoadConfig(struct GBASDLPlayer*, const struct Configuration*);
|
void GBASDLPlayerLoadConfig(struct GBASDLPlayer*, const struct Configuration*);
|
||||||
|
|
Loading…
Reference in New Issue