Getting B3D to work with XInput?

Blitz3D Forums/Blitz3D Beginners Area/Getting B3D to work with XInput?

Genexi2(Posted 2007) [#1]
Been wanting to do this for awhile, but even after doing some reading over at MSDN, I've no idea how exactly one is to go about getting B3d to actually interact with the xinput dll.

Bit of a beginner altogether when it comes to dealing with DLLs, so I'm unsure if this is something that actually requires me to copy the DLL to the folder of the project and run it from there, or if there's a global call or something I can have B3D make to interface with it and work from there...

Basically, been playing around with my bro's 360 controller on my PC (purchased me a wireless receiver for all 360 devices recently, works a charm for the most part), and with DirectInput, there are some limitations involved, which for me primarily means the controller's two triggers play tug-of-war with each other, where-as my desired result is to have them both work independently on the z-axis.

Anyone got some experience with this, or workaround means of trying to do what I want?


SLotman(Posted 2007) [#2]
I'm also pretty interested on this, specially on making the vibration part to work ;)

It will probably require a completly new dll though, since XInput is DX9 and B3D is DX7.

I dont have two controllers, but the one I have works pretty well with B3D joy commands. Just the "rumble" part is missing...


b32(Posted 2007) [#3]
I haven't got a 360 controller, however maybe you could try if these tests do *anything* ?

you need these decls:
.lib "xinput.dll"
XInputGetState( index, state* )
XInputSetState( index, vibe* )


vibration test:


input test:



Dreamora(Posted 2007) [#4]
Just make sure you don't forget to include true, WinXP DX9 conform, controller support as well.

I've a saytek with 2 analog sticks and 10 buttons as well as rumble and the second stick does not work correctly in XInput not does rumble although the game devices stuff clearly shows that everything works correctly.


Genexi2(Posted 2007) [#5]
Haven't used decls in a long time since I could never figure out how to properly work with DLLs (I'd kill for a tutorial), but basically, with a .decls, it doesn't matter what the label of the file is, and it has to be stored in the userlib folder right?

Keep getting userlib not found error here for some reason.

[EDIT] Nevermind, forgot to put the DLL in the folder with it, seems to work, off to have a play with it, thanks.

[EDIT2] Input test has a few probs with the numbers not being reset in some spots (such as the hat-switch), and right-trigger/analog are sharing the same numeric value on the display, off to see what's up. Btw, how do you figure this kind of stuff out, figuring out how to operate the DLL and interpret it and what not?
(basically, I can't for the life of me figure out which values you're supposed to peek and poke to get desired results, as all I see on the MSDN sites are pointers, which I can't make sense of)

[EDIT3] Ok, after more playing, it appears to me that the values for the thumbsticks and triggers are really off, what I was expecting to see was a transition from 0'ish to 65535 moving my thumbstick from the bottom to the top, I get the 0, and the 65535, but all the numbers in between are completely random.

Just make sure you don't forget to include true, WinXP DX9 conform, controller support as well.

Yep, I know, got a standard dual-analogue controller here as well, and my god it ticks me off just how many games don't properly support gamepads, with crap like not being able to set the dead-zone, or invert the axis, and other sorts of things.
(although, it would just be a lot more conveniant if all that could just be setup in the control panel, rather than per each individual title)


[EDIT4] Ok, got a tiny bit of work done, basically building off from what b32 supplied...., still having the weird-number issue with the joysticks, I doubt it has anything to do with the fact Blitz works with unsigned variables? Anyways, triggers working, brought the rumble into a function, I plan to try and emulate all the existing Joystick commands with xinput, once I figure out how to read that MSDN site better....

A couple questions anyhow -

1) Is it safe to create and free banks on the fly, or should I just use the one globally and just clear it's contents with a for loop whenever I need to use?

2) It appears all the buttons on the 360 controller return bit values in numeric form (1,2,4,8,16,32, etc), I'm not exactly quite sure how to take a given value of a combination of button presses (say 4097 for example, which is Dpad being pressed up{1} along with A button {4096} being pressed) without making a stupidly long list of Case/Select statements.

Haven't really coded in awhile so I'm forgetting some things, and a bit rusty on the overall code structure, but here's what I added onto from b32's code :


Hopefully I'll figure this whole DLL thing out with your guys help, so I can make this a library of functions so it'd be painless for anyone to easily integrate a native 360-controller interface in their titles.
(as I just love this freaking controller)


b32(Posted 2007) [#6]
Nice, hopefully it works out.
About the '4097', you can test for individual bits with And:
num = Input ("value=")

p = 1
For i = 1 To 16
	If (num And p) = p Then Print p
	p = p * 2
Next

WaitKey()

End


I found the types that are used in msdn are here:
http://msdn2.microsoft.com/en-us/library/aa505945.aspx

And indeed, the msdn 'short' seems to be signed:
"A 16-bit integer (range: –32768 through 32767 decimal). The first bit (Most Significant Bit (MSB)) is the signing bit."
So I guess that needs a bit conversion. Not completely sure how though, maybe something like 'number And $effffff' ?


Genexi2(Posted 2007) [#7]
Well, getting somewhere, sloppily functioned it all, and there's a memory leak somewhere, which I'm blaming on my usage of banks, as I'm not exactly familiar with them, but I need to figure it out anyhow as it's killing the performance of the application.

Current state of the files (still not too familiar with setting up DLL declarations) :


Went and looked at the actual Blitz joystick commands, and apparently the range on them goes from -1.0 to 1.0, hate to keep asking for help, but what's the math formula that would give me the equivalent of that with my 0-65535 range?
(regarding the bit conversion b32, wouldn't just subtracting 32767 from 65535 work, or do you lose precision that way?)


On a side note, can someone provide an example on how to add F1-able descriptions to home-brewed blitz functions? I know it's done via decls, but that's about it.


b32(Posted 2007) [#8]
If you put a command in a .decls, and restart Blitz, the F1 description is enabled automatically.
About the sign/unsigned conversion, I think it is:
value = value and $efff

To convert a value from (0..65535) to the range (-1.0..1.0), first substract 32767.5, then divide by 32767.5

The memory leak could be in the function xJoyZ, where the 'return' command is placed before FreeBank. Also in xJoyType and xGetJoy, no FreeBank is called.
In the msdn, 'ZeroMemory' is used to clear the bank.

That function is found in kernel32.dll.
http://www.blitzbasic.com/codearcs/codearcs.php?code=1751

Also, I made a bank with a size of 255 .. however, that is way too big. The bank should be smaller to fit the memory that is used.
For instance, if the 'rumble' structure holds 2 shorts, the bank needs to be only 4 bytes long. byte=1, short=2, integer/float=4 bytes


Genexi2(Posted 2007) [#9]
Ah, I was thinking of banks the wrong way, was under the assumption using 255 (0->255) meant it'd store a single byte, but then was curious as to why the heck the shorts weren't tossing me an out of bounds error....
(surprised my post there went through, as I had a power outage right as I clicked the post button)

And d'oh at the freebank stuff, guess that's what coding at 3AM does to ya.

So, regarding the DLL stuff, the offsets you set to the bank to send to the DLL are based on the structure of the function correct? So if the values to peek are a byte, a short, a byte, then the offsets would be 0, 1, 3 in that order?


b32(Posted 2007) [#10]
Coding at 3AM and a power outage ? That must have been quite some night then .. about the offset: yes, exactly. The offset is given in bytes, starting from zero.


Genexi2(Posted 2007) [#11]
It was somewhat, didn't notice there was even a thunderstorm going on until the power cut, and my room kept flickering every second, was a bit of a quiet storm as I couldn't hear the dang bolts even when I could see them from the window.

Anyways, mem-leak problem fixed (not going to mess with that kernel at this time), just trying to fix that analogue issue where it keeps returning random values at the most part, making it pretty much useless so far for an app. I doubled-checked the peek values, and it all appears fine.

Also, I believe the joystick peek offsets were a byte off, as when I set the peek offset up one for the joysticks, the values returned are consistent with the actual movement applied to the analogue sticks, exactly as I want them, except for the fact that that the 65535 value is split, where left-to-center range is 32768 to 65535, and from center-to-right is 0 to 32767......was curious if this also has to do with the signed/unsigned problem?

Current source files :

xinput.bb

xinputtest.bb


.decls


Should grab me my brother's second controller and see if everything reads well for it.

Btw, the app seems to be running pretty darn slow when I have it checking for everything from all controllers, and I assume it's something of my fault, as I doubt checking for the status of four controllers would do this normally if implemented correctly, as there are games designed around multi-controller usage.
(albeit rare as they are on PCs these days)

I'm guessing it'd be the constant creation and deletion of banks eh? If that's the case, would there be any problems if I made a global fair-sized bank in the library and just had all the functions reference it instead and for-loop it clear after?


b32(Posted 2007) [#12]
About the speed issue: that would require a different structure. Best is, to make a function called for instance XUpdate, that reads all the data into the bank at once. Then, the other functions can use the same bank.

This bank can be declared global. The global command can be placed right before the 'Function', like this:
Global xinputbank
Function XUpdate()

End function

I mean, it doesn't need to be in a part of the code that will be executed, as long as it appears before the bank is used.

Maybe for creating/releasing the banks, you could make an 'initialize' and a 'release' function. Users can then call initialize at the start of the program, and finalize when ending it.

ZeroMemory would be called like this:
api_ZeroMemory bank, banksize

On msdn, Microsoft suggests to clear the bank every time before using it and I think that ZeroMemory is faster than a for..next loop.

The declaration for ZeroMemory can be placed in the same decls file as the other commands. Just place .lib "kernel.dll" before it. Sort of like this:
.lib "xinput.dll"

getstatus(bank*, id)
setstatus .. etc

.lib "kernel32.dll"

zeromemroy(bank*, size)


Then, the second problem is the random-like numbers, right ? Where are they returned ? From the ThumbX/Y parameters? Or was that solved by shifting everything up one byte ? Then the problem is 'only' the signed/non-signed/byteorder issue, with the strange order of numbers as you described above:
left-to-center range is 32768 to 65535, and from center-to-right is 0 to 32767
?