Closed NicknineTheEagle closed 4 months ago
@NicknineTheEagle, I was trying to get away from requiring settings for this. I believe that more games will probably require the Windows 95/98 way because Windows XP shipped with DirectX 8.1, so presumably most games written for Windows XP use DInput8 rather than DInput. Therefore I recommend we change this to work the way Windows 98 did.
Right, we can filter out HID device of type 1 by default but if we also want to implement legacy "include aliases" behavior, that's gonna be a problem because how will we know the real type of USB device?
I am not sure what part of this is making Polaris SnoCross crash. Maybe if we filter out HID device of type 1 unless DIEDFL_INCLUDEALIASES flag is used. Then if DIEDFL_INCLUDEALIASES flag is used we can convert the type to HID flag, e.g. 0x00010102.
Basically, if we cannot completely replicate Windows 98 (because we cannot easily know which are USB devices) we can at least replicate part of what Windows 98 does, enough to get the games working. Does that make sense?
The goal of dinputto8 is for compatibility not necessarily to replicate the exact behavior of older Windows.
I am not sure what part of this is making Polaris SnoCross crash.
As I said in the OP, Polaris SnoCross crashes if it encounters device type that is not 2, 3 and 4.
Then if DIEDFL_INCLUDEALIASES flag is used we can convert the type to HID flag, e.g. 0x00010102.
Well, that's the question I've raised, how are we going to convert the type if we don't "know" the proper device type to begin with and all we got is 0x00010001? I don't think there are any additional fields that would let us extrapolate it.
I believe we can use the wUsagePage
and wUsage
fields in the DIDEVICEINSTANCE structure to differentiate between a mouse and a keyboard when dwDevType is 0x00010001 (DIDEVTYPE_DEVICE | DIDEVTYPE_HID). These fields follow the USB HID usage tables, which provide detailed information about the type of device.
Here's how you can interpret these fields:
wUsagePage
: This field specifies the usage page, which groups related usages (e.g., Generic Desktop, Simulation Controls, VR Controls).wUsage
: This field specifies the specific usage within the usage page.For USB HID devices:
So, you can differentiate between a mouse and a keyboard by checking the values of wUsagePage and wUsage.
Here is how you can implement this in code:
if (pDeviceInstance->dwDevType == 0x00010001) // DIDEVTYPE_DEVICE | DIDEVTYPE_HID
{
if (pDeviceInstance->wUsagePage == 0x01) // Generic Desktop Controls
{
switch (pDeviceInstance->wUsage)
{
case 0x02:
// This is a mouse
case 0x06:
// This is a keyboard
case 0x04:
// This is a joystick
case 0x05:
// This is a gamepad
default:
// Other device types within the Generic Desktop Controls page
}
}
else
{
// Other usage pages
}
}
else
{
// Other device types
}
My suggestion is that if device type is 1 then we look at wUsagePage
and wUsage
fields. If it is a keyboard then we change it to 3 (DIDEVTYPE_KEYBOARD). If it is a mouse then we change it to a 2 (DIDEVTYPE_MOUSE). If it is a joystick or gamepad then we change it to 4 (DIDEVTYPE_JOYSTICK).
If it is not a keyboard, mouse, joystick or gamepad then we exclude it.
Also, I am not sure what diVersion
the game is running at, but I wonder if we should only exclude type 1 devices when the game is running a specific version of DirectDraw?
I think we probably only want to do this change if diVersion
< 0x0500. Presumably Polaris SnoCross is running a version lower than 0x0500.
Polaris SnoCross uses DI version 0x0500.
Polaris SnoCross uses DI version 0x0500.
Ok, interesting. I just hate to filter out devices that other games may use. But maybe we need to do this for all DI versions.
From the header file the DIEDFL_INCLUDEALIASES
is only available on 0x050a or greater.
#if(DIRECTINPUT_VERSION >= 0x050a)
#define DIEDFL_INCLUDEALIASES 0x00010000
#define DIEDFL_INCLUDEPHANTOMS 0x00020000
#endif /* DIRECTINPUT_VERSION >= 0x050a */
I wonder if a better solution is to filter the input? What happens if we filter the below flags out if the DI version is less then 0x050a?
#define DIEDFL_INCLUDEALIASES 0x00010000
#define DIEDFL_INCLUDEPHANTOMS 0x00020000
#define DIEDFL_INCLUDEHIDDEN 0x00040000
I don't see the point in filtering flags out since they didn't exist before 0x050a to begin with and thus, games can't send them. SnoCross doesn't use them in case you're wondering.
Under Windows 98, DirectInput lists USB keyboards and mice if you pass DIEDFL_INCLUDEALIASES flag with USB devices having the usual device type but with HID flag
Ok, I misunderstood this comment. I thought the game was sending that flag and it was running DI version 0x0500 and maybe the flag was treated differently between Win98 and WinXP.
In that case, does it make sense to only modify the devices with type 1 if the DIEDFL_INCLUDEALIASES flag is NOT sent?
Edit: basically, I would like to surgically fix this so that maybe we can avoid breaking other games, if that makes sense.
Sorry for the continuous messages here!
After thinking about this for a while I think this must be a bug in the game because I think that even in Windows 98 it was possible to have a device type 1. However, it was not quite as common.
So to fix this I suggest we change:
wUsage
that it is a mouse.wUsage
that it is a keyboard.wUsage
that it is a joystick or gamepad.And otherwise we leave the device as is (we don't filter it) and go ahead and pass the device 0x00010001 type through. I think this will offer the best functionality for all games. In most cases this will prevent Polaris SnoCross from crashing, just like on Windows 98.
If you want to make a Pull Request for this go ahead. Otherwise I can put a fix in for this later.
After thinking about this for a while I think this must be a bug in the game because I think that even in Windows 98 it was possible to have a device type 1. However, it was not quite as common.
Yes, you would be right in thinking that cause DIDEVTYPE_DEVICE looks like it always existed in DirectInput so it's on devs for not handling it properly. Also worth noting that the game does officially support Windows XP according to the back of the box.
So to fix this I suggest we change
Sounds like a plan, I'll look into this soon.
I put in an update for this issue. Let me know if this helps resolve the issue with Polaris SnoCross and USB mice/keyboards.
I put in an update for this issue. Let me know if this helps resolve the issue with Polaris SnoCross and USB mice/keyboards.
1) This doesn't cover GetCapabilities and GetDeviceInfo, the former of which is used by SnoCross. 2) You're not setting device subtype.
Good catch. I missed that. Updated code to fix the device and device subtype in all three functions. Let me know if this works better with Polaris SnoCross.
I put a couple more fixes in. Hopefully the latest build will fix this issue.
@NicknineTheEagle, if you get a chance, please let me know if the latest build fixes the issue here. Thanks.
The latest release should have the fix for this. If there is still an issue you can reopen this issue.
@elishacloud Sorry about the delay, I was preoccupied. I have tested https://github.com/elishacloud/dinputto8/commit/954949d7cb96ed63334665ac99f4903369e716e3 and the crash in Polaris SnoCross is not fixed. Issue should be re-opened.
No problem. Can you give me more details on what what part of the fix is not working?
It looks like DIDEVTYPE_DEVICE conversion is not working properly cause I'm still seeing 0x00010001 being returned in the debugger. I'm guessing wUsagePage or wUsage do not fall under handled categories on my PC, that's the only reason I see why it wouldn't work.
From looking at my own devices, it looks like each of them is listed multiple times with different HID usage pages and HID_USAGE_PAGE_GENERIC isn't even necessarily present. I think it's better to just completely filter out DIDEVTYPE_DEVICE rather than trying to untangle this mess.
Here's what shows up on my desktop with USB mouse and keyboard (device type, device name, usage page, usage):
0112 Mouse 00 00
0413 Keyboard 00 00
10011 USB Device 0c 01
10011 Corsair Gaming K70 LUX RGB Keyboard 0c 01
10011 Corsair Gaming K70 LUX RGB Keyboard ffc0 02
10011 Corsair Gaming K70 LUX RGB Keyboard ffc2 03
10011 Corsair Gaming K70 LUX RGB Keyboard ffc2 04
10011 USB Device 01 80
Here's what shows up on my laptop with touchpad and USB mouse:
0112 Mouse 00 00
0413 Keyboard 00 00
10215 Controller (Rumble Gamepad F510) 01 05
10011 USB Receiver 0c 01
10011 USB Receiver ff00 01
10011 USB Receiver ff00 02
10011 HIDI2C Device 0d 0e
It looks like the only solution is to filter device type 0x00010001. I am a bit hesitant because I am not sure if it will break anything.
Ok, the latest change should fix it. I'll filter the devices for now and we can see if it causes any issues in the future.
Ok, the game starts now but doesn't react to input - it's like no input devices are found.
Sorry about that. I made a slight mistake in the last check-in. It should be fixed now.
Ok, yeah, that looks like it fixed it.
Ok, very good. Then I am closing this.
Further investigation into Polaris SnoCross has revealed that something changed about DirectInput device enumeration in Windows XP. Under Windows 98, DirectInput lists USB keyboards and mice if you pass DIEDFL_INCLUDEALIASES flag with USB devices having the usual device type but with HID flag, e.g. 0x00010102. Under Windows XP, USB keyboards and mice are always listed and their type is set to 1 (DIDEVTYPE_DEVICE), so 0x00010001. This notably makes Polaris SnoCross crash if you have USB keyboard or mouse plugged in as its code breaks if it encounters device type that isn't 2, 3, or 4. This seems like an issue within the scope of dinputto8 although I'm not sure what the best way to handle this is.