feat: honour the boards a folder offers a core on

ROCKNIX writes some add_emu_core calls under a case on DEVICE, and the
rom folders file keeps that branch as the offer's `when` (uae4arm for
amiga, emulators/package.mk:188). A board's core list names such a core
when another folder offers it there, so --target placed its files in a
folder the board does not offer it for.

offer_boards() reads `when` and board_defaults against the platform's
targets, aliases included. A board build (generate_pack and generate
--manifest with --target, verify --target) carries the board in the
config (TARGET_KEY), and content_folder_tags leaves out the pairs the
board is not offered. A manifest for every board lists in
offered_boards each profile placed in such a folder, and install.py
--target drops its files there on the other boards.

Manifests: no file moves. The cores ROCKNIX offers under a device case
read no file beside the game today, so no manifest carries
offered_boards yet.
This commit is contained in:
Abdessamad Derraz committed 2026-11-11 13:46:57 +01:00
1 parent 389ebfa132
commit 05f3f5c702
10 files changed
+383 -41

No files matched your search

+46
View File
@@ -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."""
+54
View File
@@ -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
@@ -1208,6 +1209,59 @@ class EveryCoreAFolderOffers(unittest.TestCase):
self.assertIn("arcade", folders, platform)
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