trying to use XInput

BlitzMax Forums/BlitzMax Programming/trying to use XInput

Samichan(Posted 2010) [#1]
I want to use multiple xbox360 pads in my game.
I tried using blitzmax' own joystick functions but they read all controllers as port 0 so multiple controllers was impossible.
Next choice was Microsoft's XInput. This example works fine with multiple controllers. It interfaces with a dll and uses the XInputSetState function to set rumble. This function uses only integers, but the more important ones require structs and blitzmax doesn't do structs, so I'll have to use some c++ glue. This is the part that makes me cry.

I made a little test app for this. It's my first c++/dll interfacing attempt and thus propably fails real bad in more ways than one.
Just trying to retrieve dwPacketNumber via XInputGetState for starters.

testfile.bmx


testfile.cpp


testfile.bmx fails to compile with this error log:



What's the problem here?



This example seems rather similiar and works just fine.



You can download the associated files here.
.
.
.


BlitzSupport(Posted 2010) [#2]
I'm no good with C/C++ for anything but the most trivial stuff, but I find the easiest way for me to deal with this sort of thing is to combine the structures, though it can get messy:

typedef struct _XINPUT_STATE {
    DWORD dwPacketNumber;
    XINPUT_GAMEPAD Gamepad;
} XINPUT_STATE, *PXINPUT_STATE;

typedef struct _XINPUT_GAMEPAD {
    WORD wButtons;
    BYTE bLeftTrigger;
    BYTE bRightTrigger;
    SHORT sThumbLX;
    SHORT sThumbLY;
    SHORT sThumbRX;
    SHORT sThumbRY;
} XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;


We know that the code below is meant to reserve a block of memory the size of an integer plus the size of the XINPUT_GAMEPAD structure:

Type XINPUT_STATE
   Field dwPacketNumber:Int
   Field Gamepad:XINPUT_GAMEPAD
End Type


... so you can do this:

Type XINPUT_STATE

   dwPacketNumber:Int

'   Gamepad:XINPUT_GAMEPAD ' Don't declare this, just add its fields here:

    Field wButtons:Short ' WORD = unsigned, same as Short
    Field bLeftTrigger:Byte
    Field bRightTrigger:Byte
    Field sThumbLX:Short ' Signed in C/C++ (may have to fiddle with results)
    Field sThumbLY:Short
    Field sThumbRX:Short
    Field sThumbRY:Short

End Type

Local xin:XINPUT_STATE = New XINPUT_STATE

' Call function that needs an XINPUT_STATE structure here...


... now XInput will fill in xin with all of the dwPacketNumber and Gamepad:XINPUT_GAMEPAD data since it's the correct size. Note that anything defined as a pointer should not be treated like this, just left as Field pGamepad:XINPUT_GAMPAD, for example.

You can then either access the Gamepad:XINPUT_GAMEPAD fields as xin.wButtons, etc, or copy the fields into a (separately defined) XINPUT_GAMEPAD object.

Not a lot of fun, I must admit, but I find it easier than messing with C, at least for simple projects -- example here.


Samichan(Posted 2010) [#3]
YEAH
It works!

This is my current code:

Adapted from this example.
No more c++ involved... I kinda wanted to use it but oh well.

XInputGetState correctly fills XINPUT_STATE_dummy:XINPUT_STATE with dataz and this works with 4 controllers at the same time no problem.

The signed short values (sThumbLX etc.) get filled with values ranging from [LEFT 30k...60k CENTER 0...30k RIGHT]
I managed to make sense of them by doing this:
Local abcd:Float
XINPUT_STATE_dummy.sThumbLX:+32768
abcd = (XINPUT_STATE_dummy.sThumbLX - 32768) * 0.000030517578125'	1/ 32768
If abcd > 0.999 Then abcd = 1.0
'abcd is now -1.0...0...1.0



Thanks for the help.