Guide: Advanced Controller Mappings
-
@spud11
Sorry it's taken me a while to get back to you, but I knew I was going to have to re-familiarize myself with a few things first. To tell you the truth, your current working arrangement is one I've settled on myself for a few tricky situations like this and there aren't a lot of alternatives. However, your key-cycle suggestion might just work to consolidate the commands to one button, albeit with two button presses. The cycle would look something like:--ui-buttonmap back+rt=cycle-key:KEY_ESC:KEY_LEFTCTRL+KEY_LEFTSHIFT+KEY_LEFTALT+KEY_Q
Just like what you've tried already, it's possible that combinations can't be used in the cycle, but if it works, you should be able to press the button once for 'Escape' and again for 'CTRL+Shift+Q'.
-
@mediamogul Thanks, mediamogul, for taking the time. I can confirm that that worked - by pressing twice you get the Escape key followed by Shift-Ctrl-Alt Q.
One other possibility I was thinking of but not sure whether it's actually possible: bind another key eg the 'A' key to Shift-Ctrl-Alt Q, then in a macro have:
send KEY_ESC 1 wait 100 send KEY_A 1
(Something I regularly do using Autohotkey on Windows 7.)
-
@spud11 said in Guide: Advanced Controller Mappings:
One other possibility I was thinking...
I'm almost certain xboxdrv can't bind keyboard keys with other keys/key combinations, but if you could find an outside solution to handle that part, it should work well.
-
Something that's always bothered me about launching xboxdrv using
runcommand-onstart.sh
is that it makes using the Runcommand menu itself somewhat impossible. This is because the xboxdrv mapping is made active before the Runcommand menu appears, therefore interfering with the expected control scheme. Over the weekend, I've been experimenting with some ways around this.First, I tried scripting the xboxdrv command not to launch until it detected that the intended emulator/port had launched. This worked well, except the script needed the specific executable name for the software it was looking for, making everything a little more laborous to set up than I felt it needed to be. I was prepared to live with it, until I noticed that AdvanceMame refused to recognized an xboxdrv simulated mouse event unless it was present before it launched. Seeing as how I play many games that rely on analog controls, it was important enough for me to rethink the approach.
What I needed was something that could be discovered from the
runcommand-onstart.sh
script that signals the launch of the Runcommand menu, yet yet also signals it's closing before the emulator/port software is launched. After taking a look at/opt/retropie/supplementary/runcommand/runcommand.sh
, it looked as though it invoked and exitedjoy2key.py
in exactly the way I needed. With a little more experimenting, I came up with the following that uses the xboxdrv example from the first section of my guide.if [ "$2" = "advmame" ]; then sudo killall > /dev/null 2>&1 xboxdrv j2kpid="0" until [ "$j2kpid" -gt "0" ]; do j2kpid=$(pgrep -f joy2key.py) sleep 1 done while s=$(ps -p "$j2kpid" -o s=) && [ "$s" ] && [ "$s" != 'Z' ]; do sleep 1 done /opt/retropie/supplementary/xboxdrv/bin/xboxdrv > /dev/null 2>&1 \ --evdev /dev/input/by-id/[•] \ --silent \ --detach-kernel-driver \ --force-feedback \ --deadzone-trigger 15% \ --deadzone 4000 \ --mimic-xpad \ --evdev-absmap ABS_[•]=x1,ABS_[•]=y1,ABS_[•]=x2,ABS_[•]=y2,ABS_[•]=lt,ABS_[•]=rt,ABS_[•]=dpad_x,ABS_[•]=dpad_y \ --evdev-keymap BTN_[•]=a,BTN_[•]=b,BTN_[•]=x,BTN_[•]=y,BTN_[•]=lb,BTN_[•]=rb,BTN_[•]=tl,BTN_[•]=tr,BTN_[•]=guide,BTN_[•]=back,BTN_[•]=start fi &
This waits for
joy2key.py
to launch, gets it's PID and then waits for it to end before launching whatever emulator/port is being launched (advmame in this example). So, in effect, you can now launch a game, use the Runcommand window as intended if needed and xboxdrv will launch afterwards.I've talked with so many people about xboxdrv on here that, unfortunately, a lot of it runs together. However, I do remember a few interested parties looking for a way to accomplish this, so I hope it helps. Granted there might be an easier, more effective way, so if anything comes to mind, please feel free to share.
-
I'm very stoked to say that I finally got the
exec:
argument to work in xboxdrv. This opens up a world of possibilities, as it allows any bash script to run at the press of a button, or button combo.It's important that the script reside somewhere on the SD card Linux volume and at least have the common 755 user permissions. Also, since xboxdrv is normally running as root, it's a probably a good idea to preface any of the commands in the script with
sudo --user=pi
.Below is an example that takes a screenshot using
raspi2png
by pressing 'Select' (Back) and the 'Y' button. This could be added to compliment any emulator, port, or system app that normally doesn't have a screenshot function.Additional line to any xboxdrv command:
--ui-buttonmap back+y=exec:/home/pi/raspi2png.sh
raspi2png.sh
(The script that is called above)#!/bin/bash DATE=$(date +%Y%m%d%H%M%S) sudo --user=pi raspi2png -p "/home/pi/""$DATE"".png"
This creates screenshot in the home directory named using the current time. The timestamp naming allows each image to have a unique name, preventing them from overwriting each other.
This is just one example and the ability to run scripts from within any environment from the controller opens up a ton of possibilities. It was too involved to use as an example, but I was able to duplicate the multiple save state functionality found in RetroArch from within AdvanceMAME. Keen stuff!
-
@mediamogul That is very useful information indeed. It makes the whole runcommand scenario so much more flexible. No need to reserve
runcommand-onstart
purely for xboxdrv any longer. -
Another nice use case that I'm really liking is invoking a script that kills the current map and launches another. This is particularly useful for having a universal map for a game system that can switch on the fly between digital, analog and four-way restricted controls.
-
@mediamogul That's interesting. When and for what emulator do you use this? Could you please show an example?
-
@spud11 said in Guide: Advanced Controller Mappings:
When and for what emulator do you use this?
Almost any emulator could benefit from it, as a surprising amount of retro games play so much more smoothly with 4-way restricted controls, so the ability to toggle it on and off through the use of multiple maps is a great advantage. One unfortunate exception is AdvanceMAME, due to it only recognizing input that was available at launch. Amiberry has this same requirement, so it's out as well, but everything else I've tried so far works very well.
Could you please show an example?
Sure. Below is my Atari 2600 map for Stella that now has the following features combined.
- 8-way digital directional control (Dpad/Left Thumb)
- 4-way digital directional control (Dpad/Left Thumb)
- Full analog directional control (Left Thumb with Modifier Toggle)
- Full Atari Keypad control (Right Thumb with Modifier buttons)
- Atari BoosterGrip control ('X' and 'A' buttons)
- One button cycled difficulty switch for two players ('LB' and 'RB')
- Stella user interface Control ('RT' Modifier)
default.sh
Initial launch map:#!/bin/bash sudo killall xboxdrv sleep 1 sudo /opt/retropie/supplementary/xboxdrv/bin/xboxdrv \ --evdev /dev/input/by-path/platform-3f980000.usb-usb-0:1.2:1.0-event-joystick \ --detach-kernel-driver \ --force-feedback \ --dpad-as-button \ --trigger-as-button \ --deadzone-trigger 15% \ --deadzone 4000 \ --device-name "Logitech Rumblepad 2 (xboxdrv)" \ --silent \ --axismap -Y1=Y1,-Y2=Y2 \ --buttonmap tl^toggle=tl \ --buttonmap tr^toggle=tr \ --evdev-absmap ABS_X=x1,ABS_Y=y1,ABS_Z=x2,ABS_RZ=y2,ABS_HAT0X=dpad_x,ABS_HAT0Y=dpad_y \ --evdev-keymap BTN_THUMB2=a,BTN_THUMB=b,BTN_TOP=x,BTN_TRIGGER=y,BTN_BASE3=back,BTN_BASE4=start,BTN_TOP2=lb,BTN_PINKIE=rb,BTN_BASE5=tl,BTN_BASE6=tr,BTN_BASE=lt,BTN_BASE2=rt \ --ui-axismap X1=KEY_LEFT:KEY_RIGHT,Y1=KEY_UP:KEY_DOWN \ --ui-axismap X2=KEY_1:KEY_2,Y2=KEY_3:KEY_Q,lt+X2=KEY_W:KEY_E,lt+Y2=KEY_A:KEY_S,rt+X2=KEY_D:KEY_X,rt+Y2=KEY_Z:KEY_C \ --ui-buttonmap a=KEY_LEFTBRACE,b=KEY_B,x=KEY_RIGHTBRACE,y=KEY_Y,lt=KEY_UNKNOWN,rt=KEY_UNKNOWN,tl=KEY_UNKNOWN,tr=KEY_UNKNOWN,du=KEY_UP,dd=KEY_DOWN,dl=KEY_LEFT,dr=KEY_RIGHT,start=KEY_T,back^delay:325=KEY_U \ --ui-buttonmap lb=cycle-key:KEY_GRAVE:KEY_R,rb=cycle-key:KEY_5:KEY_6 \ --ui-axismap tl+x1=REL_X:15,tl+y1=REL_Y:15 \ --ui-buttonmap tr+b=BTN_LEFT,tr+a=BTN_RIGHT \ --ui-buttonmap back+start=KEY_ESC,back+x=KEY_TAB,back+lb=KEY_F11,back+rb=KEY_F9,back+dr=KEY_F10,back+b=KEY_LEFTCTRL+KEY_R,back+a=KEY_PAUSE \ --ui-buttonmap back+y=exec:/opt/retropie/configs/all/xboxdrv/script-functions/shared/raspi2png.sh \ --ui-buttonmap lt+rt=exec:/opt/retropie/configs/all/xboxdrv/script-functions/emulators/stella/4waystrict.sh \ --ui-buttonmap rt+a=KEY_ENTER,rt+b=KEY_ESC,rt+du=KEY_UP,rt+dd=KEY_DOWN,rt+dl=KEY_LEFT,rt+dr=KEY_RIGHT,rt+y=KEY_LEFTSHIFT+KEY_TAB,rt+x=KEY_TAB,rt+lb=KEY_LEFTSHIFT+KEY_LEFT,rt+rb=KEY_LEFTSHIFT+KEY_RIGHT \ --ui-buttonmap guide=void \ &
4waystrict.sh
called from initial map by pressing 'LT+RT':#!/bin/bash sudo killall xboxdrv sleep 1 sudo /opt/retropie/supplementary/xboxdrv/bin/xboxdrv \ --evdev /dev/input/by-path/platform-3f980000.usb-usb-0:1.2:1.0-event-joystick \ --detach-kernel-driver \ --force-feedback \ --dpad-as-button \ --trigger-as-button \ --deadzone-trigger 15% \ --deadzone 4000 \ --device-name "Logitech Rumblepad 2 (xboxdrv)" \ --silent \ --four-way-restrictor \ --axismap -Y1=Y1,-Y2=Y2 \ --buttonmap tl^toggle=tl \ --buttonmap tr^toggle=tr \ --evdev-absmap ABS_X=x1,ABS_Y=y1,ABS_Z=x2,ABS_RZ=y2,ABS_HAT0X=dpad_x,ABS_HAT0Y=dpad_y \ --evdev-keymap BTN_THUMB2=a,BTN_THUMB=b,BTN_TOP=x,BTN_TRIGGER=y,BTN_BASE3=back,BTN_BASE4=start,BTN_TOP2=lb,BTN_PINKIE=rb,BTN_BASE5=tl,BTN_BASE6=tr,BTN_BASE=lt,BTN_BASE2=rt \ --ui-axismap X1=KEY_LEFT:KEY_RIGHT,Y1=KEY_UP:KEY_DOWN \ --ui-axismap X2=KEY_1:KEY_2,Y2=KEY_3:KEY_Q,lt+X2=KEY_W:KEY_E,lt+Y2=KEY_A:KEY_S,rt+X2=KEY_D:KEY_X,rt+Y2=KEY_Z:KEY_C \ --ui-buttonmap a=KEY_LEFTBRACE,b=KEY_B,x=KEY_RIGHTBRACE,y=KEY_Y,lt=KEY_UNKNOWN,rt=KEY_UNKNOWN,tl=KEY_UNKNOWN,tr=KEY_UNKNOWN,du=KEY_UP,dd=KEY_DOWN,dl=KEY_LEFT,dr=KEY_RIGHT,start=KEY_T,back^delay:325=KEY_U \ --ui-buttonmap lb=cycle-key:KEY_GRAVE:KEY_R,rb=cycle-key:KEY_5:KEY_6 \ --ui-axismap tl+x1=REL_X:15,tl+y1=REL_Y:15 \ --ui-buttonmap tr+b=BTN_LEFT,tr+a=BTN_RIGHT \ --ui-buttonmap back+start=KEY_ESC,back+x=KEY_TAB,back+lb=KEY_F11,back+rb=KEY_F9,back+dr=KEY_F10,back+b=KEY_LEFTCTRL+KEY_R,back+a=KEY_PAUSE \ --ui-buttonmap back+y=exec:/opt/retropie/configs/all/xboxdrv/script-functions/shared/raspi2png.sh \ --ui-buttonmap lt+rt=exec:/opt/retropie/configs/all/xboxdrv/script-functions/emulators/stella/default.sh \ --ui-buttonmap rt+a=KEY_ENTER,rt+b=KEY_ESC,rt+du=KEY_UP,rt+dd=KEY_DOWN,rt+dl=KEY_LEFT,rt+dr=KEY_RIGHT,rt+y=KEY_LEFTSHIFT+KEY_TAB,rt+x=KEY_TAB,rt+lb=KEY_LEFTSHIFT+KEY_LEFT,rt+rb=KEY_LEFTSHIFT+KEY_RIGHT \ --ui-buttonmap guide=void \ &
Notice that the default map can then be called back in 4-way restricted, completing the toggle. The only actual difference between the two maps is the addition of
--four-way-restrictor
and calling the alternate script. -
Hello, first of all, thank you very much for the work you do in this forum. I've been here a short time and there are always doubts that I can solve thanks to you. I'm new and I still have a lot to learn. I have a Rpi3 with the last versión of retropie.
I would like to ask you about a problem with a controller that I currently have. Recently I bought this keyboard:
https://www.amazon.com/dp/B077MDCSFQ/ref=twister_B07BSBJCBY?_encoding=UTF8&psc=1
As you can see, it has two buttons like LR but they are not part of the key map of the keyboard (event0), but of the mouse (event1), as well as the reproduction and volume buttons, and retropie and retroarch can't read it.
Looking for a long time I found xboxdrv and I think it is the only solution that can help me.
My goal is to be able to use the LR buttons and the playback buttons as if they were part of an xbox360 controller, and to configure the keymap of emulators SNES or PS together with the keyboard. Also maybe be able to use the touchpad as a joystick. The L and R keys of the keyboard are working like left and right click of the mouse.
I have found questions and answers about joypad as a mouse, but not the other way around. I have tried to configure following the guide but I have not managed to make it work.
I would like to get some help or experience, a way or a guide, to be able to get it. I can show you the logs or events if necesary. Thank you very much, and sorry if I can´t explain myself as well as you do, I still don't know about programming this tool. -
What you're looking to do is very unique, even for xboxdrv. Also, in my opinion, this device will never make a great controller, or at least one that will be worth the effort it'll take to make it work. However, I believe it would be possible to achieve both objectives in theory. However, I'm not completely sure they can be combined into one functional control scheme, as I've never attempted anything like this. First the touchpad as joystick. The map for such a thing would look something like:
/opt/retropie/supplementary/xboxdrv/bin/xboxdrv --evdev /dev/input/your-mouse-event-here \ --evdev-keymap BTN_LEFT=KEY_PICKONE,BTN_RIGHT=KEY_PICKONE \ --ui-axismap x1=REL_X,y1=REL_Y \ --mimic-xpad \ --silent
Make sure to map two mouse buttons to keys that don't already exist on the mini keyboard. At that point you would technically have two keyboards, but RetroArch will make use of them as if they were one. To find two keys that don't exist on the mini keyboard, type
/opt/retropie/supplementary/xboxdrv/bin/xboxdrv --help-key
into the command line and look for two that might work. After that, you'll need to of course map the keyboard keys you want to use in RetroArch, as well as create the udev rule mentioned in the guide at the end of section 3A. Finally, the joystick from the virtual controller will need to be mapped to the analog joystick of player one in RetroArch as well. When it's all said and done, you'll hopefully have two keyboards and a virtual XBox controller acting in tandem to control the player one events. This is a complete Frankenstein method that I believe should work, but again, I'm not positive. All in all, I'd recommend against it, as I don't think it's a great solution, but if you're really set on using this keyboard as a controller, it may be worth a shot.
-
@mediamogul
Thanks for de reply. Of course I know the difficulties of creating something like that, and I know that it isn't the best controller, but I want to use it to travel or occasional plays.
I've tried to follow your last message without success, I used the following code:sudo killall xboxdrv sudo /opt/retropie/supplementary/xboxdrv/bin/xboxdrv \ --evdev /dev/input/event1 \ --silent \ --mimic-xpad \ --evdev-keymap BTN_LEFT=rb,BTN_RIGHT=lb \ --ui-axismap x1=REL_X,y1=REL_Y \
I tried again more times with different configurations but I can not find the problem so that Retropie recognizes the right and left buttons, the axis of the joystick does not seem to work either.
I used trigger-as-button iterating configurations and I thought it worked because it showed the name (end of section 3A of the guide), but at the time of mapping, it didn't recognize the same buttons either.
Although I do not expect to get it, thanks for the help! -
Try and see if all the buttons and axis are registering in the newly created joystick with
jstest
. The command would be:jstest /dev/input/jsX
Where 'X' is the number of the xboxdrv-created controller.
-
@mediamogul
It give me this backJoystick (Xbox Gamepad (userspace driver)) has 6 axes (X, Y, Rx, Ry, Hat0X, Hat0Y) and 13 buttons (BtnX, BtnY, BtnTL, BtnTR, BtnTR2, BtnSelect, BtnStart, BtnMode, BtnThumbL, BtnThumbR, ?, ?, ?). Testing ... (interrupt to exit) Axes: 0: 0 1: 0 2: 0 3: 0 4: 0 5: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off 9:off 10:off 11:off 12:off
And nothing testing, neither evtest.
What that it means? -
So, while the testing interface was up, you didn't get any response from using the touchpad, or from pressing the buttons?
-
@mediamogul
Exactly, I don't get any reponse. I have tested with all the controllers that enable xboxdrv without success. -
I'm afraid that may mean it's not going to work. Usually, if there's an issue, xboxdrv will simply refuse to create the virtual controller and throw an error. The fact that it is created, but has no response likely means there's nothing to troubleshoot and that the two are just not compatible.
-
@mediamogul
Well, thanks for the answer, I'll try to do some tests even though we can not do anything. The best way to test the changes is as follows?sudo killall xboxdrv sudo /opt/retropie/supplementary/xboxdrv/bin/xboxdrv ((...changes...)) reboot
Thanks for the help!
-
@javisousa20 said in Guide: Advanced Controller Mappings:
The best way to test the changes is as follows?
On something like this, the best advice I can give is to keep throwing ideas at the problem as you have them. Whenever I find myself in uncharted territory, trial and error is often the mother of resolution.
-
@mediamogul
Hi, I think the problem is when I reboot to initialize xboxdrv. I have tried to use the following codesudo /opt/retropie/supplementary/xboxdrv/bin/xboxdrv --evdev /dev/input/event1 --evdev-debug --evdev-keymap BTN_LEFT=LB,BTN_RIGHT=RB
It give me this back when I press the
BTN_LEFT
, also withBTN_RIGHT
EV_KEY BTN_LEFT 1 X1: 0 Y1: 0 X2: 0 Y2: 0 du:0 dd:0 dl:0 dr:0 back:0 guide:0 start:0 TL:0 TR:0 A:0 B:0 X:0 Y:0 LB:1 RB:0 LT: 0 RT: 0 EV_KEY BTN_LEFT 0 X1: 0 Y1: 0 X2: 0 Y2: 0 du:0 dd:0 dl:0 dr:0 back:0 guide:0 start:0 TL:0 TR:0 A:0 B:0 X:0 Y:0 LB:0 RB:0 LT: 0 RT: 0 EV_KEY BTN_LEFT 1 X1: 0 Y1: 0 X2: 0 Y2: 0 du:0 dd:0 dl:0 dr:0 back:0 guide:0 start:0 TL:0 TR:0 A:0 B:0 X:0 Y:0 LB:1 RB:0 LT: 0 RT: 0
It seems that the emulation to the LB button works, but when I restart to initialize xboxdrv, the result is lost:
sudo /opt/retropie/supplementary/xboxdrv/bin/xboxdrv --evdev /dev/input/event1 --evdev-debug EV_KEY BTN_LEFT 1 X1: 0 Y1: 0 X2: 0 Y2: 0 du:0 dd:0 dl:0 dr:0 back:0 guide:0 start:0 TL:0 TR:0 A:0 B:0 X:0 Y:0 LB:0 RB:0 LT: 0 RT: 0 EV_KEY BTN_LEFT 0 X1: 0 Y1: 0 X2: 0 Y2: 0 du:0 dd:0 dl:0 dr:0 back:0 guide:0 start:0 TL:0 TR:0 A:0 B:0 X:0 Y:0 LB:0 RB:0 LT: 0 RT: 0
There may be something that I am doing wrong, Do I have to write it in rc.local?
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.