rdoeffinger / xwa_ddraw_d3d11

Direct3D 11 implementation of DDraw.dll for XWA
MIT License
63 stars 2 forks source link

InvertYAxis should be set to 1 and JoystickEmul should be set to 0 by default #6

Closed bguthrie1 closed 5 years ago

bguthrie1 commented 5 years ago

My issue is that my Y axis was not inverted. Pulling on the stick should pitch the craft up. I did not have this issue with the previous ddraw versions. Other people had this issue as well.

I believe I also recall an issue with someone who had to force the joystick emulation to off as it was messing with his physical joystick.

For those who do need Joystick emulation support, they can turn it on manually in the config, but most people will be using a joystick or controller of some sort so this should be set to off by default.

EDIT: It might be ok with JoystickEmul to -1 as default, but the InvertYAxis definitely should be set to 1.

bguthrie1 commented 5 years ago

Hello, I apologize if I was a little demanding. The motivation to having this fixed is so that I can redirect those in my discord directly to your github and download the latest version without issues. We generally help troubleshoot those who are having issues with the ddraw and some of those issues are related to the ones I mentioned in the first post. Since we have a majority of users that use a joystick/controller for this game, it made the most sense to me that the y inversion would be like the original game. I do however see the use in having the joystick emulation set to -1 as I have made great use with it in the past for testing. I'll try to find out if there are any issues with the auto detection. I still think the y inversion should be set to 1 by default as those who are using a mouse will most likely know how to tinker anyway and can edit the config file.

rdoeffinger commented 5 years ago

I think we have no disagreement on the "it should just work" and "pulling the joystick should turn the ship upwards". It's just that our facts don't seem to agree, and we will need to find out why. The facts I believe to have are (though there might be bugs or misunderstandings):

Now what makes me suspicious however is that you say you did not have this issue in older versions, this is unexpected and might indicate the issue you are seeing might actually be a bug somewhere, as JoystickEmul = 0 and InvertYAxis = 0 is supposed to show EXACTLY the same behaviour as with old versions of the dll that had no joystick emulation at all. So we'll need to dig a bit deeper into why things go wrong. Btw. one thing to check is that the Y axis inversion setting in XWA itself wasn't changed by accident...

bguthrie1 commented 5 years ago

image

Those are my settings in game.

If I restore the defaults this is what happens:

image

I wanted to confirm that the default option for the y axis was set to "No".

Something is odd here but I'm not sure what

EDIT: I think you're correct. My Xbox One controller in the usb game controller settings moves without having its y axis inverted which makes sense. Though its odd that using the default Windows system ddraw or the GoG ddraw it inverts the y axis for the controller. Or perhaps by default Microsoft made Xbox Controllers invert their Y axis if its DirectInput? Not sure.

EDIT 2: Forcing Xinput in the ddraw config did not adjust my y axis.

EDIT 3: I suspect that there is an exception made for the Xbox Controllers either in the drivers or the original ddraws. Another level on top of that could be the game detecting the joystick and setting the inversion from there. I'll have to think on where to go from here.

rdoeffinger commented 5 years ago

To my knowledge DirectInput is not involved here at all. XWA uses the old winmm.dll joystick methods, specifically joyGetPosEx. So it might be the winmm.dll? And maybe my ddraw.dll picks up a different winmm.dll from what XWINGALLIANCE.EXE picks somehow? Edit: However with JoystickEmul = 0, these function calls from XWA don't go through ddraw.dll, so that does not really add up either. Edit2: This also means that InvertYAxis can't possibly have any effect when JoystickEmul == 0?!? Since ddraw.dll does not handle the Joystick input at all in any way in that case.

bguthrie1 commented 5 years ago

I've sent you a private message on what I've found on the XWAUP forums. I've also noticed reWASD (https://www.rewasd.com/) seems to be having issues hooking onto my controller with JoystickEmul at -1.

I use win32.dll instead of winmm.dll, but I've tried both (and removed them both to use the system winmm.dll) but the result is the same. My y axis for the controller is automatically inverted somehow so the ddraw would "revert" it to normal and mess up gameplay.

rdoeffinger commented 5 years ago

The reWASD homepage seem to provide no information on how they hook into thing. JoystickEmul -1 should result in it auto-detecting JoystickEmul 2, which in turn means simple polling via XInputGetState, which is provided by XInput9_1_0.dll, is used. It will always use controller 0, probably should make sure things are configured such that that's not the real controller. Of course with that many programs involved it gets rather hard to say where the issue is, and which component is doing what...

bguthrie1 commented 5 years ago

I had reWASD turned off and my Y axis was not inverted. Something else seems to be causing the issue.

bguthrie1 commented 5 years ago

Ok I've found the issue. I've looked through the ddraw source code and found this.

if (g_config.JoystickEmul == 2) {
        XINPUT_STATE state;
        XInputGetState(0, &state);
        pji->dwFlags = JOY_RETURNALL;
        pji->dwXpos = state.Gamepad.sThumbLX + 32768;
        pji->dwYpos = state.Gamepad.sThumbLY + 32768;
        if (g_config.InvertYAxis) pji->dwYpos = 65536 - pji->dwYpos;
        // The 65536 value breaks XWA with in-game invert Y axis option
        pji->dwYpos = std::min(pji->dwYpos, DWORD(65535));
        pji->dwZpos = state.Gamepad.bRightTrigger;
        pji->dwRpos = state.Gamepad.sThumbRX + 32768;
        pji->dwUpos = state.Gamepad.sThumbRY + 32768;
        pji->dwVpos = state.Gamepad.bLeftTrigger;
        pji->dwButtons = 0;
        // Triggers first
        if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) pji->dwButtons |= 1;
        if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) pji->dwButtons |= 2;
        // Thumb and shoulder buttons next
        pji->dwButtons |= (state.Gamepad.wButtons & 0x3c0) >> 4;
        // A, B, X, Y
        pji->dwButtons |= (state.Gamepad.wButtons & 0xf000) >> 6;
        // start and back
        pji->dwButtons |= (state.Gamepad.wButtons & 0x30) << 6;
        // XWA can map only 12 buttons, so map dpad to POV
        pji->dwPOV = povmap[state.Gamepad.wButtons & 15];

For some reason this was executing even with JoystickEmul = -1

Here is why:

static int needsJoyEmul()
{
    XINPUT_STATE state;
    if (XInputGetState(0, &state) == ERROR_SUCCESS) return 2;
    UINT cnt = joyGetNumDevs();
    for (unsigned i = 0; i < cnt; ++i)
    {
        JOYINFOEX jie;
        memset(&jie, 0, sizeof(jie));
        jie.dwSize = sizeof(jie);
        jie.dwFlags = JOY_RETURNALL;
        UINT res = joyGetPosEx(0, &jie);
        if (res == JOYERR_NOERROR)
            return 0;
    }
    return 1;
}
if (XInputGetState(0, &state) == ERROR_SUCCESS) return 2;

This will return successful for Xbox Controllers.

I'll have to think on how to approach this.

EDIT: It might be better to not have g_config.JoystickEmul change its value and simply check if its 2 and check its XinputState.

rdoeffinger commented 5 years ago

Yes, I know that code, and I said it uses XInput when set to -1 (because otherwise many gamepads are not really usable unless using XInput, of course that can be worked around with something like rewasd, but that's not a "just works" solution when you have to tell people to buy something first). But that doesn't explain why InvertYAxis should be set to 1 even when JoystickEmul is 0, as per topic of this issue.

bguthrie1 commented 5 years ago

I apologize I have just noticed your message stating that.

I've been rereading your posts and I see I have been missing a lot of information. So I would like to address these.

Connecting my ThrustMaster joystick, pulling does turn upwards with InvertYAxis set to 0. Setting it to 1 would actually cause it to behave wrong

This makes sense if the ThrustMaster was not returning any Xinput state. If my Xbox Controller didn't return JoystickEmul = 2, there wouldn't be an a y-axis issue in which it would act like the ddraws before. This isolates the issue to the Xinput code in the ddraw. If there was code detecting Xinput devices in the previous ddraws (like around 1.5.1) then I am wrong and something else is clearly the problem.

I added InvertYAxis because some GamePads have an inverted Y axis when they emulate a joystick and no way to configure that

I'm curious, which gamepads have this issue?

With JoystickEmul set to 0 (or otherwise disabling XInput support) there is no simple way I know of to distinguish these cases, so one or the other would not work without manual configuration.

I fear that with certain controllers that there will have to be some manual configuration due to the way they are setup. Speaking of certain controllers…I've noticed that in the ddraw config for JoystickEmul = 2 states:

; Force XInput to use a special XInput mode that is adjusted to what worked
; best for my experiments with a Steam controller, so it might not be useful
; for anyone else.

I'm going to assume based on the text here that this solution came about to allow the Steam controller to just work. Creating a solution around the Steam controller can be problematic due to the fact that it has so much customization. I have a steam controller myself and I have in the past ran many tests to get the perfect config for the xwing series. Due to it being so problematic and that its so integrated with Steam, I gave up and decided to go with reWASD for the solution.

I ran some quick tests with a Steam Controller on a default desktop configuration (base configuration) with the ddraw to see how the y axis is set by default, but its difficult to tell due to the many configurations it has. I tried applying my old config to the steam controller and noticed that they removed (?) "Joystick Move" as an input option.

I still think that you are on the right path here to allowing all controllers to just work. Your ddraw allows those with a Steam controller to just work with XWA without having a hard connection to Steam itself which I wish I had back then as this was the problem that was frustrating me most. I believe the best solution here is to separate the Steam Controller from the other Xinput devices in the ddraw due to the sheer amount of customization it offers. Though I'm not sure how to differentiate a Steam Controller from other devices through Xinput which may be the difficult part.

Would you be able to send me your Steam Controller configuration? I'm curious as to what you use and I would like to run some tests. Also does the y axis issue also occur with an Xbox controller on your end?

EDIT: Is it possible to use the JOYCAPS fields szPname, szRegKey, szOEMVxD as differentiators? Maybe the wMid and wPid manufacturer/product identifiers?

EDIT 2: It seems these folks were having issues with Xinput and the y-axis as well: https://github.com/glfw/glfw/issues/1083

I think the best solution for now would be to have the y axis inverted for Xinput controllers by default. Any other specialized controllers are expected to have customization anyway and will most likely require changing the options in the ddraw.cfg.

rdoeffinger commented 5 years ago

I can't answer your first questions, much of the issues I heard about were not detailed or second-hand, and I do not own any normal controller to test myself, so your input is quite welcome.

I uploaded my Steam Controller configuration as "XWA with gyro". But note that using it is painful: XInput emulation (and thus most of the configuration options) for Steam Controller does not work when they start the launcher first, you have to save the configuration to a local template, then create a shortcut to XWINGALLIANCE.EXE, apply the template configuration saved earlier and then run it via the shortcut. Also note that you'll almost definitely want to change the button bindings in-game, especially "button 2" to "None".

For the Steam controller I have no particular preference on which way around the Y axis is to be honest. My point was just that if controllers have the Y axis the wrong way round, it's because they report it so. Or maybe it's that Microsoft defined the Y axis flipped for the XInput API? I'm fine with changing the XInput-specific piece of code to flip the meaning of InvertYAxis, i.e. from if (g_config.InvertYAxis) pji->dwYpos = 65536 - pji->dwYpos; to if (!g_config.InvertYAxis) pji->dwYpos = 65536 - pji->dwYpos; if you think that will improve things, though it would be nice if it could be tested with a couple of gamepads (e.g. Xbox and PS4 or so?)!

bguthrie1 commented 5 years ago

I'll take a look at the Steam controller config sometime. It does sound like I would be sticking with my reWASD setup though.

Just want to iterate something for my own understanding (more of a theory): Microsoft seems to have Xinput controllers (or just the Xbox controller, not sure) have their y axis inverted by default. But for some reason if the y axis was overriden using the joyinfoex structure it reverts to normal. Somewhere in Windows its forcing a y axis inversion on the controller unless its overridden.

Perhaps this was a way to allow old games to simply work with the controller since most of the time the y axis was expected to be y inverted for these old games? Newer developers would just override the axis and buttons anyway, so they would never deal with the issue.

As for inverting the y axis, the problem I realized is that the overriding of buttons through Xinput messes up my reWASD setup for some odd reason. Granted not everyone will be using reWASD, so I don't think its something to prioritize around but it is something to keep in mind.

This is a toughie. The best solution for myself would be to set "JoystickEmul = 0" in the config. For a majority of people, they will be using joysticks and xbox controllers (without reWASD). Flipping the y axis for Xinput like you said would fix the issue for Xbox Controllers, though I'm not sure about the buttons. More testing will be needed here and I will let you know how the buttons respond.

EDIT: I'm not sure how the PS4 controller will act. We would have to know if it uses DirectInput or Xinput (reWASD can support PS4 controllers which I would imagine would be Xinput but I can't say for sure).

One thing is for sure, if someone is using a PS4 controller, they should have the expectation that there will be some customization required since its not a default Xinput device so I don't think we should prioritize getting PS4 controllers working out of the box (unless there are default drivers for windows, but I don't have a PS4 controller so I can't say).

EDIT 2 return of the edit: I think our best bet is to make sure joysticks and Xbox Controllers work right out of the box since they are going to be the most common. I will test the xbox controller without reWASD to see if there is any issue with the buttons.

bguthrie1 commented 5 years ago

Confirmed that there is an issue with the buttons. The ddraw seems to limit the amount of buttons to like 5 or 6.

rdoeffinger commented 5 years ago

See the comments in the code, it maps 12 buttons plus dpad: // Triggers first if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) pji->dwButtons |= 1; if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) pji->dwButtons |= 2; // Thumb and shoulder buttons next pji->dwButtons |= (state.Gamepad.wButtons & 0x3c0) >> 4; // A, B, X, Y pji->dwButtons |= (state.Gamepad.wButtons & 0xf000) >> 6; // start and back pji->dwButtons |= (state.Gamepad.wButtons & 0x30) << 6; // XWA can map only 12 buttons, so map dpad to POV pji->dwPOV = povmap[state.Gamepad.wButtons & 15];

rdoeffinger commented 5 years ago

According to https://docs.microsoft.com/en-us/windows/desktop/api/xinput/ns-xinput-_xinput_gamepad that actually maps all buttons the XInput interface defines.

bguthrie1 commented 5 years ago

That's strange then...the buttons are not only limited but they are completely different from before. Several buttons that I've bound on my Xbox Controller through XWA are not binding correctly (if JoystickEmul is set to -1).

EDIT: It could seem "limited" because the buttons are rebound as other buttons?

bguthrie1 commented 5 years ago

By default, the buttons on the Xbox Controller are bound as follows:

A = Button 1 B = Button 2 X = Button 3 Y = Button 4 Left Bumper = Button 5 Right bumper = Button 6 Select or the Left menu button = Button 7 Start or the right menu button = Button 8 Joystick Left Press = Button 9 Joystick Right Press = Button 10 Then the POV buttons.

If JoystickEmul = -1 (which is set to 2 in the code)

A = Button 7 B = Button 8 X = Button 9 Y = Button 10 Left Bumper = Button 5 Right Bumper = Button 6 Select or the Left menu button = Button 12 Start or the right menu button = Button 11 Left Stick Press = Button 3 Right Stick Press = Button 4 POV Buttons are correct.

Addtionals: Left Trigger = Button 1 Right Trigger = Button 2

I will say having the triggers remappable is pretty cool, but it looks like the buttons are set out of order with the code above.

EDIT: Probably should have the triggers set as Button 11 and 12.

bguthrie1 commented 5 years ago

This code will set the buttons to that of the Xbox controller.

// shoulder buttons next
pji->dwButtons |= (state.Gamepad.wButtons & 0x300) >> 4;
// Thumb buttons
pji->dwButtons |= (state.Gamepad.wButtons & 0xc0) << 2;
// A, B, X, Y
pji->dwButtons |= (state.Gamepad.wButtons & 0xf000) >> 12;
// start and back
pji->dwButtons |= (state.Gamepad.wButtons & 0x10) << 3;
pji->dwButtons |= (state.Gamepad.wButtons & 0x20) << 1;

EDIT: I couldn't get the trigger buttons to be set to buttons 11 and 12 for some reason.

rdoeffinger commented 5 years ago

I don't see why having the trigger buttons as 11 and 12 would be "right" in any way. Especially as it would mean you can't use them at all in the old games since they did not even support that many buttons.

bguthrie1 commented 5 years ago

Because button A and B already occupy Button 1 and 2. If buttons get remapped to other buttons then people are going to wonder why their configs don't work. By having it set as button 11 and 12, it doesn't disrupt the standard that is already in place.

EDIT: I've checked that all games in the X-Wing series support to 12 buttons so I don't see the issue in having the trigger buttons as 11 and 12.

rdoeffinger commented 5 years ago

We can't avoid disrupting the standard when the standard is broken and plain doesn't work. Sure, could have different setup for XWA vs. the other games but that still would be confusing in other ways. Also how about people who do NOT have a setup already? Having the A button as fire button and the trigger button all the way down doesn't seem great even for XWA then.

bguthrie1 commented 5 years ago

The standard is fine honestly. If you start remapping buttons you're going to get people asking why they only have 5 or 6 buttons or why their controller doesn't work. If people don't have a setup, then the expectation is that they won't change anything in their config anyway.

If you don't want the A button to be the fire button, you simply remap it in XWA (or whatever X-Wing series game you're playing). Same thing for the trigger. I really don't see the issue here.

rdoeffinger commented 5 years ago

Need to check the other games how many buttons they support, but maybe putting the triggers at 7 and 8 might be a compromise. But in the end trying to be 100% compatible with the emulation just results in something just as bad as the emulation, and that you can get by just disabling the XInput support...

bguthrie1 commented 5 years ago

The other games support 12 buttons.

Heck, the games actually support 20 buttons. Minus 4 for the POV.

If we are going to remap buttons to others at the hardware level (except for the triggers), then we might as well remove the Xinput support because it would cause too much trouble.

rdoeffinger commented 5 years ago

Oh, it's XWA that supports fewest buttons? I've been trying to think why I've done it this way. I think the reason is that I assumed that the trigger would be the "normal" fire button. And the other buttons are in the order of the XInput structure. If I can't think of a better reason for how I did things I might actually agree with you... I was mostly considering people who start the game for the first time, and for that I still like my mapping a bit better, but I see that it's very confusing for people starting with an existing setup (note that based on the Steam controller I also had the impression that without XInput support gamepads would not be usable anyway and thus nobody would have an existing setup. I might need to adjust my thinking).

bguthrie1 commented 5 years ago

Sorry when I said "games" I meant all of the games in the series.

In the config for XvT or XWA:

image

Only 12 buttons are shown in game, but you can edit 20 buttons in the config. The value is the index of the button itself. X-Wing and TIE Fighter probably support the same but since their configs are encoded, one would have to edit it by a hex editor. But the idea is still possible although I would not expect casual folk to do it this way at all, so technically 12 buttons is what we should shoot for.

The Xbox controller by default probably had this weird default structure to support old games right off the bat. Of course getting it to work "out of the box" will be different to everyone and unfortunately this could cause issues. So this weird standard has to be followed or else people with established configs are going to wonder why the game doesn't respond to their controller.

I too have my trigger button as the fire button. Set through reWASD of course. By having the trigger buttons as 11 and 12, the original standard is kept and I can remap A button to something else other than fire, and remap the trigger button to fire, all in game.

rdoeffinger commented 5 years ago

You are right, I was wrong. Sorry for my stubbornness and thanks for insisting long enough to overcome it

bguthrie1 commented 5 years ago

No problem, I've dealt with worse believe me :P. I still think Xinput support is a great idea since people won't have to buy reWASD to remap their triggers.

Although something has been on my mind lately: http://www.xwaupgrade.com/phpBB3/viewtopic.php?p=156769#p156769

I'm wondering if this dude from the post was replacing the ddraw after an XWAUP installation. The symptoms he describes are similar to what I experienced just now. Makes me wonder if a T.Flight HOTAS is sending an Xinput state...but I'm not sure. I've posted a note to see if he was changing the ddraw.

Anyway, I'm glad to have gotten this all covered. I'm all for the betterment of the game and for the users experience so I'm glad to have been a part of this.

EDIT: I didn't even think about it but I wonder if modern joysticks are sending Xinput states...that could screw up things since it would reduce the buttons to 12 from whatever they had before. It might be better to support the full 20 or more just in case.

EDIT 2: The Xinput standard doesn't even support that many buttons...hmm.

EDIT 3: Is it possible to allow more than 12 buttons in the ddraw? What would be the max? We should set it to the max if possible, regardless of how many buttons XWA can support. The reason being is that lets say if their trigger button is button 20, they wouldn't be able to remap their trigger to anything.

EDIT 4: It appears the T.Flight HOTAS X (and perhaps the T.Flight HOTAS One) supports Xinput which is extremely rare for a joystick. That would be the joystick that would cause issues as of now, which interestingly is what the dude mentioned in his post...

rdoeffinger commented 5 years ago

I think I need to change the code to only use XInput if there is no joystick or it is an emulated one. Any chance you could write a program to call joyGetDevCaps and report szPname and szOEMVxD for some of your devices like the xbox controller? Seems like the best chance to figure out whether to use XInput or not. Well, or maybe just pick whichever has more axis? Or only pick the joystick if it has at least 3 axis? Any other idea?

bguthrie1 commented 5 years ago

I'll def look into it. I'll let you know what I come up with.

bguthrie1 commented 5 years ago

I think our best bet is to use szOEMVxD and check if its reporting "Microsoft" (or whatever is returning with an Xbox controller). To my knowledge Microsoft has not made a joystick controller so this would be viable, until they make one...So perhaps checking if the OEM is Microsoft as well as the device having 2 axis would solidify it being an xbox controller. I'll look into programming this.

rdoeffinger commented 5 years ago

There are a lot of gamepads that use XInput support, PS4 controller, Steam controller, ... So I don't think checking for "Microsoft" is a good idea.

bguthrie1 commented 5 years ago

I would have thought that the driver OEM support would be from the company who made the drivers, but its possible they could just use Microsoft's drivers for Xinput support so you're right. I'll have to think of another way.

bguthrie1 commented 5 years ago

szPname might be the way to go. I'll have to check and see what name is returning with the Xbox controller and we can use that. The only issue I can think of with this is if there is some way to change the name of the controller.

EDIT: Note for myself: There are two Xbox controllers (360 and One). So maybe getting certain characters that contain "XBOX" or something of the like to ensure both controller types are detected.

bguthrie1 commented 5 years ago

There may be an easy way of detecting an Xbox controller using the Xinput API.

https://docs.microsoft.com/en-us/windows/desktop/api/xinput/nf-xinput-xinputgetcapabilities

With the XINPUT_FLAG_GAMEPAD flag it will "Limit query to devices of Xbox 360 Controller type.". So this should only detect 360 (it should detect the One as well, I have a one so I can see to that) controllers.

rdoeffinger commented 5 years ago

I am very wary of this flag. Any controller that wants to actually work for programs designed for Xbox controllers will have to pretened to be a xbox 360 controller. Vice versa, some actual gamepads might not be found this way. It seems unfortunately fairly likely to me that this flag will not have correlation with anything interesting. Also even if it worked I don't think it's quite what we want. Because if someone has a proper joystick connected as well, they probably way to play XWA using that, not the gamepad. Thus I would think it would be more useful to have a joystick blacklist rather than an XInput whitelist. As for the Steam controller, unfortunately it seems to report a generic Microsoft driver via the joystick API, the only way to detect it seems to be to look for wMid == 0x45e and wPid == 0x28e

rdoeffinger commented 5 years ago

ddraw.zip Here's a build of the latest version I just pushed for you to test. I have no idea how it handles the XBox controller, if the triggers do not map to buttons it's not using XInput and we need to add a special case for it.

rdoeffinger commented 5 years ago

Forgot to reference this ticket in the commit message, commit 022ba9fa161dae3cfa371ee8f2966cd54cce2a75 tries to detect if we should use XInput or not.

bguthrie1 commented 5 years ago

The triggers aren't detected as buttons with your posted code.

I understand where you are coming from but I still think we should use the "XINPUT_FLAG_GAMEPAD" flag as a...how to say it...a backup? It's just one of many checks to ensure that we are getting is true. It wouldn't be the sole check for detecting a device.

I'll still check the szPname string and see what its returning with my controller though. That will definitely be a sure fire way of detecting an Xbox controller.

bguthrie1 commented 5 years ago

Unfortunately my C++ skills are below par...What would be the code to output szPname?

rdoeffinger commented 5 years ago

I don't really see how it would be possible to use XINPUT_FLAG_GAMEPAD "as a backup", at least not if the goal is for the solution to work when both a joystick and a gamepad are connected. Below code prints a couple of things (if it doesn't compile you might have to remove/replace the sleep() call).

include

include

include

int main() { JOYCAPS caps; joyGetDevCaps(0, &caps, sizeof(caps)); printf("%i %x mid:%x pid:%x %s %s %s\n", caps.wNumAxes, caps.wCaps, caps.wMid, caps.wPid, caps.szPname, caps.szRegKey, caps.szOEMVxD); sleep(100); }

bguthrie1 commented 5 years ago

Hmm yeah I can't seem to compile this at all. I've removed the sleep function and it wanted me to add "#include "pch.h" so I included it. Now it is throwing an error:

Error C2146 syntax error: missing ';' before identifier 'caps' OutputDeviceName c:\users\bguth\source\repos\outputdevicename\outputdevicename\outputdevicename.cpp 10

I created this as a console app by the way. This is the code so far:

#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
#include "pch.h"
int main()
{
    JOYCAPS caps;
    joyGetDevCaps(0, &caps, sizeof(caps));
    printf("%i %x mid:%x pid:%x %s %s %s\n", caps.wNumAxes, caps.wCaps, caps.wMid, caps.wPid, caps.szPname, caps.szRegKey, caps.szOEMVxD);
    //sleep(100);
}

EDIT: Looks like other errors appeared such as "caps" being an undeclared identifier.

rdoeffinger commented 5 years ago

Yeah, that's the reason I hate VisualStudio, it has stupid default settings. In the project properties, go to c/c++ -> precompiled headers and disable them. Then use the below:

include

include

include

pragma comment(lib, "winmm")

int main() { JOYCAPSA caps; joyGetDevCapsA(0, &caps, sizeof(caps)); printf("%i %x mid:%x pid:%x %s %s %s\n", caps.wNumAxes, caps.wCaps, caps.wMid, caps.wPid, caps.szPname, caps.szRegKey, caps.szOEMVxD); Sleep(10 * 1000); }

(the VisualStudio way is to put the #include lines into pch.h, then you should not need to disable precompiled headers, but who knows what goes wrong then)

bguthrie1 commented 5 years ago

Awesome that worked.

image

rdoeffinger commented 5 years ago

Interesting that the manufacturer ID is also 0x45e like for the Steam controller. I wonder if that's maybe something that's common and unique to all joysticks emulated from a controller/XInput device?

bguthrie1 commented 5 years ago

I do know that the Xbox controller supports WinMM, DirectInput and Xinput and will adapt accordingly but I would have thought it would output a different ID...interesting.

rdoeffinger commented 5 years ago

ddraw.zip Here's a version with just a check for wMid == 0x45e, maybe that works for detecting gamepads... At least a Logitech Extreme3D Pro has a different wMid, so that one is detected as non-gamepad even with such a broad check.

bguthrie1 commented 5 years ago

Seems to detect my controller and the triggers are mapped to 11 and 12 buttons.

Though I wonder if a joystick can somehow return wMid == 0x45e. It looks like its just the generic joystick driver so that seems possible....

rdoeffinger commented 5 years ago

wMid is the "manufacturer ID", so it's not an information about the driver but the device itself. It certainly would be possible for a joystick to have the same "manufacturer", but I think there is a good chance that won't be the case. Unfortunately that ID does not seem officially registered, so it's hard to say more on it.

bguthrie1 commented 5 years ago

Hmm...I don't like to leave things to chance honestly. I wonder if there is another way to approach this situation...

My brain is a bit a foggy as of now so I won't be able to think of any solutions for the time being. I will think about it later.

EDIT: https://docs.microsoft.com/en-us/windows/desktop/Multimedia/manufacturer-and-product-identifiers

It seems that the database for these identifiers aren't maintained anymore. It's definitely possible that future joysticks will report the generic value above.