feat: install files into retrobat emulator folders

RetroBat's Pico8 generator runs pico8.exe from AppConfig.GetFullPath:
the emulatorLauncher.cfg key, else the first existing of four folders of
the RetroBat install. The registry describes that search
(emulators_directory) and the manifest writes such a file as
root: emulators. The installer places it only when the BIOS folder sits
beside RetroBat's launcher config and the config does not move the
folder, and names it no_emulators_directory otherwise. Packs skip it as
they skip root: roms.

The PICO-8 0.2.7 Windows build (pico8.exe, SDL2.dll) is collected from
the archive.org copy of pico-8_0.2.7_windows.zip, its pico8.dat being
the 0.2.7 one already held.
This commit is contained in:
Abdessamad Derraz committed 2026-11-09 18:55:49 +01:00
1 parent f47c8b8e5a
commit c8fe8d914d
16 files changed
+329 -79

No files matched your search

+28 -23
View File
@@ -17,7 +17,7 @@ from common import resolve_local_file
from common import resolve_platform_cores
from common import core_system_dirs, platform_layouts, system_dir_path
from common import standalone_set as platform_standalone_set
from common import ROMS_ROOT, sanitize_pack_path
from common import OUTER_ROOTS, sanitize_pack_path
from common import size_fits
from validation import deliverable, read_from_save_dir, read_from_system_dir
from packpaths import libretro_systems, save_destination, save_layout
@@ -43,22 +43,23 @@ def extra_full_destination(fe: dict, prefix: str) -> str:
"""
if fe.get("root") == "save":
return str(fe.get("pack_path") or "")
if fe.get("root") == ROMS_ROOT:
return roms_destination(sanitize_pack_path(fe.get("destination", fe.get("name", ""))))
if fe.get("root") in OUTER_ROOTS:
return outer_destination(
fe["root"], sanitize_pack_path(fe.get("destination", fe.get("name", "")))
)
return prefixed_destination(
sanitize_pack_path(fe.get("destination", fe.get("name", ""))), prefix
)
# Keys a destination below the roms directory apart from the BIOS tree's
# paths. Never written into a pack: the pack is extracted into the BIOS
# folder, and the installer places these files (``root: roms``).
ROMS_KEY = "roms:"
def outer_destination(root: str, dest: str) -> str:
"""The key of a destination below the roms or an emulator folder.
def roms_destination(dest: str) -> str:
"""The key of a destination below the roms directory."""
return f"{ROMS_KEY}{dest}"
Kept apart from the BIOS tree's paths and never written into a pack:
the pack is extracted into the BIOS folder, and the installer places
these files (``root: roms``, ``root: emulators``).
"""
return f"{root}:{dest}"
def prefixed_destination(dest: str, prefix: str) -> str:
@@ -479,7 +480,7 @@ def unplaceable_extras(
for u in undeclared:
if not u.get("in_repo") and not u.get("unplaced"):
continue
if (not placement.slug_based and u.get("root") not in ("save", ROMS_ROOT)
if (not placement.slug_based and u.get("root") not in ("save", *OUTER_ROOTS)
and not u.get("unplaced")):
continue
dest = _extra_dest(u)
@@ -567,7 +568,7 @@ def _agnostic_scan_extras(
# The scan walks the BIOS tree: a file read below the save
# directory is placed by the gap report's pass.
if (read_from_save_dir(f, standalone) or f.get("unplaced")
or f.get("root") == ROMS_ROOT):
or f.get("root") in OUTER_ROOTS):
continue
# An agnostic BIOS mode says the BIOS filename is free, not that
# every file the emulator loads is. A free filename still has a
@@ -1018,9 +1019,12 @@ class ExtraPlacement:
self.native_systems = native_slug_systems(config)
self.flat = bool(config.get("firmware_folder_flat"))
self.save = save_layout(config)
# The roms directory the registry names, for a file a launcher runs
# from it (ROCKNIX's roms/pico-8).
self.roms = bool((config.get("roms_directory") or {}).get("path"))
# The roms directory and emulator folders the registry describes,
# for a file a launcher runs from them (ROCKNIX's roms/pico-8,
# RetroBat's emulators/pico8).
self.outer = {
root for root in OUTER_ROOTS if config.get(f"{root}_directory")
}
self.config = config
self.norm_map = (
{_norm_system_id(sid): sid for sid in self.platform_systems}
@@ -1041,8 +1045,9 @@ class ExtraPlacement:
"""
if entry.get("unplaced"):
return None
if entry.get("root") == ROMS_ROOT:
return (dest, roms_destination(dest)) if self.roms else None
if entry.get("root") in OUTER_ROOTS:
root = entry["root"]
return (dest, outer_destination(root, dest)) if root in self.outer else None
if entry.get("root") == "save":
placed = self.save_places(entry, dest)
return placed[0] if placed else None
@@ -1103,8 +1108,8 @@ class ExtraPlacement:
"""Why ``place`` returned None for this entry."""
if entry.get("unplaced"):
return str(entry["unplaced"])
if entry.get("root") == ROMS_ROOT:
return "no_roms_directory"
if entry.get("root") in OUTER_ROOTS:
return f"no_{entry['root']}_directory"
if entry.get("root") == "save":
if self.save is None:
return "no_save_directory"
@@ -1329,7 +1334,7 @@ def _collect_emulator_extras(
# covered elsewhere belongs to another program's file.
# Nor is one placed outside the BIOS tree by the layout.
if (fname not in covered_names or f.get("unsourceable") or f.get("unplaced")
or f.get("root") == ROMS_ROOT):
or f.get("root") in OUTER_ROOTS):
continue
# Installed with the emulator or by the platform's package,
# as the first pass already decided for the same entry.
@@ -1568,8 +1573,8 @@ def _report_extra(u: dict, name: str, dest: str) -> dict:
extra["root"] = "save"
if u.get("core_folder") is not None:
extra["core_folder"] = u["core_folder"]
elif u.get("root") == ROMS_ROOT:
extra["root"] = ROMS_ROOT
elif u.get("root") in OUTER_ROOTS:
extra["root"] = u["root"]
if u.get("system_dir"):
extra["system_dir"] = u["system_dir"]
if u.get("layout_path"):