From 5c51b6adf5efafa6b082d58a5e12f54205d07a43 Mon Sep 17 00:00:00 2001 From: Infiland Date: Thu, 18 Jun 2026 14:56:11 +0200 Subject: [PATCH] Harden Steam Input gamepad slot mapping --- docs/input.js | 4 ++- .../extensions/steamworks/Steamworks.yy | 4 +-- .../steamworks_cpp/GMLSteam/steam_input.cpp | 27 ++++++++++++++++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/docs/input.js b/docs/input.js index 67690711..a14e2beb 100644 --- a/docs/input.js +++ b/docs/input.js @@ -893,6 +893,8 @@ /** * @func steam_input_get_controller_for_gamepad_index * @desc This function returns the input handle for an XInput gamepad slot, or 0 if that slot is not powered by Steam Input. That can be used to match between native GameMaker `gamepad_` slots and Steam Input controllers on Windows. Since on Windows the GameMaker pad slots from 0 to 3 are XInput controllers, and from 4 to 12 are DirectInput controllers. This function only works with emulated XInput controllers. + * + * [[NOTE: Invalid slot values return `0`.]] * * @param {real} index XInput slot from 0 to 3 included. * @@ -911,7 +913,7 @@ /** * @func steam_input_get_gamepad_index_for_controller - * @desc This function is the reverse of ${function.steam_input_get_controller_for_gamepad_index}, except it allows you to determine whether a Steam Input handle is being emulated as XInput as well or not. See the definition of the reverse function for more information about slots. + * @desc This function is the reverse of ${function.steam_input_get_controller_for_gamepad_index}, except it allows you to determine whether a Steam Input handle is being emulated as XInput as well or not. It returns `-1` when no XInput slot maps to the controller handle. See the definition of the reverse function for more information about slots. * * @param {real} controller Input handle of the controller. * diff --git a/source/Steamworks_gml/extensions/steamworks/Steamworks.yy b/source/Steamworks_gml/extensions/steamworks/Steamworks.yy index 5d4f2420..e6092310 100644 --- a/source/Steamworks_gml/extensions/steamworks/Steamworks.yy +++ b/source/Steamworks_gml/extensions/steamworks/Steamworks.yy @@ -563,7 +563,7 @@ {"$GMExtensionFunction":"","%Name":"steam_input_show_binding_panel","argCount":0,"args":[2,],"documentation":"/// @param {Real} controller Input handle of the controller.\n/// @returns {Bool}","externalName":"","help":"steam_input_show_binding_panel(controller:input_handle)->bool","hidden":false,"kind":4,"name":"steam_input_show_binding_panel","resourceType":"GMExtensionFunction","resourceVersion":"2.0","returnType":2,}, {"$GMExtensionFunction":"","%Name":"steam_input_get_input_type_for_handle","argCount":0,"args":[2,],"documentation":"/// @param {Real} controller Input handle of the controller.\n/// @returns {Real}","externalName":"","help":"steam_input_get_input_type_for_handle(controller:input_handle)->input_type","hidden":false,"kind":4,"name":"steam_input_get_input_type_for_handle","resourceType":"GMExtensionFunction","resourceVersion":"2.0","returnType":2,}, {"$GMExtensionFunction":"","%Name":"steam_input_get_controller_for_gamepad_index","argCount":0,"args":[2,],"documentation":"/// @param {Real} index XInput slot from 0 to 3 included.\n/// @returns {Real}","externalName":"","help":"steam_input_get_controller_for_gamepad_index(index:real)->input_handle","hidden":false,"kind":4,"name":"steam_input_get_controller_for_gamepad_index","resourceType":"GMExtensionFunction","resourceVersion":"2.0","returnType":2,}, - {"$GMExtensionFunction":"","%Name":"steam_input_get_gamepad_index_for_controller","argCount":0,"args":[2,],"documentation":"","externalName":"","help":"steam_input_get_gamepad_index_for_controller(controller:input_handle)->real","hidden":false,"kind":4,"name":"steam_input_get_gamepad_index_for_controller","resourceType":"GMExtensionFunction","resourceVersion":"2.0","returnType":2,}, + {"$GMExtensionFunction":"","%Name":"steam_input_get_gamepad_index_for_controller","argCount":0,"args":[2,],"documentation":"/// @param {Real} controller Input handle of the controller.\n/// @returns {Real}","externalName":"","help":"steam_input_get_gamepad_index_for_controller(controller:input_handle)->real","hidden":false,"kind":4,"name":"steam_input_get_gamepad_index_for_controller","resourceType":"GMExtensionFunction","resourceVersion":"2.0","returnType":2,}, {"$GMExtensionFunction":"","%Name":"steam_input_get_string_for_xbox_origin","argCount":0,"args":[2,],"documentation":"/// @param {Real} origin A `steam_input_xbox_origin_` constant.\n/// @returns {String}","externalName":"","help":"steam_input_get_string_for_xbox_origin(origin:xbox_origin)->string","hidden":false,"kind":4,"name":"steam_input_get_string_for_xbox_origin","resourceType":"GMExtensionFunction","resourceVersion":"2.0","returnType":2,}, {"$GMExtensionFunction":"","%Name":"steam_input_get_glyph_for_xbox_origin","argCount":0,"args":[2,],"documentation":"/// @param {Real} origin A `steam_input_xbox_origin_` constant.\n/// @returns {String}","externalName":"","help":"steam_input_get_glyph_for_xbox_origin(origin:xbox_origin)->string","hidden":false,"kind":4,"name":"steam_input_get_glyph_for_xbox_origin","resourceType":"GMExtensionFunction","resourceVersion":"2.0","returnType":2,}, {"$GMExtensionFunction":"","%Name":"steam_input_get_action_origin_from_xbox_origin","argCount":0,"args":[2,2,],"documentation":"/// @param {Real} controller Target controller handle to use.\n/// @param {Real} origin A `steam_input_xbox_origin_` constant.\n/// @returns {Real}","externalName":"","help":"steam_input_get_action_origin_from_xbox_origin(controller:input_handle,origin:xbox_origin)->action_origin","hidden":false,"kind":4,"name":"steam_input_get_action_origin_from_xbox_origin","resourceType":"GMExtensionFunction","resourceVersion":"2.0","returnType":2,}, @@ -786,4 +786,4 @@ "tvosProps":false, "tvosSystemFrameworkEntries":[], "tvosThirdPartyFrameworkEntries":[], -} \ No newline at end of file +} diff --git a/source/Steamworks_gml/extensions/steamworks/steamworks_cpp/GMLSteam/steam_input.cpp b/source/Steamworks_gml/extensions/steamworks/steamworks_cpp/GMLSteam/steam_input.cpp index c50a528d..070397eb 100644 --- a/source/Steamworks_gml/extensions/steamworks/steamworks_cpp/GMLSteam/steam_input.cpp +++ b/source/Steamworks_gml/extensions/steamworks/steamworks_cpp/GMLSteam/steam_input.cpp @@ -998,6 +998,9 @@ YYEXPORT void steam_input_get_input_type_for_handle(RValue& Result, CInstance* s Result.val = static_cast(API->GetInputTypeForHandle(con)); } +static constexpr int steam_input_xinput_slot_count = 4; +static constexpr int steam_input_no_gamepad_index = -1; + /// (index:real)->input_handle YYEXPORT void steam_input_get_controller_for_gamepad_index(RValue& Result, CInstance* selfinst, CInstance* otherinst, int argc, RValue* arg) { @@ -1012,6 +1015,12 @@ YYEXPORT void steam_input_get_controller_for_gamepad_index(RValue& Result, CInst return; } + if (xinput_ind < 0 || xinput_ind >= steam_input_xinput_slot_count) + { + Result.v64 = 0; + return; + } + Result.v64 = static_cast(API->GetControllerForGamepadIndex(xinput_ind)); } @@ -1029,7 +1038,23 @@ YYEXPORT void steam_input_get_gamepad_index_for_controller(RValue& Result, CInst return; } - Result.val = API->GetGamepadIndexForController(con); + int gamepadIndex = API->GetGamepadIndexForController(con); + if (gamepadIndex >= 0 && gamepadIndex < steam_input_xinput_slot_count) + { + Result.val = gamepadIndex; + return; + } + + for (int i = 0; i < steam_input_xinput_slot_count; ++i) + { + if (API->GetControllerForGamepadIndex(i) == con) + { + Result.val = i; + return; + } + } + + Result.val = steam_input_no_gamepad_index; } /// (origin:xbox_origin)->string