mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-13 05:23:51 -06:00
fix: place openmsx system ROMs through filepool
openMSX reads share/systemroms below OPENMSX_HOME or ~/.openMSX and every filepool entry by SHA1. The profile paths drop RetroBat's openmsx/ prefix and declare those directories and the filepool. Batocera's config_directories reads the filepool lines its generator writes, KNULLI reuses it. RetroBat records OPENMSX_HOME, RetroPie the moveConfigDir of ~/.openMSX that its systemroms link lies in, and the configure --prefix of xroar that its roms link lies in. Batocera and KNULLI system ROMs move from openmsx/share/systemroms to openmsx/, beside the files their own lists declare, RetroPie's to BIOS/openmsx, the folder linked as share/systemroms.
This commit is contained in:
1 parent
cd38b9ed10
commit
e6dbbe69ed
13 files changed
+394
-60
No files matched your search
@@ -15,7 +15,8 @@ launcher looks for nothing".
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
from collections.abc import Callable
|
||||
import re
|
||||
from collections.abc import Callable, Iterable
|
||||
from typing import Any
|
||||
|
||||
from .configgen_launchers import (
|
||||
@@ -898,6 +899,56 @@ def environment_directories(cg: Configgen) -> list[Launcher]:
|
||||
return launchers
|
||||
|
||||
|
||||
# Generators that hand the emulator a /userdata/bios directory through its
|
||||
# configuration: a line written to the file it reads (openMSX's script.tcl
|
||||
# filepool entries) or a key saved to it.
|
||||
CONFIG_DIRECTORY_GENERATORS = ("openmsx.openmsxGenerator",)
|
||||
|
||||
|
||||
def config_directories(
|
||||
cg: Configgen, modules: Iterable[str] = CONFIG_DIRECTORY_GENERATORS
|
||||
) -> list[Launcher]:
|
||||
"""file.write("<line naming a BIOS directory>") and settings.save(key, <BIOS directory>)."""
|
||||
prefix = cg.bios.rstrip("/")
|
||||
inside = re.compile(rf"{re.escape(prefix)}(?:/[^\s\"';]*)?")
|
||||
launchers = []
|
||||
for module in modules:
|
||||
src = cg.generator(module)
|
||||
constants = dict(cg.paths)
|
||||
for node in src.tree.body:
|
||||
name = _assigned_name(node)
|
||||
value = _path_value(getattr(node, "value", None), constants)
|
||||
if name is not None and value is not None:
|
||||
constants[name] = value
|
||||
found: list[tuple[str, str, ast.Call]] = []
|
||||
for call in _calls(src.tree, attr="write"):
|
||||
text = call.args[0] if len(call.args) == 1 else None
|
||||
if isinstance(text, ast.Constant) and isinstance(text.value, str):
|
||||
line = text.value.strip()
|
||||
named = inside.search(line)
|
||||
if named:
|
||||
found.append((named.group(0), f"written: {line}", call))
|
||||
for call in _calls(src.tree, attr="save"):
|
||||
if len(call.args) != 2 or not isinstance(call.args[0], ast.Constant):
|
||||
continue
|
||||
value = _path_value(call.args[1], constants)
|
||||
if value is None and isinstance(call.args[1], ast.Constant):
|
||||
value = str(call.args[1].value)
|
||||
if value is not None and (value.rstrip("/") == prefix or value.startswith(prefix + "/")):
|
||||
found.append((value, str(call.args[0].value), call))
|
||||
if not found:
|
||||
src.fail("hands no /userdata/bios directory through its config")
|
||||
launchers.extend(
|
||||
Launcher(
|
||||
emulator=cg.emulator(module), build="standalone", kind="passes_path",
|
||||
names=[], search_dir=directory, passes_to=passes_to,
|
||||
source_ref=src.ref([src.span(call)]),
|
||||
)
|
||||
for directory, passes_to, call in found
|
||||
)
|
||||
return launchers
|
||||
|
||||
|
||||
# libretro core options whose value names the BIOS file the core opens.
|
||||
FILE_OPTIONS = (("_o2em_options", "o2em_bios"), ("_neocd_options", "neocd_bios"))
|
||||
|
||||
@@ -952,7 +1003,8 @@ def core_file_options(cg: Configgen) -> list[Launcher]:
|
||||
|
||||
EXTRACTORS: tuple[Callable[[Configgen], list[Launcher]], ...] = (
|
||||
duckstation, duckstation_legacy, hatari, xemu, melonds, mupen64plus,
|
||||
x16emu, gsplus, lexaloffle, environment_directories, core_file_options,
|
||||
x16emu, gsplus, lexaloffle, environment_directories, config_directories,
|
||||
core_file_options,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import yaml
|
||||
try:
|
||||
from .batocera_launchers import (
|
||||
Configgen,
|
||||
config_directories,
|
||||
_path_value,
|
||||
_render,
|
||||
_system_branches,
|
||||
@@ -53,6 +54,7 @@ try:
|
||||
except ImportError:
|
||||
from batocera_launchers import ( # type: ignore[no-redef]
|
||||
Configgen,
|
||||
config_directories,
|
||||
_path_value,
|
||||
_render,
|
||||
_system_branches,
|
||||
@@ -84,9 +86,18 @@ PICO8_INSTALLER = "board/fsoverlay/usr/bin/knulli-install-pico8"
|
||||
ES_FEATURES = "package/emulationstation/knulli-es-system/es_features.yml"
|
||||
|
||||
# Batocera's extractors that read KNULLI's generators unchanged.
|
||||
# The generators of Batocera's config_directories that KNULLI keeps in the
|
||||
# same shape: openMSX's filepool lines.
|
||||
CONFIG_DIRECTORY_GENERATORS = ("openmsx.openmsxGenerator",)
|
||||
|
||||
|
||||
def knulli_config_directories(cg: Configgen) -> list[Launcher]:
|
||||
return config_directories(cg, CONFIG_DIRECTORY_GENERATORS)
|
||||
|
||||
|
||||
SHARED = (
|
||||
duckstation, duckstation_legacy, hatari, xemu, melonds, mupen64plus, x16emu,
|
||||
environment_directories,
|
||||
environment_directories, knulli_config_directories,
|
||||
)
|
||||
|
||||
|
||||
@@ -365,7 +376,6 @@ GENERIC_SITES = (
|
||||
GenericSites("amiberry/amiberryGenerator.py", "passes_path"),
|
||||
GenericSites("fsuae/fsuaeGenerator.py", "passes_path"),
|
||||
GenericSites("mame/mameGenerator.py", "passes_path"),
|
||||
GenericSites("openmsx/openmsxGenerator.py", "passes_path"),
|
||||
GenericSites("fpinball/fpinballGenerator.py", "passes_path"),
|
||||
GenericSites(
|
||||
"libretro/libretroRetroarchCustom.py", "passes_path", "libretro", emulator="retroarch"
|
||||
|
||||
@@ -1279,6 +1279,29 @@ def openmsx(sources: dict[str, Source]) -> list[Record]:
|
||||
)
|
||||
if not records:
|
||||
raise LauncherPatternMissing(src.path, "biosFiles entries")
|
||||
# OPENMSX_HOME is the user directory: openMSX reads share/systemroms below it.
|
||||
home = src.find(
|
||||
rf'string (\w+) = Path\.Combine\({BIOS}, "([^"]+)"\);', "OPENMSX_HOME folder"
|
||||
)
|
||||
handed = src.find(
|
||||
rf'ret\.EnvironmentVariables\["(OPENMSX_HOME)"\] = {home.group(1)};',
|
||||
"OPENMSX_HOME environment", home.end(),
|
||||
)
|
||||
records.append(
|
||||
_record(
|
||||
"openmsx",
|
||||
"standalone",
|
||||
"passes_path",
|
||||
[],
|
||||
source_ref(
|
||||
(src.path, [src.lines(home.start(), home.end()),
|
||||
src.lines(handed.start(), handed.end())])
|
||||
),
|
||||
search_dir=f"bios/{home.group(2)}",
|
||||
passes_to=f"environment {handed.group(1)}",
|
||||
fails_when_missing=False,
|
||||
)
|
||||
)
|
||||
return records
|
||||
|
||||
|
||||
|
||||
@@ -525,6 +525,7 @@ class PackageReader:
|
||||
self._links(links)
|
||||
self._outside_bios(events)
|
||||
self._working_directory(events)
|
||||
self._reaching_links(events)
|
||||
return self.records
|
||||
|
||||
@staticmethod
|
||||
@@ -828,6 +829,54 @@ class PackageReader:
|
||||
)
|
||||
|
||||
|
||||
def _reaching_links(self, events: list[Event]) -> None:
|
||||
"""The directories outside the BIOS one that a whole-directory link lies in.
|
||||
|
||||
openmsx's moveConfigDir "$home/.openMSX" "$configdir/msx/openmsx"
|
||||
puts the emulator's directory where the systemroms link to BIOS/openmsx
|
||||
lies, and xroar's ./configure --prefix="$md_inst" builds the program
|
||||
whose share/xroar/roms links to $biosdir. Neither line names the BIOS
|
||||
directory, and each says where the link is read from.
|
||||
"""
|
||||
suffix = " is a symlink to it"
|
||||
linked = [
|
||||
record.passes_to.removesuffix(suffix).rstrip("/")
|
||||
for record in self.records
|
||||
if record.kind == "links" and not record.names
|
||||
and (record.passes_to or "").endswith(suffix)
|
||||
]
|
||||
if not linked:
|
||||
return
|
||||
|
||||
def holds(directory: str) -> bool:
|
||||
directory = directory.strip("\"'").rstrip("/")
|
||||
return bool(directory) and any(
|
||||
path == directory or path.startswith(directory + "/") for path in linked
|
||||
)
|
||||
|
||||
for event in events:
|
||||
if event.heredoc or not event.words or _mentions_bios(event.raw):
|
||||
continue
|
||||
command = event.words[0][0]
|
||||
if command == "moveConfigDir" and len(event.words) >= 3:
|
||||
link, real = event.words[1][0], event.words[2][0]
|
||||
if holds(real):
|
||||
self.record(
|
||||
"links", [], [(event.path, event.line)],
|
||||
search_dir=real, passes_to=f"{link}{suffix}",
|
||||
fails_when_missing=False, depends_on_option=self._depends(event),
|
||||
)
|
||||
elif command.endswith("configure"):
|
||||
for word in event.words[1:]:
|
||||
prefix = word[0].strip("\"'")
|
||||
if prefix.startswith("--prefix=") and holds(prefix[len("--prefix="):]):
|
||||
self.record(
|
||||
"passes_path", [], [(event.path, event.line)],
|
||||
search_dir=prefix[len("--prefix="):].strip("\"'"),
|
||||
passes_to="${prefix} of configure --prefix",
|
||||
fails_when_missing=False, depends_on_option=self._depends(event),
|
||||
)
|
||||
|
||||
def _working_directory(self, events: list[Event]) -> None:
|
||||
"""The folder a generated launch script enters before it runs the emulator."""
|
||||
if self.package.id not in WORKING_DIRECTORY:
|
||||
|
||||
Reference in new issue
Block a user