-
Notifications
You must be signed in to change notification settings - Fork 3
Home
Displaying a visual diagram (or legend) of how the in-game actions of the currently selected game are mapped to the hardware controls (buttons, joysticks, trackballs, spinners, etc) on my control panel.
Note: Although this project is intended to display control-map diagrams, it could easily be altered to display a dynamic marquee, box art, flyers, or any number of things. The software doesn't much care what image it's displaying.
Introduction
Background
Design Decisions
Hardware Summary
Software Summary
Installing the software components
Testing and configuration
The inspiration for this project came out of a desire to improve the user friendliness of my RetroPie arcade cabinet.
If you want to get started in retro gaming and are new to RetrioPie, I would encourage anyone to visit http://retropie.org.uk It is an excellent resource.
This project is more advanced, and is not for intended someone new to RetroPie and MAME cabinets. It assumes some basic knowledge of RetroPie, EmulationStation, RetroArch, SSH, and the linux shell. But, if you're building you own multi-player, multi-system gaming cabinet based on RetroPie, then I hope you find this helpful.
Note: This is still a work in progress, but I do have a prototype working.
My cabinet is a two player system, with 1 joystick and 6 action buttons per player, a track-ball in the center, and pinball buttons on the sides. At the heart of my system is a Raspberry Pi 3B.
As you know, virtually every original arcade cabinet had a unique control layout, with different numbers of buttons. MAME cabinets are already a design compromise with buttons going used in many games. My first step to improve user friendliness was to illuminate only the buttons that are active in any given game. I installed LED buttons, and a 16 channel LED driver from Ultimarc. The software to control the button LEDs is here: Poor-man's LEDBlinky with RetroPie and Pac-Drive. I recommend doing this as a first step before tackling a project like this.
Next, I wanted an easy way to remind myself what buttons cause what action, in any given arcade game. For console games, remembering the button functionality is less of an issue. The original consoles systems have fewer buttons, and one controller layout to deal with. However the project will easily display console diagrams too.
Solving this problem for arcade games on multi-game cabinets was the main inspiration of this project. After posting on the RetroPie forums, I was forwarded to an earlier thread with more-or-less the same objective. https://retropie.org.uk/forum/topic/21464/show-control-panel-layout-before-game-starts-in-retropie-just-like-arcade1up-does This thread has lots of great ideas on how to generate and display the button mapping.
There are many decisions that need to be made when crafting a solution. In general, you have to choose:
- Just the buttons?
- Joysticks too?
- Trackballs and spinners?
- Somewhere on a main display screen?
- On a separate screen?
- Persistently, so it is always visible during game play?
- Visible On-Demand?
- Temporarily, at the beginning of game play ?
- What format is it in?
- Since the is no such thing as a standard MAME cabinet layout, what tools are available to generate custom diagrams that match a specific cabinet's control layout?
Your requirements might be different, and there's many different ways to solve a problem. This is just one such way.
- I was concerned mostly with labeling the button actions.
- I wanted the map to be persistent, yet non-intrusive. When the game is active, I want to be able to glance at the control map, and ignore it when I don’t need it.
- I did not want a “transparent” map to obscure the main game area.
- In order to display a persistent button map on the main screen, and not obscure the game play area, the RetroArch overlay is the only place. While RetroArch can display some generic controls over the game video, I didn't find it useful. And RetroArch does not support multiple layers in overlay/bezel area of the screen.
- Alternatively, a second, much smaller dedicated LCD screen could be used to display the button map. It would not impact the existing setup or overlay art. Some of the overlays I have collected are very beautiful, designed by much more talented artists than I will ever be. I felt it would be a shame to cover up a portion of their artwork. This is the route I chose.
My hardware setup consists of two Raspberry Pi devices, each with their own display. The main rRaspberry Pi (RPi1) runs RetroPie, and drives a 28" HDMI display in my cabinet. The buttonMap display is a 5” LCD display driven by a second Raspberry Pi (RPi2). It’s located under the large HDMI monitor, close to my Player1 controls. Down the road, I might extend the project to include multiple button map displays, one for each player.
(insert picture of final setup)
(insert closeup of button map)
The software consist of three main components
- Something to generate a set of button map images
- RPi1 must tell RPi2 what game is playing, and
- RPi2 must display the appropriate button map.
Initially I thought I could use a single RPi, and have the game run via the HDMI port and also have a static image displayed on the LCD port. However Raspian only has one frame buffer. You can drive the HDMI port, or the LCD port, but not both at the same time. This limtiation is how I arrived at using a second RPi for the button map.
This section covers the scripts, directories and software the generates a custom diagram that matches the layout of the user's control panel. Generating the button map images has five main components;
- Some notes on the scriptable image editing program named ImageMagick
- A simple txt database
button_map.csv
, which associates the basename of a rom/game with a set of text strings to describe button actions. - A database of parent/clone rom names.
mame2003-plus.csv
- A shell script named:
button_map.sh
that ties of the above together - A set of directories/folders were the action takes place.
-
./SRC - A
./src
directory is provided. It contains a black background image, and small set of arcade button image files, used to compose the final button map image. -
./TMP - The
./tmp
directory is where all the intermediate images are kept during the compositing steps. Images that do not have corresponding button data end up in here. -
./ARCADE - The
./arcade
directory is where the final button map images will be placed. Warning: This should not be the same directory where you keep your rom .zip files! -
./WHEEL - The
./wheel
directory should contain a set of optional game logo images, which can be included the final button map image These logo files are not required, but it goes a long way to make the final image look nice.
USAGE
button_map.sh is a BASH shell script that does the all work to generate a custom image. It generates a single image at a time, and the script accepts only one argument. Namely: The basename of the image to be created. Note, this should be the exact same basename as the rom file being selected by EmulationStation.
For example, to generate a button map for Asteroids (rom name: ateriod.zip),
One issues the command:
./button_map.sh asteroid
The generated image type will be .png
by default
and it will be place in the directory ./arcade
.
OPERATION
- First the script determines if a rom is a parent or clone rom. Button labels from the parent are used when there is no clone-specific button label data.
- Next the script will search the
button_map.csv
data file, looking for a line that matches the command argument you gave to script. If no data is found, the script generates a place holder image in the./tmp
directory. - If there is a match, the line gets parsed, associating each active button with its corresponding action text. The script then begins composing the image. For active buttons, a green button icon is drawn, and the button is labeled. If there is no text for a button, we assume the button isn’t used in the game, and draw a darkened button icon.
- The background image, and all the button images can be found in the
./src
directory. The user can customize these images, or add new buttons icons, as desired, to match your MAME cabinet. - Next the script searches for a logo image in the
./wheel
directory. If one is available, it sizes it properly, and overlays that image onto the composite image. If a logo image is not found, the rom name is written along the top instead. - The last thing the script does is downsize the final composite image, and saves it in the
./arcade
directory.
TIPS AND LIMITATIONS
- Currently,
button_map.sh
assumes your control panel has a 2x3 button layout of:
Y X L
B A R
- The script works well in a Mac/OSX, and Linux terminals. NOTE: I have not tested this in Windows..
- The image composition is all done in high resolution, to retain image quality. Then finale image is downsized to 800x480. This is resolution of the dedicated LCD display hardware I’m using my build. If you are using the images as a game launch image, it would make sense to change the resolution to 1920x1080 or whatever to match your display.
button_map.csv
is a simple text database that associates the basename of a rom/game with a set of text strings that will become the button labels in the final button map image. This file is read by the button_map.sh
script, and should contain one line for every file image you want to generate.
Each field is separated by the comma.
The order of the fields are the MAME standard order: Button1, Button2, Button3, etc
Example contents of button_map.csv:
#BASENAME_OF_ROM,Button1,Button1,Button2,Button3,Button,Button4,
default,B,A,R,Y,X,L
asteroid,Hyperspace,,,Thrust,Fire
pacman,Speed
NOTES:
- The fields may contain spaces or other special characters if desired, just avoid the comma character.
- It does much matter if the file contains lines you will never use, like the first line that describes the field order. All lines are ignored except for the one matched.
- If your game has only one or two buttons, you do not have to specify all 6 field separators ASSUMING you need just the first two (B and A) buttons in the list.
- If your game does not use some of the buttons, AND you need to skip over some buttons; put two or more commas next to each other to indicate the unused buttons. Example:
asteroid,Hyperspace,,,Thrust,Fire
- If you want a to indicate the button is active, but don't want a label, just use whitespace between the commas. Example:
dkong, ,
TIPS
- It is best to keep the button-action text as short as possible. A single word is preferred. The script will adjust the font size, but the text can get small for lengthy labels.
This is a text database the associates parent and clone roms. It is used when a button map image for a clone is desired, but only the button label data available is that of the parent rom.
ImageMagic is the scriptable image editor, used to build up the final image, from all the pieces (background image, button images, logo image, and text labels). It's downloadable for various OS's from: https://imagemagick.org
This wiki is not intended to be a tutorial on ImageMagic. However I used the following features quite a lot:
When placing the button and logo images into the backgrounders image, or placing text, I make a lot of use of the following three options:
- -gravity ( which is immediately followed by: north, south, east, west, northwest, northeast, southeast, or southwest). -Example: -gravity south This places button image at the bottom center of the background image.
- -geometry (which is always followed by a pair signed integer numbers, bunched up together form one string).
Example: -geometry +50+100.
The pair of signed integers forms an X,Y offset. It moves the image slightly up, down, left or right from the spot that the -gravity switch placed it initially. In the above example, +50 means move the image to the right by 50 pixels, and +100 upwards by 100 pixels. It gets slightly confusing because if you use -gravity north to initially place the image at center-top, then +100 would mean to move the image downwards by 100 pixels! - -annotate (which is always followed by a pair signed integer numbers, bunched up together form one string). -annotate does for text strings, what -geometry does for images. It works in conjunction with the -gravity switch to fine tune where the text will end up.
Installing ImageMagic on the Raspberry Pi
sudo apt-get update
sudo apt-get install imagemagick
Installing ImageMagic on the Mac OSX
Follow the instructions at https://www.imagemagick.org/script/download.php
Then edit following line in the findCurrentOSType
function, inside the button_map.sh
script.
export MAGICK_HOME="$HOME/Documents/Hobby/Arcade/ImageMagick-7.0.8
Communication between the two RPi's is done by establishing a TCPIP socket between the two computers. Instructions are sent by a client running the main raspberry pi (RPi1) to a server running on the second raspberry pi (RPi2). The server listens for socket connections, interprets the instructions, takes some action, and sends an acknowledge message back to the client. Note all communication is initiated by the client. The server only responds to the message, and takes some action.
The client is a Python script named: simpleClinet.py
, which runs on RPi1
The server is a Python script named: simpleServer.py
, which runs on RPi2
I use python3, however I believe the scripts also work with python2.7
- "GET" - Used for testing. The sever will send a response back the the client "Yo, What's up".
- "REPEAT some string of text" - Used for testing. The server will strip the keyword REPEAT, and echo the string that was sent.
- "PATH subdirectory rom_basename" - Used for testing. Returns the full pathname of the image file residing on the server. Note this command does not display the image.
- "OPEN subdirectory rom_basename" - This command instructs the server on RPi2 to display the image file returned by the PATH keyword.
- "CLOSE" - This command instucts the server to kill the linux process that is currently displaying an image, but leave the server running.
- "KILL" - Instruct the server process to terminate.
Emulation Station establishes an organized directory hierarchy for storing and accessing rom files. This project follows a similar directory structure for storing the control-map diagrams.
Namely: button map_root_directory / subdirectory / rom_basename+image_suffix
For Example: The rom being selected by EmulationStation on RPi1:
/home/pi/RetroPie/roms/arcade/pacman.zip
Corresponds to the control diagram image on RPi2:
/home/pi/button_map/arcade/pacman.png
- The default button map_root_directory is
/home/pi/button_map
. If a different directory is desired, edit theimage_dir
variable near the top of thesimpleServer.py
file. - The subdirectory will be determined by EmulationStation. ES passes the system directory name to the
run_command-onstart.sh
script. The the subdirectory name is passed to client and finally to the server. Note: You must use the same directory structure on the server/RPi2 for images, as the client/RPi1 uses for roms, else the desired image won't be found. - The rom_basename is handled similarly to the subdirectory. ES passes the rom file name to
run_command-onstart.sh
where the suffix (.zip, .7x, etc.) is stripped off, leaving only the basename of the rom. The rom's basename is passed to client and finally to the server. Note: The image file on the server must have the exact same basename as the rom, else the desired image won't be found. - The default image_suffix is
.png
. However the user can change this by editing theimage_type
variable near the top of thesimpleServer.py
script. Other common extensions might be:.jpg
, or-image.jpg
If the corresponding image file is not found, the server program will look for alternative images to use. Here are the search rules:
- If the rom-specific image is not found, look file an image file with the basename "default", inside the same subdirectory. Example:
/home/pi/button_map/arcade/default.png
This is convenient for console systems like Nintendo, Sega Genesis, etc. or the MAME defaults. - If the system default image is not found, look file an image file with the basename "default", inside the "button map_root_directory" folder. Example:
/home/pi/button_map/default.png
This is convenient for the generic RetroArch button names: A, B, X, Y, L, R etc. - If that file is not found, I have selected a generic image that should be on everyone's raspberry pi.
- If none of the above is found, send a garbage string. Currently, this crashes the server process. I could use suggestion on how to make how to make this more stable.
Finally: Upon the ending a game, the client instructs the server to display the EmulationStation button mapping. The file must reside in the "all" subdirectory, and have a basename of "emulation_station". For Example: /home/pi/button_map/all/emulation_station.png
- Get a copy of the project files. From the [Code] tab at the top of this, Click on the green [Clone or Download] button, athen select [Download ZIP]. Unpack this somewhere on your computer.
- Download/Install ImageMagick. See ImageMagick section above.
- You may need to make the button_map.sh script executable.
chmod +x button_map.sh
- Build your first image
./button_map.sh 88games
- See the Testing and configuration section below.
You may ignore or delete the following files:
- simpleServer.py and simpleClient.py
- run_command_on-start, run_command-onend.sh
- Install FBI. This is a comamnd line utility that display images to the raspberry pi's frame buffer.
sudo apt-get update
sudo apt-get install fbi
- Copy the images files to
/home/pi/button_images/arcade
- Copy the server Python script to
/home/pi/bin/simpleServer.py
- Start the server
cd /home/pi/bin
python3 ./simpleServer.py > /dev/null &
exit
- Copy the client Python script to
/home/pi/bin/simpleClient.py
- Check to see if the run_comand files already exist:
ls /opt/retropie/configs/all/run_command-on*.sh
- If they already exist, you will have to edit them and append commands inside my versions.
- Else copy both files files to
/opt/retropie/configs/all/.
Emulation Station will execute these scripts just prior to launching a game, and just after exiting a game.
(how to set up a daemon on RPi2 to auto-run the server)
(testing tips)