libretro / RetroArch

Cross-platform, sophisticated frontend for the libretro API. Licensed GPLv3.
http://www.libretro.com
GNU General Public License v3.0
10.13k stars 1.82k forks source link

[xinput driver] binds not applied to correct controller port #12436

Open seanstardev opened 3 years ago

seanstardev commented 3 years ago

The following input issues occur regardless of the core selected, and have persisted for at least the last 2 weeks (may be much longer).

I have been testing how RA handles up to 4 players (all wireless gamepads). Note that I use two DS4 controllers and emulate them as XBox 360 gamepads via DS4Windows. The other 2 controllers are XBox One gamepads. I am quite confident that the emulated gamepads are not casuing problems here, as I often see RA get muddled and swap controllers when I just test with my two XBox One gamepads.

Description

RA gets very confused about attached XInput devices when the Input Driver is set to XInput and multiple gamepads are attached (only tested with all wireless gamepads). I have been testing this extensively in recent weeks and will happily elaborate and perform further testing.

360 gamepads often get confused for XBox One gamepads. i.e. When one looks at the 'Port X Controls' screen, the Device Index may state that a player is assigned to a 360 pad, but by attempting to bind buttons, one realises that player is in fact assigned to an XBox One controller. The opposite can happen just as frequently.

Sometimes, a gamepad that is marked as the first instance (e.g. "Controller (XBOX 360 for Windows)(#1)") in RA is fact the #2 gamepad, and vicaversa.

In other words: RA seems to toss a coin each time it tries to assign a gamepad to a user, such is the randomness.

Expected behavior

Two things:

  1. I certainly do not expect the XBox One and XBox 360 devices to get mixed up, but this happens more often than not and is not just a superficial / visual error. I will often go into, say, 'Port 2 Controls' and see that 'Device Index' is set as an XBox 360 controller. But - when I try to bind the controls to verify this - I notice that it is in fact bound to an XBox One gamepad, or even the other 360 gamepad. There is no rhyme or reason to how these devices are polled, and they are consistently muddled up.

  2. I would expect the devices to be mapped in either DInput order (the order they appear in the Windows' 'Game Controllers' tool (joy.cpl), or by XInput UserIndex order. As one scrolls through the 'Device Index' in a 'Port X Controls' screen, they do indeed appear to be in DInput order, but gamepads are very quickly shown to be in an unexpected order as soon as one starts binding individual buttons.

Actual behavior

360 gamepads often get confused for XBox One gamepads.

Sometimes, a gamepad that is marked as the first instance (e.g. "Controller (XBOX 360 for Windows)(#1)") in RA is fact the #2 gamepad, and vicaversa.

The assignment of XInput devices to players literally seems random.

Steps to reproduce the bug

From a 'cold start' (i.e. all gamepads should be switched off and Retroarch not started), do the following:

  1. Connect 2x XBox One gamepads wirelessly, and 2x DS4 gamepads wirelessly (via DS4Windows). (Obvioulsy - doesn't have to be this exact combination, but multiple XInput gamepads are needed).
  2. Launch a 4 player game (say, Mario Kart 64 on Mupen64 plus core).
  3. Go into Settings > Input > and look through the 'Port X Controls' for each player.

More often than not, at least 2 of the controllers will be muddled up (a 360 might appear as an XBox One, or the gamepad you'd expect to be player #1 is in fact player #2 etc). This can be shown to be the case by trying to bind keys for each of the 4 players: you will often find that keys from the expected gamepad are not registered, and that another controller is in fact being detected.

You can repeat the above steps multiple times, and if the gamepads get added by Windows in a slightly different order (as can easily happen with DInput) as they are switched on, the result when binding keys in RA will show different gamepad mapping once again.

Bisect Results

I have tried all sorts trying to figure out how gamepads are assigned in RA when the XInput driver is selected. I have been able to rule out:

  1. DInput ordering (the order gamepads appear in the Windows 'Game Controllers' tool).
  2. XInput UserIndex ordering.
  3. Raw Input / HID ordering.
  4. Any form of alphabetical ordering, be that by HID device path name (e.g. "\\?\hid#vid_045e&pid_028e&ig...'') or pid + vid combinations, etc.

Thanks for reading. I'm keen to get to the bottom of this. My hope is to reach a stage where I can be sure how gamepads will be assigned to players and write scripts to automatically set the configuration files for 'input_player1_joypad_index' through to 'input_player4_joypad_index'.

Version/Commit

RA 1.9.3 stable. All cores tested were updated in last 24 hours.

Environment information

Windows 10, x64.

markwkidd commented 3 years ago

@midget35 thank you for the detailed report. Could you update your installation to the most recent nightly build and confirm that the problem still exists?

There have been a several changes to how input is mapped since your last test. I don't expect them to have fixed your bug, but it's important to try with the latest code before going farther.

If you still have this problem with the latest nightly build, I will try to help figure out the source of the bug.

I would also like to suggest that you update the title of this issue to something more precise, for example instead of RetroArch - XInput driver. Major multiplayer confusion perhaps a title like [xinput driver] binds not applied to correct controller port

I make this suggestion only in the hopes of attracting more coders familiar with this part of the RA codebase.

seanstardev commented 3 years ago

Hey @markwkidd. Thank you for reaching out. I have updated to most recent nightly and tested with 2x XBox One and 2x DS4 gamepads.

As best I can tell - the problem has been fixed (caveat to follow). I have set the 'input_joypad_driver' to be 'xinput' in the ini... RA's Driver UI screen tells me the 'Controller' driver is 'xinput'...

... and every combination of XInput devices I have tried (altering players 1-4 by manually setting their device index in the ini) has resulted in the correct player being assigned the correct gamepad on every occassion.

However - the one way I could TELL which input driver was set in the past (be that XInput or DInput) was by testing DualShock compatible games with the psx mednafen core. Rumble would only work when the controller driver was set to XInput. And to my shagrin, I notice through my testing just now that there is no rumble.

So... I guess one of the following is happening:

  1. Though RA tells be the controller driver is XInput, it is actually still DInput.
  2. The Input changes made to recent nightlies has fixed controller port assignment, but broken rumble support (at least in psx core).
  3. Or, by complete coincidence, the psx core rumble support was accidentally broken in a very recent core update, and the input fixes we're discussing here are actually working perfectly.

I hope this feedback helps. I am very happy to continue testing. Thank you again for your time!

seanstardev commented 3 years ago

I just tested again with the same setup and the rumble works but the controller assignment is all over the place, much as in my first bug report.

I really can't get my head around it... I'm pretty sure RA was lying to me when it said the Controller Driver was set to XInput last time. I was very, very careful to make sure I checked that before filling out my last report. Crazy.

markwkidd commented 3 years ago

No problem. I was about to suggest that you generate and post some logs, which is still a good idea.

Here are some instructions on how to get logs: https://docs.libretro.com/guides/generating-retroarch-logs/

seanstardev commented 3 years ago

retroarch.log

Log attached. Behaviour is as per my first post after testing today. Many thanks!

ghost commented 3 years ago

@midget35 are your xbone controllers bluetooth or the older wireless dongle? I have a 360 wireless and an xbone older wireless can test but dont have any windows enviroment to build on. I use the older xbone wireless dongle in linux since someone made a driver for it.

seanstardev commented 3 years ago

@midget35 are your xbone controllers bluetooth or the older wireless dongle? I have a 360 wireless and an xbone older wireless can test but dont have any windows enviroment to build on. I use the older xbone wireless dongle in linux since someone made a driver for it.

This is the dongle I use for both gamepads: https://www.amazon.co.uk/gp/product/B01691M0QA/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1