fix: keep Batocera's save files apart from bios/

batocera-systems lists bios/saves/dolphin-emu/Triforce/segaboot.gcm, so the pack folder for the save directory is userdata-saves/. validate_schemas refuses a pack folder the BIOS tree already uses.
This commit is contained in:
Abdessamad Derraz committed 2026-10-22 21:44:14 +02:00
1 parent 8db393f415
commit bf22f1da47
7 files changed
+72 -7

No files matched your search

+1 -1
View File
@@ -1191,7 +1191,7 @@ def generate_pack(
_pack_registry.get(platform_name, {}).get("install", {}) or {}
).get("standalone_copies", []),
launch_folders=len(config.get("core_system_dirs") or {}),
save_folder=(save_layout(config).folder if save_count else ""),
save_folder=(save_layout(config).in_pack if save_count else ""),
save_where=(
save_place(
str(_pack_registry.get(platform_name, {}).get("extract_to") or ""),
+1 -1
View File
@@ -1371,7 +1371,7 @@ def _save_fields(extra: dict, pack_path: str, placement: ExtraPlacement) -> None
extra["pack_path"] = pack_path
if placement.save is not None:
# The path below the save directory, what the manifest writes.
extra["save_dest"] = pack_path[len(placement.save.folder) + 1:]
extra["save_dest"] = pack_path[len(placement.save.in_pack) + 1:]
if not placement.save.by_core:
extra.pop("core_folder", None)
+13 -2
View File
@@ -31,13 +31,23 @@ class SaveLayout:
/userdata/saves/<system>): a file read there is placed once for each
system that runs the core, the systems the platform file names in
``libretro_systems``. ``by_core_for`` names the cores a launcher
sorts by core where it sorts no other.
sorts by core where it sorts no other. ``pack_folder`` renames the
pack's folder when the BIOS tree holds one of the same name.
"""
folder: str
by_core: bool
by_system: bool = False
by_core_for: frozenset[str] = frozenset()
pack_folder: str = ""
@property
def in_pack(self) -> str:
"""The pack folder holding these files: ``pack_folder`` where the
platform's own BIOS tree already has a folder named ``folder``
(Batocera lists bios/saves/dolphin-emu/Triforce/segaboot.gcm),
``folder`` otherwise."""
return self.pack_folder or self.folder
def sorts(self, names: Iterable[str]) -> bool:
"""Whether the frontend inserts the core's folder for a core known
@@ -64,6 +74,7 @@ def save_layout(config: dict) -> SaveLayout | None:
return SaveLayout(
folder, bool(block.get("by_core")), bool(block.get("by_system")),
frozenset(str(core) for core in block.get("by_core_for") or []),
sanitize_pack_path(str(block.get("pack_folder") or "")),
)
@@ -85,7 +96,7 @@ def save_destination(
rel = sanitize_pack_path(path)
if not rel:
return None
root = layout.folder
root = layout.in_pack
if layout.by_system:
folder = sanitize_pack_path(system)
if not folder or "/" in folder:
+31 -1
View File
@@ -416,8 +416,10 @@ def _save_directory_blocks() -> list[str]:
if (
not isinstance(block, dict)
or not {"folder", "by_core"} <= set(block) <= {
"folder", "by_core", "by_system", "by_core_for",
"folder", "by_core", "by_system", "by_core_for", "pack_folder",
}
or not isinstance(block.get("pack_folder", "x"), str)
or "/" in str(block.get("pack_folder", ""))
or not isinstance(folder, str)
or not folder
or "\\" in folder
@@ -438,9 +440,37 @@ def _save_directory_blocks() -> list[str]:
f"platforms/_registry.yml: {name}.save_directory.by_system and "
f"platforms/{name}.yml lists no libretro_systems"
)
in_pack = block.get("pack_folder") or folder
taken = _bios_tree_below(name, in_pack)
if taken:
out.append(
f"platforms/_registry.yml: {name}.save_directory puts the save "
f"files in {in_pack}/, which the BIOS tree uses ({taken}): "
"name another pack_folder"
)
return out
def _bios_tree_below(platform: str, folder: str) -> str:
"""A destination the platform declares below ``folder``, or empty."""
from common import load_platform_config
try:
config = load_platform_config(platform, str(ROOT / "platforms"))
except FileNotFoundError:
return ""
prefix = f"{folder}/".lower()
return next(
(
str(entry["destination"])
for system in (config.get("systems") or {}).values()
for entry in system.get("files") or []
if str(entry.get("destination") or "").lower().startswith(prefix)
),
"",
)
def _libretro_systems(platform: str) -> dict:
"""The platform file's core -> systems table, inheritance included."""
from common import load_platform_config