mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-14 05:53:47 -06:00
chore: merge the last MAME fixes
This commit is contained in:
commit
3bebf75da5
77 files changed
+2424
-327
No files matched your search
@@ -52,6 +52,11 @@ class ListxmlIndex(unittest.TestCase):
|
||||
def test_device_with_roms_only(self) -> None:
|
||||
self.assertEqual(self.index["devices"], {"m68705p3": ["mslug"]})
|
||||
|
||||
def test_a_clone_lists_its_parent_game(self) -> None:
|
||||
# MAME looks a clone's shared ROMs up in its parent's archive
|
||||
# (src/emu/driver.cpp:31-38): mslugh reads mslug.zip.
|
||||
self.assertEqual(self.index["parents"], {"mslug": ["mslugh"]})
|
||||
|
||||
def test_chd_and_missing_parent(self) -> None:
|
||||
self.assertEqual(self.index["chd"], ["ikaruga"])
|
||||
self.assertEqual(self.index["missing_parents"], {"orphan": "gonebios"})
|
||||
|
||||
@@ -145,6 +145,52 @@ class ACoreOnlyTheDownloaderBrings(unittest.TestCase):
|
||||
self.assertEqual([f["dest"] for f in files], ["kick31.rom", "roms/a4091.rom"])
|
||||
|
||||
|
||||
|
||||
class CoreOfferedOnSomeBoards(unittest.TestCase):
|
||||
"""ROCKNIX writes uae4arm for roms/amiga under the devices it builds it
|
||||
for (emulators/package.mk:188), and s922x runs uae4arm for amigacd32:
|
||||
the core list alone would keep its roms/amiga files there."""
|
||||
|
||||
MANIFEST = {
|
||||
"core_names": {"uae4arm": [], "puae": []},
|
||||
"offered_boards": {
|
||||
"uae4arm": [{"root": "roms", "folder": "amiga", "boards": ["h700", "rk3326"]}],
|
||||
},
|
||||
"files": [
|
||||
{"dest": "amiga/kick.rom", "cores": ["uae4arm"], "root": "roms"},
|
||||
{"dest": "amigacd32/kick.rom", "cores": ["uae4arm"], "root": "roms"},
|
||||
{"dest": "amiga/shared.rom", "cores": ["uae4arm", "puae"], "root": "roms"},
|
||||
],
|
||||
"omitted_files": [],
|
||||
}
|
||||
|
||||
def dests(self, target):
|
||||
files, _ = install.narrow_to_cores(self.MANIFEST, ["uae4arm"], target=target)
|
||||
return [f["dest"] for f in files]
|
||||
|
||||
def test_a_board_it_is_offered_on_keeps_the_folder(self):
|
||||
self.assertEqual(self.dests("rk3326"),
|
||||
["amiga/kick.rom", "amigacd32/kick.rom", "amiga/shared.rom"])
|
||||
|
||||
def test_another_board_keeps_only_the_folders_offering_it(self):
|
||||
self.assertEqual(self.dests("s922x"), ["amigacd32/kick.rom"])
|
||||
|
||||
def test_a_core_offered_everywhere_keeps_a_shared_file(self):
|
||||
files, _ = install.narrow_to_cores(self.MANIFEST, ["uae4arm", "puae"], target="s922x")
|
||||
self.assertEqual([f["dest"] for f in files], ["amigacd32/kick.rom", "amiga/shared.rom"])
|
||||
|
||||
def test_installed_cores_are_no_board(self):
|
||||
files, _ = install.narrow_to_cores(self.MANIFEST, ["uae4arm"])
|
||||
self.assertEqual(len(files), 3)
|
||||
|
||||
def test_the_manifest_check_refuses_a_malformed_map(self):
|
||||
base = {"manifest_version": 2, "platform": "rocknix", "files": [], "omitted_files": []}
|
||||
install._validate_manifest(
|
||||
{**base, "offered_boards": self.MANIFEST["offered_boards"]}, "rocknix")
|
||||
with self.assertRaisesRegex(ValueError, "offered_boards"):
|
||||
install._validate_manifest(
|
||||
{**base, "offered_boards": {"uae4arm": [{"folder": "amiga"}]}}, "rocknix")
|
||||
|
||||
class ACoreTheListDoesNotKnow(unittest.TestCase):
|
||||
"""A core newer than the list (parallel_dc, issue 87) loses nothing its .info declares."""
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
|
||||
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
@@ -985,12 +986,12 @@ class AdvanceMameOnEmuELEC(unittest.TestCase):
|
||||
# read in both.
|
||||
view = standalone_view("advancemame", "emuelec")
|
||||
sets = [e for e in view["files"] if e.get("category") == "bios_zip"]
|
||||
self.assertEqual(len(sets), 58)
|
||||
self.assertEqual(len(sets), 52)
|
||||
places: dict[str, set[str]] = {}
|
||||
for entry in sets:
|
||||
self.assertTrue(entry.get("unprefixed"))
|
||||
places.setdefault(entry["name"], set()).add(entry["standalone_path"])
|
||||
self.assertEqual(len(places), 29)
|
||||
self.assertEqual(len(places), 26)
|
||||
for name, paths in places.items():
|
||||
self.assertEqual(paths, {"mame/" + name, "arcade/" + name})
|
||||
|
||||
@@ -1017,7 +1018,7 @@ class AdvanceMameOnEmuELEC(unittest.TestCase):
|
||||
by_dest = {f["dest"]: advancemame_copy(f) for f in manifest["files"]}
|
||||
sets = [d.removeprefix("arcade/") for d, sha1 in by_dest.items()
|
||||
if d.startswith("arcade/") and sha1]
|
||||
self.assertEqual(len(sets), 29)
|
||||
self.assertEqual(len(sets), 26)
|
||||
for name in sets:
|
||||
self.assertEqual(by_dest["arcade/" + name], by_dest["mame/" + name], name)
|
||||
|
||||
@@ -1208,6 +1209,94 @@ class EveryCoreAFolderOffers(unittest.TestCase):
|
||||
self.assertIn("arcade", folders, platform)
|
||||
|
||||
|
||||
class CloneReadsItsParent(unittest.TestCase):
|
||||
"""ES-DE starts odyssey2 with -rompath on roms/odyssey2 alone, and MAME
|
||||
finds o2bios.rom in the parent's videopac.zip (src/emu/driver.cpp:31-38)."""
|
||||
|
||||
def test_the_parent_set_goes_to_the_clone_folder(self) -> None:
|
||||
from common import rom_search_sets
|
||||
|
||||
self.assertIn("videopac", rom_search_sets("mame", "odyssey2", ["odyssey2"], False))
|
||||
for platform, dest in (("emudeck", "odyssey2/videopac.zip"),
|
||||
("retrodeck", "roms/odyssey2/videopac.zip")):
|
||||
with self.subTest(platform=platform):
|
||||
dests = {f["dest"] for f in platform_manifest(platform)["files"]}
|
||||
self.assertIn(dest, dests)
|
||||
|
||||
|
||||
class AdvanceMameOnRetroPie(unittest.TestCase):
|
||||
"""RetroPie writes dir_rom $romdir/mame-advmame:$romdir/arcade into each
|
||||
AdvanceMAME build's rc (advmame.sh:100), the list the code splits on ':'
|
||||
(advance/linux/file.c:138-141)."""
|
||||
|
||||
def test_the_sets_go_to_the_first_folder_searched(self) -> None:
|
||||
config = load_platform_config("retropie", str(REPO_ROOT / "platforms"))
|
||||
profiles = load_emulator_profiles(str(REPO_ROOT / "emulators"))
|
||||
tags = standalone_set(config)
|
||||
for emu in ("advmame", "advmame-1.4", "advmame-0.94"):
|
||||
with self.subTest(emu=emu):
|
||||
placed = [
|
||||
(f.get("root"), f.get("standalone_path"))
|
||||
for view, standalone in platform_layouts(emu, profiles[emu], tags)
|
||||
if standalone
|
||||
for f in view["files"] if isinstance(f, dict) and f["name"] == "neogeo.zip"
|
||||
]
|
||||
self.assertEqual(placed, [("roms", "mame-advmame/neogeo.zip")])
|
||||
|
||||
|
||||
class CoreOfferedOnSomeBoards(unittest.TestCase):
|
||||
"""ROCKNIX writes some add_emu_core calls under a `case "${DEVICE}"`
|
||||
branch (emulators/package.mk:188 offers uae4arm for amiga on the devices
|
||||
it builds it for). A board's pack places such a core in that folder only
|
||||
when the branch names the board, and a manifest for every board says
|
||||
where it does."""
|
||||
|
||||
ROW = {
|
||||
"folder": "amiga", "core": "puae", "emulator": "retroarch",
|
||||
"offers": [
|
||||
{"emulator": "retroarch", "core": "puae"},
|
||||
{"emulator": "retroarch", "core": "uae4arm", "when": "DEVICE H700|RK3326"},
|
||||
{"emulator": "retroarch", "core": "puae2021",
|
||||
"when": 'if [ "${PREFER_GLES}" = "yes" ]; then'},
|
||||
],
|
||||
}
|
||||
|
||||
def config(self, **extra) -> dict:
|
||||
base = load_platform_config("rocknix", str(REPO_ROOT / "platforms"))
|
||||
return {**base, "_rom_folders": [self.ROW], **extra}
|
||||
|
||||
def test_a_branch_names_the_boards(self) -> None:
|
||||
from common import when_admits
|
||||
|
||||
self.assertTrue(when_admits("DEVICE H700|RK3326", "rk3326"))
|
||||
self.assertFalse(when_admits("DEVICE H700|RK3326", "s922x"))
|
||||
self.assertTrue(when_admits("DEVICE AMD64; DEVICE RK3588*", "rk3588"))
|
||||
self.assertTrue(when_admits('if [ "${PREFER_GLES}" = "yes" ]; then', "h700"))
|
||||
|
||||
def test_an_offer_carries_the_boards_its_branch_names(self) -> None:
|
||||
from common import offer_boards
|
||||
|
||||
boards = offer_boards(self.config())
|
||||
self.assertEqual(boards[("uae4arm", "amiga")], frozenset({"h700", "rk3326"}))
|
||||
self.assertIsNone(boards[("puae", "amiga")])
|
||||
self.assertIsNone(boards[("puae2021", "amiga")])
|
||||
|
||||
def test_a_board_pack_places_the_core_where_the_board_offers_it(self) -> None:
|
||||
from common import CONTENT_FOLDER_PREFIX, TARGET_KEY, content_folder_tags
|
||||
|
||||
def placed(config: dict) -> dict:
|
||||
rows = [json.loads(t[len(CONTENT_FOLDER_PREFIX):]) for t in content_folder_tags(config)
|
||||
if t.startswith(CONTENT_FOLDER_PREFIX)]
|
||||
return {core: on for core, _folder, _where, on in rows}
|
||||
|
||||
every = placed(self.config())
|
||||
self.assertEqual(every["uae4arm"], ["h700", "rk3326"])
|
||||
self.assertIsNone(every["puae"])
|
||||
self.assertIn("uae4arm", placed(self.config(**{TARGET_KEY: "rk3326"})))
|
||||
self.assertNotIn("uae4arm", placed(self.config(**{TARGET_KEY: "s922x"})))
|
||||
self.assertIn("puae", placed(self.config(**{TARGET_KEY: "s922x"})))
|
||||
|
||||
|
||||
def platform_manifest(platform: str) -> dict:
|
||||
from common import load_database
|
||||
|
||||
|
||||
@@ -278,6 +278,38 @@ class IniSearchLists(unittest.TestCase):
|
||||
self.assertFalse([r for r in found if "hash" in str(r.get("search_dir"))])
|
||||
|
||||
|
||||
ADVMAME = module("advmame", """
|
||||
function configure_advmame() {
|
||||
iniConfig " " "" "$md_conf_root/mame-advmame/$md_id.rc"
|
||||
iniSet "dir_rom" "$romdir/mame-advmame:$romdir/arcade"
|
||||
iniSet "dir_artwork" "$romdir/mame-advmame/artwork"
|
||||
addEmulator 1 "$md_id" "arcade" "$md_inst/bin/advmame %BASENAME%"
|
||||
addSystem "arcade"
|
||||
}
|
||||
""", 95)
|
||||
|
||||
|
||||
class AdvanceMameSearchList(unittest.TestCase):
|
||||
"""AdvanceMAME splits dir_rom on ':' (advance/linux/file.c:138-141,
|
||||
advance/osd/fileio.c:696-699), and advmame.sh:100 lists two folders."""
|
||||
|
||||
def test_a_colon_list_below_the_roms_root_is_a_search_path(self):
|
||||
found = [r for r in records({f"{EMULATORS}/advmame.sh": ADVMAME}, "advmame")
|
||||
if r["kind"] == "passes_path"]
|
||||
self.assertEqual(
|
||||
[(r["search_dir"], r["passes_to"].split(" in ")[0]) for r in found],
|
||||
[("$romdir/mame-advmame:$romdir/arcade", "dir_rom")],
|
||||
)
|
||||
|
||||
def test_mame_does_not_read_a_colon_as_a_separator(self):
|
||||
from scraper.retropie_launchers import LIST_SEPARATORS
|
||||
|
||||
self.assertNotIn("mame", LIST_SEPARATORS)
|
||||
self.assertEqual(
|
||||
{LIST_SEPARATORS[p] for p in ("advmame", "advmame-0.94", "advmame-1.4")}, {":"}
|
||||
)
|
||||
|
||||
|
||||
class CommandLines(unittest.TestCase):
|
||||
def test_sdltrs_passes_one_rom_per_machine(self):
|
||||
found = records({f"{EMULATORS}/sdltrs.sh": SDLTRS}, "sdltrs")
|
||||
|
||||
+12
-5
@@ -126,10 +126,8 @@ class HeldPinsReadTheirBuildFileAgain(unittest.TestCase):
|
||||
|
||||
class EveryBuildReferenceNamesThePin(unittest.TestCase):
|
||||
"""Reads the repository: a pin_build value is what the platform builds,
|
||||
so on a pin_frozen profile it is the profile's source_commit or names
|
||||
its core_version, and the platform's own YAML was scraped from that
|
||||
repository. A pin_build standing for config_reads names the build those
|
||||
reads are made at, a revision of its own (ROCKNIX's DuckStation)."""
|
||||
so it is the profile's source_commit or names its core_version, and the
|
||||
platform's own YAML was scraped from that repository."""
|
||||
|
||||
def test_the_values_agree(self):
|
||||
from common import load_emulator_profiles
|
||||
@@ -147,11 +145,20 @@ class EveryBuildReferenceNamesThePin(unittest.TestCase):
|
||||
else {str(versions)} if versions else set()
|
||||
)
|
||||
|
||||
source = str(profile.get("source") or "").rstrip("/").removesuffix(".git")
|
||||
|
||||
def names_it(value: str) -> bool:
|
||||
if profile.get("pin_follows"):
|
||||
# A build of the branch tip names the repository it
|
||||
# clones, at no revision: RetroPie's advmame.
|
||||
return value.split()[-1].rstrip("/").removesuffix(".git") == source
|
||||
token = value.split()[-1].rsplit("/", 1)[-1].removesuffix(".tar.gz")
|
||||
return value in pins or any(token in v or v in value for v in versions)
|
||||
|
||||
if profile.get("pin_frozen") and not any(names_it(str(r["value"])) for r in references):
|
||||
# A reference that only dates a config_reads entry names the build
|
||||
# the platform reads that file at, not this profile's pin.
|
||||
justifies_pin = profile.get("pin_frozen") or profile.get("pin_follows")
|
||||
if justifies_pin and not any(names_it(str(r["value"])) for r in references):
|
||||
disagree.append(name)
|
||||
for reference in references:
|
||||
if not cf.pin_build_revision(reference, REPO_ROOT / "platforms"):
|
||||
|
||||
@@ -3077,9 +3077,14 @@ class TestDeliberatelyFrozenPin(TestBuildReport):
|
||||
# live build can add a system its frozen revision lacked
|
||||
# (advancemame's coh1002v, after advmame-1.4), so the frozen one's
|
||||
# systems are a subset, not an equal set. A live build can also drop
|
||||
# a system upstream deleted: advancemame removed its Hyper Neo Geo 64
|
||||
# driver in dff25b6ee7, which advmame-1.4 still carries.
|
||||
removed_upstream = {("advmame-1.4", "advancemame"): {"hyper-neogeo64"}}
|
||||
# a system upstream deleted: AdvanceMAME removed its Hyper Neo Geo 64
|
||||
# driver in dff25b6ee7, which advmame-1.4 and advancemame (AmberELEC's
|
||||
# 0f6a767) still carry.
|
||||
removed_upstream = {
|
||||
("advmame-1.4", "advancemame"): {"hyper-neogeo64"},
|
||||
("advmame-1.4", "advmame"): {"hyper-neogeo64"},
|
||||
("advancemame", "advmame"): {"hyper-neogeo64"},
|
||||
}
|
||||
pairs = 0
|
||||
for names in by_source.values():
|
||||
frozen = [
|
||||
@@ -3373,6 +3378,61 @@ class TestBumpCommit(unittest.TestCase):
|
||||
self.assertFalse(bump_commit(self.path, report))
|
||||
self.assertNotIn("newhead", self.path.read_text())
|
||||
|
||||
def test_a_build_of_the_branch_tip_follows_it(self):
|
||||
# RetroPie builds AdvanceMAME from the tip of master
|
||||
# (advmame.sh:16, 39-41): HEAD is the build it ships.
|
||||
self.path.write_text(
|
||||
SAMPLE + "built_by: [retropie]\n"
|
||||
+ 'pin_follows: "RetroPie builds the branch tip"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
part = PartResult(
|
||||
RefPart("a.c", 10, 12, "a.c:10-12"), "ANCHORED", None, 10, 12, []
|
||||
)
|
||||
report = ProfileReport(
|
||||
name="p", repo="o/n", pin="pin", head="newhead",
|
||||
entries=[
|
||||
EntryReport("a.bin", "a.c:10-12, (just a note)", "ANCHORED", [part])
|
||||
],
|
||||
counts={"ANCHORED": 1},
|
||||
)
|
||||
self.assertTrue(bump_commit(self.path, report))
|
||||
self.assertIn("newhead", self.path.read_text())
|
||||
|
||||
def test_a_config_read_at_the_pin_follows_it(self):
|
||||
# RetroPie reads advmame.rc at the build it installs, the pin: the
|
||||
# config_reads revision is the pin, and moves with it.
|
||||
pin = "a" * 40
|
||||
self.path.write_text(
|
||||
SAMPLE.replace('profiled_date: "2026-03-29"\n',
|
||||
f'profiled_date: "2026-03-29"\nsource_commit: "{pin}"\n', 1)
|
||||
+ "built_by: [retropie]\n"
|
||||
+ 'pin_follows: "RetroPie builds the branch tip"\n'
|
||||
+ "config_reads:\n"
|
||||
+ ' - file: "advmame.rc"\n'
|
||||
+ " platforms: [retropie]\n"
|
||||
+ f' revision: "{pin}"\n'
|
||||
+ ' source_ref: "a.c:10-12"\n'
|
||||
+ " - file: \"other.rc\"\n"
|
||||
+ " platforms: [emuelec]\n"
|
||||
+ f' revision: "{"b" * 40}"\n'
|
||||
+ ' source_ref: "a.c:10-12"\n',
|
||||
encoding="utf-8",
|
||||
)
|
||||
part = PartResult(
|
||||
RefPart("a.c", 10, 12, "a.c:10-12"), "ANCHORED", None, 10, 12, []
|
||||
)
|
||||
head = "c" * 40
|
||||
report = ProfileReport(
|
||||
name="p", repo="o/n", pin=pin, head=head,
|
||||
entries=[EntryReport("a.bin", "a.c:10-12", "ANCHORED", [part])],
|
||||
counts={"ANCHORED": 1},
|
||||
)
|
||||
self.assertTrue(bump_commit(self.path, report))
|
||||
document = yaml.safe_load(self.path.read_text(encoding="utf-8"))
|
||||
self.assertEqual(document["source_commit"], head)
|
||||
self.assertEqual([r["revision"] for r in document["config_reads"]], [head, "b" * 40])
|
||||
|
||||
def test_refused_when_no_ref_reads_the_pinned_repository(self):
|
||||
"""gam4980: every bare libretro.c ref anchored in upstream, and the
|
||||
bump wrote the fork's HEAD over refs that never described it."""
|
||||
|
||||
Reference in new issue
Block a user