Last active
March 5, 2024 18:52
-
-
Save savetheclocktower/630864d3dbc3dad9ccb6fda4c0151194 to your computer and use it in GitHub Desktop.
ServoStiks & RetroPie
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'io/console' | |
require 'json' | |
require 'optparse' | |
require 'pathname' | |
$opts = OptionParser.new do |opts| | |
opts.banner = "Usage: joystick-type [options] system game\nReturns the type of joystick for the given system and game." | |
opts.separator "" | |
opts.on_tail('-h', '--help', 'Prints this help message.') do | |
STDOUT.puts(opts) | |
exit 0 | |
end | |
end | |
begin | |
$opts.parse! | |
rescue OptionParser::InvalidArgument => e | |
STDERR.puts("#{e.message}\n\n") | |
STDERR.puts($opts) | |
exit 1 | |
end | |
SYSTEM, GAME = ARGV | |
CONTROLS_PATH = Pathname.new('/home/pi/controls') | |
SYSTEM_PATH = CONTROLS_PATH.join(SYSTEM) | |
unless SYSTEM_PATH.directory? | |
STDERR.puts(%Q{System #{SYSTEM} does not exist!}) | |
exit 1 | |
end | |
GAME_PATH = SYSTEM_PATH.join("#{GAME}.cfg") | |
if GAME_PATH.file? | |
puts GAME_PATH.read | |
exit 0 | |
end | |
# At this point, if the game doesn't have a config file, we can try to look | |
# up its joystick type _if_ it's an arcade game. Otherwise we're out of luck. | |
if SYSTEM != 'arcade' | |
STDERR.puts(%Q{Could not find joystick config file for game #{GAME} on system #{SYSTEM}}) | |
exit 1 | |
end | |
def decide_on(type) | |
GAME_PATH.open('w') { |f| f.write(type) } | |
puts type | |
exit 0 | |
end | |
JSON_PATH = SYSTEM_PATH.join('restructuredControls.json') | |
# Reluctantly read from the gigantic JSON file. But then store what we find | |
# so that we never have to do the lookup for that game again. | |
controls = JSON::load(JSON_PATH.open) | |
# Each game has control configurations. Each control configuration has | |
# control sets. Each control set, if it has a joystick, specifies whether | |
# it's 4-way or 8-way. | |
# | |
# 99% of the time, these configurations will not disagree about 4-way versus | |
# 8-way. The remaining 1% can be figured out manually. | |
game = controls['gameMap'][GAME] | |
if game.nil? | |
STDERR.puts(%Q{Game #{GAME} does not exist!}) | |
exit 1 | |
end | |
sets = game['controlConfigurations'].map { |cfg| cfg['controlSets'] }.flatten | |
begin | |
control_types = sets.map { |s| s['controls'][0]['type'] } | |
rescue Exception => e | |
STDERR.puts(%Q{Couldn't figure this game out at all. Maybe it doesn't use a joystick.}) | |
exit 1 | |
end | |
if control_types.all? { |t| t == 'joy-4way' || t == 'joy-2way-horizontal' || t == 'joy-2way-vertical' } | |
decide_on(4) | |
elsif control_types.all? { |t| t == 'joy-8way' } | |
decide_on(8) | |
else | |
STDERR.puts "Can't figure out joystick automatically. Here are the options:" | |
control_types.uniq.each do |type| | |
STDERR.puts " #{type}" | |
end | |
exit 1 | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ARGUMENTS, IN ORDER: | |
# 1. System (e.g., "arcade") | |
# 2. Emulator (e.g. "lr-fba-next") | |
# 3. Full path to game (e.g., /home/pi/RetroPie/roms/arcade/wjammers.zip) | |
if [ -z "$3" ]; then | |
exit 0 | |
fi | |
system=$1 | |
emulator=$2 | |
# Gets the basename of the game (e.g., "wjammers") | |
game=$(basename $3) | |
game=${game%.*} | |
### | |
# Return the joystick to 8-way mode no matter what. | |
# TODO: I don't know why this needs `sudo`. It seems to work fine without it | |
# in an interactive shell. Investigate. | |
sudo /home/pi/bin/set-joystick 8 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/bash | |
# ARGUMENTS, IN ORDER: | |
# 1. System (e.g., "arcade") | |
# 2. Emulator (e.g. "lr-fba-next") | |
# 3. Full path to game (e.g., /home/pi/RetroPie/roms/arcade/wjammers.zip) | |
if [ -z "$3" ]; then | |
exit 0 | |
fi | |
system=$1 | |
emulator=$2 | |
# Gets the basename of the game (e.g., "wjammers") | |
game=$(basename $3) | |
game=${game%.*} | |
### | |
# Figure out the joystick mode of the game. | |
joystick_mode=`/home/pi/bin/joystick-type "$system" "$game"` | |
# Strip all spaces. Replace "8" with an empty string so it fails the | |
# conditional below. | |
joystick_mode=${joystick_mode// /} | |
joystick_mode=${joystick_mode//8/} | |
# If the joystick type needs to be switched to 4-way mode, notify the user. | |
# We don't care about 8-way mode because that's the default. We don't care | |
# about when `joystick-mode` returns nothing, because in that case we take | |
# no action. | |
if [[ ! -z "$joystick_mode" ]]; then | |
DIALOGRC="/opt/retropie/configs/all/runcommand-launch-dialog.cfg" dialog --infobox "\nSetting joystick to ${joystick_mode}-way mode." 5 60 | |
sleep 0.5 | |
fi | |
# TODO: I don't know why this needs `sudo`. It seems to work fine without it | |
# in an interactive shell. Investigate. | |
sudo /home/pi/bin/set-joystick "$joystick_mode" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
""" | |
A script for setting the ServoStik to 4-way mode or 8-way mode. | |
""" | |
usage = """ | |
Usage: set-joystick [4|8|0] | |
Takes a single argument which should be either "4" (four-way), "8" (eight-way), | |
or "0" (which means "I have no clue what to do and am willing to leave it up to | |
this script to decide.") | |
""" | |
import sys | |
from RPi import GPIO | |
GPIO.setmode(GPIO.BCM) | |
MODE_8 = 6 # white | |
MODE_4 = 5 # green | |
GPIO.setup(MODE_4, GPIO.OUT) | |
GPIO.setup(MODE_8, GPIO.OUT) | |
def set_joystick_mode(mode): | |
target_pin = MODE_8 | |
other_pin = MODE_4 | |
if mode == 4: | |
target_pin = MODE_4 | |
other_pin = MODE_8 | |
GPIO.output(other_pin, GPIO.LOW) | |
GPIO.output(target_pin, GPIO.HIGH) | |
mode = sys.argv[1] | |
if mode not in ("0", "4", "8", ""): | |
print("Invalid argument!", file=sys.stderr) | |
print(usage) | |
GPIO.cleanup() | |
sys.exit(1) | |
if mode == "0" or mode == "": | |
# Zero equals a shrug. Put the joystick in 8-way mode. | |
set_joystick_mode(8) | |
elif mode == "4": | |
set_joystick_mode(4) | |
elif mode == "8": | |
set_joystick_mode(8) | |
GPIO.cleanup() | |
sys.exit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I was curious is this for using an Ultimarc Servostik with RetroPie?