|
@@ -44,6 +44,15 @@ enum
|
|
|
SDL_GAMEPAD_BUTTON_GAMEINPUT_SHARE = 11
|
|
SDL_GAMEPAD_BUTTON_GAMEINPUT_SHARE = 11
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+enum
|
|
|
|
|
+{
|
|
|
|
|
+ SDL_GAMEINPUT_RAWTYPE_NONE,
|
|
|
|
|
+ SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR,
|
|
|
|
|
+ SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT,
|
|
|
|
|
+ SDL_GAMEINPUT_RAWTYPE_GUITAR_HERO_LIVE_GUITAR,
|
|
|
|
|
+ SDL_GAMEINPUT_RAWTYPE_LEGACY_ADAPTER,
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
typedef struct GAMEINPUT_InternalDevice
|
|
typedef struct GAMEINPUT_InternalDevice
|
|
|
{
|
|
{
|
|
|
IGameInputDevice *device;
|
|
IGameInputDevice *device;
|
|
@@ -52,6 +61,7 @@ typedef struct GAMEINPUT_InternalDevice
|
|
|
SDL_GUID guid; // generated by SDL
|
|
SDL_GUID guid; // generated by SDL
|
|
|
SDL_JoystickID device_instance; // generated by SDL
|
|
SDL_JoystickID device_instance; // generated by SDL
|
|
|
const GameInputDeviceInfo *info;
|
|
const GameInputDeviceInfo *info;
|
|
|
|
|
+ int raw_type;
|
|
|
int steam_virtual_gamepad_slot;
|
|
int steam_virtual_gamepad_slot;
|
|
|
bool isAdded;
|
|
bool isAdded;
|
|
|
bool isDeleteRequested;
|
|
bool isDeleteRequested;
|
|
@@ -89,9 +99,66 @@ static bool GAMEINPUT_InternalIsGamepad(const GameInputDeviceInfo *info)
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static Uint8 GAMEINPUT_GetDeviceRawType(const GameInputDeviceInfo *info)
|
|
|
|
|
+{
|
|
|
|
|
+#if GAMEINPUT_API_VERSION >= 3
|
|
|
|
|
+ GameInputKind supportedInput = info->supportedInput;
|
|
|
|
|
+ if (supportedInput & GameInputKindRawDeviceReport) {
|
|
|
|
|
+ switch (info->vendorId) {
|
|
|
|
|
+ case USB_VENDOR_MADCATZ:
|
|
|
|
|
+ switch (info->productId) {
|
|
|
|
|
+ case USB_PRODUCT_MADCATZ_XB1_STRATOCASTER_GUITAR:
|
|
|
|
|
+ return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR;
|
|
|
|
|
+ case USB_PRODUCT_MADCATZ_XB1_DRUM_KIT:
|
|
|
|
|
+ return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT;
|
|
|
|
|
+ case USB_PRODUCT_MADCATZ_XB1_LEGACY_ADAPTER:
|
|
|
|
|
+ return SDL_GAMEINPUT_RAWTYPE_LEGACY_ADAPTER;
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case USB_VENDOR_PDP:
|
|
|
|
|
+ switch (info->productId) {
|
|
|
|
|
+ case USB_PRODUCT_PDP_XB1_JAGUAR_GUITAR:
|
|
|
|
|
+ case USB_PRODUCT_PDP_XB1_RIFFMASTER_GUITAR:
|
|
|
|
|
+ return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR;
|
|
|
|
|
+ case USB_PRODUCT_PDP_XB1_DRUM_KIT:
|
|
|
|
|
+ return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT;
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case USB_VENDOR_CRKD:
|
|
|
|
|
+ switch (info->productId) {
|
|
|
|
|
+ case USB_PRODUCT_PDP_XB1_JAGUAR_GUITAR:
|
|
|
|
|
+ return SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR;
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ case USB_VENDOR_RED_OCTANE:
|
|
|
|
|
+ switch (info->productId) {
|
|
|
|
|
+ case USB_PRODUCT_RED_OCTANE_XB1_GUITAR_HERO_LIVE_GUITAR:
|
|
|
|
|
+ return SDL_GAMEINPUT_RAWTYPE_GUITAR_HERO_LIVE_GUITAR;
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif // GAMEINPUT_API_VERSION >= 3
|
|
|
|
|
+ return SDL_GAMEINPUT_RAWTYPE_NONE;
|
|
|
|
|
+}
|
|
|
static Uint8 GAMEINPUT_GetDeviceSubtype(const GameInputDeviceInfo *info)
|
|
static Uint8 GAMEINPUT_GetDeviceSubtype(const GameInputDeviceInfo *info)
|
|
|
{
|
|
{
|
|
|
GameInputKind supportedInput = info->supportedInput;
|
|
GameInputKind supportedInput = info->supportedInput;
|
|
|
|
|
+ Uint8 rawType = GAMEINPUT_GetDeviceRawType(info);
|
|
|
|
|
+ if (rawType == SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR || rawType == SDL_GAMEINPUT_RAWTYPE_GUITAR_HERO_LIVE_GUITAR) {
|
|
|
|
|
+ return SDL_JOYSTICK_TYPE_GUITAR;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (rawType == SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_DRUM_KIT) {
|
|
|
|
|
+ return SDL_JOYSTICK_TYPE_DRUM_KIT;
|
|
|
|
|
+ }
|
|
|
if (supportedInput & GameInputKindRacingWheel) {
|
|
if (supportedInput & GameInputKindRacingWheel) {
|
|
|
return SDL_JOYSTICK_TYPE_WHEEL;
|
|
return SDL_JOYSTICK_TYPE_WHEEL;
|
|
|
}
|
|
}
|
|
@@ -132,6 +199,7 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
|
|
|
const char *product_string = NULL;
|
|
const char *product_string = NULL;
|
|
|
Uint8 driver_signature = 'g';
|
|
Uint8 driver_signature = 'g';
|
|
|
Uint8 subtype = 0;
|
|
Uint8 subtype = 0;
|
|
|
|
|
+ int raw_type = SDL_GAMEINPUT_RAWTYPE_NONE;
|
|
|
char tmp[4];
|
|
char tmp[4];
|
|
|
int idx = 0;
|
|
int idx = 0;
|
|
|
|
|
|
|
@@ -154,6 +222,7 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
|
|
|
product = info->productId;
|
|
product = info->productId;
|
|
|
//version = (info->firmwareVersion.major << 8) | info->firmwareVersion.minor;
|
|
//version = (info->firmwareVersion.major << 8) | info->firmwareVersion.minor;
|
|
|
subtype = GAMEINPUT_GetDeviceSubtype(info);
|
|
subtype = GAMEINPUT_GetDeviceSubtype(info);
|
|
|
|
|
+ raw_type = GAMEINPUT_GetDeviceRawType(info);
|
|
|
|
|
|
|
|
#if GAMEINPUT_API_VERSION >= 1
|
|
#if GAMEINPUT_API_VERSION >= 1
|
|
|
if (info->displayName) {
|
|
if (info->displayName) {
|
|
@@ -177,7 +246,7 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
- if (!GAMEINPUT_InternalIsGamepad(info)) {
|
|
|
|
|
|
|
+ if (!GAMEINPUT_InternalIsGamepad(info) && raw_type == SDL_GAMEINPUT_RAWTYPE_NONE) {
|
|
|
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
|
|
#if defined(SDL_JOYSTICK_DINPUT) || defined(SDL_JOYSTICK_XINPUT)
|
|
|
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_DIRECTINPUT, true) || SDL_XINPUT_Enabled()) {
|
|
if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_DIRECTINPUT, true) || SDL_XINPUT_Enabled()) {
|
|
|
// Let other backends handle non-gamepad controllers to possibly avoid bugs and/or regressions.
|
|
// Let other backends handle non-gamepad controllers to possibly avoid bugs and/or regressions.
|
|
@@ -226,6 +295,7 @@ static bool GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
|
|
|
elem->guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, product_string, driver_signature, subtype);
|
|
elem->guid = SDL_CreateJoystickGUID(bus, vendor, product, version, NULL, product_string, driver_signature, subtype);
|
|
|
elem->device_instance = SDL_GetNextObjectID();
|
|
elem->device_instance = SDL_GetNextObjectID();
|
|
|
elem->info = info;
|
|
elem->info = info;
|
|
|
|
|
+ elem->raw_type = raw_type;
|
|
|
#if GAMEINPUT_API_VERSION >= 1
|
|
#if GAMEINPUT_API_VERSION >= 1
|
|
|
elem->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(info->pnpPath);
|
|
elem->steam_virtual_gamepad_slot = GetSteamVirtualGamepadSlot(info->pnpPath);
|
|
|
#else
|
|
#else
|
|
@@ -318,11 +388,20 @@ static void CALLBACK GAMEINPUT_InternalJoystickDeviceCallback(
|
|
|
static void GAMEINPUT_JoystickDetect(void);
|
|
static void GAMEINPUT_JoystickDetect(void);
|
|
|
static void GAMEINPUT_JoystickQuit(void);
|
|
static void GAMEINPUT_JoystickQuit(void);
|
|
|
|
|
|
|
|
|
|
+static bool GAMEINPUT_IsRawGameInputEnabled(void)
|
|
|
|
|
+{
|
|
|
|
|
+#if GAMEINPUT_API_VERSION >= 3
|
|
|
|
|
+ return SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT_RAW, true);
|
|
|
|
|
+#else
|
|
|
|
|
+ return false;
|
|
|
|
|
+#endif
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static bool GAMEINPUT_JoystickInit(void)
|
|
static bool GAMEINPUT_JoystickInit(void)
|
|
|
{
|
|
{
|
|
|
HRESULT hr;
|
|
HRESULT hr;
|
|
|
|
|
|
|
|
- if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT)) {
|
|
|
|
|
|
|
+ if (!SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT) && !GAMEINPUT_IsRawGameInputEnabled()) {
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -336,8 +415,16 @@ static bool GAMEINPUT_JoystickInit(void)
|
|
|
g_pGameInput->SetFocusPolicy(GameInputEnableBackgroundInput | GameInputEnableBackgroundGuideButton | GameInputEnableBackgroundShareButton);
|
|
g_pGameInput->SetFocusPolicy(GameInputEnableBackgroundInput | GameInputEnableBackgroundGuideButton | GameInputEnableBackgroundShareButton);
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+ GameInputKind kind = GameInputKindUnknown;
|
|
|
|
|
+ if (SDL_GetHintBoolean(SDL_HINT_JOYSTICK_GAMEINPUT, SDL_GAMEINPUT_DEFAULT)) {
|
|
|
|
|
+ kind |= GameInputKindController;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (GAMEINPUT_IsRawGameInputEnabled()) {
|
|
|
|
|
+ kind |= GameInputKindRawDeviceReport;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
hr = g_pGameInput->RegisterDeviceCallback(NULL,
|
|
hr = g_pGameInput->RegisterDeviceCallback(NULL,
|
|
|
- GameInputKindController,
|
|
|
|
|
|
|
+ kind,
|
|
|
GameInputDeviceConnected,
|
|
GameInputDeviceConnected,
|
|
|
GameInputBlockingEnumeration,
|
|
GameInputBlockingEnumeration,
|
|
|
NULL,
|
|
NULL,
|
|
@@ -527,7 +614,7 @@ static bool GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
|
|
hwdata->devref = elem;
|
|
hwdata->devref = elem;
|
|
|
|
|
|
|
|
joystick->hwdata = hwdata;
|
|
joystick->hwdata = hwdata;
|
|
|
- if (GAMEINPUT_InternalIsGamepad(info)) {
|
|
|
|
|
|
|
+ if (GAMEINPUT_InternalIsGamepad(info) || GAMEINPUT_GetDeviceRawType(info) != SDL_GAMEINPUT_RAWTYPE_NONE) {
|
|
|
joystick->naxes = 6;
|
|
joystick->naxes = 6;
|
|
|
joystick->nbuttons = 11;
|
|
joystick->nbuttons = 11;
|
|
|
joystick->nhats = 1;
|
|
joystick->nhats = 1;
|
|
@@ -612,139 +699,206 @@ static bool GAMEINPUT_JoystickSetSensorsEnabled(SDL_Joystick *joystick, bool ena
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
|
|
|
|
|
|
|
+static void GAMEINPUT_GuitarUpdate(SDL_Joystick *joystick, IGameInputReading *reading, Uint64 timestamp)
|
|
|
{
|
|
{
|
|
|
- GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata;
|
|
|
|
|
- IGameInputDevice *device = hwdata->devref->device;
|
|
|
|
|
- const GameInputDeviceInfo *info = hwdata->devref->info;
|
|
|
|
|
- IGameInputReading *reading = NULL;
|
|
|
|
|
- Uint64 timestamp;
|
|
|
|
|
- GameInputGamepadState state;
|
|
|
|
|
- HRESULT hr;
|
|
|
|
|
-
|
|
|
|
|
- hr = g_pGameInput->GetCurrentReading(info->supportedInput, device, &reading);
|
|
|
|
|
- if (FAILED(hr)) {
|
|
|
|
|
- // don't SetError here since there can be a legitimate case when there's no reading avail
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- timestamp = SDL_US_TO_NS(reading->GetTimestamp() + g_GameInputTimestampOffset);
|
|
|
|
|
-
|
|
|
|
|
- if (GAMEINPUT_InternalIsGamepad(info)) {
|
|
|
|
|
- static WORD s_XInputButtons[] = {
|
|
|
|
|
- GameInputGamepadA, // SDL_GAMEPAD_BUTTON_SOUTH
|
|
|
|
|
- GameInputGamepadB, // SDL_GAMEPAD_BUTTON_EAST
|
|
|
|
|
- GameInputGamepadX, // SDL_GAMEPAD_BUTTON_WEST
|
|
|
|
|
- GameInputGamepadY, // SDL_GAMEPAD_BUTTON_NORTH
|
|
|
|
|
- GameInputGamepadView, // SDL_GAMEPAD_BUTTON_BACK
|
|
|
|
|
- 0, // The guide button is not available
|
|
|
|
|
- GameInputGamepadMenu, // SDL_GAMEPAD_BUTTON_START
|
|
|
|
|
- GameInputGamepadLeftThumbstick, // SDL_GAMEPAD_BUTTON_LEFT_STICK
|
|
|
|
|
- GameInputGamepadRightThumbstick, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
|
|
|
|
|
- GameInputGamepadLeftShoulder, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
|
|
|
|
|
- GameInputGamepadRightShoulder, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
|
|
|
|
|
|
|
+ IGameInputRawDeviceReport* rawState;
|
|
|
|
|
+ if (reading->GetRawReport(&rawState)) {
|
|
|
|
|
+ static WORD s_GuitarButtons[] = {
|
|
|
|
|
+ 0x0010, // SDL_GAMEPAD_BUTTON_SOUTH
|
|
|
|
|
+ 0x0020, // SDL_GAMEPAD_BUTTON_EAST
|
|
|
|
|
+ 0x0040, // SDL_GAMEPAD_BUTTON_WEST
|
|
|
|
|
+ 0x0080, // SDL_GAMEPAD_BUTTON_NORTH
|
|
|
|
|
+ 0x0008, // SDL_GAMEPAD_BUTTON_BACK
|
|
|
|
|
+ 0, // The guide button is not available
|
|
|
|
|
+ 0x0004, // SDL_GAMEPAD_BUTTON_START
|
|
|
|
|
+ 0, // right joystick click unavailable
|
|
|
|
|
+ 0x4000, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
|
|
|
|
|
+ 0x1000, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
|
|
|
|
|
+ 0, // right shoulder unavailable
|
|
|
};
|
|
};
|
|
|
Uint8 btnidx = 0, hat = 0;
|
|
Uint8 btnidx = 0, hat = 0;
|
|
|
-
|
|
|
|
|
- if (reading->GetGamepadState(&state)) {
|
|
|
|
|
- for (btnidx = 0; btnidx < SDL_arraysize(s_XInputButtons); ++btnidx) {
|
|
|
|
|
- WORD button_mask = s_XInputButtons[btnidx];
|
|
|
|
|
|
|
+ uint8_t rawData[40];
|
|
|
|
|
+ SDL_memset(rawData, 0, sizeof(rawData));
|
|
|
|
|
+ size_t len = rawState->GetRawData(sizeof(rawData), rawData);
|
|
|
|
|
+ uint16_t buttons = rawData[0] | rawData[1] << 8;
|
|
|
|
|
+ if (len >= 10) {
|
|
|
|
|
+ for (btnidx = 0; btnidx < SDL_arraysize(s_GuitarButtons); ++btnidx) {
|
|
|
|
|
+ WORD button_mask = s_GuitarButtons[btnidx];
|
|
|
if (!button_mask) {
|
|
if (!button_mask) {
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
- bool down = ((state.buttons & button_mask) != 0);
|
|
|
|
|
|
|
+ bool down = ((buttons & button_mask) != 0);
|
|
|
SDL_SendJoystickButton(timestamp, joystick, btnidx, down);
|
|
SDL_SendJoystickButton(timestamp, joystick, btnidx, down);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (state.buttons & GameInputGamepadDPadUp) {
|
|
|
|
|
|
|
+ if (buttons & 0x0100) {
|
|
|
hat |= SDL_HAT_UP;
|
|
hat |= SDL_HAT_UP;
|
|
|
}
|
|
}
|
|
|
- if (state.buttons & GameInputGamepadDPadDown) {
|
|
|
|
|
|
|
+ if (buttons & 0x0200) {
|
|
|
hat |= SDL_HAT_DOWN;
|
|
hat |= SDL_HAT_DOWN;
|
|
|
}
|
|
}
|
|
|
- if (state.buttons & GameInputGamepadDPadLeft) {
|
|
|
|
|
|
|
+ if (buttons & 0x0400) {
|
|
|
hat |= SDL_HAT_LEFT;
|
|
hat |= SDL_HAT_LEFT;
|
|
|
}
|
|
}
|
|
|
- if (state.buttons & GameInputGamepadDPadRight) {
|
|
|
|
|
|
|
+ if (buttons & 0x0800) {
|
|
|
hat |= SDL_HAT_RIGHT;
|
|
hat |= SDL_HAT_RIGHT;
|
|
|
}
|
|
}
|
|
|
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
|
|
SDL_SendJoystickHat(timestamp, joystick, 0, hat);
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, (rawData[3] * 257) - 32768);
|
|
|
|
|
+ // PS3 RB guitars had tilt on right shoulder
|
|
|
|
|
+ SDL_SendJoystickButton(timestamp, joystick, SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER, rawData[2] >= 0xD0);
|
|
|
|
|
+ // PS3 RB guitars send L2 when using solo buttons
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, (rawData[6]) ? 32767 : -32768);
|
|
|
|
|
+ // Align pickup selector mappings with PS3 instruments
|
|
|
|
|
+ static const Sint16 effects_mappings[] = {-26880, -13568, -1792, 11008, 24576};
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, effects_mappings[rawData[4] >> 4]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void GAMEINPUT_GamepadUpdate(SDL_Joystick *joystick, IGameInputReading *reading, Uint64 timestamp) {
|
|
|
|
|
+ GameInputGamepadState state;
|
|
|
|
|
+ static WORD s_XInputButtons[] = {
|
|
|
|
|
+ GameInputGamepadA, // SDL_GAMEPAD_BUTTON_SOUTH
|
|
|
|
|
+ GameInputGamepadB, // SDL_GAMEPAD_BUTTON_EAST
|
|
|
|
|
+ GameInputGamepadX, // SDL_GAMEPAD_BUTTON_WEST
|
|
|
|
|
+ GameInputGamepadY, // SDL_GAMEPAD_BUTTON_NORTH
|
|
|
|
|
+ GameInputGamepadView, // SDL_GAMEPAD_BUTTON_BACK
|
|
|
|
|
+ 0, // The guide button is not available
|
|
|
|
|
+ GameInputGamepadMenu, // SDL_GAMEPAD_BUTTON_START
|
|
|
|
|
+ GameInputGamepadLeftThumbstick, // SDL_GAMEPAD_BUTTON_LEFT_STICK
|
|
|
|
|
+ GameInputGamepadRightThumbstick, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
|
|
|
|
|
+ GameInputGamepadLeftShoulder, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
|
|
|
|
|
+ GameInputGamepadRightShoulder, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
|
|
|
|
|
+ };
|
|
|
|
|
+ Uint8 btnidx = 0, hat = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (reading->GetGamepadState(&state)) {
|
|
|
|
|
+ for (btnidx = 0; btnidx < SDL_arraysize(s_XInputButtons); ++btnidx) {
|
|
|
|
|
+ WORD button_mask = s_XInputButtons[btnidx];
|
|
|
|
|
+ if (!button_mask) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ bool down = ((state.buttons & button_mask) != 0);
|
|
|
|
|
+ SDL_SendJoystickButton(timestamp, joystick, btnidx, down);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (state.buttons & GameInputGamepadDPadUp) {
|
|
|
|
|
+ hat |= SDL_HAT_UP;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (state.buttons & GameInputGamepadDPadDown) {
|
|
|
|
|
+ hat |= SDL_HAT_DOWN;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (state.buttons & GameInputGamepadDPadLeft) {
|
|
|
|
|
+ hat |= SDL_HAT_LEFT;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (state.buttons & GameInputGamepadDPadRight) {
|
|
|
|
|
+ hat |= SDL_HAT_RIGHT;
|
|
|
|
|
+ }
|
|
|
|
|
+ SDL_SendJoystickHat(timestamp, joystick, 0, hat);
|
|
|
|
|
|
|
|
#define CONVERT_AXIS(v) (Sint16)(((v) < 0.0f) ? ((v)*32768.0f) : ((v)*32767.0f))
|
|
#define CONVERT_AXIS(v) (Sint16)(((v) < 0.0f) ? ((v)*32768.0f) : ((v)*32767.0f))
|
|
|
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, CONVERT_AXIS(state.leftThumbstickX));
|
|
|
|
|
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, CONVERT_AXIS(-state.leftThumbstickY));
|
|
|
|
|
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, CONVERT_AXIS(state.rightThumbstickX));
|
|
|
|
|
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, CONVERT_AXIS(-state.rightThumbstickY));
|
|
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTX, CONVERT_AXIS(state.leftThumbstickX));
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFTY, CONVERT_AXIS(-state.leftThumbstickY));
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, CONVERT_AXIS(state.rightThumbstickX));
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, CONVERT_AXIS(-state.rightThumbstickY));
|
|
|
#undef CONVERT_AXIS
|
|
#undef CONVERT_AXIS
|
|
|
#define CONVERT_TRIGGER(v) (Sint16)((v)*65535.0f - 32768.0f)
|
|
#define CONVERT_TRIGGER(v) (Sint16)((v)*65535.0f - 32768.0f)
|
|
|
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, CONVERT_TRIGGER(state.leftTrigger));
|
|
|
|
|
- SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, CONVERT_TRIGGER(state.rightTrigger));
|
|
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_LEFT_TRIGGER, CONVERT_TRIGGER(state.leftTrigger));
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER, CONVERT_TRIGGER(state.rightTrigger));
|
|
|
#undef CONVERT_TRIGGER
|
|
#undef CONVERT_TRIGGER
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void GAMEINPUT_ControllerUpdate(SDL_Joystick *joystick, IGameInputReading *reading, Uint64 timestamp)
|
|
|
|
|
+{
|
|
|
|
|
+ bool *button_state = SDL_stack_alloc(bool, joystick->nbuttons);
|
|
|
|
|
+ float *axis_state = SDL_stack_alloc(float, joystick->naxes);
|
|
|
|
|
+ GameInputSwitchPosition *switch_state = SDL_stack_alloc(GameInputSwitchPosition, joystick->nhats);
|
|
|
|
|
+
|
|
|
|
|
+ if (button_state) {
|
|
|
|
|
+ uint32_t i;
|
|
|
|
|
+ uint32_t button_count = reading->GetControllerButtonState(joystick->nbuttons, button_state);
|
|
|
|
|
+ for (i = 0; i < button_count; ++i) {
|
|
|
|
|
+ SDL_SendJoystickButton(timestamp, joystick, (Uint8)i, button_state[i]);
|
|
|
}
|
|
}
|
|
|
- } else {
|
|
|
|
|
- bool *button_state = SDL_stack_alloc(bool, joystick->nbuttons);
|
|
|
|
|
- float *axis_state = SDL_stack_alloc(float, joystick->naxes);
|
|
|
|
|
- GameInputSwitchPosition *switch_state = SDL_stack_alloc(GameInputSwitchPosition, joystick->nhats);
|
|
|
|
|
-
|
|
|
|
|
- if (button_state) {
|
|
|
|
|
- uint32_t i;
|
|
|
|
|
- uint32_t button_count = reading->GetControllerButtonState(joystick->nbuttons, button_state);
|
|
|
|
|
- for (i = 0; i < button_count; ++i) {
|
|
|
|
|
- SDL_SendJoystickButton(timestamp, joystick, (Uint8)i, button_state[i]);
|
|
|
|
|
- }
|
|
|
|
|
- SDL_stack_free(button_state);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ SDL_stack_free(button_state);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
#define CONVERT_AXIS(v) (Sint16)((v)*65535.0f - 32768.0f)
|
|
#define CONVERT_AXIS(v) (Sint16)((v)*65535.0f - 32768.0f)
|
|
|
- if (axis_state) {
|
|
|
|
|
- uint32_t i;
|
|
|
|
|
- uint32_t axis_count = reading->GetControllerAxisState(joystick->naxes, axis_state);
|
|
|
|
|
- for (i = 0; i < axis_count; ++i) {
|
|
|
|
|
- SDL_SendJoystickAxis(timestamp, joystick, (Uint8)i, CONVERT_AXIS(axis_state[i]));
|
|
|
|
|
- }
|
|
|
|
|
- SDL_stack_free(axis_state);
|
|
|
|
|
|
|
+ if (axis_state) {
|
|
|
|
|
+ uint32_t i;
|
|
|
|
|
+ uint32_t axis_count = reading->GetControllerAxisState(joystick->naxes, axis_state);
|
|
|
|
|
+ for (i = 0; i < axis_count; ++i) {
|
|
|
|
|
+ SDL_SendJoystickAxis(timestamp, joystick, (Uint8)i, CONVERT_AXIS(axis_state[i]));
|
|
|
}
|
|
}
|
|
|
|
|
+ SDL_stack_free(axis_state);
|
|
|
|
|
+ }
|
|
|
#undef CONVERT_AXIS
|
|
#undef CONVERT_AXIS
|
|
|
|
|
|
|
|
- if (switch_state) {
|
|
|
|
|
- uint32_t i;
|
|
|
|
|
- uint32_t switch_count = reading->GetControllerSwitchState(joystick->nhats, switch_state);
|
|
|
|
|
- for (i = 0; i < switch_count; ++i) {
|
|
|
|
|
- Uint8 hat;
|
|
|
|
|
- switch (switch_state[i]) {
|
|
|
|
|
- case GameInputSwitchUp:
|
|
|
|
|
- hat = SDL_HAT_UP;
|
|
|
|
|
- break;
|
|
|
|
|
- case GameInputSwitchUpRight:
|
|
|
|
|
- hat = SDL_HAT_UP | SDL_HAT_RIGHT;
|
|
|
|
|
- break;
|
|
|
|
|
- case GameInputSwitchRight:
|
|
|
|
|
- hat = SDL_HAT_RIGHT;
|
|
|
|
|
- break;
|
|
|
|
|
- case GameInputSwitchDownRight:
|
|
|
|
|
- hat = SDL_HAT_DOWN | SDL_HAT_RIGHT;
|
|
|
|
|
- break;
|
|
|
|
|
- case GameInputSwitchDown:
|
|
|
|
|
- hat = SDL_HAT_DOWN;
|
|
|
|
|
- break;
|
|
|
|
|
- case GameInputSwitchDownLeft:
|
|
|
|
|
- hat = SDL_HAT_DOWN | SDL_HAT_LEFT;
|
|
|
|
|
- break;
|
|
|
|
|
- case GameInputSwitchLeft:
|
|
|
|
|
- hat = SDL_HAT_LEFT;
|
|
|
|
|
- break;
|
|
|
|
|
- case GameInputSwitchUpLeft:
|
|
|
|
|
- hat = SDL_HAT_UP | SDL_HAT_LEFT;
|
|
|
|
|
- break;
|
|
|
|
|
- case GameInputSwitchCenter:
|
|
|
|
|
- default:
|
|
|
|
|
- hat = SDL_HAT_CENTERED;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- SDL_SendJoystickHat(timestamp, joystick, (Uint8)i, hat);
|
|
|
|
|
|
|
+ if (switch_state) {
|
|
|
|
|
+ uint32_t i;
|
|
|
|
|
+ uint32_t switch_count = reading->GetControllerSwitchState(joystick->nhats, switch_state);
|
|
|
|
|
+ for (i = 0; i < switch_count; ++i) {
|
|
|
|
|
+ Uint8 hat;
|
|
|
|
|
+ switch (switch_state[i]) {
|
|
|
|
|
+ case GameInputSwitchUp:
|
|
|
|
|
+ hat = SDL_HAT_UP;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case GameInputSwitchUpRight:
|
|
|
|
|
+ hat = SDL_HAT_UP | SDL_HAT_RIGHT;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case GameInputSwitchRight:
|
|
|
|
|
+ hat = SDL_HAT_RIGHT;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case GameInputSwitchDownRight:
|
|
|
|
|
+ hat = SDL_HAT_DOWN | SDL_HAT_RIGHT;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case GameInputSwitchDown:
|
|
|
|
|
+ hat = SDL_HAT_DOWN;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case GameInputSwitchDownLeft:
|
|
|
|
|
+ hat = SDL_HAT_DOWN | SDL_HAT_LEFT;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case GameInputSwitchLeft:
|
|
|
|
|
+ hat = SDL_HAT_LEFT;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case GameInputSwitchUpLeft:
|
|
|
|
|
+ hat = SDL_HAT_UP | SDL_HAT_LEFT;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case GameInputSwitchCenter:
|
|
|
|
|
+ default:
|
|
|
|
|
+ hat = SDL_HAT_CENTERED;
|
|
|
|
|
+ break;
|
|
|
}
|
|
}
|
|
|
- SDL_stack_free(switch_state);
|
|
|
|
|
|
|
+ SDL_SendJoystickHat(timestamp, joystick, (Uint8)i, hat);
|
|
|
}
|
|
}
|
|
|
|
|
+ SDL_stack_free(switch_state);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
|
|
|
|
|
+{
|
|
|
|
|
+ GAMEINPUT_InternalJoystickHwdata *hwdata = joystick->hwdata;
|
|
|
|
|
+ GAMEINPUT_InternalDevice *internal_device = hwdata->devref;
|
|
|
|
|
+ IGameInputDevice *device = hwdata->devref->device;
|
|
|
|
|
+ const GameInputDeviceInfo *info = hwdata->devref->info;
|
|
|
|
|
+ IGameInputReading *reading = NULL;
|
|
|
|
|
+ Uint64 timestamp;
|
|
|
|
|
+ HRESULT hr;
|
|
|
|
|
+
|
|
|
|
|
+ hr = g_pGameInput->GetCurrentReading(info->supportedInput, device, &reading);
|
|
|
|
|
+ if (FAILED(hr)) {
|
|
|
|
|
+ // don't SetError here since there can be a legitimate case when there's no reading avail
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ timestamp = SDL_US_TO_NS(reading->GetTimestamp() + g_GameInputTimestampOffset);
|
|
|
|
|
+ if (internal_device->raw_type == SDL_GAMEINPUT_RAWTYPE_ROCK_BAND_GUITAR) {
|
|
|
|
|
+ GAMEINPUT_GuitarUpdate(joystick, reading, timestamp);
|
|
|
|
|
+ } else if (GAMEINPUT_InternalIsGamepad(info)) {
|
|
|
|
|
+ GAMEINPUT_GamepadUpdate(joystick, reading, timestamp);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ GAMEINPUT_ControllerUpdate(joystick, reading, timestamp);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#ifdef GAMEINPUT_SENSOR_SUPPORT
|
|
#ifdef GAMEINPUT_SENSOR_SUPPORT
|
|
@@ -821,7 +975,7 @@ static bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMap
|
|
|
{
|
|
{
|
|
|
GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index);
|
|
GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index);
|
|
|
|
|
|
|
|
- if (!GAMEINPUT_InternalIsGamepad(elem->info)) {
|
|
|
|
|
|
|
+ if (!GAMEINPUT_InternalIsGamepad(elem->info) && elem->raw_type == SDL_GAMEINPUT_RAWTYPE_NONE) {
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
|