mrchrisster / MiSTer_SAM

154 stars 22 forks source link

Update joypad detection with dpad and specific buttons #210

Closed wizzomafizzo closed 2 years ago

wizzomafizzo commented 2 years ago

This new version of the joy detect script includes joysticks and dpads in detection. It also has optional support for detecting individual buttons. It should be a drop in replacement for the current script.

As discussed, I don't believe it will ever be possible to use mister's existing mapping files, since it uses evdev codes and these devices are always busy when you want to use them. I'm proposing an alternative solution to manually maintain a map of common controllers' buttons to their js device event codes instead. I've included a working example of it for the PS4 controller. This method of detection won't ever be perfect, but I think it will work well enough for most users.

Paradox commented 2 years ago

So, this checks all controllers, instead of just watching a single controller, passed to it, as was done, previously? and, I see you hardcoded the activity file, instead of taking it as a commandline argument. Also, it seems controller dependent, are we going to need to add a declaration in controllers for each device anyone could ever use? Are they just special cases?

mrchrisster commented 2 years ago

It works the same way as before. The activity file was hardcoded before as well and it only checks one joystick at a time. It detects all button pushes now (including dpad) but start button is mapped differently for every controller hence the option to map the start button. The idea is that a user can push start to play the current game or any other button to exit SAM. Unfortunately it doesn't look promising to get the button layout through a map file so we would have to add controllers to it manually.

wizzomafizzo commented 2 years ago

I see you hardcoded the activity file, instead of taking it as a commandline argument.

It was also hard coded in the previous script but it could certainly be an argument instead.

Also, it seems controller dependent, are we going to need to add a declaration in controllers for each device anyone could ever use? Are they just special cases?

To cover everything, yes, but this is meant more as a compromise. My assumption is that yeah technically there's a million controllers out there, but I think most people only use a small subset of those, so it would still be valuable hardcoded

If it turns out there's a direct correlation between a joystick file number and an evdev file number it could be changed to use mapping files after all. But I only have 2 controllers so I couldn't say for sure

wizzomafizzo commented 2 years ago

Possible workaround, the scripts runs two threads: one is scanning for activity on /dev/input/jsX like it does currently and that is responsible for interpreting inputs, another thread is monitoring the /dev/input/eventX device and waiting for a moment that the mister binary gives up control and allows us to use it, which we know happens for a second duing core changes.

When we can get control, query the event device for a list of all capabilities/keycodes for the controller. Store them in a database. Use that data to interpret the mister mapping file and associate it with the value output from the jsX device.

After that, we should have reliable and complete knowledge of what buttons are pressed for any controller. Without any manual config.

Paradox commented 2 years ago

I see you hardcoded the activity file, instead of taking it as a commandline argument.

It was also hard coded in the previous script but it could certainly be an argument instead.

I guess this is something that never got backported to main, but, I made this change in named-pipes, because it's using a named pipe, instead of just a normal file, and, because we changed the name of that file, and, for a while, couldn't figure out why keypresses were being ignored..., but, no big deal, it can be changed for named-pipes, easily enough.

Paradox commented 2 years ago

ok, I've tried to adapt this for named-pipes, and, I don't know if I did something wrong, or, if I just don't have a joystick that is detected, but, all activity on all of my controllers seem to be ignored. I don't currently have a ps4 or ps5 controller connected, and, I haven't tried any of my xbox controllers, yet. SuperAttract_joy.txt

Paradox commented 2 years ago

SuperAttract_joy.txt

Updated to set DEBUG based on the setting samdebug, and still get nothing.

wizzomafizzo commented 2 years ago

I can't test myself until tomorrow. The DEBUG = sys.argv[3] line won't ever evaluate to false unless the arg is omitted and it hits the except, you'd need to do something like 'DEBUG = sys.argv[3] == "True"' but that wouldn't be affecting what's happening for you.

If you can do "cat /dev/input/js0" and get any output then your controller will work with this. The same way the old script worked. You could try get rid of all the if DEBUG clauses before the print statements and make it print debug output regardless.

Paradox commented 2 years ago

SuperAttract_joy.txt

I fixed it, you were exiting on any number of arguments other than 2

I also got it working, somewhat, MCP still isn't resetting the counter or stopping SAM, but, what I need to know is, can we filter out the actual press and only detect the release? so it doesn't fire twice? This can cause issues with named pipes, as they block until the file is read, and, it would also cause the activity to be detected twice, which can cause issues.

Edit:

Or, even just catch press and ignore any further events from that same button/axis for a period of time.

Edit2:

Our future plans are to use the specific button press to choose what option needs to happen, so, if the activity could be Button 0 pressed, etc. we can use that in MCP to determine whether to reset the counter, play the current game (without it needing to be set in the ini ahead of time) or, just exit SAM, like normal, etc. maybe even add some other actions we haven't thought of, yet.

Edit3:

We were just discussing it, and, it would be nice to ignore second events from the same button, but, also either catch a combo of buttons, or, press button 1 and then button 2 combine them in the activity, and then we could use that for functions you don't want to happen, accidentally, such as exiting the entire script (stop)

Paradox commented 2 years ago

https://github.com/mrchrisster/MiSTer_SAM/tree/named-pipes-joy

here's the current code I have feel free to submit PRs for it, if you can do any of the above.

Paradox commented 2 years ago

well, I figured out why it wasn't reacting to button presses... no newline (\n) being written to the pipe, so, that now works, but, as I said, before, it's sending both press and release, so, it gets detected twice for one press.

Paradox commented 2 years ago

I've merged it to the named-pipes branch, now that it works at least as well as the old method (a bit better now that dpad/axis can be detected) but, we still need to get rid of the second detection, and see if we can implement the other features I mentioned.

Of greatest importance, after the dual detection, is sending which button/dpad/axis was pressed, so we can add an option to ignore dpad/axis (at least, when a game is running) for anyone who used that "feature" and wants it back, I know, when I'm testing, it's nice to open the OSD and look through some of the settings, without ending the game.

Paradox commented 2 years ago

It might also be nice to adapt this to keyboard if possible so we can detect the keys there as well and react on certain key presses

Paradox commented 2 years ago

@wizzomafizzo I've been waiting to hear from you, have you been working on this, at all? I've been looking through the code, and, I have some ideas on how to do what i want, and one thing I have noticed, is, on all of my controllers 8 is select, 9 is start, buttons 0-4 are the face buttons (one controller has them laid out a bit different from the rest, but, not a big deal) etc. so, I think we could go ahead and implement the generic controller layout and assign actions to start, select, the 4 main face buttons, at the very least, and have enough buttons available to implement using start to start playing the current game, select to skip to a new core, and, for now, each of the 4 face buttons could exit SAM, the axis inputs could be ignored by SAM, but, MCP would still reset the timer We have absolutely no reason to use MiSTer input files, at all.. Of course, your idea about having some sort of configuration mode that would write a config file to implement special controllers, or, alternate button layouts, would be nice.

[054c_05c4]
name="Sony DualShock 4"
buttons=(
    [start]=9
    [select]=8
    [button_0]=0
    [button_1]=1
    [button_2]=2
    [button_3]=3
    [button_4]=4
)
axis=()

etc.
wizzomafizzo commented 2 years ago

@Paradox I have not been working on anything. My job has ramped up again and I'm going to be pretty short on free time for a while. That's good news the start button appears to be consistent across common controllers, it will save on a lot of work. I'm on discord if you'd like to discuss further

I like the ideas but it's not an insignificant amount of effort and requires some design before implementation is possible

Paradox commented 2 years ago

No worries, I understand how it is.

I was thinking of the keyboard support as a separate script, as it is, now, but, if we could combine the three scripts to one script, and keep the functionality, I'd be fine with that.