fix: find RetroArch in Steam libraries and ES-DE

The installer looked for retroarch.exe in C:\RetroArch-Win64 and
Program Files\RetroArch only, so a RetroArch under Program Files\
RetroArch-Win64, in a Steam library on another drive, or in an
installed ES-DE's Emulators folder went undetected. All three are
searched; Steam libraries come from Steam's own library list.
This commit is contained in:
Abdessamad Derraz committed 2026-10-18 05:26:39 +02:00
1 parent d0312428e4
commit 8d0b6d5f93
4 files changed
+85 -5

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@ param(
$ErrorActionPreference = "Stop"
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
$defaultInstallSha256 = "973e116ab59e233cd4fe5ebb77d4973bc06013b22b6388e80d12fa1d61fb0c73"
$defaultInstallSha256 = "bfc3a2127689147e8a5f729a9ed668608f06dbd3b14ca6e768cdf2a7f90d5d32"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
+40 -3
View File
@@ -457,14 +457,51 @@ def _retroarch_cfg_dir(
return None
def _steam_libraries() -> list[Path]:
"""Every Steam library, the default one first.
Steam lists the others in steamapps/libraryfolders.vdf, each as a
"path" line; a RetroArch installed on D:/SteamLibrary was not found
when only Program Files was searched.
"""
roots: list[Path] = []
for var in ("ProgramFiles(x86)", "ProgramFiles"):
base = os.environ.get(var, "")
if base and (Path(base) / "Steam").is_dir():
roots.append(Path(base) / "Steam")
libraries = list(roots)
for root in roots:
vdf = root / "steamapps" / "libraryfolders.vdf"
try:
text = vdf.read_text(encoding="utf-8", errors="replace")
except OSError:
continue
for raw in re.findall(r'"path"\s+"([^"]+)"', text):
library = Path(raw.replace("\\\\", "\\"))
if library not in libraries:
libraries.append(library)
return libraries
def _windows_retroarch_dirs() -> list[Path]:
"""Folders holding retroarch.exe where the installer and the archive put
it: C:/RetroArch-Win64 by default, C:/RetroArch for 32-bit builds."""
"""Folders holding retroarch.exe where its installers put it.
C:/RetroArch-Win64 by default, C:/RetroArch for 32-bit builds, the same
names under Program Files, every Steam library, and the Emulators folder
of an installed ES-DE (es_find_rules.xml lists all of them).
"""
candidates = [Path("C:/RetroArch-Win64"), Path("C:/RetroArch")]
for var in ("ProgramFiles", "ProgramFiles(x86)"):
root = os.environ.get(var, "")
if root:
candidates.append(Path(root) / "RetroArch")
candidates += [Path(root) / "RetroArch-Win64", Path(root) / "RetroArch"]
candidates += [
Path(root) / "ES-DE" / "Emulators" / name
for name in ("RetroArch-Win64", "RetroArch")
]
candidates += [
library / "steamapps" / "common" / "RetroArch" for library in _steam_libraries()
]
return [folder for folder in candidates if (folder / "retroarch.exe").is_file()]
+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="973e116ab59e233cd4fe5ebb77d4973bc06013b22b6388e80d12fa1d61fb0c73"
DEFAULT_INSTALL_SHA256="bfc3a2127689147e8a5f729a9ed668608f06dbd3b14ca6e768cdf2a7f90d5d32"
MAX_INSTALLER_BYTES=2097152
cleanup() {
+43
View File
@@ -970,6 +970,49 @@ class DetectionFollowsTheRegistry(unittest.TestCase):
self.assertEqual(found, [("emudeck", home / "elsewhere" / "bios")])
class RetroArchIsFoundWhereWindowsInstallsPutIt(unittest.TestCase):
"""Program Files\\RetroArch-Win64, a Steam library on another drive and
an installed ES-DE's Emulators folder all held a RetroArch the one-liner
reported as "no supported platform detected"."""
def _env(self, program_files: Path) -> None:
patcher = unittest.mock.patch.dict(
os.environ, {"ProgramFiles": str(program_files), "ProgramFiles(x86)": ""}
)
patcher.start()
self.addCleanup(patcher.stop)
@staticmethod
def _exe(folder: Path) -> Path:
folder.mkdir(parents=True)
(folder / "retroarch.exe").write_bytes(b"MZ")
return folder
def test_program_files_win64(self):
program_files = Path(_tempdir(self))
self._env(program_files)
found = self._exe(program_files / "RetroArch-Win64")
self.assertIn(found, install._windows_retroarch_dirs())
def test_a_steam_library_on_another_drive(self):
program_files = Path(_tempdir(self))
library = Path(_tempdir(self))
steamapps = program_files / "Steam" / "steamapps"
steamapps.mkdir(parents=True)
(steamapps / "libraryfolders.vdf").write_text(
'"libraryfolders"\n{\n\t"1"\n\t{\n\t\t"path"\t\t"' + str(library) + '"\n\t}\n}\n'
)
self._env(program_files)
found = self._exe(library / "steamapps" / "common" / "RetroArch")
self.assertIn(found, install._windows_retroarch_dirs())
def test_an_installed_es_de(self):
program_files = Path(_tempdir(self))
self._env(program_files)
found = self._exe(program_files / "ES-DE" / "Emulators" / "RetroArch-Win64")
self.assertIn(found, install._windows_retroarch_dirs())
class InstallerStaysOnPython38AndTheStdlib(unittest.TestCase):
"""install.py runs where the bootstraps let it run: Python 3.8, stdlib only.