chore: merge main into the engine round

This commit is contained in:
Abdessamad Derraz committed 2026-10-23 19:07:44 +02:00
commit b34a6058f7
47 files changed
+2731 -442

No files matched your search

+30 -34
View File
@@ -67,44 +67,44 @@ curl -fsSL https://raw.githubusercontent.com/Abdess/retrobios/main/install.sh |
On Batocera, Recalbox and similar setups, see
[Get your files](../which-pack.md).
## 2. Check the folder it found
## 2. Check the setup it found
It shows your setup and its BIOS folder:
It opens a menu:
```
Found <your setup> at <its folder>
RetroBIOS: Where do you play?
Found on this machine:
> <your setup>
Another setup or folder
BIOS folder: <its folder>
```
- **Right folder?** Go on.
- **Wrong folder?** Press Ctrl+C. Run it again with your folder:
- **Right folder?** Press Enter.
- **Wrong folder?** Choose **Another setup or folder**, then browse to yours.
- **A handheld's SD card in a reader?** It is listed, as **muOS SD card**.
<!-- os-tabs windows: --dest D:\path\to\bios -->
```sh
curl -fsSL https://raw.githubusercontent.com/Abdess/retrobios/main/install.sh | sh -s -- --dest ~/path/to/bios
```
Arrows move, Enter chooses, Esc goes back. A controller's A and B do the same.
## 3. Choose what to install
## 3. Install
```
Enter) install everything
i) only what the installed cores read
c) choose systems, cores and regions
q) quit
```
The next screen counts the missing files and the free space.
Press Enter on **Install**. **Choose systems** keeps the consoles you
play.
**Enter** installs everything. **c** lets you pick consoles.
**Old card?** In a card reader, choose **Copy the BIOS files from your old
card or a folder**, then the card. It stays unchanged.
## 4. Wait
Ctrl+C stops it. Run the command again to carry on.
B or Ctrl+C stops it. Run it again to carry on.
## 5. Read the last line
## 5. Read the result
- **`Done.`** `N files installed, M already up to date.` All files are in place.
- **`Finished with errors.`** Some files failed. Run the same command again.
It retries only those.
- **`Nothing was installed.`** The lines above it say why. See
[If it stops](#if-it-stops).
- **Done**: all files are in place.
- **Finished with errors**: run the command again. It retries only those.
- **Nothing installed**: the screen says why. See [If it stops](#if-it-stops).
For questions line by line (screen readers), add `--plain`.
## What the command does
@@ -127,18 +127,14 @@ All good:
## Undo
Every file it replaces goes to a `retrobios-backup` folder next to your BIOS
folder. The last lines say how to put them back.
Files it replaces go to a `retrobios-backup` folder beside your BIOS folder.
The result says how to restore them.
## If it stops
### No supported platform detected.
### Nothing was found here.
At a terminal, a menu follows. Pick your setup by its number, then type its
BIOS folder, or press Enter for the usual one.
With `--no-input`, or without a terminal, it stops and prints the command to
use.
Choose **Another setup or folder**, then your setup and its folder.
### Error: Python 3.8 or newer is required.
@@ -157,9 +153,9 @@ The download was cut short. Nothing was changed. Run the command again.
You cannot write there. Do what the message says.
### Not enough space on the drive holding ...
### The card is full
Nothing was written. Free some space, or pick another drive with `--dest`.
Nothing was written. Free some space, or choose another folder.
### The game still does not start
+80 -29
View File
@@ -67,7 +67,10 @@ curl -fsSL https://raw.githubusercontent.com/Abdess/retrobios/main/install.sh \
```
`--dest` is the BIOS folder itself: on a card, `retroarch/cores/system` for
RetroArch on Switch, `RetroArch/system` on Android.
RetroArch on Switch, `RetroArch/system` on Android. The root of a handheld's
card works too when the installer knows that card (muOS, Onion, spruceOS,
KNULLI, ROCKNIX and the MinUI family, see
[Platform detection](#platform-detection)): the files go where its system reads.
PowerShell needs another form. `iex` takes the script text as its own argument,
so anything appended to `irm ... | iex` is read as an argument to `iex` and
@@ -454,6 +457,9 @@ python install.py --from ~/Downloads --from /media/me/backup
python install.py --check --from /media/me/STOCK
```
The first line names the root of the muOS card, the one holding `MUOS`: the
files go to `MUOS/bios` on it, where muOS reads them, and the run says so.
Every file is recognised by its contents, never by its name:
`PSX BIOS (USA).bin` in a subfolder lands as `scph5501.bin` when it holds those
bytes, and a file of the right name with other bytes (an empty file left by a
@@ -750,6 +756,26 @@ family writes the release name as the first line of `.system/version.txt` at
the card root (`MinUI-`, `NextUI-`, `MyMinUI-`), and that line names the file
list.
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:
| On the card | System | Files go to |
|-------------|--------|-------------|
| `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 |
| `.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 |
The full screen lists such a card on its first screen ("muOS SD card (E:\)").
Named by its system (`--platform muos`, `--platform onion`), a `--dest` that
is neither such a card nor its BIOS folder is refused, with the folder that
system reads.
Desktop installs are read from their own configuration, and several can be
found on one machine.
@@ -953,22 +979,25 @@ python install.py --platform retroarch --dest /storage/emulated/0/RetroArch/syst
RetroBIOS also runs on the handheld itself, in the
[full-screen interface](#the-full-screen-interface), with the controller.
Take the file for your system from the
[latest release](https://github.com/Abdess/retrobios/releases/latest), copy
it to the SD card, then start RetroBIOS from the menu.
Copy the file for your system to the SD card, then start RetroBIOS from the
menu.
The files below ship with the next release. Until then, build them from a
clone of the repository with `python scripts/build_port.py`, which writes all
four into `dist/`, or use the computer route at the end of this section.
| System | File | Copy it to | Start it from |
|--------|------|------------|---------------|
| Any system with [PortMaster](https://portmaster.games/): ArkOS, dArkOS, ROCKNIX, AmberELEC, JELOS, muOS, Knulli | `RetroBIOS.zip` | PortMaster's `autoinstall` folder: `/roms/ports/PortMaster/autoinstall/` on ROCKNIX and AmberELEC, `/roms/tools/PortMaster/autoinstall/` on ArkOS, `/mmc/MUOS/PortMaster/autoinstall/` on muOS, `/userdata/system/.local/share/PortMaster/autoinstall/` on Knulli | Ports, after opening PortMaster once |
| Batocera, Knulli | `RetroBIOS-batocera.zip`, extracted | `roms/ports` on the SHARE partition | Ports, after updating the game list |
| muOS | `RetroBIOS.muxapp` | `ARCHIVE` at the root of the card, then install it from the Archive Manager | Applications |
| Any other system with [PortMaster](https://portmaster.games/): ArkOS, dArkOS, ROCKNIX, AmberELEC, JELOS, Knulli | `RetroBIOS.zip` | PortMaster's `autoinstall` folder: `/roms/ports/PortMaster/autoinstall/` on ROCKNIX and AmberELEC, `/roms/tools/PortMaster/autoinstall/` on ArkOS, `/userdata/system/.local/share/PortMaster/autoinstall/` on Knulli | Ports, after opening PortMaster once |
| Batocera, Knulli | `RetroBIOS-batocera.zip`, extracted | `roms/ports` on the SHARE partition | Ports, after updating the game list |
| ArkOS, dArkOS | `RetroBIOS-tools.zip`, extracted | `tools` on the EASYROMS partition | Options, then Tools |
| ROCKNIX, JELOS | `RetroBIOS-tools.zip`, extracted | `/storage/.config/modules`, over the network share or SSH | Tools |
| AmberELEC | `RetroBIOS-tools.zip`, extracted | `/storage/.config/distribution/modules` | Tools |
A release cut before these files existed carries none of them. From a clone
of the repository, `python scripts/build_port.py` writes all four into
`dist/`.
`RetroBIOS.zip` also installs on muOS, from `MUOS/PortMaster/autoinstall/`
on the first card (`/mnt/mmc` on the device). It then shows the interface in
muxterm, as the muOS app does.
| Button | Action |
|--------|--------|
@@ -978,19 +1007,34 @@ of the repository, `python scripts/build_port.py` writes all four into
| X | Tick or untick a system |
| Y | Options |
| L1, R1 | Page up, page down |
| Start + Select | Quit at once (PortMaster port, Tools) |
| Hold Select, then Start | Quit at once (PortMaster port, muOS, Tools) |
On muOS the interface runs in muxterm, which already reads Start, B, Y (tick)
and the D-pad. A, X, L1 and R1 come from PortMaster's gptokeyb2 when
PortMaster is installed, and Menu quits.
Start pressed first also chooses the line in focus: hold Select first. A
running install is then stopped the way B stops it, and the last screen says
what it wrote. On muOS without PortMaster, muxterm reads the pad itself: Y
ticks a system, Select shows its keyboard, and Menu quits.
**Without Wi-Fi.** On a computer, download the BIOS pack whose name contains
your system (every part, for a pack in parts) and copy it next to RetroBIOS:
into `ports/retrobios` for the PortMaster port and on Batocera, to the root
of the card on muOS, into the `retrobios` folder of the Tools entry. With no
Each launcher tells the interface which buttons reach it, in
`RETROBIOS_PAD`, so the hints can name them:
| Value | Input | Set by |
|-------|-------|--------|
| `gptokeyb` | gptokeyb or gptokeyb2 with `retrobios.gptk`, the table above | the PortMaster port, the Tools entry, the muOS app with PortMaster |
| `muxterm` | muxterm's own keys: D-pad, Start as Enter, B as Backspace, Y as Space | the muOS app without PortMaster |
| `evmapy` | `RetroBIOS.sh.keys`, the same buttons as the table | the Batocera and Knulli port |
| `miyoo` | buttons that are already keys, A as Space and B as Left Ctrl | no launcher yet |
A launcher with no mapper at all (a keyboard) leaves it unset.
**Without Wi-Fi.** On a computer, download the BIOS pack that serves your
system (every part, for a pack in parts): RetroArch's on muOS, ArkOS,
dArkOS and JELOS, Batocera's on Batocera. Copy it next to RetroBIOS: into
`ports/retrobios` for the PortMaster port and on Batocera, to the root of
either card on muOS, into the `retrobios` folder of the Tools entry. With no
connection, RetroBIOS installs from it, as
[`--from-pack`](#without-a-network-offline-install) does. With no pack there,
it names the pack and the folder.
it names the pack and the folder. The releases carry no pack for ROCKNIX,
Knulli or AmberELEC: there RetroBIOS needs Wi-Fi, or the computer route.
On a two-card device, RetroBIOS without Wi-Fi first asks to **copy the BIOS
files from your other card**: muOS's `MUOS/bios` on the card the system does
@@ -1003,28 +1047,24 @@ still comes from the pack, so the pack is needed too.
first use and the Tools entry then reuses. That runtime uses the system's
OpenSSL 1.1, so on an image with OpenSSL 3 only it may not download (not
tried on a device). The BIOS folder must be one the installer detects, see
[Platform detection](#platform-detection).
[Platform detection](#platform-detection). On a read-only or full card,
RetroBIOS keeps its log in `retrobios` under `XDG_RUNTIME_DIR` or `/tmp`, and the interface names the
folder it cannot write.
**Where no terminal shows.** The PortMaster port draws on the console, or in
foot or xterm under a desktop session. Where neither can, it opens
PortMaster's own screens instead: the same check, update and choice of
systems, one list at a time. On Batocera and Knulli the visible terminal is
not verified on a device yet: RetroBIOS tries xterm or foot, then console 4,
and `retrobios/log.txt` names the route it took.
and stops when console 4 does not come to the front. `retrobios/log.txt`
names each route it tried, and `log.prev.txt` keeps the run before.
**From a computer.** Onion, MinUI, NextUI, Allium, GarlicOS and the Switch
have no Python 3 to run the installer. Put the card in a computer and run the
[one-line command](#one-line) there with
have no Python 3 to run the installer. Put the card in a computer and run
the [one-line command](#one-line) there with
`--platform <platform> --dest <BIOS folder on the card>`. This works for
every system above too.
**Which installer runs.** Each file carries `install.py`, the one the
one-line command of the same commit downloads: `scripts/build_port.py`
refuses any other (it compares it with the SHA-256 `install.sh` pins). The
file lists come from `main`. The launchers in `ports/` start it with `--tui`,
and read it through [Machine-readable events](#machine-readable-events) for
the rest.
## Without a network (offline install) { #without-a-network-offline-install }
<span id="without-a-network"></span>
@@ -1150,6 +1190,13 @@ The build scripts need 3.9 and are not bound by this.
Every change to `install.py` recomputes the SHA-256 pinned in `install.sh` and
`install.ps1` in the same commit. The tests compare the pins with the file.
The [handheld](#on-a-handheld-the-retrobios-port) archives each carry
`install.py`, the one the one-line command of the same commit downloads:
`scripts/build_port.py` refuses any other (it compares it with the SHA-256
`install.sh` pins). The file lists come from `main`. The launchers in
`ports/` start it with `--tui`, and read it through
[Machine-readable events](#machine-readable-events) for the rest.
Narrowing by system, core, region or target replays the pack builder's rules
from fields the manifest carries, and a parity test compares an installer
selection with the pack built the same way. Given a manifest without those
@@ -1165,6 +1212,10 @@ fields, the installer refuses to narrow rather than install everything.
| `130` | stopped with Ctrl+C, or with `q`, Ctrl+C or Ctrl+D at a question. Run the same command again to carry on |
| `141` | the output was piped to a reader that closed early (`--list-platforms \| head`) |
The full screen ended by SIGTERM (Start+Select on a handheld) before any
install exits `143`. During an install it stops the install first, and exits
`130`.
`install.ps1` passes the installer's code on unchanged: run as a file it exits
with it, run through `irm \| iex` it sets `$LASTEXITCODE` (an `exit` there
would close the PowerShell window). It declares no parameter of its own, so
+1
View File
@@ -591,6 +591,7 @@ does not look.
| `known_hash_adler32` | expected Adler-32 hash (Dolphin's DSP ROMs). Pair with `adler32_byteswap` when the code hashes 16-bit byte-swapped data |
| `adler32_pairs_with`, `adler32_pairs` | the file hashed together with this one and the combinations the code accepts, this file's value first, in table order: Dolphin warns on a DSP ROM pair outside its `known_roms` even when each file passes alone |
| `pin_frozen` | why `source_commit` is held on purpose rather than followed. The profile is then judged against its own revision, like one pinned to a superseded tag |
| `data_root` | per operating system (`android`, `ios`, `windows`, `macos`, `linux`), the folder the app reads its user data from, under which `standalone_path` destinations sit: `path` as the user finds it (`Android/data/<package>/files`, `%APPDATA%/...`), with the `source_ref` that builds it. Only the systems the app runs on are keyed |
| `upstream_frozen` | why `upstream_commit` is held: the port vendors that upstream tree, synced to that release, or merged that commit. The upstream view is read at its own pin and a bump leaves it. Without it, a port that is a GitHub fork of its upstream follows the merge base of the two |
| `prose_written_at` | the pin a reader confirmed the prose citations against. When the profile's history shows a text living under several pins, profile_sync takes this one as the revision the text describes, so a bump is no longer refused for a citation already reread. It never overrides a history with a single candidate |
| `version_source` | for a project published outside any forge, `{url, pattern}`: the page that announces releases and a regular expression whose first group is the latest version. `profile_sync --check-version` compares it with `core_version`, and `check_freshness --profiles` calls the profile stale when they differ. `no_genuine_copy` names an announced version found only rebuilt or re-signed: the profile stays on the newest unmodified build and is not stale until the page announces a later one |
+10 -7
View File
@@ -274,13 +274,16 @@ pins).
Each launcher then runs from its extracted archive on a simulated device: a
pseudo-terminal stands for the console, and fakes stand for `install.py`,
gptokeyb, setfont, chvt, curl, foot, xterm, muxterm, PortMaster's
`control.txt` and muOS's `retro.sh`. The checks: gptokeyb starts in kill mode
on the installer's path and is stopped, the console's settings and font are
put back, an offline run picks the pack of its system from the card or says
where to put one, a refused console falls back to PortMaster's screens, and
each firmware's terminal is the one used. What reaches the screen and the
pad on a real device is not exercised.
gptokeyb and gptokeyb2 (each killing the way its source does), setfont,
chvt, curl, sudo, foot, xterm, muxterm, PortMaster's `control.txt` and
muOS's `retro.sh`. The checks: gptokeyb's kill reaches only the Start +
Select sentinel and the interface then stops with its result written, the
console's settings and font are put back, an offline run says so at once,
picks the pack of its system from the card or says where to put one, and
each firmware's terminal is the one used. The fakes also fail: a mapper that
dies, a chvt the compositor refuses, a terminal app that cannot open, a
read-only card. None of these may leave a console waiting for a button.
What reaches the screen and the pad on a real device is not exercised.
```bash
python -m unittest tests.test_handheld_launchers -v
+2 -1
View File
@@ -38,7 +38,8 @@ Run it without `--check`. It adds missing files and replaces wrong ones.
- **Right folder?** [Get your files](../which-pack.md) names it.
- **Exact name?** `scph5501.bin` and `SCPH-5501.BIN` differ. On Linux,
capitals count too.
- **A `bios` folder inside your BIOS folder?** Move its files up one level.
- **A `bios` folder inside your BIOS folder?** Run the installer: it copies
those files up one level.
- **Unzipped by hand on Linux?** The command adds names that differ by
capitals.
- **A ZIP in parts, like `Pack.part1of2.zip`?** Unzip every part into one