chore: merge card markers and game data counts

This commit is contained in:
Abdessamad Derraz committed 2026-10-27 17:10:59 +01:00
commit 1f6c018006
46 files changed
+2510 -910

No files matched your search

+1 -1
View File
@@ -11,7 +11,7 @@
$ErrorActionPreference = "Stop"
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
$defaultInstallSha256 = "71fa422aa38f9710c9aab81ba038cad71df66f574a527dc62e0307c69c30d1b0"
$defaultInstallSha256 = "749d14547ad7a5504ff6ee4c62aca2ec710839174e149df77759c70d3e4fe951"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
+1021 -220
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -18,7 +18,7 @@ esac
TEMP_INSTALLER=""
TEMP_DIRECTORY=""
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
DEFAULT_INSTALL_SHA256="71fa422aa38f9710c9aab81ba038cad71df66f574a527dc62e0307c69c30d1b0"
DEFAULT_INSTALL_SHA256="749d14547ad7a5504ff6ee4c62aca2ec710839174e149df77759c70d3e4fe951"
MAX_INSTALLER_BYTES=2097152
cleanup() {
+8 -8
View File
@@ -27,8 +27,8 @@
{
"dest": "roms/ports/retrobios/install.py",
"repo_path": "install.py",
"size": 775811,
"sha256": "71fa422aa38f9710c9aab81ba038cad71df66f574a527dc62e0307c69c30d1b0",
"size": 818600,
"sha256": "749d14547ad7a5504ff6ee4c62aca2ec710839174e149df77759c70d3e4fe951",
"executable": false
},
{
@@ -71,8 +71,8 @@
"muos": {
"archive": {
"dest": "ARCHIVE/RetroBIOS.muxapp",
"size": 828360,
"sha256": "dc3204c1dab8db00fb10e47cb9d2cad8ad6320b9d5c7d8fff9168c238620d5ef"
"size": 871149,
"sha256": "cbca9dd0e3d7de656965dbff79512991856a03853c0e771da97e5e95d7d31f49"
},
"members": [
{
@@ -92,8 +92,8 @@
{
"name": "RetroBIOS/install.py",
"repo_path": "install.py",
"size": 775811,
"sha256": "71fa422aa38f9710c9aab81ba038cad71df66f574a527dc62e0307c69c30d1b0",
"size": 818600,
"sha256": "749d14547ad7a5504ff6ee4c62aca2ec710839174e149df77759c70d3e4fe951",
"executable": false
},
{
@@ -166,8 +166,8 @@
{
"dest": ".config/modules/retrobios/install.py",
"repo_path": "install.py",
"size": 775811,
"sha256": "71fa422aa38f9710c9aab81ba038cad71df66f574a527dc62e0307c69c30d1b0",
"size": 818600,
"sha256": "749d14547ad7a5504ff6ee4c62aca2ec710839174e149df77759c70d3e4fe951",
"executable": false
},
{
+6
View File
@@ -43,6 +43,12 @@
"system_names": {
"type": "object",
"additionalProperties": { "type": "array", "items": { "type": "string" } }
},
"list_records": {
"description": "What the platform's install list narrows by: the installer names that list as the remedy for --core or --region given with the pack alone only when it records them.",
"type": "array",
"uniqueItems": true,
"items": { "enum": ["systems", "cores", "regions"] }
}
}
}
+37 -1
View File
@@ -22,7 +22,7 @@ import ast
import importlib.util
import re
import sys
from pathlib import Path
from pathlib import Path, PurePosixPath
ROOT = Path(__file__).resolve().parent.parent
PAGE = ROOT / "wiki" / "installer.md"
@@ -154,6 +154,40 @@ def route_keys() -> str:
return _table(heading, rows)
def _marker(rule: _install._OsRule) -> str:
"""A card rule's evidence in words: the file or folder, and the line it
holds for a rule that reads one."""
if rule.method == "file_matches":
path, pattern = rule.values
line = re.sub(r"\\s\*\$$", "", re.sub(r"^(\^|\\A)", "", pattern)).replace("\\", "")
return f"`{path}` holding the line `{line}`"
return ", ".join(f"`{value}`" if PurePosixPath(value).suffix else f"`{value}/`"
for value in rule.values)
def _list_words(plat: str) -> str:
name = _install.display_name(plat)
return f"{name}'{'' if name.endswith('s') else 's'} list"
def card_marker_rows() -> list[list[str]]:
"""The files that name a card or a SHARE drive, in the order they are
read: install.py's card rules, then its SHARE drive files."""
rows = [[_marker(rule), rule.name, f"`{rule.bios}`, {_list_words(rule.manifest)}"]
for rule in _install._card_rules()]
hostname = "system.hostname=BATOCERA"
for plat, marker in _install._SHARE_DRIVES:
name = _install.display_name(plat)
evidence = (f"`{marker}` holding `{hostname}` or no hostname line, and no KNULLI file "
"above" if plat == "batocera" else f"`{marker}`")
rows.append([evidence, f"{name} SHARE drive", f"`bios`, {_list_words(plat)}"])
rows.append([f"`{_install._SHARE_DRIVES[0][1]}` with any other hostname, and no KNULLI "
"file above, or the files of two SHARE drives",
"named by neither: the run says which systems it could be",
"the folder of the system named with `--platform`"])
return rows
def render(page: str) -> str:
"""The page with each marked table written from install.py."""
writers = {
@@ -162,6 +196,8 @@ def render(page: str) -> str:
"events": lambda body: _table(["Kind", "Keys", "When"], event_rows(body)),
"pad-routes": lambda body: _table(["Value", "Input", "Set by"], pad_rows(body)),
"route-keys": lambda _body: route_keys(),
"card-markers": lambda _body: _table(["On the card", "System", "Files go to"],
card_marker_rows()),
}
seen = []
+17 -1
View File
@@ -4759,11 +4759,25 @@ def pack_systems(install_manifest: dict) -> dict:
("the file list comes from an older release") and offered no Choose
systems, the route of a handheld without Wi-Fi.
"""
files = install_manifest.get("files", [])
entries = [*files, *install_manifest.get("omitted_files", [])]
# What the install list narrows by, the installer's recorded_axes: with
# the pack alone it names that list as the way to --core and --region
# only when the list records them. It named install/misterfpga.json for
# --core, a list that records no core.
records = {"systems"} if any("systems" in entry for entry in entries) else set()
if any(copy.get("cores") for entry in files
for copy in [entry, *entry.get("alternatives", []),
*entry.get("slot_choices", [])]):
records.add("cores")
if records or any("regions" in entry for entry in entries):
records.add("regions")
return {
"files": {entry["dest"]: list(entry.get("systems") or [])
for entry in install_manifest.get("files", []) if "systems" in entry},
for entry in files if "systems" in entry},
"system_titles": dict(install_manifest.get("system_titles") or {}),
"system_names": dict(install_manifest.get("system_names") or {}),
"list_records": sorted(records),
}
@@ -4779,6 +4793,8 @@ def annotate_pack_systems(manifest: dict, systems: dict | None) -> None:
for key in ("system_titles", "system_names"):
if systems.get(key):
manifest[key] = systems[key]
if "list_records" in systems:
manifest["list_records"] = systems["list_records"]
def inject_manifest(zip_path: str, manifest: dict) -> None:
+1 -1
View File
@@ -9,4 +9,4 @@
Ctrl-C Quit B/Esc Quit
Ctrl-C Quit B Quit
+1 -1
View File
@@ -12,4 +12,4 @@
Ctrl-C Quit B/Esc Quit
Ctrl-C Quit B Quit
+1 -1
View File
@@ -9,4 +9,4 @@
A/Enter Back
A Back
+1 -1
View File
@@ -12,4 +12,4 @@
A/Enter Back
A Back
+1 -1
View File
@@ -9,4 +9,4 @@
> Install
Back
A/Enter Install B/Esc Back ? Help
A Install B Back ? Help
+1 -1
View File
@@ -12,4 +12,4 @@
A/Enter Install B/Esc Back ? Help
A Install B Back ? Help
+1 -1
View File
@@ -9,4 +9,4 @@
A/Enter Create B/Esc Quit
A Create B Quit
+1 -1
View File
@@ -12,4 +12,4 @@
A/Enter Create B/Esc Quit
A Create B Quit
+3 -3
View File
@@ -5,8 +5,8 @@
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
1-5 of 7
> Choose another setup or folder
Quit
A/Enter Choose B/Esc Back
A Choose B Back PgUp/PgDn Scroll
+1 -1
View File
@@ -12,4 +12,4 @@
Quit
A/Enter Choose B/Esc Back
A Choose B Back
+1 -1
View File
@@ -9,4 +9,4 @@
> Browse for a folder
Type a path
Look again
A/Enter Browse B/Esc Back ? Help
A Browse B Back ? Help
+1 -1
View File
@@ -12,4 +12,4 @@
Look again
A/Enter Browse B/Esc Back ? Help
A Browse B Back ? Help
+1 -1
View File
@@ -9,4 +9,4 @@
FAILED scph5500.bin (HTTP 404)
ok gba_bios.bin
B/Esc Stop ? Help
B Stop ? Help
+1 -1
View File
@@ -12,4 +12,4 @@
B/Esc Stop ? Help
B Stop ? Help
+8 -8
View File
@@ -2,14 +2,14 @@
Each row is an option of the command line, named on the right.
> Preferred regions: North America, Japan --region
Game data: kept --no-game-data
Installed cores only: no (1 found) --installed-cores
Cores: all --core
Parallel downloads: 8 --jobs
BIOS folder: ~/.config/retroarch/system --dest
Copy from: none --from
Preview the file list --dry-run
> Preferred regions: North America, Japan --region
Game data: kept --no-game-data
Installed cores only: no (1 found) --installed-cores
Cores: all --core
Parallel downloads: 8 --jobs
BIOS folder: ~/.config/retroarch/system --dest
Copy from: none --from
Preview the file list --dry-run
Show the command line
+13 -13
View File
@@ -14,26 +14,26 @@
BizHawk
MiSTer FPGA
RetroPie
Allium, SD card Miyoo Mini, Miyoo Mini Plus, Miyoo Mini Flip
AmberELEC, SD card RG351, RG552
Anbernic stock firmware, SD card RG35XX Plus, RG35XX H, RG35XX SP, RG28XX
Allium, SD card Miyoo Mini, Miyoo Mini Plus, Miyoo Mini Flip
AmberELEC, SD card RG351, RG552
Anbernic stock firmware, SD card RG35XX Plus, RG35XX H, RG35XX SP, RG28XX
ArchR, SD card R36S, R33S, R36S Soysauce, Odroid Go Advance, Odroid Go Super, RG351V, +6
ArkOS, SD card RG353M, RG353V, RG503, RGB30, RK2023, RG351MP, RG351V, R35S, RGB10
CrossMix-OS, SD card TrimUI Smart Pro
dArkOS, SD card Odroid Go Advance, RGB10, RG351MP, G350
EmuELEC, SD card Odroid Go
ArkOS, SD card RG353M, RG353V, RG503, RGB30, RK2023, RG351MP, RG351V, R35S, RGB10
CrossMix-OS, SD card TrimUI Smart Pro
dArkOS, SD card Odroid Go Advance, RGB10, RG351MP, G350
EmuELEC, SD card Odroid Go
JELOS, SD card RG351M, RG351V, RG353M, RG353P, RG353V, RG353VS, RG503, RG552, R33S, R36S, +24
KNULLI, SD card RG ARC-S, RG28XX, RG34XX, RG35XX, RG35XX Plus, RG35XX H, RG35XX 2024, +15
KOLOS, SD card RG353P, RG353M, RG353V, RG353VS, RG503, RK2023, RGB30, RGB10 Max 3
Koriki, SD card Miyoo Mini
KOLOS, SD card RG353P, RG353M, RG353V, RG353VS, RG503, RK2023, RGB30, RGB10 Max 3
Koriki, SD card Miyoo Mini
MinUI, SD card RG28XX, RG34XX, RG34XX SP, RG35XX, RG35XX Plus, RG35XX H, RG35XX SP, +16
MiyooCFW, SD card BittBoy, Pocket Go, PowKiddy Q90, PowKiddy V90, PowKiddy Q20 Mini, Sup M3, +1
muOS, SD card RG35XX H, RG35XX Plus, RG35XX SP, RG35XX 2024, RG34XX, RG40XX H, RG40XX V, +4
MyMinUI, SD card RG35XX, Miyoo Mini, Miyoo Mini Flip, Miyoo Mini Plus, Miyoo A30, +16
NextUI, SD card TrimUI Brick, TrimUI Smart Pro
Onion, SD card Miyoo Mini, Miyoo Mini Plus
plumOS, SD card MagicX XU20 V32
RetroOZ, SD card Odroid Go Super, Odroid Go Advance, RGB10 Max, RGB10 Max 2
NextUI, SD card TrimUI Brick, TrimUI Smart Pro
Onion, SD card Miyoo Mini, Miyoo Mini Plus
plumOS, SD card MagicX XU20 V32
RetroOZ, SD card Odroid Go Super, Odroid Go Advance, RGB10 Max, RGB10 Max 2
ROCKNIX, SD card RG351, RG353, RG503, RG552, RG 55G1, RG ARC, RG35XX 2024, RG35XX Plus, +37
spruceOS, SD card Miyoo A30, Miyoo Flip, Miyoo Mini, Miyoo Mini Plus, Miyoo Mini Flip, +5
UnofficialOS, SD card R35S, R36S, RG351M, RG351P, RG351V, RG353M, RG353P, RG353V, RG503, +5
+1 -1
View File
@@ -9,4 +9,4 @@
missing 16.0 KB gba_bios.bin
A/Enter Back
A Back
+1 -1
View File
@@ -12,4 +12,4 @@
A/Enter Back
A Back
+1 -1
View File
@@ -9,4 +9,4 @@
A/Enter Quit B/Esc Stay
A Quit B Stay
+1 -1
View File
@@ -12,4 +12,4 @@
A/Enter Quit B/Esc Stay
A Quit B Stay
+3 -3
View File
@@ -5,8 +5,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
To put them back: python3 install.py
1-8 of 17
A/Enter Exit Up/Down Scroll
A Exit ^v Scroll
+5 -5
View File
@@ -5,11 +5,11 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
To put them back: python3 install.py
--restore
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
1-11 of 17
A/Enter Exit Up/Down Scroll
A Exit ^v Scroll
+10 -142
View File
@@ -322,35 +322,6 @@
A Use this folder B Back
=== create 40x12
RetroBIOS: Create the folder?
/home/user/bios/new does not exist.
The nearest folder that does:
/home/user
> Create it and continue
Choose another folder
A Create B Quit
=== create 40x15
RetroBIOS: Create the folder?
/home/user/bios/new does not exist.
The nearest folder that does:
/home/user
> Create it and continue
Choose another folder
A Create B Quit
=== create 80x24
RetroBIOS: Create the folder?
@@ -604,7 +575,7 @@
Copy from: none
Preview the file list
Show the command line
A Open B Back Left/Right Set
A Open B Back <> Set
=== options 40x15
RetroBIOS: Options
@@ -620,7 +591,7 @@
Sets --region
A Open B Back Left/Right Set
A Open B Back <> Set
=== options 80x24
RetroBIOS: Options
@@ -658,7 +629,7 @@
[ ] Japan
A Tick B Done Left/Right Order
A Tick B Done <> Order
=== regions 40x15
RetroBIOS: Preferred regions
@@ -674,7 +645,7 @@
A Tick B Done Left/Right Order
A Tick B Done <> Order
=== regions 80x24
RetroBIOS: Preferred regions
@@ -754,35 +725,6 @@
A Filter B Back X Tick
=== preview 40x12
RetroBIOS: Preview
4 files to download, 1.0 MB. Nothing
is written.
missing 512.0 KB scph5500.bin
wrong copy 512.0 KB scph5501.bin
missing 4 B pcsx/extra.bin
missing 16.0 KB gba_bios.bin
A Back
=== preview 40x15
RetroBIOS: Preview
4 files to download, 1.0 MB. Nothing
is written.
missing 512.0 KB scph5500.bin
wrong copy 512.0 KB scph5501.bin
missing 4 B pcsx/extra.bin
missing 16.0 KB gba_bios.bin
A Back
=== preview 80x24
RetroBIOS: Preview
@@ -807,35 +749,6 @@
A Back
=== command 40x12
RetroBIOS: Command line
The same choice without questions:
python3 install.py --platform
retroarch --dest
/home/user/.config/retroarch/system
--system nintendo-gba
A Back
=== command 40x15
RetroBIOS: Command line
The same choice without questions:
python3 install.py --platform
retroarch --dest
/home/user/.config/retroarch/system
--system nintendo-gba
A Back
=== command 80x24
RetroBIOS: Command line
@@ -978,8 +891,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
A Exit
@@ -991,8 +904,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
@@ -1032,27 +945,11 @@
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
> Choose another setup or folder
Quit
A Choose B Back
=== error 40x15
RetroBIOS: Something went wrong
Could not fetch the file list for
retroarch after 3 attempts: [Errno
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
1-5 of 7
> Choose another setup or folder
Quit
A Choose B Back
A Choose B Back L1/R1 Scroll
=== error 80x24
RetroBIOS: Something went wrong
@@ -1078,35 +975,6 @@
A Choose B Back
=== quit 40x12
RetroBIOS: Quit?
Quit without installing? Nothing was
written.
> Quit
Stay
A Quit B Stay
=== quit 40x15
RetroBIOS: Quit?
Quit without installing? Nothing was
written.
> Quit
Stay
A Quit B Stay
=== quit 80x24
RetroBIOS: Quit?
+10 -142
View File
@@ -322,35 +322,6 @@
A Use this folder B Back
=== create 40x12
RetroBIOS: Create the folder?
/home/user/bios/new does not exist.
The nearest folder that does:
/home/user
> Create it and continue
Choose another folder
A Create B Quit
=== create 40x15
RetroBIOS: Create the folder?
/home/user/bios/new does not exist.
The nearest folder that does:
/home/user
> Create it and continue
Choose another folder
A Create B Quit
=== create 80x24
RetroBIOS: Create the folder?
@@ -604,7 +575,7 @@
Copy from: none
Preview the file list
Show the command line
A Open B Back Left/Right Set
A Open B Back <> Set
=== options 40x15
RetroBIOS: Options
@@ -620,7 +591,7 @@
Sets --region
A Open B Back Left/Right Set
A Open B Back <> Set
=== options 80x24
RetroBIOS: Options
@@ -658,7 +629,7 @@
[ ] Japan
A Tick B Done Left/Right Order
A Tick B Done <> Order
=== regions 40x15
RetroBIOS: Preferred regions
@@ -674,7 +645,7 @@
A Tick B Done Left/Right Order
A Tick B Done <> Order
=== regions 80x24
RetroBIOS: Preferred regions
@@ -754,35 +725,6 @@
A Filter B Back X Tick
=== preview 40x12
RetroBIOS: Preview
4 files to download, 1.0 MB. Nothing
is written.
missing 512.0 KB scph5500.bin
wrong copy 512.0 KB scph5501.bin
missing 4 B pcsx/extra.bin
missing 16.0 KB gba_bios.bin
A Back
=== preview 40x15
RetroBIOS: Preview
4 files to download, 1.0 MB. Nothing
is written.
missing 512.0 KB scph5500.bin
wrong copy 512.0 KB scph5501.bin
missing 4 B pcsx/extra.bin
missing 16.0 KB gba_bios.bin
A Back
=== preview 80x24
RetroBIOS: Preview
@@ -807,35 +749,6 @@
A Back
=== command 40x12
RetroBIOS: Command line
The same choice without questions:
python3 install.py --platform
retroarch --dest
/home/user/.config/retroarch/system
--system nintendo-gba
A Back
=== command 40x15
RetroBIOS: Command line
The same choice without questions:
python3 install.py --platform
retroarch --dest
/home/user/.config/retroarch/system
--system nintendo-gba
A Back
=== command 80x24
RetroBIOS: Command line
@@ -978,8 +891,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
A Exit
@@ -991,8 +904,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
@@ -1032,27 +945,11 @@
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
> Choose another setup or folder
Quit
A Choose B Back
=== error 40x15
RetroBIOS: Something went wrong
Could not fetch the file list for
retroarch after 3 attempts: [Errno
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
1-5 of 7
> Choose another setup or folder
Quit
A Choose B Back
A Choose B Back L1/R1 Scroll
=== error 80x24
RetroBIOS: Something went wrong
@@ -1078,35 +975,6 @@
A Choose B Back
=== quit 40x12
RetroBIOS: Quit?
Quit without installing? Nothing was
written.
> Quit
Stay
A Quit B Stay
=== quit 40x15
RetroBIOS: Quit?
Quit without installing? Nothing was
written.
> Quit
Stay
A Quit B Stay
=== quit 80x24
RetroBIOS: Quit?
+9 -141
View File
@@ -322,35 +322,6 @@
A Use this folder B Back
=== create 40x12
RetroBIOS: Create the folder?
/home/user/bios/new does not exist.
The nearest folder that does:
/home/user
> Create it and continue
Choose another folder
A Create B Quit
=== create 40x15
RetroBIOS: Create the folder?
/home/user/bios/new does not exist.
The nearest folder that does:
/home/user
> Create it and continue
Choose another folder
A Create B Quit
=== create 80x24
RetroBIOS: Create the folder?
@@ -604,7 +575,7 @@
Copy from: none
Preview the file list
Show the command line
A Open B Back Left/Right Set
A Open B Back <> Set
=== options 40x15
RetroBIOS: Options
@@ -620,7 +591,7 @@
Sets --region
A Open B Back Left/Right Set
A Open B Back <> Set
=== options 80x24
RetroBIOS: Options
@@ -658,7 +629,7 @@
[ ] Japan
A Tick B Done Left/Right Order
A Tick B Done <> Order
=== regions 40x15
RetroBIOS: Preferred regions
@@ -674,7 +645,7 @@
A Tick B Done Left/Right Order
A Tick B Done <> Order
=== regions 80x24
RetroBIOS: Preferred regions
@@ -754,35 +725,6 @@
A Filter B Back X Tick
=== preview 40x12
RetroBIOS: Preview
4 files to download, 1.0 MB. Nothing
is written.
missing 512.0 KB scph5500.bin
wrong copy 512.0 KB scph5501.bin
missing 4 B pcsx/extra.bin
missing 16.0 KB gba_bios.bin
A Back
=== preview 40x15
RetroBIOS: Preview
4 files to download, 1.0 MB. Nothing
is written.
missing 512.0 KB scph5500.bin
wrong copy 512.0 KB scph5501.bin
missing 4 B pcsx/extra.bin
missing 16.0 KB gba_bios.bin
A Back
=== preview 80x24
RetroBIOS: Preview
@@ -807,35 +749,6 @@
A Back
=== command 40x12
RetroBIOS: Command line
The same choice without questions:
python3 install.py --platform
retroarch --dest
/home/user/.config/retroarch/system
--system nintendo-gba
A Back
=== command 40x15
RetroBIOS: Command line
The same choice without questions:
python3 install.py --platform
retroarch --dest
/home/user/.config/retroarch/system
--system nintendo-gba
A Back
=== command 80x24
RetroBIOS: Command line
@@ -978,8 +891,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
A Exit
@@ -991,8 +904,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
@@ -1032,26 +945,10 @@
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
> Choose another setup or folder
Quit
A Choose B Back
=== error 40x15
RetroBIOS: Something went wrong
Could not fetch the file list for
retroarch after 3 attempts: [Errno
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
1-5 of 7
> Choose another setup or folder
Quit
A Choose B Back
=== error 80x24
RetroBIOS: Something went wrong
@@ -1078,35 +975,6 @@
A Choose B Back
=== quit 40x12
RetroBIOS: Quit?
Quit without installing? Nothing was
written.
> Quit
Stay
A Quit B Stay
=== quit 40x15
RetroBIOS: Quit?
Quit without installing? Nothing was
written.
> Quit
Stay
A Quit B Stay
=== quit 80x24
RetroBIOS: Quit?
+10 -10
View File
@@ -924,11 +924,11 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
To put them back: python3 install.py
1-8 of 17
Enter Exit Up/Down Scroll
Enter Exit ^v Scroll
=== result 40x15
RetroBIOS: Finished with errors
@@ -937,14 +937,14 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
To put them back: python3 install.py
--restore
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
1-11 of 17
Enter Exit Up/Down Scroll
Enter Exit ^v Scroll
=== result 80x24
RetroBIOS: Finished with errors
@@ -978,8 +978,8 @@
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
1-5 of 7
> Choose another setup or folder
Quit
Enter Choose Esc Back
+11 -69
View File
@@ -604,7 +604,7 @@
Copy from: none
Preview the file list
Show the command line
A Open R2 Back Left/Right Set
A Open R2 Back <> Set
=== options 40x15
RetroBIOS: Options
@@ -620,7 +620,7 @@
Sets --region
A Open R2 Back Left/Right Set
A Open R2 Back <> Set
=== options 80x24
RetroBIOS: Options
@@ -658,7 +658,7 @@
[ ] Japan
A Tick R2 Done Left/Right Order
A Tick R2 Done <> Order
=== regions 40x15
RetroBIOS: Preferred regions
@@ -674,7 +674,7 @@
A Tick R2 Done Left/Right Order
A Tick R2 Done <> Order
=== regions 80x24
RetroBIOS: Preferred regions
@@ -754,35 +754,6 @@
A Filter R2 Back
=== preview 40x12
RetroBIOS: Preview
4 files to download, 1.0 MB. Nothing
is written.
missing 512.0 KB scph5500.bin
wrong copy 512.0 KB scph5501.bin
missing 4 B pcsx/extra.bin
missing 16.0 KB gba_bios.bin
A Back
=== preview 40x15
RetroBIOS: Preview
4 files to download, 1.0 MB. Nothing
is written.
missing 512.0 KB scph5500.bin
wrong copy 512.0 KB scph5501.bin
missing 4 B pcsx/extra.bin
missing 16.0 KB gba_bios.bin
A Back
=== preview 80x24
RetroBIOS: Preview
@@ -807,35 +778,6 @@
A Back
=== command 40x12
RetroBIOS: Command line
The same choice without questions:
python3 install.py --platform
retroarch --dest
/home/user/.config/retroarch/system
--system nintendo-gba
A Back
=== command 40x15
RetroBIOS: Command line
The same choice without questions:
python3 install.py --platform
retroarch --dest
/home/user/.config/retroarch/system
--system nintendo-gba
A Back
=== command 80x24
RetroBIOS: Command line
@@ -978,8 +920,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
A Exit
@@ -991,8 +933,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
@@ -1032,11 +974,11 @@
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
1-5 of 7
> Choose another setup or folder
Quit
A Choose R2 Back
A Choose R2 Back L1/R1 Scroll
=== error 40x15
RetroBIOS: Something went wrong
+10 -10
View File
@@ -604,7 +604,7 @@
Copy from: none
Preview the file list
Show the command line
Start Open B Back Left/Right Set
Start Open B Back <> Set
=== options 40x15
RetroBIOS: Options
@@ -620,7 +620,7 @@
Sets --region
Start Open B Back Left/Right Set
Start Open B Back <> Set
=== options 80x24
RetroBIOS: Options
@@ -658,7 +658,7 @@
[ ] Japan
Start Tick B Done Left/Right Order
Start Tick B Done <> Order
=== regions 40x15
RetroBIOS: Preferred regions
@@ -674,7 +674,7 @@
Start Tick B Done Left/Right Order
Start Tick B Done <> Order
=== regions 80x24
RetroBIOS: Preferred regions
@@ -978,8 +978,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
Start Exit
@@ -991,8 +991,8 @@
/home/user/.config/retroarch/system
failed: scph5500.bin (HTTP 404)
The files it replaced are kept in
/home/user/.config/retroarch/
retrobios-backup/2026-10-23_1200
/home/user/.config/retroarch/retrobios-backup/2026-10-23_1200
Details: /tmp/retrobios-x/install.log
@@ -1032,8 +1032,8 @@
-2] Name or service not known
Address:
https://raw.githubusercontent.com/
Abdess/retrobios/main/install/
retroarch.json
1-5 of 7
> Choose another setup or folder
Quit
Start Choose B Back
+1 -1
View File
@@ -9,4 +9,4 @@
BIOS folder:
/home/user/.config/retroarch/system
ES-DE found: its BIOS files go to each
A/Enter Continue B/Esc Quit ? Help
A Continue B Quit ? Help
+1 -1
View File
@@ -12,4 +12,4 @@
emulator, not to ES-DE itself.
A/Enter Continue B/Esc Quit ? Help
A Continue B Quit ? Help
+3 -3
View File
@@ -3,9 +3,9 @@
All
None
Filter (/ to type)
> [x] nintendo-gba (gba) 1 file, 16.0 KB
[x] sony-playstation 3 files, 1.0 MB
[ ] nintendo-famicom-disk (ファミコン) in place
> [x] nintendo-gba (gba) 1 file, 16.0 KB
[x] sony-playstation 3 files, 1.0 MB
[ ] nintendo-famicom-disk (ファミコン) in place
+25 -13
View File
@@ -370,18 +370,28 @@ class RefusedBeforeAnyInstall(unittest.TestCase):
(tmp / "retroarch.cfg").write_text("")
(tmp / "cores").mkdir()
(tmp / "cores" / "mgba_libretro.so").write_bytes(b"")
with mock.patch.object(install, "detect_os", return_value="linux"), \
mock.patch.object(install, "detect_frontends", return_value=[]), \
mock.patch.object(install, "detect_platforms", return_value=detected), \
mock.patch.object(install, "fetch_manifest") as fetch, \
mock.patch.object(sys, "argv", ["install.py", "--installed-cores", "--no-input"]), \
contextlib.redirect_stdout(io.StringIO()), \
contextlib.redirect_stderr(io.StringIO()) as err:
with self.assertRaises(SystemExit) as stop:
install.main()
self.assertEqual(stop.exception.code, 1)
self.assertIn("batocera ships its cores", err.getvalue())
fetch.assert_not_called()
# Two setups found stop a run without questions before either is
# read (code_audit_18 P2-3): the refusal is checked with Batocera
# named, and with both found nothing is fetched either.
for argv, said in (
(["--platform", "batocera", "--dest", str(tmp / "bios")],
"batocera ships its cores"),
([], "2 setups were found here")):
with self.subTest(argv=argv), \
mock.patch.object(install, "detect_os", return_value="linux"), \
mock.patch.object(install, "detect_frontends", return_value=[]), \
mock.patch.object(install, "detect_platforms", return_value=detected), \
mock.patch.object(install, "_mounted_cards", return_value=[]), \
mock.patch.object(install, "fetch_manifest") as fetch, \
mock.patch.object(sys, "argv", ["install.py", "--installed-cores",
"--no-input", *argv]), \
contextlib.redirect_stdout(io.StringIO()), \
contextlib.redirect_stderr(io.StringIO()) as err:
with self.assertRaises(SystemExit) as stop:
install.main()
self.assertEqual(stop.exception.code, 1)
self.assertIn(said, err.getvalue())
fetch.assert_not_called()
class AnUnknownTargetStopsTheRunFirst(unittest.TestCase):
@@ -393,12 +403,14 @@ class AnUnknownTargetStopsTheRunFirst(unittest.TestCase):
self.addCleanup(shutil.rmtree, tmp, True)
detected = [("emudeck", tmp / "bios"), ("retroarch", tmp / "system")]
lists = {"emudeck": {"steamos": {"cores": []}}, "retroarch": {"x86_64": {"cores": []}}}
# Listed for both platforms: a listing reads every list found.
with mock.patch.object(install, "detect_os", return_value="linux"), \
mock.patch.object(install, "detect_frontends", return_value=[]), \
mock.patch.object(install, "detect_platforms", return_value=detected), \
mock.patch.object(install, "fetch_targets", side_effect=lists.get), \
mock.patch.object(install, "fetch_manifest") as fetch, \
mock.patch.object(sys, "argv", ["install.py", "--target", "steamos", "--no-input"]), \
mock.patch.object(sys, "argv", ["install.py", "--target", "steamos",
"--list-systems", "--no-input"]), \
contextlib.redirect_stdout(io.StringIO()), \
contextlib.redirect_stderr(io.StringIO()) as err:
with self.assertRaises(SystemExit) as stop:
+9 -3
View File
@@ -1174,11 +1174,17 @@ class ADetectedClosedFolderSaysWhereItCameFrom(unittest.TestCase):
said = " ".join(proc.stderr.split())
self.assertIn(f"than the one {self.cfg} names (name another with --dest)", said)
def test_nothing_installed_comes_after_the_error(self):
def test_two_setups_stop_before_either_folder_is_read(self):
"""code_audit_18 P2-3: a run without questions installs for one
setup, so two found stop on what to name before either folder is
read, the closed one included."""
proc = self.run_detected(True)
self.assertEqual(proc.returncode, 1, proc.stdout + proc.stderr)
error = proc.stderr.index("Error: ")
self.assertGreater(proc.stderr.index("Nothing was installed."), error, proc.stderr)
said = " ".join(proc.stderr.split())
self.assertIn("2 setups were found here, and a run without questions installs for "
"one", said)
self.assertIn("--platform emudeck --dest", said)
self.assertNotIn("Downloading", proc.stdout)
def test_an_assumed_default_reads_plainly(self):
self.assertIn("used by default, since {display_name(name)} was not found",
+4 -3
View File
@@ -828,8 +828,8 @@ class OfflineLeavesFilesMissing(Scratch):
self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
self.assertNotIn("Would download", proc.stdout)
self.assertIn("4 files (", proc.stdout)
self.assertIn("need the internet, which --offline does not use. Without --offline "
"they would go to", proc.stdout)
self.assertIn("need the internet, which --offline does not use. Run without "
"--offline, and they would go to", proc.stdout)
def test_an_archive_not_read_is_only_its_error(self):
listed = manifest()
@@ -967,7 +967,8 @@ class AuditFifteenOffline(Scratch):
# The screen reads that summary as missing files, not failures.
state = install.TuiState()
state.summary = summary
with unittest.mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE: "1"}):
with unittest.mock.patch.dict(os.environ,
{install.OFFLINE_VARIABLE: install.OFFLINE_FLAG_VALUE}):
title, lines = install.tui_outcome(state)
self.assertEqual(title, "Finished with files missing")
self.assertIn("1 installed, 3 not fetched (--offline).", lines[0])
+6 -4
View File
@@ -612,7 +612,8 @@ class TheOneLinerNarrows(unittest.TestCase):
with FakeRepository(selection=False) as repo:
proc = repo.run("--region", "us")
self.assertEqual(proc.returncode, 1)
self.assertIn("records no systems or regions", proc.stderr)
self.assertIn("records no regions, so --region cannot narrow it", proc.stderr)
self.assertIn("older release", proc.stderr)
self.assertEqual(repo.installed(), [])
def test_a_pinned_ref_is_named_as_the_way_out(self):
@@ -675,18 +676,19 @@ class TheOneLinerNarrows(unittest.TestCase):
@unittest.skipUnless(shutil.which("script"), "script(1) provides the terminal")
def test_the_custom_mode_at_a_terminal(self):
"""Typed answers: customise, PlayStation only, no core, US first."""
"""Typed answers: customise, PlayStation only, US first. Its one
core is not asked about (tui_audit_11 P3-10)."""
with FakeRepository() as repo:
command = " ".join(shlex.quote(part) for part in repo.command())
proc = subprocess.run(
["script", "-qec", command, "/dev/null"],
input="c\n2\n\n2\n\n", env=repo.env(), capture_output=True,
input="c\n2\n2\n\n", env=repo.env(), capture_output=True,
text=True, timeout=60, check=False,
)
out = proc.stdout
self.assertEqual(proc.returncode, 0, out + proc.stderr)
self.assertIn("choose systems, cores and regions", out)
self.assertIn("pcsx_rearmed", out)
self.assertNotIn("Cores:", out)
self.assertIn("--system sony-playstation --region north-america", out)
self.assertEqual(repo.installed(), ["pcsx/extra.bin", "scph5501.bin"])
+1160 -57
View File
File diff suppressed because it is too large. Load diff
+4 -3
View File
@@ -181,9 +181,10 @@ class FaqInstallsFromWhatYouHold(unittest.TestCase):
for name in ("muOS", "Onion", "spruceOS", "MinUI", "KNULLI", "ROCKNIX"):
with self.subTest(card=name):
self.assertIn(name, known)
source = (REPO_ROOT / "install.py").read_text(encoding="utf-8")
self.assertIn('f"{card[2]} {kind} ({_mount_name(mount)})"', source)
self.assertIn('else "SD card"', source)
# The label the first screen gives a card found: "Onion SD card".
self.assertEqual(install._card_word(("retroarch", Path("/x/BIOS"), "Onion")), "SD card")
self.assertEqual(install._card_word(("batocera", Path("/x/bios"), "Batocera")),
"SHARE drive")
def test_a_wiped_card_links_the_copy(self):
section = self._section("Lost or wiped card?")
+8 -6
View File
@@ -88,10 +88,12 @@ Arrows move, Enter chooses, Esc goes back, as A and B on a handheld.
## 3. Install
The next screen counts missing files and free space.
It counts missing files and free space.
Press Enter on **Install**. **Choose systems** keeps the consoles you
play.
**Game data** (only a game reads it) has its own row.
**Old card?** In a card reader, choose **Copy the BIOS files from your old
card or a folder**, then the card.
@@ -102,11 +104,11 @@ Esc or Ctrl+C stops, B on a handheld. Run again to resume.
## 5. Read the result
- **Done**: all files are in place.
- **Finished with errors**: run the command again. It retries only those.
- **Finished with errors**: run it again. It retries only those.
- **Finished with files missing**: run it again online.
- **Nothing installed**: the screen says why. See [If it stops](#if-it-stops).
For questions line by line (screen readers), add `--plain`.
For line-by-line questions (screen readers), add `--plain`.
## What the command does
@@ -129,8 +131,8 @@ All good:
## Undo
Files it replaces go to a `retrobios-backup` folder beside your BIOS folder.
The result says how to restore them.
Replaced files go to `retrobios-backup` beside your BIOS folder. The result
says how to restore them.
## If it stops
@@ -166,7 +168,7 @@ You cannot write there. Do what the message says.
### The card is full
Nothing was written. Free some space, or choose another folder.
Nothing was written. Free some space there.
### The game still does not start
+89 -21
View File
@@ -176,7 +176,7 @@ install starts.
| Back | Esc, Backspace | B, Select (B alone with muxterm's own keys, where Select shows its keyboard) |
| Options | `o`, Tab | Y |
| Filter a long list | `/` then type, Enter on a lone match chooses it | muxterm: Select shows a keyboard. Elsewhere none (the setup list puts the SD cards after RetroArch) |
| Keys of the screen | `?`, F1 | |
| Keys of the screen | `?`, F1 (F1 alone while typing a filter, where the help lists the keys that do not type) | |
| Stop an install | Esc, `q`, Ctrl+C | B, Select+Start (B alone with muxterm's own keys) |
| Quit | `q`, Ctrl+C | B on the first screen |
| Pause, back with `fg` (Linux, macOS) | Ctrl+Z | |
@@ -197,10 +197,17 @@ progress, and a second one stops at once. Select+Start on a handheld ends the
installer with a signal (SIGTERM), which stops it the same way. Either way the
result says how many files were installed, and it stays printed in the terminal
once the screen closes, with the command that repeats the run. A run that failed
keeps its log and names it, and every other run leaves nothing behind.
keeps its log and names it, and every other run leaves nothing behind. A path
or a command on the result is never split inside a word: one longer than the
window takes a line of its own, which the terminal folds, and a command breaks
only between its arguments. Every path a run names is spelled the way its BIOS
folder was named, the backup folder and the save directory included
(`/sdcard/RetroArch` on Android, not the `/storage/emulated/0` it links to).
It opens only for an install, at a terminal of at least 40 columns and 12 rows
(a smaller window says so, with its size) whose `TERM` is set, is not `dumb`
(a smaller window says so, with its size, before the first question:
`The window is 39x12: questions come line by line (40x12 for the full
screen).`) whose `TERM` is set, is not `dumb`
and can draw it: where the terminal's description
(terminfo) has no way to move the cursor, or moves it with other sequences
than the ANSI ones the screen writes (`TERM=vt52`), the questions come line by
@@ -217,7 +224,10 @@ However the screen ends (Enter on the result, `q`, Ctrl+C, Ctrl+D, SIGTERM, a
hangup), the terminal is given back as the screen found it: the cursor shown,
the main screen back, echo and line editing on. Ctrl+Z, or SIGTSTP from
outside, gives it back the same way and stops the run, and `fg` redraws the
screen where it was.
screen where it was. Ctrl+Z stops it only when a shell with job control
started it, the one thing that can resume it: started from a terminal app's
`-e`, a desktop entry or a launcher's `sh -c`, the key is ignored and the bar
says why.
- `--tui` asks for the full screen, and names the reason when it cannot open
(code 2).
@@ -599,15 +609,24 @@ the full screen cannot open (a terminal smaller than 40x12, `TERM=dumb`), the
same choice comes as questions after detection:
```
RetroArch: 8069 files, 6.5 GB.
RetroArch: 8348 files, 7.1 GB.
3259 BIOS files (4.4 GB) and 5089 game data files (2.7 GB).
BIOS folder: /home/me/.config/retroarch/system
Enter) install everything
i) only what the installed cores read: 100 files, 44.2 MB
c) choose systems, cores and regions
f) copy from a folder or an old card
g) leave out the 5089 game data files (2.7 GB), game data: files a game or a game engine reads, of no use to the other cores
q) quit
```
A list that marks its game data counts it apart from the BIOS files, on the
plan, in this menu and on the result (`Installed: 3259 BIOS files and 5089 game
data files.`). `g` leaves it out, as `--no-game-data` does, and counts again
(`g` then keeps it). The plan screen has the same choice as a row of its own,
**Game data (5089 files, 2.7 GB): kept, leave out**, one press toggling it,
and Options keeps its **Game data** row too.
`i` appears for RetroArch, Lakka and RetroPie when cores are found installed,
and the line above is a RetroArch with Beetle PSX HW, Snes9x, mGBA, Genesis Plus GX
and FCEUmm.
@@ -615,7 +634,9 @@ It keeps what those cores read and drops the systems none of them emulates,
the rule `--installed-cores` applies.
`c` walks through three numbered lists, each answered with numbers such as
`1,4,7-9`, or Enter to keep everything on that axis.
`1,4,7-9`, or Enter to keep everything on that axis. The letter names the
lists it asks (`c) choose systems` with a MiSTer pack), and a list with one
answer is not asked.
- **Systems.** The consoles and computers the platform declares, titled and
ordered as the full screen's Choose systems lists them, the id `--system`
@@ -637,6 +658,16 @@ without questions, every other option of the run in it, for instance
--system sony-playstation --region north-america`. Enter then installs, and
`c` chooses again.
An option is refused by the axis the list does not record, with what works
instead. The MinUI, NextUI and MyMinUI lists record cores and regions and no
system: `--core` and `--region` narrow them, `--system` is refused with
`Run it without --system, or narrow with --core and --region`. A pack records
the systems of its files and what its platform's list narrows by: with the
pack alone, `--core` or `--region` names that list (`--manifest FILE`, a copy
of `install/minui.json`) only when it records them, and MiSTer FPGA's pack
says its list records no cores. A list from an older release records none of
the three, and the one-line installer fetches the current one.
The same choices on the command line:
```bash
@@ -746,7 +777,7 @@ what the options name, everything by default.
| <span id="option-list-cores"></span>`--list-cores` | Print the cores whose extra files a platform installs |
| <span id="option-list-emulators"></span>`--list-emulators` | Print every name `--emulator` accepts, each buildbot name beside the emulator it stands for |
| <span id="option-romm-firmware"></span>`--romm-firmware TEMPLATE` | RomM: where each platform's firmware goes in the library, as `filesystem.structure.firmware` in RomM's `config.yml` says (`{platform}/bios` for a library laid out as `{platform}/roms`). Read from `config.yml` beside the library when it is there. See [RomM firmware layout](#romm-firmware-layout) |
| <span id="option-no-input"></span>`--no-input` | Never ask a question, even at a terminal. A run whose output goes to a file or a pipe asks nothing either, and says so on stderr |
| <span id="option-no-input"></span>`--no-input` | Never ask a question, even at a terminal. A run whose output goes to a file or a pipe asks nothing either, and says so on stderr. It finds the setups and the mounted cards the screen finds: one is taken, as Enter takes it, and two stop the run with an `error` event (`stage` `detect`, `reason` `conflict`) naming each with its `--platform` and `--dest` |
| <span id="option-check"></span>`--check` | Report and exit without writing |
| <span id="option-dry-run"></span>`--dry-run` | Show what would be downloaded, the totals first, then by system and with sizes, without writing anything. A plan taller than the screen names the ten largest systems, and `--verbose` lists every system and file |
| <span id="option-yes"></span>`--yes`, `-y` | Do not ask before a download of 1 GB or more, nor anything else. Implies `--no-input`, so a run that needs an answer (nothing found here, two setups found) stops on what to name instead |
@@ -864,20 +895,42 @@ A card that holds a system's own files is read the same way, without
`--platform` or with the one that names its list, by the rules the table above
gives for the device, below the card's root instead of its mount point:
<!-- generated: card-markers -->
| On the card | System | Files go to |
|-------------|--------|-------------|
| `system/configs/emulationstation/about.info` holding the line `KNULLI` | KNULLI | `bios`, KNULLI's list |
| `system/batocera.conf` holding the line `system.hostname=KNULLI` | KNULLI | `bios`, KNULLI's list |
| `.config/system/configs/system.cfg` holding the line `root.password=rocknix` | ROCKNIX | `roms/bios`, ROCKNIX's list |
| `MUOS/` | muOS | `MUOS/bios`, RetroArch's list |
| `.tmp_update/onionVersion/version.txt` | Onion | `BIOS`, RetroArch's list |
| `spruce/` | spruceOS | `BIOS`, RetroArch's list |
| `System/usr/trimui/crossmix-version.txt` | CrossMix-OS | `BIOS`, RetroArch's list |
| `.tmp_update/onionVersion/version.txt` | Onion | `BIOS`, RetroArch's list |
| `.allium/` | Allium | `BIOS`, RetroArch's list |
| `Koriki/version.txt` | Koriki | `BIOS`, RetroArch's list |
| `system/batocera.conf` with `system.hostname=KNULLI`, as KNULLI's first boot writes its share | KNULLI | `bios`, KNULLI's list |
| `.config/system/configs/system.cfg` with `root.password=rocknix`, as ROCKNIX's first boot writes its storage | ROCKNIX | `roms/bios`, ROCKNIX's list |
| `system/batocera.conf` holding `system.hostname=BATOCERA` or no hostname line, and no KNULLI file above | Batocera SHARE drive | `bios`, Batocera's list |
| `system/recalbox.conf` | Recalbox SHARE drive | `bios`, Recalbox's list |
| `system/batocera.conf` with any other hostname, and no KNULLI file above, or the files of two SHARE drives | named by neither: the run says which systems it could be | the folder of the system named with `--platform` |
The full screen lists such a card on its first screen ("muOS SD card (E:\)").
<!-- /generated: card-markers -->
Each file is one the system writes. KNULLI is read by `about.info` first,
which no menu writes: its HOSTNAME row rewrites `system.hostname`, and a KNULLI
card renamed there was read as a Batocera SHARE drive. ROCKNIX's line changes
with its root password, and a card whose password was changed is named by
nothing, never by another system. A drive whose files fit two systems is named
by neither: the first screen and `--plain` say which systems it could be and
the two commands that name it, and a `--dest` named with one of them takes it
as that system's, with a note.
The full screen lists such a card on its first screen ("muOS SD card (E:\)"),
and a SHARE drive the same way ("Batocera SHARE drive (SHARE)"): its root, typed
or given with `--dest`, stands for its `bios` folder. Two cards of one system
say what their BIOS folder holds ("Onion SD card (OLDONION, 6 BIOS files)"),
the one holding fewer first.
Named by its system (`--platform muos`, `--platform knulli`), a `--dest` that
is another system's card is refused. One that holds none of the system's
is another system's card is refused, and so is another system's SHARE drive
for Batocera and Recalbox. One that holds none of the system's
files is refused where the card always carries them. For KNULLI, ROCKNIX and
the systems no file on the card names, it gets the system's folder below it
(`bios`, `roms/bios`), with a note. Named with a file list instead
@@ -1009,9 +1062,16 @@ and `--plain` gives the same list numbered, in the same order, with `--dest`
too. Both find the SD cards mounted here, the screen under **Found on this
machine**. With a setup found, the setup screen lists it with **Another setup
or folder**, and `--plain` asks the same: Enter takes the first, `o` opens the
numbered list and then the folder, `q` quits. A platform named, or read from
a list or a pack, and found nowhere gets its folder asked, its usual one under
Enter, the mounted drives numbered. A folder typed is read from the current
numbered list and then the folder, `q` quits. A platform named and found
nowhere gets its folder asked, its usual one under Enter, the mounted drives
numbered. A list or a pack read by card setups too (RetroArch's, read by Onion,
muOS, ArkOS and the others) opens the setup list instead, filtered to the
setups that read it, RetroArch first: Enter on it asks RetroArch's folder. At
that question a drive is numbered by the folder its system reads (`ONION:
BIOS`), a drive nothing names by its `bios` folder (`EASYROMS: bios`), never
by its root, which no setup reads. Another system's card or SHARE drive, and a
drive two systems fit, are left out, and a line names them: each is reached
through its own setup. A folder typed is read from the current
one when it is not a full path, and named in full after. `q` quits there too
(a folder named `q` is typed `./q`), and Enter with no default says what to
type. On a computer Batocera and Recalbox have no default: the drives are
@@ -1360,12 +1420,20 @@ That keeps the installer's questions working when the script is piped from
The manifest is fetched over the network and treated as untrusted input. Every
path it carries goes through one validator that refuses an absolute path, a
drive letter, a backslash, a null byte, a doubled separator, a trailing slash
and any `..` component, so a destination cannot climb out of the BIOS
directory. Manifest, target list and payloads each have a size cap, the file
drive letter, a backslash, a null byte or any other control character, a
doubled separator, a trailing slash and any `..` component, so a destination
cannot climb out of the BIOS directory and no file is named with a terminal
command. Manifest, target list and payloads each have a size cap, the file
list a count cap, and the sum of the declared sizes is checked against the
total the manifest claims.
Every other string from outside is shown, never obeyed: the names a list or
a pack records, a card's label and a folder a configuration names reach the
terminal, line by line or on the screen, and the `--events` stream with a `?`
for each control character. A folder a configuration names with one is not
taken: the run says so and asks for `--dest`, its default being no answer
for a setup that reads another folder.
Symbolic links met under the BIOS root are followed on purpose: they are the
user's own layout, and EmuDeck links `bios/shadps4/sys_modules` into shadPS4's
data directory where the emulator actually reads it. The boundary is lexical,
@@ -1419,7 +1487,7 @@ fields, the installer refuses to narrow rather than install everything.
| `0` | everything asked for is installed or already up to date |
| `1` | a failure: the one-liner could not download or verify `install.py`, or found no Python 3.8 (nothing was run), an unusable base URL, an unknown platform or target, `--installed-cores` with no core found, a manifest that fails validation, a fetch that never succeeded, no platform to install for in a non-interactive run, some files failed or were left out by `--offline` while others installed, `--check` found files to fetch, a `--from-pack` pack that cannot be read, lacks a part or is for another platform, a `--from` folder that does not exist or cannot be read, a `--dest` that is not the card of the system named (another system's card, a folder inside one, a drive with none of its files where its card always has them, or a folder that does not exist), `--restore` could not put a file back, or `--add-app` could not put every file of the app on the card |
| `2` | nothing was installed: every file the run tried failed (a BIOS folder that cannot be written, for one), or `--offline` left every file out, the drive has too little free space for the download (checked before any folder is created), or the question about a folder that does not exist, named with `--dest` or typed at the folder question, was answered no. Also an option the installer refused before any download: an unknown option, `--jobs` outside 1 to 32, `--target` with `--every-board` or `--from-pack`, `--target` or `--list-targets` with `--offline` (or `RETROBIOS_INSTALL_OFFLINE` set), which read a core list from the network, `--add-app` with `--check`, `--dry-run`, a listing, `--from-pack` or `--offline`. The message then starts with `install.py: error:`. Also `--add-app` for a folder on no card that takes the app, said in an `Error:` line and an `app` event before anything is written. With `--restore`, a folder that is not a dated folder inside `retrobios-backup` |
| `130` | stopped with Ctrl+C, or with `q`, Ctrl+C or Ctrl+D at a question, or the full screen closed with no button pressed (`RETROBIOS_IDLE_EXIT`) before an install. Run the same command again to carry on |
| `130` | stopped with Ctrl+C, or with `q`, Ctrl+C or Ctrl+D at a question, or the full screen closed with no button pressed (`RETROBIOS_IDLE_EXIT`) before an install. A quit chosen (`q`, **Quit**) is code `130` too, and the terminal keeps `RetroBIOS: quit. Nothing was installed.` where a stop keeps `stopped`. Run the same command again to carry on |
| `141` | the output was piped to a reader that closed early (`--list-platforms \| head`) |
<!-- /generated: exit-codes -->
@@ -1475,7 +1543,7 @@ other schemas under `api/v1/schemas/`.
| `data` | `platform`, `files`, `bytes` | Right after `declared`: the data-tree files to fetch (the `data_missing` of `check`) and the bytes they write once in place |
| `found` | `platform`, `dest`, `folder`, `path`, `member`, `reason` | Each file to install that this machine already holds, after `check` and before anything is written, in `--check` and `--dry-run` too. `folder` is the `--from` folder as given, or the `bios_dir` of the check when the BIOS folder holds the file at another place, and then `reason` says where in words (`nested folder: ...` for a misplaced file, `the same file is at ...` for one the list installs there too). `path` is the file, and `member` the ZIP member holding the bytes when `path` is an archive, an empty string otherwise. Its copy is reported by a `downloaded` event |
| `unreadable` | `platform`, `folder`, `path`, `member`, `reason` | Each file in a `--from` folder that could not be read and may be one the run still needs, right after the `found` events: its size is that of a file no copy was found for, or unknown (a folder that could not be listed, a ZIP that would not open). `member` names the ZIP member, or is empty. `reason` says why in words (`Permission denied`, `it is encrypted, a password is needed`) |
| `saves` | `platform`, `files`, `folder` | After `choices` and before `checking`, when the files the run installs (once `--system` and the other choices narrowed the list) hold some read from the frontend's save directory and that directory is known: how many, and the `folder` they go to, where `<system>` and `<core>` stand for one folder per system or per core. When it is not known, the files are counted in the summary's `skipped` instead (`no_save_directory`) |
| `saves` | `platform`, `files`, `folder` | After `choices` and before `checking`, when the files the run installs (once `--system` and the other choices narrowed the list) hold some read from the frontend's save directory and that directory is known: how many, and the `folder` they go to, where `<system>` and `<core>` stand for one folder per system or per core (the screen and `--plain` say it in words: "a folder per core under /sdcard/RetroArch/saves"). When it is not known, the files are counted in the summary's `skipped` instead (`no_save_directory`) |
| `download` | `platform`, `files`, `bytes` | Before the downloads start. Counts the files copied from this machine too |
| `progress` | `files_done`, `files_total`, `bytes_done`, `bytes_total` | At most every half second while bytes arrive |
| `transfer` | `bytes_local`, `bytes_network` | Right after each `progress` event, and once when the files of a `download` event are done. It splits `bytes_done`: `bytes_local` came from this machine (a copy found by `--from` or in the BIOS folder, the pack, a partial copy resumed), `bytes_network` from the network. A download speed is `bytes_network` over the time elapsed |
@@ -1510,7 +1578,7 @@ RetroArch folder that holds only `scph5501.bin`, in the order written:
|----------|--------|
| `RETROBIOS_REF` | Branch or tag the file list and the files committed to the repository are read from. Defaults to `main`. Files the manifest marks `release_asset` always come from the `large-files` release, whatever the ref, and that release replaces an asset in place when it is rebuilt. Each release deletes the previous release tags, so a tag holds a file list until the next release. For contributors: [release process](release-process.md#cutting-a-release) |
| `RETROBIOS_BASE_URL` | Base URL for the manifest and the files it declares. HTTPS only, plain HTTP allowed to loopback for end-to-end tests. Whoever controls this base controls the expected hashes, hence the check. A file list that cannot be fetched names the address, and this variable when it is set |
| `RETROBIOS_INSTALL_OFFLINE` | Set to anything but `0`: no network request, as with `--offline`. The runs the full-screen interface starts inherit it. `RETROBIOS_OFFLINE` is the build scripts' own and leaves the installer alone |
| `RETROBIOS_INSTALL_OFFLINE` | Set to anything but `0`: no network request, as with `--offline`. The runs the full-screen interface starts inherit it. The words then name the variable (`not fetched (RETROBIOS_INSTALL_OFFLINE=1)`, `run it with RETROBIOS_INSTALL_OFFLINE unset`), and `--offline` where the option was given. `RETROBIOS_OFFLINE` is the build scripts' own and leaves the installer alone |
| `RETROBIOS_OS` | Names the host outright (`linux`, `wsl`, `windows`, `darwin`, `android`) instead of detecting it |
| `EXTERNAL_STORAGE` | Android only, the shared storage root RetroArch builds its default directories from. Defaults to `/storage/emulated/0` |
| `RETROBIOS_INSTALL_URL` | Where the bootstrap fetches `install.py`. HTTPS only |