From 36f621842b9aa5b07fdf5820b59223f1d2a5f584 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Wed, 10 Jun 2026 12:57:43 -0700 Subject: [PATCH] Use the Microsoft provided GameInputCreate() function (#15797) It does better version checking and has better compatibility. This also fixes a crash in GameInputRedist.dll when attempting to load v3 when v2 is installed on the system. In this case, a thread is created in GameInputCreate() which is not cleaned up when the object is released, and can crash later with a NULL pointer dereference. --- .github/workflows/create-test-plan.py | 20 ++++--- .github/workflows/generic.yml | 13 +++-- CMakeLists.txt | 36 +++++++++++-- VisualC-GDK/SDL/SDL.vcxproj | 12 ++--- build-scripts/build-release.py | 12 +++-- ...t-headers.py => download-gameinput-sdk.py} | 21 ++++---- build-scripts/release-info.json | 2 +- cmake/sdlcommands.cmake | 4 +- include/build_config/SDL_build_config.h.cmake | 1 + src/core/windows/SDL_gameinput.cpp | 54 ++++++++++++------- src/core/windows/SDL_gameinput.h | 11 ++-- 11 files changed, 124 insertions(+), 62 deletions(-) rename build-scripts/{download-gameinput-headers.py => download-gameinput-sdk.py} (62%) diff --git a/.github/workflows/create-test-plan.py b/.github/workflows/create-test-plan.py index 963c06bde1..941a84ff24 100755 --- a/.github/workflows/create-test-plan.py +++ b/.github/workflows/create-test-plan.py @@ -12,7 +12,6 @@ from typing import Optional logger = logging.getLogger(__name__) -WINDOWS_GAMEINPUT_VERSION = "v3.3.195.0 " class AppleArch(Enum): Aarch64 = "aarch64" @@ -222,7 +221,8 @@ class JobDetails: msys2_packages: list[str] = dataclasses.field(default_factory=list) cygwin_packages: list[str] = dataclasses.field(default_factory=list) werror: bool = True - microsoft_gameinput_version: str = "" + microsoft_gameinput: bool = False + microsoft_gameinput_arch: str = "" msvc_vcvars_arch: str = "" msvc_vcvars_sdk: str = "" msvc_project: str = "" @@ -293,7 +293,8 @@ class JobDetails: "android-mk": self.android_mk, "werror": self.werror, "sudo": self.sudo, - "microsoft-gameinput-version": self.microsoft_gameinput_version, + "microsoft-gameinput": self.microsoft_gameinput, + "microsoft-gameinput-arch": self.microsoft_gameinput_arch, "msvc-vcvars-arch": self.msvc_vcvars_arch, "msvc-vcvars-sdk": self.msvc_vcvars_sdk, "msvc-project": self.msvc_project, @@ -445,9 +446,14 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool, ctest_args job.setup_libusb_arch = "x86" case MsvcArch.X64: job.setup_libusb_arch = "x64" - job.microsoft_gameinput_version = WINDOWS_GAMEINPUT_VERSION - job.cflags.append("-I$GAMEINPUT_INCLUDE") - job.cxxflags.append("-I$GAMEINPUT_INCLUDE") + job.microsoft_gameinput = True + match spec.msvc_arch: + case MsvcArch.X64: + job.microsoft_gameinput_arch = "x64" + case MsvcArch.Arm64: + job.microsoft_gameinput_arch = "arm64" + job.cflags.append("-I$GAMEINPUT_INCLUDE") + job.cxxflags.append("-I$GAMEINPUT_INCLUDE") case SdlPlatform.Linux: if spec.name.startswith("Ubuntu"): assert spec.os.value.startswith("ubuntu-") @@ -775,7 +781,7 @@ def spec_to_job(spec: JobSpec, key: str, trackmem_symbol_names: bool, ctest_args job.msys2_packages.append(f"{msys2_env}-clang-tools-extra") if job.ccache: job.msys2_packages.append(f"{msys2_env}-ccache") - job.microsoft_gameinput_version = WINDOWS_GAMEINPUT_VERSION + job.microsoft_gameinput = True job.cflags.append("-I$GAMEINPUT_INCLUDE") job.cxxflags.append("-I$GAMEINPUT_INCLUDE") case SdlPlatform.Cygwin: diff --git a/.github/workflows/generic.yml b/.github/workflows/generic.yml index 928ee1f9e0..ccfdb1da3b 100644 --- a/.github/workflows/generic.yml +++ b/.github/workflows/generic.yml @@ -173,14 +173,12 @@ jobs: done done - name: 'Set up Microsoft.GameInput headers' - if: ${{ matrix.platform.microsoft-gameinput-version != '' }} + if: ${{ !!matrix.platform.microsoft-gameinput }} run: | - python build-scripts/download-gameinput-headers.py \ - --version ${{ matrix.platform.microsoft-gameinput-version }} \ - -o $HOME/gameinput - echo "GAMEINPUT_INCLUDE=$(cygpath -w "$HOME/gameinput")" >>$GITHUB_ENV - echo "INCLUDE=$INCLUDE;$(cygpath -w "$HOME/gameinput")" >>$GITHUB_ENV - + python build-scripts/download-gameinput-sdk.py -o $HOME/gameinput + echo "GAMEINPUT_INCLUDE=$(cygpath -w "$HOME/gameinput/include")" >>$GITHUB_ENV + echo "INCLUDE=$(cygpath -w "$HOME/gameinput/include");$INCLUDE" >>$GITHUB_ENV + ${{ (!!matrix.platform.microsoft-gameinput-arch && format('echo "LIB=$(cygpath -w "$HOME/gameinput/lib/{0}");$LIB" >>$GITHUB_ENV', matrix.platform.microsoft-gameinput-arch)) || '' }} - name: 'Calculate ccache key' if: ${{ matrix.platform.ccache }} id: prepare-restore-ccache @@ -439,6 +437,7 @@ jobs: path: | build/dist/SDL3* build/include* + build/CMakeFiles/CMakeConfigureLog.yaml - name: 'Upload minidumps' uses: actions/upload-artifact@v7 continue-on-error: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 5c61b53832..99962e327d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -938,7 +938,7 @@ if(SDL_ASSEMBLY) }]==] COMPILER_SUPPORTS_ARMSVE2) if(COMPILER_SUPPORTS_ARMSVE2) # IMPORTANT: As not all AArch64 processors support SVE2, we only - # attach the following compilation option to SVE + # attach the following compilation option to SVE # dedicated source files. set(SVE2_MARCH_FLAG "-march=armv8-a+sve2") set(HAVE_ARMSVE2 TRUE) @@ -2313,12 +2313,42 @@ elseif(WINDOWS OR CYGWIN) static __x_ABI_CWindows_CGaming_CInput_CIGamepadStatics2 *s2; int main(int argc, char **argv) { return 0; }" HAVE_WINDOWS_GAMING_INPUT_H ) + check_cxx_source_compiles(" - #include - #define COBJMACROS #include int main(int argc, char **argv) { return 0; }" HAVE_GAMEINPUT_H ) + if(HAVE_GAMEINPUT_H) + set(SDL_GAMEINPUT_DYNAMIC 1) + find_library(GAMEINPUT_LIB NAMES "gameinput.lib") + if(GAMEINPUT_LIB) + cmake_push_check_state() + list(APPEND CMAKE_REQUIRED_LIBRARIES "${GAMEINPUT_LIB}") + check_cxx_source_compiles(" + #include + #include + #if defined(GAMEINPUT_API_VERSION) && GAMEINPUT_API_VERSION > 0 + #define STR_JOIN2(A, B) A##B + #define STR_JOIN(A, B) STR_JOIN2(A, B) + using namespace GameInput::STR_JOIN(v, GAMEINPUT_API_VERSION); + #endif + int main(int argc, char **argv) { + IGameInput *gameInput; + HRESULT hr = GameInputCreate(&gameInput); + if (SUCCEEDED(hr)) { + gameInput->Release(); + } + (void) argc; (void) argv; + return 0; + }" HAVE_GAMEINPUT_LIB + ) + if(HAVE_GAMEINPUT_LIB) + sdl_link_dependency(gameinput LIBS gameinput.lib PKG_CONFIG_LINK_OPTIONS -lgameinput) + set(SDL_GAMEINPUT_DYNAMIC 0) + endif() + endif() + endif() + check_include_file(dxgi1_5.h HAVE_DXGI1_5_H) check_include_file(dxgi1_6.h HAVE_DXGI1_6_H) check_include_file(tpcshrd.h HAVE_TPCSHRD_H) diff --git a/VisualC-GDK/SDL/SDL.vcxproj b/VisualC-GDK/SDL/SDL.vcxproj index d09e24c5d0..b116c521c1 100644 --- a/VisualC-GDK/SDL/SDL.vcxproj +++ b/VisualC-GDK/SDL/SDL.vcxproj @@ -132,7 +132,7 @@ _DEBUG;%(PreprocessorDefinitions) - setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;vcruntimed.lib;msvcrtd.lib;ucrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + gameinput.lib;setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;vcruntimed.lib;msvcrtd.lib;ucrtd.lib;msvcprtd.lib;%(AdditionalDependencies) true Windows true @@ -161,7 +161,7 @@ _DEBUG;%(PreprocessorDefinitions) - setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;d3d12_xs.lib;uuid.lib;vcruntimed.lib;msvcrtd.lib;ucrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + gameinput.lib;setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;d3d12_xs.lib;uuid.lib;vcruntimed.lib;msvcrtd.lib;ucrtd.lib;msvcprtd.lib;%(AdditionalDependencies) true Windows true @@ -199,7 +199,7 @@ _DEBUG;%(PreprocessorDefinitions) - setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;d3d12_x.lib;uuid.lib;vcruntimed.lib;msvcrtd.lib;ucrtd.lib;msvcprtd.lib;%(AdditionalDependencies) + gameinput.lib;setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;d3d12_x.lib;uuid.lib;vcruntimed.lib;msvcrtd.lib;ucrtd.lib;msvcprtd.lib;%(AdditionalDependencies) true Windows true @@ -238,7 +238,7 @@ NDEBUG;%(PreprocessorDefinitions) - setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;vcruntime.lib;msvcrt.lib;ucrt.lib;msvcprt.lib;%(AdditionalDependencies) + gameinput.lib;setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;vcruntime.lib;msvcrt.lib;ucrt.lib;msvcprt.lib;%(AdditionalDependencies) true Windows true @@ -268,7 +268,7 @@ NDEBUG;%(PreprocessorDefinitions) - setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;d3d12_xs.lib;uuid.lib;vcruntime.lib;msvcrt.lib;ucrt.lib;msvcprt.lib;%(AdditionalDependencies) + gameinput.lib;setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;d3d12_xs.lib;uuid.lib;vcruntime.lib;msvcrt.lib;ucrt.lib;msvcprt.lib;%(AdditionalDependencies) true Windows true @@ -307,7 +307,7 @@ NDEBUG;%(PreprocessorDefinitions) - setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;d3d12_x.lib;uuid.lib;vcruntime.lib;msvcrt.lib;ucrt.lib;msvcprt.lib;%(AdditionalDependencies) + gameinput.lib;setupapi.lib;winmm.lib;imm32.lib;version.lib;xgameruntime.lib;d3d12_x.lib;uuid.lib;vcruntime.lib;msvcrt.lib;ucrt.lib;msvcprt.lib;%(AdditionalDependencies) true Windows true diff --git a/build-scripts/build-release.py b/build-scripts/build-release.py index 4e153a1bf9..2201edb7a2 100755 --- a/build-scripts/build-release.py +++ b/build-scripts/build-release.py @@ -175,7 +175,7 @@ class VisualStudio: assert msbuild_path.is_file(), "MSBuild.exe does not exist" return msbuild_path - def build(self, arch_platform: VsArchPlatformConfig, projects: list[Path], include_paths: list[str]): + def build(self, arch_platform: VsArchPlatformConfig, projects: list[Path], include_paths: list[str], lib_paths: list[str]): assert projects, "Need at least one project to build" vsdev_cmd_str = f"\"{self.vsdevcmd}\" -arch={arch_platform.arch}" @@ -183,7 +183,10 @@ class VisualStudio: include_contents = "%INCLUDE%" if include_paths: include_contents = f"{';'.join(str(p) for p in include_paths)};" + include_contents - bat_contents = textwrap.dedent(f"{vsdev_cmd_str} && set INCLUDE={include_contents} && {msbuild_cmd_str}") + lib_contents = "%LIB%" + if lib_paths: + lib_contents = f"{';'.join(str(p) for p in lib_paths)};" + lib_contents + bat_contents = textwrap.dedent(f"{vsdev_cmd_str} && set INCLUDE={include_contents} && set LIB={lib_paths} && {msbuild_cmd_str}") bat_path = Path(tempfile.gettempdir()) / "cmd.bat" with bat_path.open("w") as f: f.write(bat_contents) @@ -1218,9 +1221,12 @@ class Releaser: def _build_msvc_msbuild(self, arch_platform: VsArchPlatformConfig, vs: VisualStudio): platform_context = self.get_context(arch_platform.extra_context()) include_paths = [] + lib_paths = [] for dep in self.release_info.get("dependencies", {}):#release_info["msvc"].get("dependencies", {}).items(): if "command" in self.release_info["dependencies"][dep]: include_paths.append(self.deps_path / dep / "include") + lib_paths.append(self.deps_path / dep / "lib") + lib_paths.append(self.deps_path / dep / "lib" / arch_platform.arch) continue depinfo = self.release_info["msvc"]["dependencies"][dep] msvc_zip = self.deps_path / glob.glob(depinfo["artifact"], root_dir=self.deps_path)[0] @@ -1270,7 +1276,7 @@ class Releaser: shutil.copy(src=src, dst=dir_b_props) with self.section_printer.group(f"Build {arch_platform.arch} VS binary"): - vs.build(arch_platform=arch_platform, projects=projects, include_paths=include_paths) + vs.build(arch_platform=arch_platform, projects=projects, include_paths=include_paths, lib_paths=lib_paths) if self.dry: for b in built_paths: diff --git a/build-scripts/download-gameinput-headers.py b/build-scripts/download-gameinput-sdk.py similarity index 62% rename from build-scripts/download-gameinput-headers.py rename to build-scripts/download-gameinput-sdk.py index 13d50028c0..8a85d55199 100755 --- a/build-scripts/download-gameinput-headers.py +++ b/build-scripts/download-gameinput-sdk.py @@ -7,24 +7,27 @@ import urllib.request logger = logging.getLogger(__name__) -def download_headers(tag: str, lowercase: bool, output: Path): +DEFAULT_GAMEINPUT_VERSION = "v3.3.195.0" + +def download_sdk(tag: str, lowercase: bool, output: Path): base_url = f"https://raw.githubusercontent.com/microsoftconnect/GameInput/refs/tags/{tag}/" url_relpaths = ( "include/GameInput.h", "include/v0/GameInput.h", "include/v1/GameInput.h", "include/v2/GameInput.h", + "lib/arm64/GameInput.lib", + "lib/x64/GameInput.lib", ) - remove_prefix = "include/" for url_relpath in url_relpaths: url = base_url + url_relpath - local_relpath = url_relpath.removeprefix(remove_prefix) + local_relpath = url_relpath if lowercase: local_relpath = local_relpath.lower() local_path = output / local_relpath local_dirpath = local_path.parent - local_dirpath.mkdir(parents=False, exist_ok=True) + local_dirpath.mkdir(parents=True, exist_ok=True) logger.info("Downloading %s to %s...", url, local_path) urllib.request.urlretrieve(url, local_path) @@ -33,12 +36,12 @@ def download_headers(tag: str, lowercase: bool, output: Path): def main(): logging.basicConfig(level=logging.INFO) - parser = argparse.ArgumentParser(description="Download Microsoft.GameInput headers", allow_abbrev=False) - parser.add_argument("--version", required=True, help="GameInput release tag (see https://github.com/microsoftconnect/GameInput/tags)") - parser.add_argument("--no-lowercase", action="store_false", dest="lowercase", help="Don't lowercase downloaded headers") - parser.add_argument("-o", "--output", type=Path, default=Path.cwd(), help="Headers will be stored here (subdirectories created as ") + parser = argparse.ArgumentParser(description="Download Microsoft.GameInput SDK", allow_abbrev=False) + parser.add_argument("--version", help="GameInput release tag (see https://github.com/microsoftconnect/GameInput/tags)", default=DEFAULT_GAMEINPUT_VERSION) + parser.add_argument("--no-lowercase", action="store_false", dest="lowercase", help="Don't lowercase downloaded files") + parser.add_argument("-o", "--output", type=Path, default=Path.cwd(), help="SDK will be stored here (in include and lib subdirectories)") args = parser.parse_args() - download_headers(tag=args.version, lowercase=args.lowercase, output=args.output) + download_sdk(tag=args.version, lowercase=args.lowercase, output=args.output) if __name__ == "__main__": raise SystemExit(main()) diff --git a/build-scripts/release-info.json b/build-scripts/release-info.json index e70683bc3a..e9e30e1d16 100644 --- a/build-scripts/release-info.json +++ b/build-scripts/release-info.json @@ -3,7 +3,7 @@ "remote": "libsdl-org/SDL", "dependencies": { "gameinput": { - "command": "build-scripts/download-gameinput-headers.py -o @<@DEPS_PATH@>@/include --version v3.3.195.0", + "command": "build-scripts/download-gameinput-sdk.py -o @<@DEPS_PATH@>@", "artifact": "gameinput/include/gameinput.h" } }, diff --git a/cmake/sdlcommands.cmake b/cmake/sdlcommands.cmake index 58889d19f3..1f781bc9dc 100644 --- a/cmake/sdlcommands.cmake +++ b/cmake/sdlcommands.cmake @@ -65,11 +65,12 @@ endfunction() # - LIBS: list of libraries to link to (cmake and pkg-config) # - LINK_OPTIONS: list of link options (also used in pc file, unless PKG_CONFIG_LINK_OPTION is used) function(sdl_generic_link_dependency ID) - cmake_parse_arguments(ARGS "" "COLLECTOR" "SHARED_TARGETS;STATIC_TARGETS;INCLUDES;PKG_CONFIG_LINK_OPTIONS;PKG_CONFIG_LIBS;PKG_CONFIG_PREFIX;PKG_CONFIG_SPECS;CMAKE_MODULE;LIBS;LINK_OPTIONS" ${ARGN}) + cmake_parse_arguments(ARGS "" "COLLECTOR" "SHARED_TARGETS;STATIC_TARGETS;INCLUDES;PKG_CONFIG_LINK_OPTIONS;PKG_CONFIG_LIBS;PKG_CONFIG_PREFIX;PKG_CONFIG_SPECS;CMAKE_MODULE;PUBLIC_LIBS;LIBS;LINK_OPTIONS" ${ARGN}) foreach(target IN LISTS ARGS_SHARED_TARGETS) if(TARGET ${target}) target_include_directories(${target} SYSTEM PRIVATE ${ARGS_INCLUDES}) target_link_libraries(${target} PRIVATE ${ARGS_LIBS}) + target_link_libraries(${target} PUBLIC ${ARGS_PUBLIC_LIBS}) target_link_options(${target} PRIVATE ${ARGS_LINK_OPTIONS}) endif() endforeach() @@ -77,6 +78,7 @@ function(sdl_generic_link_dependency ID) if(TARGET ${target}) target_include_directories(${target} SYSTEM PRIVATE ${ARGS_INCLUDES}) target_link_libraries(${target} PRIVATE ${ARGS_LIBS}) + target_link_libraries(${target} PUBLIC ${ARGS_PUBLIC_LIBS}) target_link_options(${target} INTERFACE ${ARGS_LINK_OPTIONS}) endif() endforeach() diff --git a/include/build_config/SDL_build_config.h.cmake b/include/build_config/SDL_build_config.h.cmake index 341b9e689e..a93090f890 100644 --- a/include/build_config/SDL_build_config.h.cmake +++ b/include/build_config/SDL_build_config.h.cmake @@ -231,6 +231,7 @@ #cmakedefine HAVE_XINPUT_H 1 #cmakedefine HAVE_WINDOWS_GAMING_INPUT_H 1 #cmakedefine HAVE_GAMEINPUT_H 1 +#cmakedefine SDL_GAMEINPUT_DYNAMIC 1 #cmakedefine HAVE_DXGI_H 1 #cmakedefine HAVE_DXGI1_5_H 1 #cmakedefine HAVE_DXGI1_6_H 1 diff --git a/src/core/windows/SDL_gameinput.cpp b/src/core/windows/SDL_gameinput.cpp index f9996916a5..225407552a 100644 --- a/src/core/windows/SDL_gameinput.cpp +++ b/src/core/windows/SDL_gameinput.cpp @@ -25,6 +25,13 @@ #ifdef HAVE_GAMEINPUT_H +#ifndef SDL_GAMEINPUT_DYNAMIC +#define USE_GAMEINPUT_LIB +#ifdef _MSC_VER +#pragma comment(lib, "gameinput.lib") +#endif +#endif // !SDL_GAMEINPUT_DYNAMIC + static SDL_SharedObject *g_hGameInputDLL; static IGameInput *g_pGameInput; static int g_nGameInputRefCount; @@ -33,6 +40,32 @@ static int g_nGameInputRefCount; bool SDL_InitGameInput(IGameInput **ppGameInput) { if (g_nGameInputRefCount == 0) { +#ifdef USE_GAMEINPUT_LIB + // This is recommended, as Microsoft's GameInputCreate() is robust + // and better handles various GameInput installations + HRESULT hr = GameInputCreate(&g_pGameInput); + if (FAILED(hr)) { + return WIN_SetErrorFromHRESULT("GameInputCreate failed", hr); + } +#elif GAMEINPUT_API_VERSION > 0 + g_hGameInputDLL = SDL_LoadObject("gameinputredist.dll"); + if (!g_hGameInputDLL) { + return false; + } + + typedef HRESULT (WINAPI *pfnGameInputInitialize)(REFIID riid, void **ppvObject); + pfnGameInputInitialize pGameInputInitialize = (pfnGameInputInitialize)SDL_LoadFunction(g_hGameInputDLL, "GameInputInitialize"); + if (!pGameInputInitialize) { + SDL_UnloadObject(g_hGameInputDLL); + return false; + } + + HRESULT hr = pGameInputInitialize(IID_IGameInput, (void **)&g_pGameInput); + if (FAILED(hr)) { + SDL_UnloadObject(g_hGameInputDLL); + return WIN_SetErrorFromHRESULT("GameInputInitialize failed", hr); + } +#else g_hGameInputDLL = SDL_LoadObject("gameinput.dll"); if (!g_hGameInputDLL) { return false; @@ -45,29 +78,12 @@ bool SDL_InitGameInput(IGameInput **ppGameInput) return false; } - IGameInput *pGameInput = NULL; - HRESULT hr = pGameInputCreate(&pGameInput); + HRESULT hr = pGameInputCreate(&g_pGameInput); if (FAILED(hr)) { SDL_UnloadObject(g_hGameInputDLL); return WIN_SetErrorFromHRESULT("GameInputCreate failed", hr); } - -#ifdef SDL_PLATFORM_WIN32 -#if GAMEINPUT_API_VERSION >= 1 - hr = pGameInput->QueryInterface(IID_IGameInput, (void **)&g_pGameInput); -#else - // We require GameInput v1.1 or newer - hr = E_NOINTERFACE; -#endif - pGameInput->Release(); - 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 - g_pGameInput = pGameInput; -#endif +#endif // USE_GAMEINPUT_LIB } ++g_nGameInputRefCount; diff --git a/src/core/windows/SDL_gameinput.h b/src/core/windows/SDL_gameinput.h index ea16b85dce..2b01e61e73 100644 --- a/src/core/windows/SDL_gameinput.h +++ b/src/core/windows/SDL_gameinput.h @@ -40,12 +40,11 @@ #define GAMEINPUT_API_VERSION 0 #endif -#if GAMEINPUT_API_VERSION == 3 -using namespace GameInput::v3; -#elif GAMEINPUT_API_VERSION == 2 -using namespace GameInput::v2; -#elif GAMEINPUT_API_VERSION == 1 -using namespace GameInput::v1; +#if GAMEINPUT_API_VERSION > 0 +// Use the namespace of the current GameInput version +#define STR_JOIN2(A, B) A##B +#define STR_JOIN(A, B) STR_JOIN2(A, B) +using namespace GameInput::STR_JOIN(v, GAMEINPUT_API_VERSION); #endif // Default value for SDL_HINT_JOYSTICK_GAMEINPUT