protonscr

Virtualize controllers to retrofit hotplug into games that don't support it

steamopen Feature RequestGeneral controller / Steam Input
ValveSoftware/steam-for-linux#7929 · opened 2021-07-15 by jmgao · updated 2021-07-20 · 2 comments · github
1 matching comments, n / p to jump
Jjmgao 2021-07-15 github

Feature Request

I confirm:

  • [X] that I haven't found another request for this feature.
  • [X] that I have checked whether there are updates for my system available that
    contain this feature already.

Description

There's been some drama in the fighting game community recently because Guilty Gear Strive's implementation has multiple frames of additional input latency on PS4 compared to PC, but no one wants to run tournaments on PC because of expense and device nonuniformity. I was excited to see this picture on the website for the Steam Deck, as it seems to be perfect for local tournaments/casual meetups.

Unfortunately, many fighting games don't actually implement controller hotplugging, and only look at the devices that are connected on initial startup, which would make it almost unusable for those games.

My best guess at the reason for this is a combination of the following:

  • they need to use DirectInput for non-Xinput controller support (since the fighting game community is almost entirely on PS4 right now)
  • DirectInput is not sufficient for Xinput controllers (left trigger and right trigger are represented on the same axis)
  • the documentation for disambiguating DirectInput devices from Xinput devices appears to be some sort of malicious joke (specifically, the fact that there appears to be no way to tell which Xinput controller a DirectInput device corresponds to)
  • DirectInput doesn't even give you events for device connections, you apparently have to just poll all of the devices in response to a generic device connection notification (and polling can be insanely slow, and blocks some (all?) other simultaneous DirectInput calls, so you can't even punt it off to a background thread: you have to actually think about when you can afford have your input thread hang for a few hundred milliseconds to scan for devices)
    • the solution for this is to use RawInput, except that means you now have to parse the USB HID report yourself!

To fix this on Windows, I wrote a set of wrapper DLLs for dinput/xinput.dll that retrofits hotplugging into games that didn't implement it by showing a fixed number of virtual controllers that real devices get their inputs mapped on top of. I think a similar approach would be pretty useful for Proton.

Justification

AIUI, the input system in Proton is already a downstream fork, so nothing would change there.

Risks

Pretty much the entirety of my understanding of the architecture of the input system comes from the ASCII art in this doc. I'm assuming that the thing that's actually fetching inputs via SDL is not in the wine process, since I don't think you can open and read from a hidraw device multiple times and get reasonable behavior, and the wine process hanging probably shouldn't break long pressing home to kill wine, but I might be completely misunderstanding how things work. If there isn't one centralized input handler process, then this probably needs some more thought.

Ideally, there'd be a way to remap which controllers are connected to which virtual controller (akin to "Switch User" on the PS4). (In my implementation, I chose to just populate the lowest number virtual devices with whatever came in and leave them there forever, because all of the games I use it for allow all of the controllers to handle menu inputs, and even if they didn't, the common use case is that any time a controller leaves, it's because it's about to be replaced by a new one shortly).

Some games will likely be confused by a bunch of idle controllers being connected (I don't recall the game in particular, but I've definitely had issues where a PS4 controller being connected made it so that I couldn't actually play a game with keyboard and mouse), so this needs to be configurable (just at startup, or dynamically?) and possibly with quirks to disable it on games known to be broken with it?

You might have thought of this, and this might already be done? :-)

YYellowOnion 2021-07-18 github

Issue here might be worth mentioning https://github.com/ValveSoftware/steam-for-linux/issues/7746 note the included emulator script written in python ;-)

Aaeikum 2021-07-20 github

This is outside the scope of Proton, I think, as you could want this for native games as well. The Steam client could implement this as part of its SteamInput stuff, and then Proton would benefit like any other native game would.

Proton versions

Upstream links

DLLs