Skip to content

Commit

Permalink
Refactored GameInput initialization
Browse files Browse the repository at this point in the history
Also fixed a bug with keyboard and mouse readings
  • Loading branch information
slouken committed Feb 12, 2025
1 parent 715c187 commit f4d0dad
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 60 deletions.
2 changes: 2 additions & 0 deletions VisualC-GDK/SDL/SDL.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@
<ClInclude Include="..\..\src\camera\SDL_syscamera.h" />
<ClInclude Include="..\..\src\core\gdk\SDL_gdk.h" />
<ClInclude Include="..\..\src\core\windows\SDL_directx.h" />
<ClInclude Include="..\..\src\core\windows\SDL_gameinput.h" />
<ClInclude Include="..\..\src\core\windows\SDL_hid.h" />
<ClInclude Include="..\..\src\core\windows\SDL_immdevice.h" />
<ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
Expand Down Expand Up @@ -640,6 +641,7 @@
<ClCompile Include="..\..\src\audio\SDL_wave.c" />
<ClCompile Include="..\..\src\audio\wasapi\SDL_wasapi.c" />
<ClCompile Include="..\..\src\core\SDL_core_unsupported.c" />
<ClCompile Include="..\..\src\core\windows\SDL_gameinput.c">
<ClCompile Include="..\..\src\core\windows\SDL_hid.c" />
<ClCompile Include="..\..\src\core\windows\SDL_immdevice.c" />
<ClCompile Include="..\..\src\core\windows\SDL_windows.c" />
Expand Down
2 changes: 2 additions & 0 deletions VisualC-GDK/SDL/SDL.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<ClCompile Include="..\..\src\audio\SDL_wave.c" />
<ClCompile Include="..\..\src\audio\wasapi\SDL_wasapi.c" />
<ClCompile Include="..\..\src\core\SDL_core_unsupported.c" />
<ClCompile Include="..\..\src\core\windows\SDL_gameinput.c" />
<ClCompile Include="..\..\src\core\windows\SDL_hid.c" />
<ClCompile Include="..\..\src\core\windows\SDL_immdevice.c" />
<ClCompile Include="..\..\src\core\windows\SDL_windows.c" />
Expand Down Expand Up @@ -314,6 +315,7 @@
<ClInclude Include="..\..\src\audio\wasapi\SDL_wasapi.h" />
<ClInclude Include="..\..\src\core\gdk\SDL_gdk.h" />
<ClInclude Include="..\..\src\core\windows\SDL_directx.h" />
<ClInclude Include="..\..\src\core\windows\SDL_gameinput.h" />
<ClInclude Include="..\..\src\core\windows\SDL_hid.h" />
<ClInclude Include="..\..\src\core\windows\SDL_immdevice.h" />
<ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
Expand Down
2 changes: 2 additions & 0 deletions VisualC/SDL/SDL.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@
<ClInclude Include="..\..\src\camera\SDL_camera_c.h" />
<ClInclude Include="..\..\src\camera\SDL_syscamera.h" />
<ClInclude Include="..\..\src\core\windows\SDL_directx.h" />
<ClInclude Include="..\..\src\core\windows\SDL_gameinput.h" />
<ClInclude Include="..\..\src\core\windows\SDL_hid.h" />
<ClInclude Include="..\..\src\core\windows\SDL_immdevice.h" />
<ClInclude Include="..\..\src\core\windows\SDL_windows.h" />
Expand Down Expand Up @@ -538,6 +539,7 @@
<ClCompile Include="..\..\src\audio\SDL_wave.c" />
<ClCompile Include="..\..\src\audio\wasapi\SDL_wasapi.c" />
<ClCompile Include="..\..\src\core\SDL_core_unsupported.c" />
<ClCompile Include="..\..\src\core\windows\SDL_gameinput.c" />
<ClCompile Include="..\..\src\core\windows\SDL_hid.c" />
<ClCompile Include="..\..\src\core\windows\SDL_immdevice.c" />
<ClCompile Include="..\..\src\core\windows\SDL_windows.c" />
Expand Down
9 changes: 9 additions & 0 deletions VisualC/SDL/SDL.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,12 @@
<ClInclude Include="..\..\src\audio\SDL_audioresample.h">
<Filter>audio</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\windows\SDL_directx.h">
<Filter>core\windows</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\windows\SDL_gameinput.h">
<Filter>core\windows</Filter>
</ClInclude>
<ClInclude Include="..\..\src\core\windows\SDL_hid.h">
<Filter>core\windows</Filter>
</ClInclude>
Expand Down Expand Up @@ -1028,6 +1034,9 @@
<ClCompile Include="..\..\src\core\SDL_core_unsupported.c">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\windows\SDL_gameinput.c">
<Filter>core\windows</Filter>
</ClCompile>
<ClCompile Include="..\..\src\core\windows\SDL_hid.c">
<Filter>core\windows</Filter>
</ClCompile>
Expand Down
98 changes: 98 additions & 0 deletions src/core/windows/SDL_gameinput.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"

#ifdef HAVE_GAMEINPUT_H

#include "SDL_windows.h"
#include "SDL_gameinput.h"

#ifdef SDL_PLATFORM_WIN32
#include <initguid.h>
// {11BE2A7E-4254-445A-9C09-FFC40F006918}
DEFINE_GUID(SDL_IID_GameInput, 0x11BE2A7E, 0x4254, 0x445A, 0x9C, 0x09, 0xFF, 0xC4, 0x0F, 0x00, 0x69, 0x18);
#endif

static SDL_SharedObject *g_hGameInputDLL;
static IGameInput *g_pGameInput;
static int g_nGameInputRefCount;

bool SDL_InitGameInput(IGameInput **ppGameInput)
{
if (g_nGameInputRefCount == 0) {
g_hGameInputDLL = SDL_LoadObject("gameinput.dll");
if (!g_hGameInputDLL) {
return false;
}

typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput);
GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(g_hGameInputDLL, "GameInputCreate");
if (!GameInputCreateFunc) {
SDL_UnloadObject(g_hGameInputDLL);
return false;
}

IGameInput *pGameInput = NULL;
HRESULT hr = GameInputCreateFunc(&pGameInput);
if (FAILED(hr)) {
SDL_UnloadObject(g_hGameInputDLL);
return WIN_SetErrorFromHRESULT("GameInputCreate failed", hr);
}

#ifdef SDL_PLATFORM_WIN32
hr = IGameInput_QueryInterface(pGameInput, &SDL_IID_GameInput, &g_pGameInput);
IGameInput_Release(pGameInput);
if (FAILED(hr)) {
SDL_UnloadObject(g_hGameInputDLL);
return WIN_SetErrorFromHRESULT("GameInput QueryInterface failed", hr);
}
#else
// Assume that the version we get is compatible with the current SDK
// If that isn't the case, define the correct GUID for SDL_IID_GameInput above
g_pGameInput = pGameInput;
#endif
}
++g_nGameInputRefCount;

if (ppGameInput) {
*ppGameInput = g_pGameInput;
}
return true;
}

void SDL_QuitGameInput(void)
{
SDL_assert(g_nGameInputRefCount > 0);

--g_nGameInputRefCount;
if (g_nGameInputRefCount == 0) {
if (g_pGameInput) {
IGameInput_Release(g_pGameInput);
g_pGameInput = NULL;
}
if (g_hGameInputDLL) {
SDL_UnloadObject(g_hGameInputDLL);
g_hGameInputDLL = NULL;
}
}
}

#endif // HAVE_GAMEINPUT_H
36 changes: 36 additions & 0 deletions src/core/windows/SDL_gameinput.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "SDL_internal.h"

#ifndef SDL_gameinput_h_
#define SDL_gameinput_h_

#ifdef HAVE_GAMEINPUT_H

#define COBJMACROS
#include <gameinput.h>

extern bool SDL_InitGameInput(IGameInput **ppGameInput);
extern void SDL_QuitGameInput(void);

#endif // HAVE_GAMEINPUT_H

#endif // SDL_gameinput_h_
33 changes: 4 additions & 29 deletions src/joystick/gdk/SDL_gameinputjoystick.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@

#include "../SDL_sysjoystick.h"
#include "../usb_ids.h"

#define COBJMACROS
#include <gameinput.h>
#include "../../core/windows/SDL_gameinput.h"

// Default value for SDL_HINT_JOYSTICK_GAMEINPUT
#if defined(SDL_PLATFORM_GDK)
Expand Down Expand Up @@ -67,12 +65,10 @@ typedef struct joystick_hwdata
} GAMEINPUT_InternalJoystickHwdata;

static GAMEINPUT_InternalList g_GameInputList = { NULL };
static SDL_SharedObject *g_hGameInputDLL = NULL;
static IGameInput *g_pGameInput = NULL;
static GameInputCallbackToken g_GameInputCallbackToken = GAMEINPUT_INVALID_CALLBACK_TOKEN_VALUE;
static Uint64 g_GameInputTimestampOffset;


static bool GAMEINPUT_InternalIsGamepad(const GameInputDeviceInfo *info)
{
if (info->supportedInput & GameInputKindGamepad) {
Expand Down Expand Up @@ -245,24 +241,8 @@ static bool GAMEINPUT_JoystickInit(void)
return true;
}

if (!g_hGameInputDLL) {
g_hGameInputDLL = SDL_LoadObject("gameinput.dll");
if (!g_hGameInputDLL) {
return false;
}
}

if (!g_pGameInput) {
typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput);
GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(g_hGameInputDLL, "GameInputCreate");
if (!GameInputCreateFunc) {
return false;
}

hR = GameInputCreateFunc(&g_pGameInput);
if (FAILED(hR)) {
return SDL_SetError("GameInputCreate failure with HRESULT of %08lX", hR);
}
if (!SDL_InitGameInput(&g_pGameInput)) {
return false;
}

hR = IGameInput_RegisterDeviceCallback(g_pGameInput,
Expand Down Expand Up @@ -689,14 +669,9 @@ static void GAMEINPUT_JoystickQuit(void)
GAMEINPUT_InternalRemoveByIndex(0);
}

IGameInput_Release(g_pGameInput);
SDL_QuitGameInput();
g_pGameInput = NULL;
}

if (g_hGameInputDLL) {
SDL_UnloadObject(g_hGameInputDLL);
g_hGameInputDLL = NULL;
}
}

static bool GAMEINPUT_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
Expand Down
48 changes: 17 additions & 31 deletions src/video/windows/SDL_windowsgameinput.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@

#ifdef HAVE_GAMEINPUT_H

#define COBJMACROS
#include <gameinput.h>

#include "../../core/windows/SDL_gameinput.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_keyboard_c.h"
#include "../../events/scancodes_windows.h"
Expand Down Expand Up @@ -61,7 +59,6 @@ typedef struct GAMEINPUT_Device

struct WIN_GameInputData
{
void *hGameInputDLL;
IGameInput *pGameInput;
GameInputCallbackToken gameinput_callback_token;
int num_devices;
Expand Down Expand Up @@ -237,20 +234,7 @@ bool WIN_InitGameInput(SDL_VideoDevice *_this)
goto done;
}

data->hGameInputDLL = SDL_LoadObject("gameinput.dll");
if (!data->hGameInputDLL) {
goto done;
}

typedef HRESULT (WINAPI *GameInputCreate_t)(IGameInput * *gameInput);
GameInputCreate_t GameInputCreateFunc = (GameInputCreate_t)SDL_LoadFunction(data->hGameInputDLL, "GameInputCreate");
if (!GameInputCreateFunc) {
goto done;
}

hr = GameInputCreateFunc(&data->pGameInput);
if (FAILED(hr)) {
SDL_SetError("GameInputCreate failure with HRESULT of %08X", hr);
if (!SDL_InitGameInput(&data->pGameInput)) {
goto done;
}

Expand Down Expand Up @@ -485,12 +469,13 @@ void WIN_UpdateGameInput(SDL_VideoDevice *_this)
device->last_mouse_reading = reading;
}
if (hr != GAMEINPUT_E_READING_NOT_FOUND) {
// The last reading is too old, resynchronize
IGameInputReading_Release(device->last_mouse_reading);
device->last_mouse_reading = NULL;
if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindMouse, device->pDevice, &reading))) {
GAMEINPUT_HandleMouseDelta(data, window, device, device->last_mouse_reading, reading);
IGameInputReading_Release(device->last_mouse_reading);
device->last_mouse_reading = reading;
}
}
}
if (!device->last_mouse_reading) {
} else {
if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindMouse, device->pDevice, &reading))) {
GAMEINPUT_InitialMouseReading(data, window, device, reading);
device->last_mouse_reading = reading;
Expand All @@ -514,12 +499,13 @@ void WIN_UpdateGameInput(SDL_VideoDevice *_this)
device->last_keyboard_reading = reading;
}
if (hr != GAMEINPUT_E_READING_NOT_FOUND) {
// The last reading is too old, resynchronize
IGameInputReading_Release(device->last_keyboard_reading);
device->last_keyboard_reading = NULL;
if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindKeyboard, device->pDevice, &reading))) {
GAMEINPUT_HandleKeyboardDelta(data, window, device, device->last_keyboard_reading, reading);
IGameInputReading_Release(device->last_keyboard_reading);
device->last_keyboard_reading = reading;
}
}
}
if (!device->last_keyboard_reading) {
} else {
if (SUCCEEDED(IGameInput_GetCurrentReading(data->pGameInput, GameInputKindKeyboard, device->pDevice, &reading))) {
GAMEINPUT_InitialKeyboardReading(data, window, device, reading);
device->last_keyboard_reading = reading;
Expand Down Expand Up @@ -587,9 +573,9 @@ void WIN_QuitGameInput(SDL_VideoDevice *_this)
data->pGameInput = NULL;
}

if (data->hGameInputDLL) {
SDL_UnloadObject(data->hGameInputDLL);
data->hGameInputDLL = NULL;
if (data->pGameInput) {
SDL_QuitGameInput();
data->pGameInput = NULL;
}

if (data->lock) {
Expand Down

0 comments on commit f4d0dad

Please sign in to comment.