mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-06 01:53:56 -06:00
fix: add a retropie file to its own system's list
Only the first BIOS clause of a help string was read, so naomi2.zip and segasp.zip went into flycast's Dreamcast sentence. A file now joins the clause whose names the platform files under its system, or is not added.
This commit is contained in:
1 parent
4e5b48ddbe
commit
a434c1a8a0
2 files changed
+96
-20
No files matched your search
@@ -156,6 +156,30 @@ class Exporter(BaseExporter):
|
||||
|
||||
@classmethod
|
||||
def _enumeration(cls, help_text: str) -> tuple[int, int, list[str]] | None:
|
||||
"""The first BIOS clause's list of names to extend, or None."""
|
||||
clauses = cls._clauses(help_text)
|
||||
return clauses[0][2] if clauses else None
|
||||
|
||||
@classmethod
|
||||
def _clauses(
|
||||
cls, help_text: str
|
||||
) -> list[tuple[int, list[str], tuple[int, int, list[str]] | None]]:
|
||||
"""Each BIOS clause that names files: its start, its names, and the
|
||||
list to extend or None when it cannot be extended.
|
||||
|
||||
flycast's help has a Dreamcast clause and a Naomi/Atomiswave one.
|
||||
Only the first was read, and naomi2.zip and segasp.zip were added to
|
||||
the Dreamcast list.
|
||||
"""
|
||||
found = []
|
||||
for clause in _BIOS_CLAUSE.finditer(help_text):
|
||||
names = [m.group(0) for m in cls._names_in(clause.group(0))]
|
||||
if names:
|
||||
found.append((clause.start(), names, cls._extendable(clause)))
|
||||
return found
|
||||
|
||||
@classmethod
|
||||
def _extendable(cls, clause: re.Match[str]) -> tuple[int, int, list[str]] | None:
|
||||
"""The list of names to extend: its span and its names, or None.
|
||||
|
||||
A list of alternatives ("a or b", "a/b") is not an enumeration: an
|
||||
@@ -164,9 +188,6 @@ class Exporter(BaseExporter):
|
||||
are a list of examples ("eg. a, b") and one with words between its
|
||||
names, which a rewrite would lose.
|
||||
"""
|
||||
clause = _BIOS_CLAUSE.search(help_text)
|
||||
if clause is None:
|
||||
return None
|
||||
text = clause.group(0)
|
||||
names = cls._names_in(text)
|
||||
if not names:
|
||||
@@ -308,13 +329,12 @@ class Exporter(BaseExporter):
|
||||
by_core = self._files_by_core(systems)
|
||||
# Aliases count as names we know: RetroPie writes dc_flash.bin where
|
||||
# flycast's profile files it as an alias of another primary.
|
||||
known: set[str] = set()
|
||||
systems_of: dict[str, set[str]] = {}
|
||||
for system in systems.values():
|
||||
for fe in system.files:
|
||||
known.add(fe.name.lower())
|
||||
known.update(
|
||||
str(a).lower() for a in (fe.native("aliases", []) or [])
|
||||
)
|
||||
for name in [fe.name, *(fe.native("aliases", []) or [])]:
|
||||
systems_of.setdefault(str(name).lower(), set()).add(fe.native_system)
|
||||
known = set(systems_of)
|
||||
self._skipped: dict[str, list[str]] = {}
|
||||
self._named: set[int] = set()
|
||||
produced: dict[str, str] = {}
|
||||
@@ -362,30 +382,52 @@ class Exporter(BaseExporter):
|
||||
and (slot := self._slot_of(fe)) is not None
|
||||
}
|
||||
proposed = self._one_per_slot(candidates, filled)
|
||||
missing = self._in_search_order(proposed)
|
||||
if not missing:
|
||||
if not proposed:
|
||||
continue
|
||||
|
||||
enumeration = self._enumeration(help_text)
|
||||
if enumeration is None:
|
||||
# No enumeration to extend, and a sentence we would have to
|
||||
# write ourselves is a documentation change, not a correction.
|
||||
skip("whose help text lists no files to add to", module_id)
|
||||
# A file joins the list of its own system: the clause whose
|
||||
# names the platform files under that system, and only one.
|
||||
clauses = self._clauses(help_text)
|
||||
homes: dict[int, list[NativeFile]] = {}
|
||||
homeless = False
|
||||
for fe in proposed:
|
||||
owners = [
|
||||
i for i, (_, names, _) in enumerate(clauses)
|
||||
if fe.native_system in set().union(
|
||||
*(systems_of.get(n.lower(), set()) for n in names))
|
||||
]
|
||||
if len(owners) == 1 and clauses[owners[0]][2] is not None:
|
||||
homes.setdefault(owners[0], []).append(fe)
|
||||
else:
|
||||
homeless = True
|
||||
if homeless:
|
||||
# No enumeration of that system to extend, and a sentence we
|
||||
# would have to write ourselves is a documentation change,
|
||||
# not a correction.
|
||||
skip("whose help text lists no files of that system to add to", module_id)
|
||||
if not homes:
|
||||
continue
|
||||
|
||||
if len(listed) + len(missing) > self._longest:
|
||||
added = sum(len(self._in_search_order(fes)) for fes in homes.values())
|
||||
if len(listed) + added > self._longest:
|
||||
skip("whose help text would grow longer than any it has today", module_id)
|
||||
continue
|
||||
|
||||
new_help = self._extended(help_text, enumeration, missing)
|
||||
if len(listed) + len(missing) > 1:
|
||||
new_help = _BIOS_NOUN.sub(r"\1 files", new_help, count=1)
|
||||
new_help = help_text
|
||||
for i in sorted(homes, reverse=True):
|
||||
start, _, enumeration = clauses[i]
|
||||
missing = self._in_search_order(homes[i])
|
||||
new_help = self._extended(new_help, enumeration, missing)
|
||||
if len(enumeration[2]) + len(missing) > 1:
|
||||
new_help = new_help[:start] + _BIOS_NOUN.sub(
|
||||
r"\1 files", new_help[start:enumeration[0]], count=1
|
||||
) + new_help[enumeration[0]:]
|
||||
self._named.update(id(fe) for fe in homes[i])
|
||||
produced[relative] = originals[relative].replace(
|
||||
f'rp_module_help="{help_text}"',
|
||||
f'rp_module_help="{new_help}"',
|
||||
1,
|
||||
)
|
||||
self._named.update(id(fe) for fe in proposed)
|
||||
|
||||
return produced
|
||||
|
||||
|
||||
@@ -737,6 +737,40 @@ class SearchOrder(unittest.TestCase):
|
||||
self.assertNotIn("us_scd2_9306", produced)
|
||||
self.assertNotIn("jp_mcd1_9112", produced)
|
||||
|
||||
def test_a_file_joins_the_list_of_its_own_system(self):
|
||||
"""flycast's help names the Dreamcast BIOS, then the Naomi/Atomiswave
|
||||
ones. naomi2.zip, an arcade archive, went into the Dreamcast list:
|
||||
only the first BIOS clause was read."""
|
||||
from exporter.baseline import NativeSystem # noqa: PLC0415
|
||||
|
||||
def entry(name, system):
|
||||
return NativeFile(name=name, destination=f"dc/{name}", native_system=system,
|
||||
truth={"name": name, "required": True, "md5": "0" * 32,
|
||||
"_cores": ["flycast"], "_required_by": ["flycast"]})
|
||||
|
||||
dc, arcade = "Sega - Dreamcast", "Sega - Dreamcast-based Arcade"
|
||||
systems = {
|
||||
dc: NativeSystem(dc, files=[entry("dc_boot.bin", dc)]),
|
||||
arcade: NativeSystem(arcade, files=[entry("naomi.zip", arcade),
|
||||
entry("awbios.zip", arcade),
|
||||
entry("naomi2.zip", arcade)]),
|
||||
"other": NativeSystem("other", files=[entry("other.zip", "other")]),
|
||||
}
|
||||
script = ('rp_module_id="lr-flycast"\nrp_module_help="Copy the required Dreamcast '
|
||||
'BIOS file dc_boot.bin to $biosdir/dc\\n\\nCopy the required '
|
||||
'Naomi/Atomiswave BIOS files naomi.zip and awbios.zip to $biosdir/dc"\n')
|
||||
longest = ('rp_module_id="xm7"\nrp_module_help="Copy bios files '
|
||||
+ ", ".join(f"n{i}.rom" for i in range(12)) + ' and n12.rom to $biosdir"\n')
|
||||
exporter = discover_exporters()["retropie"]()
|
||||
produced = exporter.render(
|
||||
systems, None,
|
||||
{"scriptmodules/libretrocores/lr-flycast.sh": script,
|
||||
"scriptmodules/emulators/xm7.sh": longest},
|
||||
)["scriptmodules/libretrocores/lr-flycast.sh"]
|
||||
self.assertIn("Dreamcast BIOS file dc_boot.bin to", produced)
|
||||
self.assertIn("BIOS files naomi.zip, awbios.zip and naomi2.zip to", produced)
|
||||
self.assertNotIn("other.zip", produced)
|
||||
|
||||
def test_cores_that_disagree_keep_the_best_rank(self):
|
||||
"""Nothing is dropped on the rank here, so the best one wins.
|
||||
|
||||
|
||||
Reference in new issue
Block a user