Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

XInput - Xbox 360 Controller API


  • Please log in to reply
57 replies to this topic
Temil2008
  • Members
  • 364 posts
  • Last active: Jun 14 2015 09:02 PM
  • Joined: 10 Dec 2012

hey there. I was wondering if there was a way to use this script/code to return the current "left" and "right" vibration motors speeds, and display them in a tooltip?

 

The reason I want to do this, is so that when the motor is triggered by the game (vibration over a certain amount), have it activate a 2nd script/function. I have tried to have it return the motor speeds, but with no luck. any help would be greatly appreciated.


________________________________________________________________

Did a solution provided fix your issue? please mark as "Answered" if so. thank you!


Bael1988
  • Members
  • 1 posts
  • Last active: Oct 04 2013 09:23 AM
  • Joined: 04 Oct 2013

Hello! \o/

 

EDIT: i figured it out! \o/

 

 

From the #13 comment of Lexikos i replaced this part:

 

 

if XInput_GetState(A_Index-1, State)=0 {
LT := json(State,"bLeftTrigger") >= Threshold
RT := json(State,"bRightTrigger") >= Threshold

 

To This:

 

if State := XInput_GetState(A_Index-1) {
LT := State.bLeftTrigger
RT := State.bRightTrigger

 

Now i can bind keys and mouse buttons to the triggers

But include doesn't work for me somehow... ;(

 

EDIT2: I can't figure out how i bind keys for the buttons...



Kein
  • Members
  • 8 posts
  • Last active:
  • Joined: 02 Jan 2011

Does the creator still visits this thread? Is there a simple example script how to do rebinding? 

 

UPD: Okay, apparently script does not work anymore with AHK



Paradoxy
  • Members
  • 22 posts
  • Last active: Jun 22 2016 09:34 AM
  • Joined: 31 Oct 2013

Hi, sorry for the following dumb question. But i have spent over an hour trying to something that im guessing will be ridiculously easy

 

i am trying to read the state of the back button... so if it is pressed, it does something, a message box for testing purposes...

 

basically a simple hotkey.

 

any ideas?  :D



oomek
  • Members
  • 1 posts
  • Last active: Dec 23 2013 06:18 PM
  • Joined: 12 Dec 2013

Do you have any plans to implement the guide button support?



druidvav
  • Members
  • 1 posts
  • Last active: Mar 23 2014 05:13 PM
  • Joined: 02 Feb 2014

I've implemented Guide button and integrated AHK into my HTPC. You can use my source code from here: https://github.com/d...av/htpc-gamepad

 

Remember, if you want to use guide - you should include KillXboxStat.ahk, so the button will not force battery status popup.

 

If you have any questions - feel free to ask!



qqqbbb
  • Members
  • 1 posts
  • Last active: Apr 03 2014 10:37 AM
  • Joined: 29 Mar 2014

  Can someone give an example how to send gamepad button press using keyboard?



Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006

Can't be done with the XInput API.  Search the forum for "ppjoy".



CreeAll
  • Members
  • 3 posts
  • Last active: Apr 21 2014 02:34 PM
  • Joined: 31 Mar 2014
Hi Lexikos
I played a bit with your Xinput lib and this other thread.
I got this Guide button on xbox Pad to be returned as any other buttons with the wButtons property (returning 1024 aka 0x0400 the undocumented value)
Just by adding 2 dllcalls, and of course with no idea what they do because I have no knowledge on this dll, hexa, deep stuff.
here is the final code, witsh is your raw xinput + those 2 lines :
/*  XInput by Lexikos
 *  This version of the script uses objects, so requires AutoHotkey_L.
 */

/*
    Function: XInput_Init
    
    Initializes XInput.ahk with the given XInput DLL.
    
    Parameters:
        dll     -   The path or name of the XInput DLL to load.
*/
XInput_Init(dll:="xinput1_3")
{
    global
    if _XInput_hm
        return
    
    ;======== CONSTANTS DEFINED IN XINPUT.H ========
    
    ; NOTE: These are based on my outdated copy of the DirectX SDK.
    ;       Newer versions of XInput may require additional constants.
    
    ; Device types available in XINPUT_CAPABILITIES
    XINPUT_DEVTYPE_GAMEPAD          := 0x01

    ; Device subtypes available in XINPUT_CAPABILITIES
    XINPUT_DEVSUBTYPE_GAMEPAD       := 0x01

    ; Flags for XINPUT_CAPABILITIES
    XINPUT_CAPS_VOICE_SUPPORTED     := 0x0004

    ; Constants for gamepad buttons
    XINPUT_GAMEPAD_DPAD_UP          := 0x0001
    XINPUT_GAMEPAD_DPAD_DOWN        := 0x0002
    XINPUT_GAMEPAD_DPAD_LEFT        := 0x0004
    XINPUT_GAMEPAD_DPAD_RIGHT       := 0x0008
    XINPUT_GAMEPAD_START            := 0x0010
    XINPUT_GAMEPAD_BACK             := 0x0020
    XINPUT_GAMEPAD_LEFT_THUMB       := 0x0040
    XINPUT_GAMEPAD_RIGHT_THUMB      := 0x0080
    XINPUT_GAMEPAD_LEFT_SHOULDER    := 0x0100
    XINPUT_GAMEPAD_RIGHT_SHOULDER   := 0x0200
    XINPUT_GAMEPAD_GUIDE            := 0x0400
    XINPUT_GAMEPAD_A                := 0x1000
    XINPUT_GAMEPAD_B                := 0x2000
    XINPUT_GAMEPAD_X                := 0x4000
    XINPUT_GAMEPAD_Y                := 0x8000

    ; Gamepad thresholds
    XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE  := 7849
    XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE := 8689
    XINPUT_GAMEPAD_TRIGGER_THRESHOLD    := 30

    ; Flags to pass to XInputGetCapabilities
    XINPUT_FLAG_GAMEPAD             := 0x00000001
    
    ;=============== END CONSTANTS =================
    
    _XInput_hm := DllCall("LoadLibrary" ,"str",dll)
    
    if !_XInput_hm
    {
        MsgBox, Failed to initialize XInput: %dll%.dll not found.
        return
    }
    
    _XInput_GetState        := DllCall("GetProcAddress" ,"ptr",_XInput_hm ,"astr","XInputGetState")
    _XInput_SetState        := DllCall("GetProcAddress" ,"ptr",_XInput_hm ,"astr","XInputSetState")
    _XInput_GetCapabilities := DllCall("GetProcAddress" ,"ptr",_XInput_hm ,"astr","XInputGetCapabilities")
	;#######################################################################################
	;############                                                                  #########
	;############      This dllcall add guide state for some reason...             #########
	;############                                                                  #########
        ;#######################################################################################
	_XInput_GuideState := DllCall("GetProcAddress", "Uint", _XInput_hm, "Uint", 100)
	
    
    if !(_XInput_GetState && _XInput_SetState && _XInput_GetCapabilities)
    {
        XInput_Term()
        MsgBox, Failed to initialize XInput: function not found.
        return
    }
}

/*
    Function: XInput_GetState
    
    Retrieves the current state of the specified controller.

    Parameters:
        UserIndex   -   [in] Index of the user's controller. Can be a value from 0 to 3.
        State       -   [out] Receives the current state of the controller.
    
    Returns:
        If the function succeeds, the return value is ERROR_SUCCESS (zero).
        If the controller is not connected, the return value is ERROR_DEVICE_NOT_CONNECTED (1167).
        If the function fails, the return value is an error code defined in Winerror.h.
            http://msdn.microsoft.com/en-us/library/ms681381.aspx

    Remarks:
        XInput.dll returns controller state as a binary structure:
            http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.xinput_state
            http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.xinput_gamepad
        XInput.ahk converts this structure to an AutoHotkey_L object.
*/
XInput_GetState(UserIndex)
{
    global _XInput_GetState, _XInput_GuideState
    
    VarSetCapacity(xiState,16)

    if ErrorLevel := DllCall(_XInput_GetState ,"uint",UserIndex ,"uint",&xiState)
        return 0
    
	;#######################################################################################
	;############                                                                  #########
	;############  This dllcall inside the loop makes                              #########
	;############  wButton show Guide button down by returning 1024 (0x0400)       #########
	;############                                                                  #########
        ;#######################################################################################
	; 
	DllCall(_XInput_GuideState, "uint", UserIndex, "uint", &xiState)
	
    return {
    (Join,
        dwPacketNumber: NumGet(xiState,  0, "UInt")
        wButtons:       NumGet(xiState,  4, "UShort")
        bLeftTrigger:   NumGet(xiState,  6, "UChar")
        bRightTrigger:  NumGet(xiState,  7, "UChar")
        sThumbLX:       NumGet(xiState,  8, "Short")
        sThumbLY:       NumGet(xiState, 10, "Short")
        sThumbRX:       NumGet(xiState, 12, "Short")
        sThumbRY:       NumGet(xiState, 14, "Short")
    )}
}


/*
    Function: XInput_SetState
    
    Sends data to a connected controller. This function is used to activate the vibration
    function of a controller.
    
    Parameters:
        UserIndex       -   [in] Index of the user's controller. Can be a value from 0 to 3.
        LeftMotorSpeed  -   [in] Speed of the left motor, between 0 and 65535.
        RightMotorSpeed -   [in] Speed of the right motor, between 0 and 65535.
    
    Returns:
        If the function succeeds, the return value is 0 (ERROR_SUCCESS).
        If the controller is not connected, the return value is 1167 (ERROR_DEVICE_NOT_CONNECTED).
        If the function fails, the return value is an error code defined in Winerror.h.
            http://msdn.microsoft.com/en-us/library/ms681381.aspx
    
    Remarks:
        The left motor is the low-frequency rumble motor. The right motor is the
        high-frequency rumble motor. The two motors are not the same, and they create
        different vibration effects.
*/
XInput_SetState(UserIndex, LeftMotorSpeed, RightMotorSpeed)
{
    global _XInput_SetState
    return DllCall(_XInput_SetState ,"uint",UserIndex ,"uint*",LeftMotorSpeed|RightMotorSpeed<<16)
}

/*
    Function: XInput_GetCapabilities
    
    Retrieves the capabilities and features of a connected controller.
    
    Parameters:
        UserIndex   -   [in] Index of the user's controller. Can be a value in the range 0–3.
        Flags       -   [in] Input flags that identify the controller type.
                                0   - All controllers.
                                1   - XINPUT_FLAG_GAMEPAD: Xbox 360 Controllers only.
        Caps        -   [out] Receives the controller capabilities.
    
    Returns:
        If the function succeeds, the return value is 0 (ERROR_SUCCESS).
        If the controller is not connected, the return value is 1167 (ERROR_DEVICE_NOT_CONNECTED).
        If the function fails, the return value is an error code defined in Winerror.h.
            http://msdn.microsoft.com/en-us/library/ms681381.aspx
    
    Remarks:
        XInput.dll returns capabilities via a binary structure:
            http://msdn.microsoft.com/en-us/library/microsoft.directx_sdk.reference.xinput_capabilities
        XInput.ahk converts this structure to an AutoHotkey_L object.
*/
XInput_GetCapabilities(UserIndex, Flags)
{
    global _XInput_GetCapabilities
    
    VarSetCapacity(xiCaps,20)
    
    if ErrorLevel := DllCall(_XInput_GetCapabilities ,"uint",UserIndex ,"uint",Flags ,"ptr",&xiCaps)
        return 0
    
    return,
    (Join
        {
            Type:                   NumGet(xiCaps,  0, "UChar"),
            SubType:                NumGet(xiCaps,  1, "UChar"),
            Flags:                  NumGet(xiCaps,  2, "UShort"),
            Gamepad:
            {
                wButtons:           NumGet(xiCaps,  4, "UShort"),
                bLeftTrigger:       NumGet(xiCaps,  6, "UChar"),
                bRightTrigger:      NumGet(xiCaps,  7, "UChar"),
                sThumbLX:           NumGet(xiCaps,  8, "Short"),
                sThumbLY:           NumGet(xiCaps, 10, "Short"),
                sThumbRX:           NumGet(xiCaps, 12, "Short"),
                sThumbRY:           NumGet(xiCaps, 14, "Short")
            },
            Vibration:
            {
                wLeftMotorSpeed:    NumGet(xiCaps, 16, "UShort"),
                wRightMotorSpeed:   NumGet(xiCaps, 18, "UShort")
            }
        }
    )
}

/*
    Function: XInput_Term
    Unloads the previously loaded XInput DLL.
*/
XInput_Term() {
    global
    if _XInput_hm
        DllCall("FreeLibrary","uint",_XInput_hm), _XInput_hm :=_XInput_GetState :=_XInput_SetState :=_XInput_GetCapabilities :=0
}

; TODO: XInputEnable, 'GetBatteryInformation and 'GetKeystroke.
So if I I use :

XInput_Init()

Loop {
    Loop, 4 {
	if State := XInput_GetState(A_Index-1) {
                tooltip % button := State.wButtons
        }
    }
    Sleep, 100
}
return
#include <XINPUT>
I have a number that represent the button pressed or the sum of the buttons pressed.

How can I translate this number into a list of pressed button human readable names (such as the constants XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_LEFT_SHOULDER, or anything else ?

Parsing a decimal number to retrieve each (if several) of its hexadecimal components in short :)

ReynoldsCahoon
  • Members
  • 5 posts
  • Last active: Jun 01 2014 08:59 AM
  • Joined: 20 May 2014

This code (based on the examples provided), is detecting when a specific gamepad's left or right triggers are pressed, and sends "[" or "]" to it's matching game window. Unfortunately, in its current state, the triggers get detected, and then they never let up. So pulling the left trigger ironsights, and then it never stops ironsighting. Likewise pulling the right trigger starts shooting, and then it never stops shooting. What am I doing wrong?

; Minimum to be considered "pressed", between 1 (0.39%) and 255 (100%).
Threshold = 64

LastRT := LastLT := 0
XInput_Init()

Loop {
    Loop, 2
	{
		if State := XInput_GetState(A_Index-1) {
			Window := GameWindow%A_Index%
			LT := State.bLeftTrigger >= Threshold
			RT := State.bRightTrigger >= Threshold
			if (LT != LastLT) {
				ControlSend,, % "{ ] " (LT ? "Down" : "Up") "}", ahk_id %Window%
				LastLT := LT
			}
			if (RT != LastRT) {
				ControlSend,, % "{ [ " (RT ? "Down" : "Up") "}", ahk_id %Window%
				LastRT := RT
			}
		}
	}
	Sleep, 100
}
return

Edit: It appears that if I pull the left trigger on controller1, it holds the ironsight infinitely. However, if I pull the left trigger on controller2 while gamewindow1 is ironsighted (infinitely) it releases that gamewindows ironsight trigger, and then infinitely ironsights gamewindow2, and vice versa. I suppose it's something to do with the assigning of the window variable, or the A_Index'd GameWindow.

Gamewindow is basically a dynamically created variable set by the number of game instances running at the time the script loads. It is set like this:
 

windowsFound=0
WinGet, id, list,,, Program Manager
Loop, %id%
{
	this_id := id%A_Index%
	WinGetClass, this_class, ahk_id %this_id%
	if this_class=CoD-WaW
	{
		windowsFound++
		gamewindow%windowsFound% = %this_id%
	}
}


ffhighwind
  • Members
  • 1 posts
  • Last active: Oct 20 2014 12:03 PM
  • Joined: 20 Oct 2014

I've implemented a bit more functionality, added some constants, and added a lot of documentation.

 

I took the modification from CreeAll's post that fixes the guide button for XInputGetState . I've implemented XinputGetKeystroke and XInputGetBatteryInformation. XinputGetKeystroke does not work as it seems to not be implemented in xinput1_3.dll and am not going to test it on xinput1_4.dll which I believe comes on Windows 8. XInputGetBatteryInformation may work but I do not have a wireless controller to test it on.

 

XInput.ahk

/*  XInput by Lexikos
 *  This version of the script uses objects, so requires AutoHotkey_L.
 */


/*
*   Loads and initializes XInput.dll, wrapper functions, and globals/constants.
*
*   Parameters:
*       dll     -   The path or name of the XInput DLL to load.
*                   
*                   xinput1_3.dll     - Windows 7
*                   xinput1_4.dll     - Windows 8
*                   xinput9_1_0.dll   - Vista
*/
XInput_Init(dll="xinput1_3.dll")
{
    global
    if _XInput_hm
        return
    
    ;======== CONSTANTS DEFINED IN XINPUT.H ========

    ; User index definitions
    XUSER_MAX_COUNT   := 4
    XUSER_INDEX_ANY   := 0x0FF
    
    /*
    ; Gamepad thresholds (XInput standards)
    XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE    := 7849
    XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE   := 8689
    XINPUT_GAMEPAD_TRIGGER_THRESHOLD      := 30
    */
    
    ; Values stored in ErrorLevel after calling an XInput function
    ERROR_SUCCESS   := 0x000
    ERROR_EMPTY     := 0x10D2 ; 4306
    ERROR_DEVICE_NOT_CONNECTED   := 0X48F ; 1167

    
    /* ------------------------------------------
    *   Xinput_GetCapabilities constants
    */
    
    ; Type - Device types
    ;XINPUT_DEVTYPE_GAMEPAD   := 0x01

    ; SubType - Device subtypes
    XINPUT_DEVSUBTYPE_UNKNOWN          := 0x00
    XINPUT_DEVSUBTYPE_GAMEPAD          := 0x01
    XINPUT_DEVSUBTYPE_WHEEL            := 0x02
    XINPUT_DEVSUBTYPE_ARCADE_STICK     := 0x03
    XINPUT_DEVSUBTYPE_FLIGHT_SICK      := 0x04
    XINPUT_DEVSUBTYPE_DANCE_PAD        := 0x05
    XINPUT_DEVSUBTYPE_GUITAR           := 0x06
    XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE := 0x07
    XINPUT_DEVSUBTYPE_DRUM_KIT         := 0x08
    XINPUT_DEVSUBTYPE_GUITAR_BASS      := 0x0B
    XINPUT_DEVSUBTYPE_ARCADE_PAD       := 0x13
    
    ; Flags
    XINPUT_CAPS_VOICE_SUPPORTED   := 0x0004
    ; For Windows 8 only
    XINPUT_CAPS_FFB_SUPPORTED     := 0x0001
    XINPUT_CAPS_WIRELESS          := 0x0002
    XINPUT_CAPS_PMD_SUPPORTED     := 0x0008
    XINPUT_CAPS_NO_NAVIGATION     := 0x0010

    ; Buttons (bitmask, bitwise OR combination)
    XINPUT_GAMEPAD_DPAD_UP          := 0x0001
    XINPUT_GAMEPAD_DPAD_DOWN        := 0x0002
    XINPUT_GAMEPAD_DPAD_LEFT        := 0x0004
    XINPUT_GAMEPAD_DPAD_RIGHT       := 0x0008
    XINPUT_GAMEPAD_START            := 0x0010
    XINPUT_GAMEPAD_BACK             := 0x0020
    XINPUT_GAMEPAD_LEFT_THUMB       := 0x0040
    XINPUT_GAMEPAD_RIGHT_THUMB      := 0x0080
    XINPUT_GAMEPAD_LEFT_SHOULDER    := 0x0100
    XINPUT_GAMEPAD_RIGHT_SHOULDER   := 0x0200
    XINPUT_GAMEPAD_A                := 0x1000
    XINPUT_GAMEPAD_B                := 0x2000
    XINPUT_GAMEPAD_X                := 0x4000
    XINPUT_GAMEPAD_Y                := 0x8000

    /** --------------------------------------
    *   Xinput_GetKeystroke constants
    */
    ;GetKeystroke is not implemented at the moment but may work in a future xinput dll
    
    /*
    ; Unicode - Reserved values
    XINPUT_FLAG_GAMEPAD      := 0x01
    XINPUT_FLAG_KEYBOARD     := 
    XINPUT_FLAG_REMOTE       := 
    XINPUT_FLAG_BIGBUTTON    := 
    XINPUT_FLAG_ANYDEVICE    := 
    XINPUT_FLAG_ANYUSER      := 
    */
    
    ; VirtualKey
    VK_PAD_A                  := 0x5800
    VK_PAD_B                  := 0x5801
    VK_PAD_X                  := 0x5802
    VK_PAD_Y                  := 0x5803
    VK_PAD_RSHOULDER          := 0x5804
    VK_PAD_LSHOULDER          := 0x5805
    VK_PAD_LTRIGGER           := 0x5806
    VK_PAD_RTRIGGER           := 0x5807

    VK_PAD_DPAD_UP            := 0x5810
    VK_PAD_DPAD_DOWN          := 0x5811
    VK_PAD_DPAD_LEFT          := 0x5812
    VK_PAD_DPAD_RIGHT         := 0x5813
    VK_PAD_START              := 0x5814
    VK_PAD_BACK               := 0x5815
    VK_PAD_LTHUMB_PRESS       := 0x5816
    VK_PAD_RTHUMB_PRESS       := 0x5817

    VK_PAD_LTHUMB_UP          := 0x5820
    VK_PAD_LTHUMB_DOWN        := 0x5821
    VK_PAD_LTHUMB_RIGHT       := 0x5822
    VK_PAD_LTHUMB_LEFT        := 0x5823
    VK_PAD_LTHUMB_UPLEFT      := 0x5824
    VK_PAD_LTHUMB_UPRIGHT     := 0x5825
    VK_PAD_LTHUMB_DOWNRIGHT   := 0x5826
    VK_PAD_LTHUMB_DOWNLEFT    := 0x5827

    VK_PAD_RTHUMB_UP          := 0x5830
    VK_PAD_RTHUMB_DOWN        := 0x5831
    VK_PAD_RTHUMB_RIGHT       := 0x5832
    VK_PAD_RTHUMB_LEFT        := 0x5833
    VK_PAD_RTHUMB_UPLEFT      := 0x5834
    VK_PAD_RTHUMB_UPRIGHT     := 0x5835
    VK_PAD_RTHUMB_DOWNRIGHT   := 0x5836
    VK_PAD_RTHUMB_DOWNLEFT    := 0x5837
    
    ; Flags
    XINPUT_KEYSTROKE_KEYDOWN   := 0x0001
    XINPUT_KEYSTROKE_KEYUP     := 0x0002
    XINPUT_KEYSTROKE_REPEAT    := 0x0004
    
    /** -----------------------------------------------
    *   Xinput_GetBatteryInformation constants
    */
    
    ; Type - Devices that support batteries
    BATTERY_DEVTYPE_GAMEPAD   :=  0x00
    BATTERY_DEVTYPE_HEADSET   :=  0x01
    
    ; BatteryType - battery status level
    BATTERY_TYPE_DISCONNECTED   := 0x00 ; This device is not connected
    BATTERY_TYPE_WIRED          := 0x01 ; Wired device, no battery
    BATTERY_TYPE_ALKALINE       := 0x02 ; Alkaline battery source
    BATTERY_TYPE_NIMH           := 0x03 ; Nickel Metal Hydride battery source
    BATTERY_TYPE_UNKNOWN        := 0xFF ; Cannot determine the battery type
    
    ; BatteryLevel
    ; These are only valid for wireless, connected devices, with known battery types
    ; The amount of use time remaining depends on the type of device.
    BATTERY_LEVEL_EMPTY    := 0x00
    BATTERY_LEVEL_LOW      := 0x01
    BATTERY_LEVEL_MEDIUM   := 0x02
    BATTERY_LEVEL_FULL     := 0x03
    
    ;=============== END CONSTANTS =================
    
    _XInput_hm := DllCall("LoadLibrary" ,"str", dll)
    
    if !_XInput_hm {
        MsgBox, Failed to initialize XInput: %dll%.dll not found.
        return
    }

    _XInput_GetState        := DllCall("GetProcAddress", "uint", _XInput_hm, "uint", 100) ; guide/home button works with this. __stdcall int secret_get_gamepad (int, XINPUT_GAMEPAD_SECRET*)
    ;_XInput_GetState       := DllCall("GetProcAddress", "uint", _XInput_hm, "AStr", "XInputGetState")
    _XInput_SetState        := DllCall("GetProcAddress", "uint", _XInput_hm, "AStr", "XInputSetState")
    _XInput_GetKeystroke    := DllCall("GetProcAddress", "uint", _XInput_hm, "AStr", "XInputGetKeystroke")  
    _XInput_GetCapabilities := DllCall("GetProcAddress", "uint", _XInput_hm, "AStr", "XInputGetCapabilities")
    _XInput_GetBatteryInformation := DllCall("GetProcAddress", "uint", _XInput_hm, "AStr", "XInputGetBatteryInformation")
    
    ;OnExit, XInput_Term__
    if !(_XInput_GetState && _XInput_SetState && _XInput_GetKeystroke && _XInput_GetCapabilities && _XInput_GetBatteryInformation) {
        XInput_Term()
        MsgBox, Failed to initialize XInput: function not found.
        return
    }
}


/*
*   Unloads XInput library/dll if it has been previously loaded.
*/
XInput_Term() {
    ;XInput_Term__:
    global
    if _XInput_hm {
        DllCall("FreeLibrary", "uint", _XInput_hm)
        _XInput_hm :=_0
        _XInput_GetState := 0
        _XInput_SetState := 0
        _XInput_GetKeystroke := 0
        _XInput_GetCapabilities := 0
        _XInput_GetBatteryInformation := 0
    }
}


/*
*   Retrieves the current state of the specified controller.
*
*   Parameters:
*       UserIndex        -   [in] Index of the signed-in gamer associated with the device. 
*                                 Can be a value of 0 to XUSER_MAX_COUNT - 1.
*
*   Returns:
*       If the function succeeds, the return value is object containing the xinput state, 0 otherwise.
*       {
*           UserIndex     ; Index of the user's controller. Can be a value of 0 to XUSER_MAX_COUNT - 1.
*           PacketNumber  ; (unused) This value increments whenever the state of the gamepad changes.
*           Buttons       ; Which buttons are pressed (Bitwise OR).
*           LeftTrigger   ; Between 0 and 255
*           RightTrigger
*           ThumbLX       ; Between -32768 to 32767. 0 is centered. Negative is down or left.
*           ThumbLY
*           ThumbRX
*           ThumbRY
*       }
*
*   Remarks:
*       If the function succeeds, ErrorLevel will be set to ERROR_SUCCESS (0).
*       If the controller is not connected, ErrorLevel will be set to ERROR_DEVICE_NOT_CONNECTED (1167).
*       Otherwise ErrorLevel is set to the error code defined in Winerror.h.
*/
XInput_GetState(UserIndex = 0) 
{
    global _XInput_GetState
    VarSetCapacity(xiState, 16)
    if ErrorLevel := DllCall(_XInput_GetState, "uint", UserIndex , "uint", &xiState)
        return 0
    
    return {
        (Join,
            UserIndex    : UserIndex
            PacketNumber : NumGet(xiState, 0) 
            Buttons      : NumGet(xiState, 4, "UShort")
            LeftTrigger  : NumGet(xiState, 6, "UChar")
            RightTrigger : NumGet(xiState, 7, "UChar")
            ThumbLX      : NumGet(xiState, 8, "Short")
            ThumbLY      : NumGet(xiState, 10, "Short")
            ThumbRX      : NumGet(xiState, 12, "Short")
            ThumbRY      : NumGet(xiState, 14, "Short")
        )}
}


/*
*   Retrieves a gamepad input event.
*
*   Parameters:
*       UserIndex        -   [in] Index of the signed-in gamer associated with the device. 
*                                 Can be a value of 0 to XUSER_MAX_COUNT - 1, 
*                                 or XUSER_INDEX_ANY (0x0FF) to fetch the next available input event from any user.
*
*   Returns:
*       If the function succeeds, the return value is object containing the xinput event, 0 otherwise.
*       {
*           VirtualKey   ; VirtualKey   ; Virtual-key code of the key, button, or stick movement. 
*           ;Unicode     ; (unused) This member is unused and the value is zero.
*           Flags        ; Flags that indicate the keyboard state at the time of the input event. 
*           UserIndex    ; Index of the signed-in gamer associated with the device. Can be a value in the range 0–3.
*           HidCode      ; HID code corresponding to the input. If there is no corresponding HID code, this value is zero.
*       }   
*
*    Remarks:
*       If the function succeeds, ErrorLevel will be set to ERROR_SUCCESS (0).
*       If no new keys have been pressed, ErrorLevel will be set to XINPUT_ERROR_EMPTY (4306).
*       If the controller is not connected, ErrorLevel will be set to ERROR_DEVICE_NOT_CONNECTED (1167).
*       Otherwise ErrorLevel is set to the error code defined in Winerror.h.
*/
XInput_GetKeystroke(UserIndex = 0x0FF) ; XUSER_INDEX_ANY = 0x0FF
{
    global _XInput_GetKeystroke
    VarSetCapacity(xiKeystroke, 8)
    if ErrorLevel := DllCall(_XInput_GetKeystroke, "uint", UserIndex, "uint", 0, "uint", &xiKeystroke)
        return 0
    
    ;Unicode : NumGet(xiKeystroke, 2, "UShort")
    return {
        (Join,
            VirtualKey : NumGet(xiKeystroke, 0, "UShort")
            Flags : NumGet(xiKeystroke, 4, "UShort")
            UserIndex : NumGet(xiKeystroke, 6, "UChar")
            HidCode : NumGet(xiKeystroke, 7, "UChar")
        )}
}

/*
*    Sends data to a connected controller. This function is used to activate the vibration
*    function of a controller.
*    
*   Parameters:
*       UserIndex        -   [in] Index of the user's controller. Can be a value of 0 to XUSER_MAX_COUNT - 1.
*       LeftMotorSpeed   -   [in] Speed of the left motor, between 0 and 65535.
*       RightMotorSpeed  -   [in] Speed of the right motor, between 0 and 65535.
*    
*   Returns:
*       If the function succeeds, the return value is true, otherwise false.
*
*   Remarks:
*       If the function succeeds, ErrorLevel will be set to ERROR_SUCCESS (0).
*       If the controller is not connected, ErrorLevel will be set to ERROR_DEVICE_NOT_CONNECTED (1167).
*       Otherwise ErrorLevel is set to the error code defined in Winerror.h.
*       The left motor is the low-frequency rumble motor. The right motor is the
*           high-frequency rumble motor. The two motors are not the same, and they create
*           different vibration effects.
*/
XInput_SetState(UserIndex, LeftMotorSpeed, RightMotorSpeed)
{
    global _XInput_SetState
    return DllCall(_XInput_SetState ,"uint", UserIndex , "uint*", LeftMotorSpeed|RightMotorSpeed<<16) = 0
}
    
    
/*
*   Retrieves the capabilities and features of a connected controller.
*
*   Parameters:
*       UserIndex  -   [in] Index of the user's controller. Can be a value in the range 0-3.
*       Flags      -   [in] Identifies the controller type.
*                            0   - All controllers.
*                            1   - XINPUT_FLAG_GAMEPAD: Xbox 360 Controllers only.
*
*   Returns:
*       If the function succeeds, the return value is object containing the xinput controller's capabilities, 0 otherwise.
*       {
*           UserIndex    ; Index of the user's controller. Can be a value of 0 to XUSER_MAX_COUNT - 1.
*           Type         ; Currently always XINPUT_DEVTYPE_GAMEPAD (may change in a later version).
*           SubType      ; Subtype of the game controller.
*           Flags        ; Features of the controller.
*           Buttons      ; Bitwise or of available buttons.
*           LeftTrigger  ; Resolution of left trigger (0 means unsupported, 255 for max resolution).
*           RightTrigger
*           ThumbLX      ; Resolution of thumb sticks
*           ThumbLY
*           ThumbRX
*           ThumbRY
*           LeftMotorSpeed  ; Resolution of motor
*           RightMotorSpeed
*       }
*
*   Remarks:
*       If the function succeeds, ErrorLevel will be set to ERROR_SUCCESS (0).
*       If the controller is not connected, ErrorLevel will be set to ERROR_DEVICE_NOT_CONNECTED (1167).
*       Otherwise ErrorLevel is set to the error code defined in Winerror.h.
*/
XInput_GetCapabilities(UserIndex = 0, Flags = 0) 
{
    global _XInput_GetCapabilities
    VarSetCapacity(xiCaps, 20)
    if ErrorLevel := DllCall(_XInput_GetCapabilities, "uint", UserIndex, "uint", Flags, "uint", &xiCaps)
        return 0
    
    return {
        (Join,
            UserIndex : UserIndex
            Type : NumGet(xiCaps, 0 "UChar")
            SubType : NumGet(xiCaps, 1, "UChar")
            Flags : NumGet(xiCaps, 2, "UShort")
            Buttons : NumGet(xiCaps, 4, "UShort")
            LeftTrigger : NumGet(xiCaps, 6, "UChar")
            RightTrigger : NumGet(xiCaps, 7, "UChar")
            ThumbLX : NumGet(xiCaps, 8, "UShort")
            ThumbLY : NumGet(xiCaps, 10, "UShort")
            ThumbRX : NumGet(xiCaps, 12, "UShort")
            ThumbRY : NumGet(xiCaps, 14, "UShort")
            LeftMotorSpeed : NumGet(xiCaps, 16, "UShort")
            RightMotorSpeed : NumGet(xiCaps,  18, "UShort")
        )}
}

/*
*   Retrieves the capabilities and features of a connected controller.
*
*   Parameters:
*       UserIndex  -   [in] Index of the user's controller. Can be a value in the range 0-3.
*       DevType    -   [in] Identifies the controller type
*                            0   - BATTERY_DEVTYPE_GAMEPAD
*                            1   - BATTERY_DEVTYPE_HEADSET
*
*   Returns:
*       If the function succeeds, the return value is true, otherwise false.
*       {
*           UserIndex      ; Index of the user's controller. Can be a value of 0 to XUSER_MAX_COUNT - 1.
*           DevType        ; Specifies which device associated with this user index should be queried. Must be BATTERY_DEVTYPE_GAMEPAD or BATTERY_DEVTYPE_HEADSET.
*           BatteryType    ; The type of battery.
*           BatteryLevel   ; The charge state of the battery. This value is only valid for wireless devices with a known battery type.
*       }
*
    Function: XInput_GetCapabilities
    
    Retrieves the capabilities and features of a connected controller.
        
    Returns:
*       If the function succeeds, ErrorLevel will be set to ERROR_SUCCESS (0).
*       If the controller is not connected, ErrorLevel will be set to ERROR_DEVICE_NOT_CONNECTED (1167).
*       Otherwise ErrorLevel is set to the error code defined in Winerror.h.
*/
XInput_GetBatteryInformation(UserIndex = 0, DevType = 1) 
{
    global _XInput_GetBatteryInformation
    VarSetCapacity(xiBattery, 8) ; actually 7 but 8 may have better performance
    if ErrorLevel := DllCall(_XInput_GetBatteryInformation, "uint", UserIndex, "uchar", DevType, "uint", &xiBattery)
        return 0
    
    return {
        (Join,
            UserIndex : UserIndex
            DevType : DevType
            BatteryType : NumGet(xiBattery, 0, "UChar")
            BatteryLevel : NumGet(xiBattery, 1, "UChar")
        )}
}

Test.ahk

#Singleinstance force
#NoEnv ;may improve performance
SendMode Input

#include %A_ScriptDir%\XInput.ahk

XInput_Init()

F1::
	Caps := XInput_GetCapabilities()
	if Caps {
		MsgBox % "UserIndex: " . Caps.UserIndex . "`n"
			. "SubType: " . Caps.SubType . "`n" 
			. "Flags: " . Caps.Flags . "`n" 
			. "Buttons: " . Caps.Buttons . "`n" 
			. "LeftTrigger: " . Caps.LeftTrigger . "`n" 
			. "RightTrigger: " . Caps.RightTrigger . "`n" 
			. "ThumbLX: " . Caps.ThumbLX . "`n" 
			. "ThumbLY: " . Caps.ThumbLY . "`n" 
			. "ThumbRX: " . Caps.ThumbRX . "`n" 
			. "ThumbRY: " . Caps.ThumbRY . "`n" 
			. "LeftMotorSpeed: " . Caps.LeftMotorSpeed . "`n" 
			. "RightMotorSpeed: " . Caps.RightMotorSpeed . "`n" 
	}
	else if ErrorLevel = ERROR_DEVICE_NOT_CONNECTED
		MsgBox, Failed to find a connected XInput gamepad controller.
	else
		MsgBox, ErrorLevel: %ErrorLevel% `n`nERROR_SUCCESS = 0`nERROR_DEVICE_NOT_CONNECTED = 1167
return


F2::
	State := XInput_GetState()
	
	if State {
		MsgBox % "UserIndex: " . State.UserIndex . "`n" ; The index number of the gamepad
			;. "PacketNumber: " . State.PacketNumber . PacketNumber . "`n" ; This value increments whenever the state of the gamepad changes.
			. "Buttons: " . State.Buttons . "`n" ; Which buttons are pressed (Bitwise OR). See XInput_Init (above) for the list of buttons.
			. "LeftTrigger: " . State.LeftTrigger . "`n" ; Between 0 and 255
			. "RightTrigger: " . State.RightTrigger . "`n" 
			. "ThumbLX: " State.ThumbLX . "`n" ; Between -32768 to 32767. 0 is centered. Negative is down or left.
			. "ThumbLY: " . State.ThumbLY . "`n" 
			. "ThumbRX: " . State.ThumbRX . "`n" 
			. "ThumbRY: " . State.ThumbRY . "`n" 
	}
	else if ErrorLevel = ERROR_DEVICE_NOT_CONNECTED
		MsgBox, Failed to find a connected XInput gamepad controller.
	else
		MsgBox, ErrorLevel: %ErrorLevel% `n`nERROR_SUCCESS = 0`nERROR_DEVICE_NOT_CONNECTED = 1167
return


F3::
	Battery := XInput_GetBatteryInformation()
	if Battery {
		MsgBox % "UserIndex: " . Battery.UserIndex . "`n" ; Index of the user's controller. Can be a value of 0 to XUSER_MAX_COUNT - 1.
			. "DevType: " . DevType . "`n" ; Specifies which device associated with this user index should be queried. Must be BATTERY_DEVTYPE_GAMEPAD or BATTERY_DEVTYPE_HEADSET.
			. "BatteryType: " . BatteryType . "`n" ; The type of battery.
			. "BatteryLevel: " . BatteryLevel . "`n"  ; The charge state of the battery. This value is only valid for wireless devices with a known battery type.
	}
	else if ErrorLevel = ERROR_DEVICE_NOT_CONNECTED
		MsgBox, Failed to find a connected XInput gamepad controller.
	else
		MsgBox, ErrorLevel: %ErrorLevel% `n`nERROR_SUCCESS = 0`nERROR_DEVICE_NOT_CONNECTED = 1167
return


F4::
	Keystroke = XInput_GetKeystroke()
	
	if Keystroke {
		MsgBox % "UserIndex: " . Keystroke.UserIndex . "`n" ; Index of the signed-in gamer associated with the device. Can be a value in the range 0–3.
			. "VirtualKey: " . Keystroke.VirtualKey . "`n" ; Virtual-key code of the key, button, or stick movement. 
			;. "Unicode: " . Keystroke.Unicode . "`n" ; This member is unused and the value is zero.
			. "Flags: " . Keystroke.Flags . "`n" ; Flags that indicate the keyboard state at the time of the input event. 
			. "HidCode: " . Keystroke.HidCode . "`n" ; HID code corresponding to the input. If there is no corresponding HID code, this value is zero.
	}
	else if ErrorLevel = ERROR_EMPTY
		MsgBox, No new gamepad keystrokes.
	else if ErrorLevel = ERROR_DEVICE_NOT_CONNECTED
		MsgBox, Failed to find a connected XInput gamepad controller.
	else
		MsgBox, ErrorLevel: %ErrorLevel% `n`nERROR_SUCCESS = 0`nERROR_DEVICE_NOT_CONNECTED = 1167`nERROR_EMPTY = 4306
return

F5::Reload
F6::Suspend
F7::ExitApp 


qwertyspace
  • Members
  • 16 posts
  • Last active: Jan 12 2016 06:23 PM
  • Joined: 15 Jan 2014

Is the original code going to be updated?  Because it doesn't work anymore.



nighliber
  • New members
  • 1 posts
  • Last active: Oct 26 2015 02:46 AM
  • Joined: 11 Oct 2015

Using CreeALL's post I was able to sort of rebind the guide/home button to Scroll Lock (for ptt). It's not as clean as I'd like, am I doing this correctly?

#include xinput.ahk

XInput_Init()

Loop {
    Loop, 4 {
	if State := XInput_GetState(A_Index-1) {
                if (State.wButtons == 1024) {
			Send {ScrollLock}
		}
        }
    }
    Sleep, 100
}
return

 

I suppose there's not a foolproof way to rebind it since it's having to poll for the special guide button return instead of just rebinding a key, i.e. a::c ... or is there a way to do that? The issue I'm having is occasional misses, be nice if it was more reliable.
 
Also I couldn't figure out a way to hold it down and release, but toggle is ok (easier to play with toggle anyway).