-
Notifications
You must be signed in to change notification settings - Fork 174
Expand file tree
/
Copy pathretrogame.py
More file actions
executable file
·192 lines (156 loc) · 6.02 KB
/
Copy pathretrogame.py
File metadata and controls
executable file
·192 lines (156 loc) · 6.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# SPDX-FileCopyrightText: 2024 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
Adafruit Retrogame Setup Script
Downloads and installs the retrogame GPIO-to-keypress utility plus one
of several pre-baked configuration files, and sets up a systemd unit
to auto-start retrogame at boot.
Notes on modernization (2026):
- rc.local is deprecated on Bookworm/Trixie. Autostart uses a
retrogame.service systemd unit instead of editing /etc/rc.local.
- The udev rule string is now a plain (non-raw) string so the
double-quotes inside the rule aren't backslash-escaped, which is
invalid udev syntax and broke the rule on the previous version.
"""
import os
from adafruit_shell import Shell
shell = Shell()
shell.group = "Retrogame"
RETROGAME_URL = (
"https://raw.githubusercontent.com/adafruit/Adafruit-Retrogame/master/retrogame"
)
RETROGAME_CFG_BASE = (
"https://raw.githubusercontent.com/adafruit/Adafruit-Retrogame/master/configs"
)
def write_retrogame_service():
"""Install (or overwrite) the retrogame.service systemd unit."""
shell.write_text_file(
"/etc/systemd/system/retrogame.service",
"""[Unit]
Description=Adafruit Retrogame GPIO-to-keypress daemon
After=multi-user.target
[Service]
Type=simple
ExecStart=/usr/local/bin/retrogame
Restart=on-failure
RestartSec=2
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
""",
append=False,
)
shell.run_command("systemctl daemon-reload")
shell.run_command("systemctl enable retrogame.service")
def uninstall():
"""Remove retrogame and all files this installer creates."""
print("\nThis will remove retrogame, its systemd service,\nand the udev rule.\n")
if not shell.prompt("Uninstall retrogame?", default="n"):
print("Canceled.")
shell.exit()
print("Stopping and removing retrogame service...", end="")
# Tolerate an already-stopped/absent unit so uninstall stays idempotent.
shell.run_command("systemctl stop retrogame.service", suppress_message=True)
shell.run_command("systemctl disable retrogame.service", suppress_message=True)
shell.remove("/etc/systemd/system/retrogame.service")
shell.run_command("systemctl daemon-reload")
print("OK")
print("Removing retrogame binary...", end="")
shell.remove("/usr/local/bin/retrogame")
print("OK")
print("Removing udev rule...", end="")
shell.remove("/etc/udev/rules.d/10-retrogame.rules")
print("OK")
# Clean up any legacy rc.local autostart line from older installs.
if shell.exists("/etc/rc.local"):
shell.pattern_replace(
"/etc/rc.local", r"[^\n]*retrogame[^\n]*\n", multi_line=True
)
# The config file is user-editable; keep it by default.
if shell.exists("/boot/retrogame.cfg"):
if shell.prompt("Also remove /boot/retrogame.cfg?", default="n"):
shell.remove("/boot/retrogame.cfg")
print("Removed /boot/retrogame.cfg")
else:
print("Keeping /boot/retrogame.cfg")
print("\nretrogame has been uninstalled.")
shell.prompt_reboot()
print("Done")
shell.exit()
def main():
shell.clear()
print("""This script downloads and installs
retrogame, a GPIO-to-keypress utility
for adding buttons and joysticks, plus
one of several configuration files.
Run time <1 minute. Reboot recommended.
""")
# Grouped by config name and menu label.
config = {
"pigrrl2": "PiGRRL 2 controls",
"pocket": "Pocket PiGRRL",
"zero": "PiGRRL Zero",
"super": "Super Game Pi",
"2button": "Two buttons + joystick",
"6button": "Six buttons + joystick",
"bonnet": "Adafruit Arcade Bonnet",
"cupcade-orig": "Cupcade (gen 1 & 2 only)",
}
retrogame_select = shell.select_n(
"Select configuration:",
list(config.values()) + ["Uninstall retrogame", "Quit without installing"],
)
if retrogame_select == len(config) + 1:
uninstall()
return
if retrogame_select > len(config):
return
config_name = list(config.keys())[retrogame_select - 1]
if shell.exists("/boot/retrogame.cfg"):
print("/boot/retrogame.cfg already exists.\nContinuing will overwrite file.\n")
if not shell.prompt("CONTINUE?", default="n"):
print("Canceled.")
shell.exit()
print("Downloading, installing retrogame...", end="")
# Download to tmpfile because the daemon might already be running.
if shell.run_command(f"curl -f -s -o /tmp/retrogame {RETROGAME_URL}"):
shell.move("/tmp/retrogame", "/usr/local/bin/retrogame")
os.chmod("/usr/local/bin/retrogame", 0o755)
print("OK")
else:
print("ERROR")
print("Downloading, installing retrogame.cfg...", end="")
if shell.run_command(
f"curl -f -s -o /boot/retrogame.cfg {RETROGAME_CFG_BASE}/retrogame.cfg.{config_name}"
):
print("OK")
else:
print("ERROR")
print("Performing other system configuration...", end="")
# Add udev rule (will overwrite if present). Plain string, no raw prefix:
# raw strings keep the backslashes in front of the inner quotes, which is
# invalid udev syntax and silently breaks the rule.
shell.write_text_file(
"/etc/udev/rules.d/10-retrogame.rules",
'SUBSYSTEM=="input", ATTRS{name}=="retrogame", ENV{ID_INPUT_KEYBOARD}="1"',
append=False,
)
if config_name == "bonnet":
# Arcade Bonnet uses an MCP23017 over I2C; make sure I2C is on.
shell.run_raspi_config("do_i2c 0")
# Auto-start retrogame at boot via systemd unit.
write_retrogame_service()
# Clean up any legacy rc.local autostart line from older installs so we
# don't double-launch retrogame alongside the systemd unit.
if shell.exists("/etc/rc.local"):
shell.pattern_replace(
"/etc/rc.local", r"[^\n]*retrogame[^\n]*\n", multi_line=True
)
print("OK")
shell.prompt_reboot()
print("Done")
if __name__ == "__main__":
shell.require_root()
main()