[Day 006] Redefined XInputGetState inaccessible

1
if(XInputGetState(ControllerIndex, &ControllerState) == ERROR_SUCCESS)
condition always fails.

In the watch window, I tried to see the value of XInputGetState but it says
1
identifier "XInputGetState" is undefined"


It turns out, after the following code, XInputGetState is still undefined:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define X_INPUT_GET_STATE(name) DWORD WINAPI name(DWORD dwUserIndex, XINPUT_STATE *pState)
typedef X_INPUT_GET_STATE(x_input_get_state);
X_INPUT_GET_STATE(XInputGetStateStub)
{
  return(ERROR_DEVICE_NOT_CONNECTED);
}
global_variable x_input_get_state *XInputGetState_ = XInputGetStateStub;
#define XInputGetState XInputGetState_

internal void
Win32LoadXInput(void)
{
  HMODULE XInputLibrary = LoadLibraryA("xinput1_4.dll");
  if(!XInputLibrary)
    {
      XInputLibrary = LoadLibraryA("xinput1_3.ll");
    }
  if(XInputLibrary)
    {
      XInputGetState = (x_input_get_state *)GetProcAddress(XInputLibrary, "XInputGetState");
      XInputSetState = (x_input_set_state *)GetProcAddress(XInputLibrary, "XInputSetState");
    }
}


What am I doing wrong?



Edited by shyam on
What value it actually returns? Assign to local variable to see its value. Typical error code is ERROR_DEVICE_NOT_CONNECTED - meaning device is not connected.

You cannot see "XInputGetState" value in debugger because it is a macro. Debuggers typically do not know anything about macros. What you can see is "XInputGetState_" value - which is real function pointer variable (not sure how it will help you though).
In addition to mmozeiko's comment, in later episodes Casey changes the code to try to load another dll if the first can't be loaded. Put a breakpoint on each LoadLiraryA call to see if XInputLibrary gets a correct value (not 0).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
internal void
Win32LoadXInput(void)    
{
    // TODO(casey): Test this on Windows 8
    HMODULE XInputLibrary = LoadLibraryA("xinput1_4.dll");
    if(!XInputLibrary)
    {
        // TODO(casey): Diagnostic
        XInputLibrary = LoadLibraryA("xinput9_1_0.dll");
    }
    
    if(!XInputLibrary)
    {
        // TODO(casey): Diagnostic
        XInputLibrary = LoadLibraryA("xinput1_3.dll");
    }
    
    if(XInputLibrary)
    {
        XInputGetState = (x_input_get_state *)GetProcAddress(XInputLibrary, "XInputGetState");
        if(!XInputGetState) {XInputGetState = XInputGetStateStub;}

        XInputSetState = (x_input_set_state *)GetProcAddress(XInputLibrary, "XInputSetState");
        if(!XInputSetState) {XInputSetState = XInputSetStateStub;}

        // TODO(casey): Diagnostic

    }
    else
    {
        // TODO(casey): Diagnostic
    }
}
mmozeiko
What value it actually returns? Assign to local variable to see its value.


Hi, I tried this now. It returns an int and its value is 1167 which does stand for ERROR_DEVICE_NOT_CONNECTED.

mrmixer
Put a breakpoint on each LoadLiraryA call to see if XInputLibrary gets a correct value (not 0)


Hi, trying to load other dlls part is already there in the code. I should have added that xinput1_4.dll does get loaded.

Thank you both for your help. It seems my gamepad does not get detected?
Is your controller XInput capable? A lot of older controllers are DirectInput only.

That said, there is an open-source software that emulates XInput device from DirectInput or directly from USB protocol. It allows, for example, using PS4 controller as Xbox controller - useful for games that have only Xbox/Xinput support.

https://www.x360ce.com/ (for any controller)
http://ds4windows.com/ (only for PS4 controllers)
http://betterds3.ciebiera.net/ (only for PS3 controllers)
https://emulation.gametechwiki.com/index.php/SCP_Driver_Package (for PS2/PS3/PS4 controllers)
mmozeiko
That said, there is an open-source software that emulates XInput device from DirectInput or directly from USB protocol.


Thank you. I'll check these out.