In the last blog post, I showed you how to make a Raspberry Pi emulator using the Open Source project RetroPie. In this post, I will share with you some interesting tricks involving keyboard mapping and save states.
There are many games that provide some sort of save-game functionality. Maybe that happens through a battery or an EEPROM in the cartridge. Maybe that is through a password you write down and use later. But there are a great many more that offer no way to save games. Even the cartridges that do allow this usually only allow saves from specific locations, not from any position in the game.
The fun thing about running games through an emulator is that the emulator itself can provide extensive save-state functionality. It can take a snapshot of the entire state of the game: the ROM, the RAM, the registers and stack of the CPU, and so on. It allows you to freeze-dry the entire state of the universe (as it pertains to the game console) and return to it later. It’s like having a universal pause button and time machine.
Case in point: in the game Megaman, you travel through levels that are maybe a dozen screens long. There is usually a built-in save point half-way through the level and another toward the end, at the level-boss. If you die somewhere along the level, you’re returned to one of these two save points (or the beginning of the level if you haven’t yet reached one). But in a virtual machine, you can progress one screen, then take a snapshot of the game state. You can keep doing this – pass a screen, take a snapshot – until you die on a screen. Then instead of returning to the last save point, minus a life, you instruct the emulator to restore its last snapshot. You are then back at the beginning of that particular screen without having lost anything. “It’s like cheating, but different!”
With almost no work, you can set up the RetroPie to let you save/restore using a plugged-in USB keyboard. With a bit more work, you can map it to controller buttons.
NOTE that throughout this walkthrough I am using the RetroPie 3.0 beta release. My understanding is that it’s a little different on earlier releases, but I do not know in what way.
Enabling Keyboard Saves
Let’s start with enabling saves on the keyboard. You’ll need to perform this step, anyway, if you also want to map saves/loads to controller chords.
Plug in a USB keyboard.
Log in to your RetroPie. You can do this by exiting the user interface with F4 and using the TV and keyboard directly. Alternately, you can use ssh to connect to your Raspberry Pi over the network.
Select menu item 3, configuration.
Select menu item 310, Change hotkey behavior.
Select 2: press ALT to enable hotkeys.
Exit and save.
Now when you play a game, the following two keyboard shortcuts are enabled:
- ALT-F2 : save game
- ALT-F4 : load previous save
(There are actually quite a few more, but those are the important ones for now.)
Verify that the keyboard actions work before continuing to the controller chords.
Enabling Controller Saves
I play a lot of NES games using an SNES controller. This means there are a few vestigial buttons – X, Y, L, and R – that do nothing. My plan is to map X plus the right shoulder button to save, so it’s entirely one-handed, and X plus the left shoulder button to load, marginally more difficult to trigger because it uses both hands. I want to do this for the SNES controller on NES games only. Those may be perfectly valid button combinations for SNES games. You don’t want to be accidentally triggering saves. If you want to save/load state with SNES games, you’ll have to go the keyboard route, find a controller with even more buttons (so you have a vestigial one), or remap to a more rare (but more difficult to hit) combination like Start+R and Start+L.
This is where it gets complicated because there are at least three different config files, based on your emulator and controller. For me, they are:
The first is specific to the controller I’m using. This may be different for your controller. You’ll know which one to use based on what controller name pops up on screen when you start a game or plug in a controller mid-game. This file gives you the information you need about what names the RetroPie gives to the buttons. The second is the global config. Changes here get applied to all controllers and all emulators. You may want to peek at this file but you probably don’t want to change it. The third is specific to the NES emulator. We’ll use this to map the vestigial buttons.
Let’s start by looking at the controller file. It holds entries like these:
input_device = "USB,2-axis 8-button gamepad " input_driver = "udev" input_b_btn = "1" input_y_btn = "3" input_select_btn = "6" input_start_btn = "7" input_up_axis = "-1" input_down_axis = "+1" input_left_axis = "-0" input_right_axis = "+0" input_a_btn = "0" input_x_btn = "2" input_l_btn = "4" input_r_btn = "5" input_enable_hotkey_btn = "6" input_exit_emulator_btn = "7" input_menu_toggle_btn = "2" input_load_state_btn = "4" input_save_state_btn = "5" input_reset_btn = "1" input_state_slot_increase_axis = "+0" input_state_slot_decrease_axis = "-0"
Take note: the top section shows the button definitions (A, B, X, Y, L, R, up, down, left, right). The bottom section shows the default mappings, using those definitions. The hotkey button is “6”, which looking up above means “Select”. The exit button is “7”, which we see is “Start”. That matches the expected default behavior: hit Select+Start to exit the game. We want to remap these in the NES config file for easier access.
We want to edit the NES config file, adding a few lines, to look something like this:
#include "/opt/retropie/configs/all/retroarch.cfg" # All settings made here will override the global settings for the current emulator core input_remapping_directory = /opt/retropie/configs/nes/ video_shader = /opt/retropie/emulators/retroarch/shader/phosphor.glslp video_shader_enable = false video_smooth = false # X button on SNES controller input_enable_hotkey_btn = "2" # Left shoulder button on SNES controller input_save_state_btn = "4" # Right shoulder button on SNES controller input_load_state_btn = "5" # Exit emulator, Select input_exit_emulator_btn = "6" # Save slot, left input_state_slot_increase_axis = "+0" # Save slot, right input_state_slot_decrease_axis = "-0"
This overrides the definitions in the gamepad file, but only for the NES. One caveat to keep in mind is that these mappings are specific to the SNES gamepad. That isn’t a problem if you always keep your controllers with the RetroPie. If you frequently swap the controllers for something wildly different, there is a chance that the buttons won’t quite map the same.
But that’s it. The next time you start a game in the NES emulator with the SNES controller, you’ll have the quick save/load button chord mappings.