HOWTO: Multiple controller configs in ScummVM + virtual kbd!
-
Note: This HOWTO assumes you're using the 2.0.0 release branch of ScummVM, as supplied by the RetroPie scripts. If/when RetroPie moves to a more recent release, this will be obsolete.
You can get the entire modified file from my Github fork to save you typing it all out. Copy, paste and make your own changes.
Edit 20180218: removed <string> dependency. Moved button definitions to separate functions near the top of the file. Added detailed instructions on how to add your own configuration. Moved code to Github so you can see easily what has been modified from the original file.
Edit 20180224: Added virtual keyboard button and instructions to compile with virtual keyboard support.
Edit 20180227: ScummVM has its own strcmp replacement function scumm_stricmp(). Using that instead.
Here goes...
- I have never written a line of C or C++ in my life until today. I know the code sucks. Seriously, I know.
- If your preferred controller works fine in ScummVM and you're happy with it, stop reading now.
- If you have no interest in compiling ScummVM from source, stop reading now.
- Major credit to dudleydes on Reddit for the original inspiration.
Ok, since you're still here... ScummVM is a weird case. The controller configuration is hardcoded, and for certain controllers (like the PS3 controller) this results in really weird button assignments by default.
The solution, proposed in this Reddit thread works fine and is great if you only want to ever use one controller in ScummVM, but if like me you have multiple controllers and want to be able to use any of them in ScummVM (independently, not at the same time!), this post may interest you.
Some of the steps here are identical to those in the Reddit thread, but I'll copy them here for consistency:
1. Get Sources
Run the commands:
cd RetroPie-Setup sudo ./retropie_packages.sh scummvm sources
2. Open source file in nano for editing
Ok, let's open our file for editing...
sudo nano /home/pi/RetroPie-Setup/tmp/build/scummvm/backends/events/sdl/sdl-events.cpp
3. Delete existing button macros, replace with static variables, add per-controller functions
I'm sure this is very bad practice (for reasons I don't understand), but I'm not trying to win a programming award, I'm trying to make ScummVM less of a pain to use.
A little further down around line 49/50 are the hardcoded DEFINE macros that have the current default buttons.
Delete these lines:
#define JOY_BUT_LMOUSE 0 #define JOY_BUT_RMOUSE 2 #define JOY_BUT_ESCAPE 3 #define JOY_BUT_PERIOD 1 #define JOY_BUT_SPACE 4 #define JOY_BUT_F5 5
Replace them with these lines:
// ScummVM SDL default button layout - if the controller is configured below these get overwritten static uint8 JOY_BUT_LMOUSE=0; // LMB static uint8 JOY_BUT_RMOUSE=2; // RMB static uint8 JOY_BUT_ESCAPE=3; // Esc static uint8 JOY_BUT_PERIOD=1; // . static uint8 JOY_BUT_SPACE=4; // Space static uint8 JOY_BUT_F5=5; // F5 static uint8 JOY_BUT_VKBD=10; // Virtual Keyboard (no key assigned by default) const char *charPS3 = "Sony PLAYSTATION(R)3 Controller"; // must match SDL name for PS3 controller void setPS3buttons() { JOY_BUT_LMOUSE=14; // Cross (LMB) JOY_BUT_RMOUSE=13; // Circle (RMB) JOY_BUT_ESCAPE=15; // Square (Esc) JOY_BUT_PERIOD=12; // Triangle (.) JOY_BUT_SPACE=3; // Start (Space) JOY_BUT_F5=0; // Select (F5) JOY_BUT_VKBD=10; // Virtual Keyboard - L1 (no default in SDL2) } const char *charX360 = "Microsoft X-Box 360 pad"; // must match SDL name for X360 controller void setX360buttons() { JOY_BUT_LMOUSE=0; // A (LMB) JOY_BUT_RMOUSE=1; // B (RMB) JOY_BUT_ESCAPE=2; // X (Esc) JOY_BUT_PERIOD=3; // Y (.) JOY_BUT_SPACE=9; // Start (Space) JOY_BUT_F5=8; // Select (F5) JOY_BUT_VKBD=4; // Virtual Keyboard - LB (no default in SDL2) } const char *charBuffaloSNES = "USB,2-axis 8-button gamepad "; // must match SDL name for Buffalo Classic USB Gamepad void setBuffaloSNESbuttons() { // Same layout as PSX and X360 - reverse A&B and X&Y for SNES style controls JOY_BUT_LMOUSE=1; // B (LMB) JOY_BUT_RMOUSE=0; // A (RMB) JOY_BUT_ESCAPE=3; // Y (Esc) JOY_BUT_PERIOD=2; // X (.) JOY_BUT_SPACE=7; // Start ( ) JOY_BUT_F5=6; // Select (F5) JOY_BUT_VKBD=4; // Virtual Keyboard - LB (no default in SDL2) } const char *charF300 = "MAYFLASH Arcade Fightstick F300"; // must match SDL name for MAYFLASH Arcade Fightstick F300 void setF300buttons() { // Unlike the above, I've set Start to F5 (because I think it'll be used more) // The small Home button is the Pause (Spacebar) key // On this controller, confusingly, RT is on the LEFT and LT is on the RIGHT JOY_BUT_LMOUSE=1; // A (LMB) JOY_BUT_RMOUSE=2; // B (RMB) JOY_BUT_ESCAPE=0; // X (Esc) //JOY_BUT_ESCAPE=6; // LT - uncomment if you want to use for Escape JOY_BUT_PERIOD=3; // Y (.) //JOY_BUT_PERIOD=7; // RT - uncomment if you want to use for Period JOY_BUT_SPACE=12; // Home (Space) JOY_BUT_F5=9; // Start (F5) JOY_BUT_VKBD=5; // Virtual Keyboard - LB (no default in SDL2) } const char *charRaphClassic = "raphnet technologies 1-player WUSBMote v2.1"; // must match SDL name for Raphnet Adapter void setRaphClassicbuttons() { // Same layout as PSX and X360 - reverse A&B and X&Y for SNES style controls JOY_BUT_LMOUSE=1; // B (LMB) JOY_BUT_RMOUSE=4; // A (RMB) JOY_BUT_ESCAPE=0; // Y (Esc) JOY_BUT_PERIOD=5; // X (.) JOY_BUT_SPACE=3; // Start ( ) JOY_BUT_F5=2; // Select (F5) JOY_BUT_VKBD=5; // Virtual Keyboard - LB (no default in SDL2) }
4. Insert IF statements to set your controller buttons at runtime
This is the main part. We're going to compare the name of the controller that SDL2 uses to our known controller names and, if they match, set the buttons accordingly.
Down around line 163 (if you've pasted in the stuff in step 3 already) is this:
// Enable joystick if (SDL_NumJoysticks() > joystick_num) { _joystick = SDL_JoystickOpen(joystick_num); debug("Using joystick: %s", #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_JoystickName(_joystick) #else SDL_JoystickName(joystick_num) #endif );
We are now going to paste the following lines between the // HACK comment and the // END HACK comment in a new line directly under the ); line so that it should look like this:
// Enable joystick if (SDL_NumJoysticks() > joystick_num) { _joystick = SDL_JoystickOpen(joystick_num); debug("Using joystick: %s", #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_JoystickName(_joystick) #else SDL_JoystickName(joystick_num) #endif ); // HACK by someone who has never written a line of C or C++ in his life #if SDL_VERSION_ATLEAST(2, 0, 0) if (scumm_stricmp(SDL_JoystickName(_joystick), charPS3) == 0) { debug("Setting PS3 controller button assignments..."); setPS3buttons(); } else if (scumm_stricmp(SDL_JoystickName(_joystick), charX360) == 0) { debug("Setting XBOX360 controller button assignments..."); setX360buttons(); } else if (scumm_stricmp(SDL_JoystickName(_joystick), charBuffaloSNES) == 0) { debug("Setting Buffalo SNES controller button assignments..."); setBuffaloSNESbuttons(); } else if (scumm_stricmp(SDL_JoystickName(_joystick), charF300) == 0) { debug("Setting Mayflash Arcade Fightstick F300 button assignments..."); setF300buttons(); } else if (scumm_stricmp(SDL_JoystickName(_joystick), charRaphClassic) == 0) { debug("Setting Raphnet Classic to USB adapter button assignments..."); setRaphClassicbuttons(); } else { debug("Using default button assignments..."); } #endif // END HACK } else { warning("Invalid joystick: %d", joystick_num); } } }
If you look at the code above, it should be fairly obvious what we're doing. If the name that SDL2 is using matches one of the strings we set in the lines like:
const char *charPS3 = "Sony PLAYSTATION(R)3 Controller";
then the variables in the matching function near the top of the file get set to the corresponding values.
Obviously, you need to tailor these button assignments this to your own controllers. I'll get to that later.
5. Change the SWITCH statement to IF statements (because CASE labels in SWITCH statements cannot be variables)
Down somewhere around line 900 is the following function that handles joystick button keydown events:
bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONDOWN; return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { event.type = Common::EVENT_RBUTTONDOWN; return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else { switch (ev.jbutton.button) { case JOY_BUT_ESCAPE: event.kbd.keycode = Common::KEYCODE_ESCAPE; event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod)ev.key.keysym.mod, 0); break; case JOY_BUT_PERIOD: event.kbd.keycode = Common::KEYCODE_PERIOD; event.kbd.ascii = mapKey(SDLK_PERIOD, (SDLMod)ev.key.keysym.mod, 0); break; case JOY_BUT_SPACE: event.kbd.keycode = Common::KEYCODE_SPACE; event.kbd.ascii = mapKey(SDLK_SPACE, (SDLMod)ev.key.keysym.mod, 0); break; case JOY_BUT_F5: event.kbd.keycode = Common::KEYCODE_F5; event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0); break; } return true; } }
In this function, we need to replace the SWITCH statement with IF statements.
We're going to delete the entire SWITCH statement and replace it, like this:
bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONDOWN; return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { event.type = Common::EVENT_RBUTTONDOWN; return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else { // HACK replace SWITCH with IF statements event.type = Common::EVENT_KEYDOWN; if (ev.jbutton.button == JOY_BUT_ESCAPE) { event.kbd.keycode = Common::KEYCODE_ESCAPE; event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod)ev.key.keysym.mod, 0); } else if (ev.jbutton.button == JOY_BUT_PERIOD) { event.kbd.keycode = Common::KEYCODE_PERIOD; event.kbd.ascii = mapKey(SDLK_PERIOD, (SDLMod)ev.key.keysym.mod, 0); } else if (ev.jbutton.button == JOY_BUT_SPACE) { event.kbd.keycode = Common::KEYCODE_SPACE; event.kbd.ascii = mapKey(SDLK_SPACE, (SDLMod)ev.key.keysym.mod, 0); } else if (ev.jbutton.button == JOY_BUT_F5) { event.kbd.keycode = Common::KEYCODE_F5; event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0); } #ifdef ENABLE_VKEYBD else if (ev.jbutton.button == JOY_BUT_VKBD) { // our virtual keyboard button event.type = Common::EVENT_VIRTUAL_KEYBOARD; // fires the virtual keyboard event directly } #endif return true; } }
You need to make exactly the same change in the next block that handles joystick keyup events:
bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) { if (ev.jbutton.button == JOY_BUT_LMOUSE) { event.type = Common::EVENT_LBUTTONUP; return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else if (ev.jbutton.button == JOY_BUT_RMOUSE) { event.type = Common::EVENT_RBUTTONUP; return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER); } else { // HACK replace SWITCH with IF statements event.type = Common::EVENT_KEYUP; if (ev.jbutton.button == JOY_BUT_ESCAPE) { event.kbd.keycode = Common::KEYCODE_ESCAPE; event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod)ev.key.keysym.mod, 0); } else if (ev.jbutton.button == JOY_BUT_PERIOD) { event.kbd.keycode = Common::KEYCODE_PERIOD; event.kbd.ascii = mapKey(SDLK_PERIOD, (SDLMod)ev.key.keysym.mod, 0); } else if (ev.jbutton.button == JOY_BUT_SPACE) { event.kbd.keycode = Common::KEYCODE_SPACE; event.kbd.ascii = mapKey(SDLK_SPACE, (SDLMod)ev.key.keysym.mod, 0); } else if (ev.jbutton.button == JOY_BUT_F5) { event.kbd.keycode = Common::KEYCODE_F5; event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0); } return true; } }
6. If you happen to have the same controllers as me and you're happy with the way the buttons are bound, move on to step 7!
If not, you'll need to find out what SDL2 thinks your controller is called and copy and modify one of the functions in step 3.
If your controller is configured in EmulationStation then a good place to look is in this file:
\\retropie\configs\all\emulationstation\es_input.cfg
Each controller's name appears in lines similar to this:
<inputConfig type="joystick" deviceName="USB,2-axis 8-button gamepad " deviceGUID="03000000830500006020000010010000">
I used that one as an example for a reason; this is my Buffalo Classic USB Gamepad. Notice that there are two trailing spaces in the name. YOU MUST INCLUDE ANY TRAILING SPACES IN YOUR STRINGS, as I have here:
const char *charBuffaloSNES = "USB,2-axis 8-button gamepad ";
The names must match exactly, or the default button assignments will be used.
You can use es_input.cfg to determine which SDL2 button numbers map to which controls in ES, and use those numbers to set your own buttons in the functions at the top of the file.
For example, if you want to add one of your own joypads, check your es_input.cfg file and determine which entry matches the joypad you want to add.
Here's an example:
<inputConfig type="joystick" deviceName="CHEAP UNRELIABLE JOYPAD" deviceGUID="01010101010101010101010101010101"> <input name="pageup" type="button" id="9" value="1"/> <input name="start" type="button" id="12" value="1"/> <input name="up" type="hat" id="0" value="1"/> <input name="a" type="button" id="2" value="1"/> <input name="b" type="button" id="3" value="1"/> <input name="down" type="hat" id="0" value="4"/> <input name="pagedown" type="button" id="5" value="1"/> <input name="right" type="hat" id="0" value="2"/> <input name="x" type="button" id="0" value="1"/> <input name="select" type="button" id="13" value="1"/> <input name="y" type="button" id="1" value="1"/> <input name="left" type="hat" id="0" value="8"/> </inputConfig>
Copy one of the existing functions at the top of the file and modify it. Here I copied the X360 function:
const char *charX360 = "Microsoft X-Box 360 pad"; // must match SDL name for X360 controller void setX360buttons() { JOY_BUT_LMOUSE=0; // A (LMB) JOY_BUT_RMOUSE=1; // B (RMB) JOY_BUT_ESCAPE=2; // X (Esc) JOY_BUT_PERIOD=3; // Y (.) JOY_BUT_SPACE=9; // Start (Space) JOY_BUT_F5=8; // Select (F5) JOY_BUT_VKBD=4; // Virtual Keyboard - LB (no default in SDL2) }
Here it is after modification. Notice that I've changed four elements:
- the name of the constant (charCHEAP)
- the name of the controller value IN the constant (CHEAP UNRELIABLE JOYPAD)
- The name of the function (setCHEAPbuttons)
- The number values that correspond to the controller buttons. (A is now 2, etc.)
const char *charCHEAP = "CHEAP UNRELIABLE JOYPAD"; // must match SDL name for your cheap unreliable joypad void setCHEAPbuttons() { JOY_BUT_LMOUSE=2; // A (LMB) JOY_BUT_RMOUSE=3; // B (RMB) JOY_BUT_ESCAPE=0; // X (Esc) JOY_BUT_PERIOD=1; // Y (.) JOY_BUT_SPACE=12; // Start (Space) JOY_BUT_F5=13; // Select (F5) JOY_BUT_VKBD=9; // Virtual Keyboard - LB (no default in SDL2) }
Paste this in under the other similar functions at the top of the file.
Finally, add another three lines to the IF ELSE statements that we added before, substituting our new constant name and function name:
<snipped> } else if (scumm_stricmp(SDL_JoystickName(_joystick), charRaphClassic) == 0) { debug("Setting Raphnet Classic to USB adapter button assignments..."); setRaphClassicbuttons(); } else if (scumm_stricmp(SDL_JoystickName(_joystick), charCHEAP) == 0) { debug("Setting cheap unreliable joypad adapter button assignments..."); setCHEAPbuttons(); } else { debug("Using default button assignments..."); } #endif // END HACK
7. Save the file and build ScummVM!
To save the file in nano: Ctrl-O and Enter when prompted. To exit nano: Ctrl-X.
OPTIONAL: If you want Virtual Keyboard support in your build, you now need to edit /home/pi/RetroPie-Setup/scriptmodules/emulators/scummvm.sh and add --enable-vkeybd to the following line (line 53).
Before:
local params=(--enable-all-engines --enable-release --disable-debug --disable-eventrecorder --prefix="$md_inst")
After:
local params=(--enable-all-engines --enable-release --enable-vkeybd --disable-debug --disable-eventrecorder --prefix="$md_inst")
You also need to edit the scummvm.ini file to set the virtual keyboard paths. See section 10b for details.
To build the ScummVM binary run the following command (assuming /RetroPie-Setup is still the active directory):
sudo ./retropie_packages.sh scummvm build
This takes 6 to 7 hours on RPi 1 or about an hour on RPi 2/3.
Fun fact: sdl-events.cpp doesn't get processed until near the end so if you made a typo you wasted 50+ mins! Yay!
8. Install your newly built ScummVM binary
In his original Reddit post, dudleydes said "I couldn't install the binary using the RetroPie script"
I didn't try to use the RetroPie script either, but it's straightforward to do it manually. Run the following commands:
cd /home/pi/RetroPie-Setup/tmp/build/scummvm sudo make install
If all went well, you should be able to run scummvm and test it!
9. OPTIONAL
You may have noticed that I put some debug lines in the code. These only get written to the scummvm log file if debug mode is enabled. All you have to do for that is:
nano "/home/pi/RetroPie/roms/scummvm/+Start ScummVM.sh"
In this file there is a line that begins something like:
/opt/retropie/emulators/scummvm/bin/scummvm --fullscreen... <line continues>
Just add -d 1 after the path to scummvm to enable debug mode:
/opt/retropie/emulators/scummvm/bin/scummvm -d 1 --fullscreen... <line continues>
This will print some debug messages to the log file. It will allow you to confirm whether or not the IF statement with your button bindings is actually running. (although tbh if you've made a mistake it probably just won't build at all).
Regarding controller names:
I think that the names in the es_input.cfg file will always match the SDL2 names (
does ES use SDL2?Yes it does. Does SDL2 just use the names directly from evdev?), but if you want to be certain, you can do the following:cd ~ git clone https://github.com/Grumbel/sdl-jstest.git sudo apt-get install libncurses5-dev cd sdl-jstest mkdir build cd build cmake .. make
Then, with the controller in question connected:
./sdl2-jstest -l
The Joystick Name field should give you the name SDL2 uses.
10. PAQs (Preemptively Answered Questions)
Q. This is bad code, you should do this instead...
A. Yep, I know just enough to know that I don't know anything. If you can do better, PLEASE DO IT! Sometimes seeing someone else do something badly is actually better motivation to help than seeing nothing at all.Q. Why did you do X? Y would have been so much better!
A. Because a document/tutorial said X and after some trial and error, X worked. Also, I've never heard of Y.Q. Why not just read the controller configs from es_input.cfg and use them at runtime?
A. Please refer to the previous two answers.Q. What happens if more than one controller is connected?
A. ScummVM seems to only use the controller with the highest index, which is usually the controller you plugged in most recently, unless you've been swapping controllers like a madman.Q. What happens if I swap controllers while ScummVM is running?
A. Ooh, you maverick! ScummVM will no longer communicate with any controllers until it is restarted. You'll need to exit by terminating it from SSH or with a keyboard/mouse. You should connect the controller you want to use before you start ScummVM, and you should exit ScummVM before disconnecting the controller.Q. If I get a new controller and I want to add a configuration for it, do I have to enter a new configuration for it in the code and compile ScummVM again?
A. Yes. Perhaps someone with actual programming experience will improve controller support in ScummVM one day so this will no longer be required.Q. The virtual keyboard isn't great.
A. That's not really a question, but yes, it's a little bit cumbersome and could do with some TLC. Although the ScummVM wiki states "The virtual keyboard is being actively developed" there hasn't been any real development on the feature for about 7 years.10b. About the Virtual Keyboard
If you enabled vkbd support in your build (refer to step 7), you will need to modify a couple of lines in /opt/retropie/configs/scummvm/scummvm.ini under the [scummvm] section of the file (or create them if they don't already exist).
vkeybdpath=/opt/retropie/emulators/scummvm/extra vkeybd_pack_name=vkeybd_default
The way the virtual keyboard works:
- You press the virtual keyboard button on your controller
- ScummVM freezes the game and displays the keyboard
- You enter characters by pressing the key bound to the LMB on your controller
- The characters you enter appear separated in square brackets on the input line at the top of the keyboard
- You press the green tick button on the virtual keyboard or press the virtual keyboard button again
- ScummVM unfreezes the game and sends the keystrokes on the input line
It works well enough (see my YouTube video later in this thread) that you can use it in SCI/AGI games to enter keywords with a joypad, or enter names for save files, or press Y or N for yes or no. You can't really use it to directly control a character's movements, etc, for obvious reasons.
The virtual keyboard sends EXACTLY the keystrokes you enter. By that I mean pressing the green tick or pressing the controller button that opens/closes the virtual keyboard does NOT send an automatic Enter/Return command, so if you would normally press Enter/Return at the end of your typed line you must put that in as a keystroke on the virtual keyboard before you press the green tick or press the controller button. It'll appear as [Return] on the input line.
Finally, I've found that in a few games (BASS, EoB1, EoB2 and Simon1 identified so far) the virtual keyboard sends inputs too fast for the keystrokes to properly register in the game's engine, and so far I haven't found a way to add a delay between keystrokes. In those cases you'll need to enter keystrokes one at a time. Frustrating.
-
Although I don't use multiple controllers myself, I have to say great tutorial. I wonder if it would be possible to gather all infos for different controllers and create a file that can be downloaded by others or (if thats even possible) can be directly imported when building it from the RetroPie menu. I have not looked at the entire code, but does this have a fallback option if an unknown controller is attached? If that's the case, you probably should make a pull request to the main scummvm github.
I even would suggest to add more bindings to this. I personally have added some keys and have this layout on my Logitech F710 controller now:
#define JOY_BUT_LMOUSE 0 // A #define JOY_BUT_RMOUSE 1 // B #define JOY_BUT_ESCAPE 3 // Y #define JOY_BUT_PERIOD 5 // RB #define JOY_BUT_SPACE 2 // X #define JOY_BUT_F5 10 // Home/Guide #define JOY_BUT_F1 9 // Start #define JOY_BUT_RETURN 8 // Back/Select #define JOY_BUT_y 6 // LT #define JOY_BUT_n 7 // RT
The default keybings mostly cover only Lucas Arts games. I added F1 for Discworld, Y and N for Simon the Sorcerer and to input simple names for savegames (not perfect but at least I don't need a keyboard). I also added ENTER because I thought it could be useful in some cases where I have to confirm something.
I can see problems with controllers that don't have that much buttons, but maybe there is a way to configure a modifier button that can be hold/toggle to change the bindings of the face buttons. I did that before when we had to use xboxdrv for scummvm, but I'm lacking the knowledge if it can be done here.
-
@EctoOne I'll look into adding more bindings to controllers that support it. Thanks for the suggestion.
If none of the controller strings match then it falls back to the default buttons as set in the original source.
Yep, it could be the basis of a larger file that contains configurations for lots of controller types. On the other hand, a better and more comprehensive solution would be some method of either letting users set the binds themselves in a config file (this seems to be some kind of heresy in ScummVM land) or reads the ES or RA configs and uses that instead. This is well outside of my capabilities at the moment.
I'd need to read more of the code to determine how they handle modifier buttons.
ScummVM is an awesome project and does what it does extremely well, but for some reason their work on the UX side appears, to a casual external observer like me, to be haphazard and extremely slow. I mean 10+ years of debate about whether or not to allow users to set their own controls in the config file! 10+ years of a "kinda usable" on-screen keyboard implementation. The documentation on the Wiki is also really outdated in parts, and again I suspect that's because actually finding out what's what is difficult.
I don't know if this is because the internal politics of ScummVM makes it change-resistant or (more likely) that reverse-engineering game engines and interpreters is more fun and sexy than mundane backend work.
This hack would never survive a PR for many reasons,
but the main one is it uses a standard C++ lib which is frowned upon in ScummVM. Why does it use a C++ lib? Because I don't know any better.Removed C++ lib dependency!It is ultimately my hope that a ScummVM dev sees this hack and is horrified enough to do something about it. :D
-
I'm rebuilding ScummVM with the keymapper and virtual keyboard enabled to see if/how they work. Maybe some useful functionality is in here already but disabled. Probably not, but we'll see.
-
@stoo Of course having a way to change bindings with the gui would be awesome. I mean I installed Amiberry again last night because they managed to get custom controls working and it is just so good to find the perfect mapping while playing.
I also have to agree that the front end development seems to be not that important. The fact that there aren't even simple things like working themes around since they changed the theme engine is kinda sad. Also, even though I'm not really following the development very hard, but when they released version 2.0 and I was looking for the Android SDL version, I believe that someone said that he is the only maintainer of that port and that's why it will take some time to get it working.Yet again I'm happy enough that the game engine development is so active and that there are ways to work around the small issues. I grew up with the Lucas Arts games and in general Point and Click games is my favorite genre. I'm looking forward to play some of the recently added SCI games because there are some I missed when they were initially released. And nowadays I don't enjoy it to sit in front of my PC to play games but I like to play console games and scummvm on the Pi is just that.
-
@ectoone I just checked the Master branch of ScummVM on Github and it looks like someone has recently started preliminary work on proper gamepad support.
Obviously, they might never actually finish it, but the recent activity on that front gives me hope that this hack will not be needed in the nearish future.
-
@stoo said in HOWTO: Multiple controller configs in ScummVM:
Obviously, they might never actually finish it
I've been pretty impressed with how extensive scummvm development is. I have high hopes for this
-
@herb_fargus As I noted above, they're awesome when it comes to the engine side...
...the backends are slightly more hit-and-miss :P
-
The current scummvm master branch has a branch for SDL2 controller support (PR1088) merged in. This maps most of the buttons to keyboard+mouse functions.
If you want to try it out you can compile from current master or wait till the next non-bug-fix release (2.1.0).
-
@dafioram Sounds good. Depends, of course, on:
- How is button/axis mapping performed? (i.e. ES uses SDL2 but, of course, you still have to provide the controller mapping)
- Is it configurable in the UI or .ini file? This is more important than actually having SDL2 controller functionality enabled.
I'll take a look at the branch and see what the progress is like.
On a semi-related note:
@EctoOne The built-in keymapping stuff is quite unfinished and would require a lot of work that I'm not qualified to do to make it usable in the sdl2 backend.
On the other hand, I enabled virtual keyboard support in ScummVM and bound a button to it in sdl-events.cpp and it works!
It's a little bit cumbersome, and the way it works is it simply pauses the game, displays the keyboard and you enter characters (remembering to press Return/Enter on the virtual keyboard at the end!) and when you press the green tick button it unpauses the game and sends the respective keystrokes as input.
It works well enough that you could use it in SCI/AGI games to enter keywords with a joypad. You can't really use it to directly control the character's movements, etc, for obvious reasons.
Afterthought: it would be awesome if it had a list of built-in general keywords for each game and had a rudimentary predictive engine based on them (being careful to exclude potential puzzle-spoiling words, item names, etc). This feature appears to exist in the Nintendo DS port.
Edit: stupid youtube embedding thing screwed up my markdown.
-
@dafioram Lol, I only just now realised you're the same guy from the ScummVM forums where I mentioned the vkbd speed bug. /wave
-
Hey,
I just did this tutorial and built and installed from source twice after making said adjustments and my PS3 controller STILL is using the default mappings. What am i missing here? Do i need to first remove previous existing installed Scummvm by retropie before doing this one or what is the thing i am missing?
Cheers
-
Nevermind i figured it out. The guide dosen't it make it noob clear that after you have built your own version you still have to actually move the binary to the appropriate folder but as i said in the end i figured it out :)
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.