On a WSL host install.main() reads USERPROFILE, APPDATA and the rest through cmd.exe and sets them in os.environ. Two selection tests left them set, and the detection test, run later in the jsonschema-free suite, found a Scoop folder no registry rule publishes. The selection tests restore os.environ, and the detection test clears the Windows variables it does not set.
--declared-only keeps the entries the platform's own list declares
(cores: null), each slot settled to the platform's copy with no core
alternative left behind. Install, --check, --dry-run, --events,
--list-systems, --system, --region, --emulator, --target,
--installed-cores, --manifest and --from-pack apply it. --core,
--list-cores, --list-emulators, --list-platforms, --list-targets,
--standalone-copies, --restore and --tui refuse it, and the interface
does not open by itself with it. On Batocera it gives 353 files of
14531, the list batocera-systems checks.
Event decision: no schema bump. A `declared` key on `file` would add a
key to an existing kind, which schema 1 forbids. A new kind, `declared`,
follows `check` with the same counts over the platform's own files and
their dests in file-event order. Readers already skip a kind they do
not know (rbevents.py and the interface reader were checked), so
EVENT_SCHEMA stays 1.
An unknown --system is answered with the systems the list files its
key file under: --platform retroarch --system snk-neogeo now suggests
arcade, which holds neogeo.zip, instead of snk-neogeo-cd. neogeo, mvs
and aes follow the same route. Never taken, only suggested. A system
title the manifest carries (SNK Neo Geo CD) is taken for its id when
no other system shares it and no platform name reads the same.
schemas/install-events.schema.json is written from EVENT_KEYS by
scripts/generate_event_schema.py. validate_schemas.py reports a stale
file, and tests compare it with EVENT_KEYS and validate a real run.
Bootstrap pins recomputed.
The engine counts the bytes a copy, the pack or a resumed partial copy
supplied, and those the network brought. A transfer event carries both
after each progress event and once when the downloads end, so a screen
shows a download speed without guessing.
A stop by SIGTERM (Start+Select under gptokeyb) reads the summary like
Ctrl-C and prints the count on disk. The systems filter keeps the ticks
and the focus. The bar names what A does on the focused row. Options
check the folder again, a missing network fails in 15 s with plain words,
an unwritable folder offers another one, a folder inside a card offers
its root, and only a failure keeps its log.
New event kind: checking, with files_done and files_total, while the
files in place are hashed. The exact event lists of the check and
install runs now carry two of them, for the two files in place.
With nothing detected, the menu had no Enter default, while --help and
the --dest menu name RetroArch as the fallback. Its title now also says
why the question is asked.
--system nintendo-gba wrote system events for gb, gbc and ds, each made
of the few SkyEmu files the choice kept. With systems chosen, only those
are described.
Offline, the run printed "[Errno -2] Name or service not known". The
common failures now read as words, the raw text kept under --verbose.
A refused certificate under a clock set before the installer was written
is reported as reason clock, with the date it reads, and no trusted
certificate list on the machine as reason no_ca, naming SSL_CERT_FILE.
Neither is retried, and verification is never turned off.
--list-platforms said the MinUI layout was not written yet while
--from-pack and --dest wrote it. On the device the card root is now
found and its version.txt names the file list, and a card without one
gets the --platform and --dest to use. A core with no file of its own
says its files are the platform's, always kept, instead of 0 files.
--system gba, psx or ps1 was refused with no suggestion on RetroArch.
Short names now suggest the ids they stand for, never taken in their
place, and two aliases of one system name it once. --platform muos and
the other systems --list-platforms names stand for the file list they
get, and the run says which.
A folder typed in quotes at the BIOS folder question was used with its
quotes, and its missing parents were created without the question
--dest asks. The quotes go, ~ and variables expand on every system, and
a default folder that does not exist is named as such, not as found.
q at a menu now leaves with 130 like Ctrl+C, and Ctrl+C before anything
started no longer offers to carry on.
Between the check and the creation of the run folder, retrobios-backup could be swapped for a link. The holder's device and inode are confirmed unchanged once the run folder exists. Directory file descriptors would close the window entirely but do not exist on Windows; the remaining window is the instant between that confirmation and the move.
When every dated name in retrobios-backup already existed, the loop ended on the last one and wrote into it. It now raises, so the next location is tried and the file stays in place if none works. A holder another user owns is refused on systems with user ids.
A BIOS folder can sit on a share other people write to. A retrobios-backup that is a link is no longer written through (the backup goes inside the BIOS folder instead), run folders are created for the user only and carry a marker, and --restore only takes a folder holding that marker, walking it without following links. Beginner pages label their links to the installer page as details.
A file in place whose contents differ (another revision, a personal
dump) was overwritten and lost. It is now moved to
retrobios-backup/<date-time>/ beside the folder written to, under the
same path, before the verified copy replaces it. Beside, not inside:
DuckStation, SwanStation and Rustation read every file of the BIOS
folder and BizHawk walks its firmware folder recursively.
Identical files are never kept. --dry-run counts what would be kept,
the summary and the summary event name the folder, files and bytes,
and --restore FOLDER puts the files back. Data trees and standalone
copies keep their replaced files the same way.
install.py --no-game-data leaves out the files and omissions the manifest
marks game data, in an install, --check and --dry-run, and names them with
their category. The --events summary gains left_out, one group per
category with every destination. A list without categories is refused.
AmberELEC, PAN4ELEC and EmuELEC detection now installs their own lists
at /storage/roms, the root those lists are written against; KNULLI its
own list at /userdata/bios. JELOS, KOLOS, UnofficialOS and Arch R keep
RetroArch's list with the folder their retroarch.cfg names.
One JSON object per line on stdout (detection, per-file and per-system
check, download progress, summary, exit code) and the usual text on
stderr, so a program driving install.py never parses prose. EVENT_KEYS
is the one schema. The installer page documents it, and a test holds the
two equal. The handheld port reads it.
The Google Play and retroarch.com builds share com.retroarch and com.retroarch.aarch64 but build their defaults under different roots (RetroArch v1.22.2 MainMenuActivity.java:182-183). The build is told by the version code it records in retroarch.cfg, else by the folder it wrote. A Google Play folder Termux cannot write is named, as for DraStic and Flycast.
DraStic keeps its BIOS in its private data and Flycast in Android/data,
which Termux cannot write on Android 11 and later. An installed one is now
named with the files not copied, and a writable Flycast folder is a
standalone copy target.
RetroDECK moves each of its folders on its own and records the new place
in retrodeck.json paths (api_data_processing.sh:913-935). Only
rd_home_path was read, so files went to <home>/bios after a move.
AmberELEC, EmuELEC, JELOS, KOLOS, UnofficialOS, ArchR, PAN4ELEC, dArkOS,
RetroOZ, spruceOS, CrossMix-OS, Onion, Allium, Koriki, MiyooCFW and plumOS
are found by what their builds write, named as they name themselves, and
installed to the system_directory of their RetroArch config, which follows
ArkOS and dArkOS to a second card. TrimUI stock, MinUI and a plumOS build
without a known folder are named and not installed to. Two unrelated
systems matching stop a run without a terminal.
Without Python, install.ps1 at a console now offers to run winget install Python.Python.3.12, rereads PATH from the registry and carries on. The Store's python.exe placeholder fails the version check like a missing Python.
Without Python the bootstrap told every system to run sudo apt install python3. It now reads Termux, macOS and /etc/os-release to name pkg, xcode-select, apt, dnf, pacman, zypper or apk, and in Termux offers to run pkg install python, which needs no root.
With no platform detected, a machine running standalone emulators (ES-DE with DuckStation and PCSX2) was offered RetroArch's folder. The installer now fills the emulator folders of the standalone copies list that exist here, from the EmuDeck then RetroArch file lists, asking first at a terminal.
Every install ended on 'Standalone copies skipped', on machines with no standalone emulator as on one whose DuckStation lacked its BIOS. The line now lists the emulator folders that exist here, and nothing is said when there are none.
A mistyped --dest was created with every missing parent and reported done. The run now names the missing folder and the nearest one that exists, asks at a terminal before creating more than one level, and prints the folder it created. The free-space check now runs before the folder is made and ends with 2, nothing installed.
--list-systems, --list-cores, --list-emulators and --list-targets with nothing detected were answered with an install command that dropped the listing and added --dest. The hint now names the platform and keeps the listing.
EROFS was advised like a permission refusal, and sudo fails the same way on a read-only mount. The advice now reads the mount flag and says to check and remount the card or drive.
BusyBox wget has no --https-only and refused the whole command, so a curl-less Alpine system (the RomM image) could never bootstrap. The flag is passed only when wget lists it.
EmuDeck's macOS build reads ~/.config/EmuDeck/settings.sh like the Linux one (functions/all.sh:3-4,24 and vars.sh:2 at dddb3022). The settings and ~/Emulation/bios rules now run on darwin too.
RomM 5.4 reads each platform's firmware where filesystem.structure.firmware
in config.yml says, bios/{platform} by default, and suggests {platform}/bios
for a {platform}/roms library (rommapp/romm 5.4.0,
backend/config/config_manager.py:58,101-109,205-225,564-568,1105-1124).
The installer only wrote bios/<platform>/. It now reads the template from
config.yml beside the library, takes --romm-firmware when that file is
elsewhere, refuses a platform-first library with no template, and detects
RomM by /romm/config/config.yml too.
No Batocera build writes /etc/batocera-version: batocera-system.mk:21-22
(batocera.linux 38845725, unchanged since batocera-30) writes
/usr/share/batocera/batocera.version. Knulli (knulli-linux 57afa662) adds
OS_NAME=knulli to os-release, writes /usr/share/knulli/knulli.version and
removes /usr/share/batocera, and no Knulli source writes /etc/knulli-release.
Neither was detected. A Knulli board is named and not narrowed by
Batocera's per-board lists, and an unlisted board is named.
muOS runs RetroArch on a config copied from its default, which reads
/run/muos/storage/bios, bound to MUOS/bios on the second card when that
card holds one, and loads cores from /opt/muos/share/core (MustardOS/internal
f41f4a89, script/control/retroarch.sh:8-20, script/device/bind.sh:116-150,
retroarch.default.cfg:2806,3151). The installer wrote to /mnt/mmc/MUOS/bios
and --installed-cores found no core. The config now decides both.
functions/all.ps1:4-14 (emudeck-we 037460ef) reads the APPDATA
settings.ps1, else the one under the profile, and takes C:\Emulation when
neither names a folder. Only the first was read and a forced platform fell
back to %USERPROFILE%\Emulation\bios. A network install names its share
through $VolName (JSONtoPS1.ps1:166-172), and a UTF-16 settings file is
decoded.
RetroBat.exe writes its folder to HKCU\SOFTWARE\RetroBat
LatestKnownInstallPath on every start (retrobat-executable 702da66a,
Program.cs:57 and 99, RegistryTools.cs:15-50). Only C:\RetroBat and the
profile folder were looked at, so an install on D: was missed and a forced
--platform retrobat wrote into C:\RetroBat\bios. The value is read
through winreg, or reg.exe under WSL, before the fixed folders.
A run whose downloads were all cut ended on "Location that was being
written to" and "once that is resolved", pointing at the disk. A
failure caused by the connection (lookup, reset, timeout, TLS, a cut
transfer, HTTP 5xx or 429) is now marked as such, and the summary says to
check the connection and HTTPS_PROXY.
An unknown --emulator name pointed at --list-cores and counted 441 names
while --list-cores prints 189: the buildbot names --emulator accepts
(mednafen_psx for beetle_psx) were listed nowhere. --list-emulators prints
each accepted name beside the emulator it stands for, and the hint names
it.
A [Parameter()] attribute made install.ps1 an advanced script: its common
parameters took -v (-Verbose), -vb, -d and -ea before install.py saw them,
and the scriptblock form printed PowerShell's own VERBOSE lines. The
wrapper now forwards $args as typed.
A link already at the destination was skipped without a word and counted
as "dir not found" while the folder existed, so the emulator kept the file
the link pointed at. The link now gives way to the file, written beside it
and renamed over the name, and a name leading out of the folder is a named
failure.
On Windows a verified partial copy is closed before its rename. A second
run that claimed it in that moment truncated it and the first rename failed
with a sharing violation, reported as an unwritable folder. A complete
partial is now left whole there, the rename waits for a sharing violation
to clear, and a sharing violation no longer reads as a refused folder.
The check walked the published keys only and skipped null lists: a
target the builder knows and the installer lacks, or a null left behind
once the builder filters it, passed. It now compares both key sets and
every value, null included.
Names are matched on letters and digits, so the site's display names
work, and a typo gets the closest names instead of a full list. Hints
and advice give back the command the user ran (curl or PowerShell form,
every flag kept), --dest alone follows detection and says whose list it
installs, Ctrl+C at a question exits 130, and --cores-dir names a core
folder. install.ps1 runs in its own scope so irm | iex leaves the
session alone, and an override that causes a fingerprint mismatch is
named. --check lists hash mismatches first, missing required files are
grouped by system, and --help ends with examples.
install.py --emulator NAME keeps what the named emulators read on the detected platform: their own files and the platform's files of the systems they run, as a pack built for them carries, without the systems no core is mapped to. Each emulator page now gives that command for Linux, macOS and Windows, beside the per-file links.