|
@@ -18,6 +18,8 @@
|
|
|
misrepresented as being the original software.
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
*/
|
|
|
+#include "SDL_internal.h"
|
|
|
+
|
|
|
#include "SDL_gameinputjoystick_c.h"
|
|
|
|
|
|
#if defined(SDL_JOYSTICK_GAMEINPUT) && SDL_JOYSTICK_GAMEINPUT
|
|
@@ -39,9 +41,9 @@ typedef struct GAMEINPUT_InternalDevice
|
|
|
SDL_JoystickGUID joystickGuid; /* generated by SDL. */
|
|
|
SDL_JoystickID instanceId; /* generated by SDL. */
|
|
|
int playerIndex;
|
|
|
- Uint32 caps;
|
|
|
+ GameInputRumbleMotors supportedRumbleMotors;
|
|
|
char devicePath[(APP_LOCAL_DEVICE_ID_SIZE * 2) + 1];
|
|
|
- bool isAdded, isDeleteRequested;
|
|
|
+ SDL_bool isAdded, isDeleteRequested;
|
|
|
} GAMEINPUT_InternalDevice;
|
|
|
|
|
|
typedef struct GAMEINPUT_InternalList
|
|
@@ -59,6 +61,7 @@ typedef struct joystick_hwdata
|
|
|
|
|
|
|
|
|
static GAMEINPUT_InternalList g_GameInputList = { NULL };
|
|
|
+static void *g_hGameInputDLL = NULL;
|
|
|
static IGameInput *g_pGameInput = NULL;
|
|
|
static GameInputCallbackToken g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE;
|
|
|
|
|
@@ -75,7 +78,7 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
|
|
|
return SDL_SetError("GAMEINPUT_InternalAddOrFind argument pDevice cannot be NULL");
|
|
|
}
|
|
|
|
|
|
- devinfo = pDevice->GetDeviceInfo();
|
|
|
+ devinfo = IGameInputDevice_GetDeviceInfo(pDevice);
|
|
|
if (!devinfo) {
|
|
|
return SDL_SetError("GAMEINPUT_InternalAddOrFind GetDeviceInfo returned NULL");
|
|
|
}
|
|
@@ -95,8 +98,8 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
|
|
|
|
|
|
/* generate a device name */
|
|
|
for (idx = 0; idx < APP_LOCAL_DEVICE_ID_SIZE; ++idx) {
|
|
|
- (void)SDL_snprintf(tmpbuff, SDL_arraysize(tmpbuff), "%02hhX", devinfo->deviceId.value[idx]);
|
|
|
- (void)strncat_s(elem->devicePath, tmpbuff, SDL_arraysize(tmpbuff));
|
|
|
+ SDL_snprintf(tmpbuff, SDL_arraysize(tmpbuff), "%02hhX", devinfo->deviceId.value[idx]);
|
|
|
+ SDL_strlcat(elem->devicePath, tmpbuff, SDL_arraysize(tmpbuff));
|
|
|
}
|
|
|
|
|
|
devicelist = (GAMEINPUT_InternalDevice **)SDL_realloc(g_GameInputList.devices, sizeof(elem) * (g_GameInputList.count + 1LL));
|
|
@@ -106,16 +109,10 @@ static int GAMEINPUT_InternalAddOrFind(IGameInputDevice *pDevice)
|
|
|
}
|
|
|
|
|
|
g_GameInputList.devices = devicelist;
|
|
|
- pDevice->AddRef();
|
|
|
+ IGameInputDevice_AddRef(pDevice);
|
|
|
elem->device = pDevice;
|
|
|
elem->deviceName = "GameInput Gamepad";
|
|
|
- elem->caps = 0;
|
|
|
- if (devinfo->supportedRumbleMotors & (GameInputRumbleLowFrequency | GameInputRumbleHighFrequency)) {
|
|
|
- elem->caps |= SDL_JOYSTICK_CAP_RUMBLE;
|
|
|
- }
|
|
|
- if (devinfo->supportedRumbleMotors & (GameInputRumbleLeftTrigger | GameInputRumbleRightTrigger)) {
|
|
|
- elem->caps |= SDL_JOYSTICK_CAP_TRIGGER_RUMBLE;
|
|
|
- }
|
|
|
+ elem->supportedRumbleMotors = devinfo->supportedRumbleMotors;
|
|
|
elem->joystickGuid = SDL_CreateJoystickGUID(
|
|
|
SDL_HARDWARE_BUS_BLUETOOTH,
|
|
|
USB_VENDOR_MICROSOFT,
|
|
@@ -142,7 +139,7 @@ static int GAMEINPUT_InternalRemoveByIndex(int idx)
|
|
|
return SDL_SetError("GAMEINPUT_InternalRemoveByIndex argument idx %d is out of range", idx);
|
|
|
}
|
|
|
|
|
|
- g_GameInputList.devices[idx]->device->Release();
|
|
|
+ IGameInputDevice_Release(g_GameInputList.devices[idx]->device);
|
|
|
|
|
|
if (g_GameInputList.devices[idx]) {
|
|
|
SDL_free(g_GameInputList.devices[idx]);
|
|
@@ -199,7 +196,7 @@ static void CALLBACK GAMEINPUT_InternalJoystickDeviceCallback(
|
|
|
elem = g_GameInputList.devices[idx];
|
|
|
if (elem && elem->device == device) {
|
|
|
/* will be deleted on the next Detect call */
|
|
|
- elem->isDeleteRequested = true;
|
|
|
+ elem->isDeleteRequested = SDL_TRUE;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -212,29 +209,40 @@ static int GAMEINPUT_JoystickInit(void)
|
|
|
{
|
|
|
HRESULT hR;
|
|
|
|
|
|
+ if (!g_hGameInputDLL) {
|
|
|
+ g_hGameInputDLL = SDL_LoadObject("gameinput.dll");
|
|
|
+ if (!g_hGameInputDLL) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (!g_pGameInput) {
|
|
|
- hR = GameInputCreate(&g_pGameInput);
|
|
|
+ typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput);
|
|
|
+ GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(g_hGameInputDLL, "GameInputCreate");
|
|
|
+ if (!GameInputCreateFunc) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ hR = GameInputCreateFunc(&g_pGameInput);
|
|
|
if (FAILED(hR)) {
|
|
|
return SDL_SetError("GameInputCreate failure with HRESULT of %08X", hR);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- hR = g_pGameInput->RegisterDeviceCallback(
|
|
|
- nullptr,
|
|
|
- GameInputKindGamepad,
|
|
|
- GameInputDeviceConnected,
|
|
|
- GameInputBlockingEnumeration,
|
|
|
- nullptr,
|
|
|
- GAMEINPUT_InternalJoystickDeviceCallback,
|
|
|
- &g_GameInputCallbackToken
|
|
|
- );
|
|
|
+ hR = IGameInput_RegisterDeviceCallback(g_pGameInput,
|
|
|
+ NULL,
|
|
|
+ GameInputKindGamepad,
|
|
|
+ GameInputDeviceConnected,
|
|
|
+ GameInputBlockingEnumeration,
|
|
|
+ NULL,
|
|
|
+ GAMEINPUT_InternalJoystickDeviceCallback,
|
|
|
+ &g_GameInputCallbackToken);
|
|
|
if (FAILED(hR)) {
|
|
|
return SDL_SetError("IGameInput::RegisterDeviceCallback failure with HRESULT of %08X", hR);
|
|
|
}
|
|
|
|
|
|
GAMEINPUT_JoystickDetect();
|
|
|
|
|
|
- /* no need to free IGameInput on failure. */
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -256,10 +264,10 @@ static void GAMEINPUT_JoystickDetect(void)
|
|
|
|
|
|
if (!elem->isAdded) {
|
|
|
SDL_PrivateJoystickAdded(elem->instanceId);
|
|
|
- elem->isAdded = true;
|
|
|
+ elem->isAdded = SDL_TRUE;
|
|
|
}
|
|
|
|
|
|
- if (elem->isDeleteRequested || !(elem->device->GetDeviceStatus() & GameInputDeviceConnected)) {
|
|
|
+ if (elem->isDeleteRequested || !(IGameInputDevice_GetDeviceStatus(elem->device) & GameInputDeviceConnected)) {
|
|
|
SDL_PrivateJoystickRemoved(elem->instanceId);
|
|
|
GAMEINPUT_InternalRemoveByIndex(idx--);
|
|
|
}
|
|
@@ -332,8 +340,8 @@ static SDL_JoystickGUID GAMEINPUT_JoystickGetDeviceGUID(int device_index)
|
|
|
GAMEINPUT_InternalDevice *elem = GAMEINPUT_InternalFindByIndex(device_index);
|
|
|
|
|
|
if (!elem) {
|
|
|
- /* empty guid */
|
|
|
- return { { 0 } };
|
|
|
+ static SDL_JoystickGUID emptyGUID;
|
|
|
+ return emptyGUID;
|
|
|
}
|
|
|
|
|
|
return elem->joystickGuid;
|
|
@@ -371,6 +379,13 @@ static int GAMEINPUT_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
|
|
joystick->nbuttons = 11;
|
|
|
joystick->nhats = 1;
|
|
|
|
|
|
+ if (elem->supportedRumbleMotors & (GameInputRumbleLowFrequency | GameInputRumbleHighFrequency)) {
|
|
|
+ SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, SDL_TRUE);
|
|
|
+ }
|
|
|
+ if (elem->supportedRumbleMotors & (GameInputRumbleLeftTrigger | GameInputRumbleRightTrigger)) {
|
|
|
+ SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, SDL_TRUE);
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -381,7 +396,7 @@ static int GAMEINPUT_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency
|
|
|
GameInputRumbleParams *params = &hwdata->rumbleParams;
|
|
|
params->lowFrequency = (float)low_frequency_rumble / (float)SDL_MAX_UINT16;
|
|
|
params->highFrequency = (float)high_frequency_rumble / (float)SDL_MAX_UINT16;
|
|
|
- hwdata->devref->device->SetRumbleState(params);
|
|
|
+ IGameInputDevice_SetRumbleState(hwdata->devref->device, params);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -392,15 +407,10 @@ static int GAMEINPUT_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_
|
|
|
GameInputRumbleParams *params = &hwdata->rumbleParams;
|
|
|
params->leftTrigger = (float)left_rumble / (float)SDL_MAX_UINT16;
|
|
|
params->rightTrigger = (float)right_rumble / (float)SDL_MAX_UINT16;
|
|
|
- hwdata->devref->device->SetRumbleState(params);
|
|
|
+ IGameInputDevice_SetRumbleState(hwdata->devref->device, params);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static Uint32 GAMEINPUT_JoystickGetCapabilities(SDL_Joystick *joystick)
|
|
|
-{
|
|
|
- return joystick->hwdata->devref->caps;
|
|
|
-}
|
|
|
-
|
|
|
static int GAMEINPUT_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue)
|
|
|
{
|
|
|
return SDL_Unsupported();
|
|
@@ -418,7 +428,7 @@ static int GAMEINPUT_JoystickSendEffect(SDL_Joystick *joystick, const void *data
|
|
|
|
|
|
effect = (const GAMEINPUT_JoystickEffectData *)data;
|
|
|
if (effect->type == GAMEINPUT_JoystickEffectDataType_HapticFeedback) {
|
|
|
- hR = hwdata->devref->device->SetHapticMotorState(
|
|
|
+ hR = IGameInputDevice_SetHapticMotorState(hwdata->devref->device,
|
|
|
effect->hapticFeedbackMotorIndex,
|
|
|
&effect->hapticFeedbackParams
|
|
|
);
|
|
@@ -450,7 +460,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
|
|
|
IGameInputReading *reading = NULL;
|
|
|
uint64_t ts = 0;
|
|
|
GameInputGamepadState state;
|
|
|
- HRESULT hR = g_pGameInput->GetCurrentReading(
|
|
|
+ HRESULT hR = IGameInput_GetCurrentReading(g_pGameInput,
|
|
|
GameInputKindGamepad,
|
|
|
device,
|
|
|
&reading
|
|
@@ -463,9 +473,9 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
|
|
|
|
|
|
/* GDKX private docs for GetTimestamp: "The microsecond timestamp describing when the input was made." */
|
|
|
/* SDL expects a nanosecond timestamp, so I guess US_TO_NS should be used here? */
|
|
|
- ts = SDL_US_TO_NS(reading->GetTimestamp());
|
|
|
+ ts = SDL_US_TO_NS(IGameInputReading_GetTimestamp(reading));
|
|
|
|
|
|
- if (((!hwdata->lastTimestamp) || (ts != hwdata->lastTimestamp)) && reading->GetGamepadState(&state)) {
|
|
|
+ if (((!hwdata->lastTimestamp) || (ts != hwdata->lastTimestamp)) && IGameInputReading_GetGamepadState(reading, &state)) {
|
|
|
/* `state` is now valid */
|
|
|
|
|
|
#define tosint16(_TheValue) ((Sint16)(((_TheValue) < 0.0f) ? ((_TheValue) * 32768.0f) : ((_TheValue) * 32767.0f)))
|
|
@@ -507,7 +517,7 @@ static void GAMEINPUT_JoystickUpdate(SDL_Joystick *joystick)
|
|
|
hwdata->lastTimestamp = ts;
|
|
|
}
|
|
|
|
|
|
- reading->Release();
|
|
|
+ IGameInputReading_Release(reading);
|
|
|
}
|
|
|
|
|
|
static void GAMEINPUT_JoystickClose(SDL_Joystick* joystick)
|
|
@@ -520,26 +530,29 @@ static void GAMEINPUT_JoystickQuit(void)
|
|
|
{
|
|
|
int idx;
|
|
|
|
|
|
- if (!g_pGameInput) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ if (g_pGameInput) {
|
|
|
+ /* free the callback */
|
|
|
+ IGameInput_UnregisterCallback(g_pGameInput, g_GameInputCallbackToken, /*timeoutInUs:*/ 10000);
|
|
|
+ g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE;
|
|
|
|
|
|
- /* free the callback */
|
|
|
- g_pGameInput->UnregisterCallback(g_GameInputCallbackToken, /*timeoutInUs:*/ 10000);
|
|
|
- g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE;
|
|
|
+ /* free the list */
|
|
|
+ for (idx = 0; idx < g_GameInputList.count; ++idx) {
|
|
|
+ IGameInputDevice_Release(g_GameInputList.devices[idx]->device);
|
|
|
+ SDL_free(g_GameInputList.devices[idx]);
|
|
|
+ g_GameInputList.devices[idx] = NULL;
|
|
|
+ }
|
|
|
+ SDL_free(g_GameInputList.devices);
|
|
|
+ g_GameInputList.devices = NULL;
|
|
|
+ g_GameInputList.count = 0;
|
|
|
|
|
|
- /* free the list */
|
|
|
- for (idx = 0; idx < g_GameInputList.count; ++idx) {
|
|
|
- g_GameInputList.devices[idx]->device->Release();
|
|
|
- SDL_free(g_GameInputList.devices[idx]);
|
|
|
- g_GameInputList.devices[idx] = NULL;
|
|
|
+ IGameInput_Release(g_pGameInput);
|
|
|
+ g_pGameInput = NULL;
|
|
|
}
|
|
|
- SDL_free(g_GameInputList.devices);
|
|
|
- g_GameInputList.devices = NULL;
|
|
|
- g_GameInputList.count = 0;
|
|
|
|
|
|
- g_pGameInput->Release();
|
|
|
- g_pGameInput = NULL;
|
|
|
+ if (g_hGameInputDLL) {
|
|
|
+ SDL_UnloadObject(g_hGameInputDLL);
|
|
|
+ g_hGameInputDLL = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static SDL_bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
|
@@ -563,7 +576,6 @@ SDL_JoystickDriver SDL_GAMEINPUT_JoystickDriver =
|
|
|
GAMEINPUT_JoystickOpen,
|
|
|
GAMEINPUT_JoystickRumble,
|
|
|
GAMEINPUT_JoystickRumbleTriggers,
|
|
|
- GAMEINPUT_JoystickGetCapabilities,
|
|
|
GAMEINPUT_JoystickSetLED,
|
|
|
GAMEINPUT_JoystickSendEffect,
|
|
|
GAMEINPUT_JoystickSetSensorsEnabled,
|