Please do not post a support request without first reading and following the advice in https://retropie.org.uk/forum/topic/3/read-this-first

Is fluid controller priority possible?



  • Hello, I'm working on a bartop arcade build and I need some help with the configuration. I've been struggling to get my controller priority to work as I want it too. I'm on RetroPie 4.4 and I'm using two Zero Delay USB encoders (DragonRise) which are used for two built-in arcade controllers. I also have a PS4 and Xbox One controller that I plug in with USB if I need them, so those aren't always plugged in. I would prefer being able to plug in any old USB controller, but if need be I can restrict it to just these two. All the controllers are tested and work fine. The assignment to players however, has been an issue for me.

    This is the situation I want to achieve:

    • If no USB controllers are plugged in, the two built-in arcade controllers should be player 1 and 2 by default
    • If I do plug in one or two USB controllers, I want those controllers to take priority over the arcade sticks for all console games
    • Arcade games (MAME/FBA) should be the only exception to this rule with the arcade sticks taking player 1 and 2 by default and any other connected USB controllers taking player 3 and 4 if applicable.

    I currently have my arcade sticks plugged into port 2 and 3 on the Pi itself, the USB controllers go into port 0 and 1. This order achieves the situation I want for console games without any further configuration because it's the default USB port assignment (0-1-2-3), but getting the reverse effect on arcade games has been an issue. I've tried to achieve this using the joystick-selection package by setting player 1 and 2 to the arcade sticks for the arcade systems and leaving the other two players UNSET. This is fine for two player games, but in four-player games the arcade sticks will control two players at the same time (1 and 3, 2 and 4 respectively). I'm pretty sure this is due to joystick-selection/retroarch taking the default port if anything in the order is left UNSET. Which would result in assigning USB port 2 to both player 1 and 3, and USB port 3 to player 2 and 4.

    Assigning all four by name through joystick-selection would solve the issue (EDIT: it doesn't, actually), but that means that I can't use other USB controllers and that I would also have to pay attention to the order I use them in. Three player games would always require the USB controller I assigned to spot three for example. I'll admit it's a luxury problem, but I would prefer being able to use any generic USB controller. Being limited to the PS4 and Xbox ones is also fine, but in that case, I would love to be able to plug in either one of them and use it as player 3. At the moment I would have to assign specifically either of the PS4 or Xbox controller to player 3 and go into the configs if I want to use the other one for player 3.

    Is there a way to apply static port assignment instead of naming based or index based assignment? I currently have to use the name assignment from joystick-selection due to the controller index changing if I unplug USB controllers, but if I could directly assign players a static USB port number from the Pi none of this would be a problem. Of course, this would still have to be possible on a per system basis since console games are fine with the default 0-1-2-3 port assignment and only arcade games would use 2-3-0-1 assignment.

    Sorry if this is vague.

    Pi Model: 3B+
    RetroPie Version Used: 4.4
    Built From: Pre-made official SD Image

    EDIT:
    Ended up editing the joystick-selection package script to achieve the behaviour I want. I had zero experience with shell scripts when I started and it shows. I won't be providing any support or troubleshooting. If you decide to use it you'll be on your own. I mean, I'll probably answer questions and try to help, but I can't promise that it won't screw up your entire setup. It's a shoddy solution at best, but I've done a lot of searching for a solution to this issue and I can imagine someone else would like one as well. Honestly, it doesn't do that much. So it really shouldn't be dangerous, but I'm just covering my ass. I've only edited one function, the js_to_retroarchcfg function, and added the elementIn function. The rest is all from the original script by meleu, so all props go to him.

    My edits change the behaviour of what unset means. Instead of defaulting to the usual USB ports, it'll now actually go out of its way to assign a unique controller to each player that is left unset in the joystick-selection. It does that by first applying any static naming based assignments you might've set and afterwards assigns any unused controller indexes to players that have been left unset. So it ends up being a mixture of your preset name assignments and automatic index assignments. This achieves the following:

    • It'll still apply port priority to anything left UNSET. So if you leave everything unset in joystick-selection, it will still default to the standard order (USB ports 0-1-2-3).
    • There should be zero situations where controllers are assigned twice due to defaults
    • It also allows for very easy swapping of controllers. UNSET is now filled automatically and doesn't just assume that player 3 uses USB slot 2 for example. So if you want to have a couple of static, name assigned, controllers and a couple of slots that you use situationally, that should work without any manual config. For example, if I only statically assign my PS4 controller (let's assume it's in USB slot 2) to player 1 and leave all other players UNSET, you'll get this controller assignment: 2-0-1-3. In the old situation with defaults it would've been 2-1-2-3 if you have four controllers plugged in.
    • It'll actually always assign four controllers, even if they're not plugged in. Which means you can totally plug-in any controller you want mid-game and it should work just fine.

    It'll stop working at anything past four controllers, but joystick-selection also doesn't support more than four. I haven't tested it extensively, but it seems to be doing everything I hoped it would. Also, you need to have the named assignment option on in joystick-selection for this to work.

    The location of the file on your Raspberry Pi should be /opt/retropie/supplementary/joystick-selection/jsfuncs.sh
    You can either edit the file manually and add the changes, or replace the entire file with this pastebin content.

    And here's just the two added/edited functions:

    function elementIn () {
      local e match="$1"
      shift
      for e; do [[ "$e" == "$match" ]] && return 0; done
      return 1
    }
    
    ###############################################################################
    # Make the retroarch.cfg configs match the joystick-selection.cfg. Only works
    # if the BYNAME is on. Makes sure Retroarch won't default to a joystick already in use.
    # Assigns controllers to UNSET spots based on port order and availability.
    # Needs the system as an argument.
    #
    # Globals:
    #   None
    #
    # Arguments:
    #   $1  the system to configure
    #
    # Returns:
    #   1   if BYNAME is off
    #   0   otherwise
    function js_to_retroarchcfg() {
        [[ "$BYNAME" != "ON" ]] && return 1
        [[ "$1" ]] && [[ -d "$configdir/$1" ]] || fatalError "js_to_retroarchcfg: the argument must be a valid system!"
    
        local jscfg="$configdir/$1/joystick-selection.cfg"
        local retroarchcfg="$configdir/$1/retroarch.cfg"
    
        [[ -f "$jscfg" ]] || return 1
    
        fill_jslist_file
    
        local js_index
    	declare -a used_controller_indices
    	declare -a unset_player_indices
    	
        for i in 1 2 3 4; do
            iniGet "input_player${i}_joypad_index" "$jscfg"
            js_index=$(js_name2index "$ini_value")
    
            if [[ -z "$js_index" ]]; then            
    			unset_player_indices+=("$i")
            else
                iniSet "input_player${i}_joypad_index" "$js_index" "$retroarchcfg"
    			used_controller_indices+=("$js_index")
            fi
        done
    	
    	#all of the below is a pretty ugly solution, but I'm garbage at shell scripts so...	
    	for unset_player_index in ${unset_player_indices[@]}; do
    		for i in 0 1 2 3; do		
    			if ! elementIn $i "${used_controller_indices[@]}" ; then
    				iniSet "input_player${unset_player_index}_joypad_index" "$i" "$retroarchcfg"
    				used_controller_indices+=("$i")	
    				break
    			elif [[ "$i" -eq 3 ]] ; then
    					iniSet "input_player${unset_player_index}_joypad_index" "16" "$retroarchcfg" #disable the player if there are no remaining controllers, this is probably not actually needed
    			fi
    		done		
    	done
    }
    

  • Global Moderator

    The joystick-selection script created by @meleu is usually the right tool for such joystick re-ordering, but your desired configuration needs a bit more than that - a way to detect if a new gamepad (besides the built-in ones) is plugged in and adding it to the top of the priority list when that happens.

    One think that you can use right now is to trigger the Runcommand launch menu and choose your joystick order from there, before starting the game. It's tedious, but would be useful to override the default configuration in case you plug in a new controller for console systems.



  • I really hope someone finds a way to make it possible for retropie recognize different controllers being plugged in at different times


  • Global Moderator

    @simpleethat What do you mean ? This is already supported - the topic here is about configuring the order in which they are distributed to players.



  • Thanks for the suggestion, but I'm afraid I'm way too lazy to manually adjust it like that all the time. I've actually decided to edit the joystick-selection script to make it work as I want it too. It's a shoddy solution at best and I won't be providing any support or troubleshooting for it, but I'll post it anyway just in case someone wants it. EDIT: It's at the end of my original post.



  • Pi Model or other hardware: 3 B+
    RetroPie Version Used (eg 3.6, 3.8.1, 4.1 - do not write latest): 4.4.1
    Built From: Pre-made SD Image on RetroPie website
    USB Devices connected: Dashtop Joystick Set X2 (https://www.amazon.com/gp/product/B01J33VPGC/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1)...and 8bitdo SN30 Pro Bluetooth Controllers X2
    Controller used: Dashtop Joysticks/buttons and SN30 Pro
    Guide used: meleu's Retropie-Joystick-Selection (https://github.com/meleu/RetroPie-joystick-selection)

    I have a similar setup where I have two Joystick/button sets and two 8bitdo SN30 Pro Bluetooth controllers. What I really want is for the two SN30 Pro controllers to be assigned to Player #1 and #2 if they're on and if they're off to default the Joysticks/buttons to Player #1 and #2.

    I've been testing and troubleshooting my configuration for weeks now and am frustrated that I can't seem to find a solution. Ideally, my controllers would be assigned to the appropriate player without any interaction with the system, but I've resigned myself to the fact that this is not possible (at least my hours of research, testing and troubleshooting haven't yielded a solution).

    I've followed the install instructions for the Retropie-Controller-Selection tool on a clean build of Retropie thinking that I could just manually set Player #1 and #2 whenever needed, but even when running the tool I don't get the behavior that I'd expect (my changes in the tool don't seem to have any effect on which device is assigned to Player #1 and #2...at least not consistently allowing me to swap the controllers assigned Player #1 and #2). I've tried and retried this process from scratch a number of times and can't seem to nail down a consistent behavior. Am I running into issues because my SN30 Pro controllers are Bluetooth?

    I tried the solution that worked for @RauTheLegendary but I get the same results.

    At this point, I'm at my wit's end and am reaching out to this fantastic community for support, encouragement and any ideas on how to troubleshoot or address my challenge. I can't help but think with all of the DIY cabinet-makers out there that someone wants the behavior I'm looking for.



  • @RauTheLegendary said in Is fluid controller priority possible?:

    If I do plug in one or two USB controllers, I want those controllers to take priority over the arcade sticks for all console games

    iirc this part is possible by tweaking udev rules, but udev is unaware of the emulator you'll run so exceptions won't work.



  • @Mondo-Gecko

    I've never tried using Bluetooth controllers, but I'll give it a shot and check what happens. I don't have access to my Raspberry Pi until at least the end of next week though.



Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.