mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-14 14:03:47 -06:00
feat: install the fewest files for a card's games
--for-games --required-only on a dArkOS card from a computer kept every file of the list: --dest skipped the card's detection, so its rom folders were never found. The games part beside the BIOS folder now names them. The manifest marks a data tree every core runs without (optional), and --required-only leaves it out: one GBA and one SNES game took FBNeo's cheats and samples, 3,472 files no game opened.
This commit is contained in:
1 parent
adce8dd0d4
commit
072380c268
24 files changed
+184
-78
No files matched your search
@@ -51,10 +51,12 @@ data_directories:
|
|||||||
- ref: fbneo-cheats
|
- ref: fbneo-cheats
|
||||||
unread_on: [romm]
|
unread_on: [romm]
|
||||||
destination: fbneo/cheats
|
destination: fbneo/cheats
|
||||||
|
required: false
|
||||||
source_ref: "source src/burner/conc.cpp:167"
|
source_ref: "source src/burner/conc.cpp:167"
|
||||||
- ref: fbneo-samples
|
- ref: fbneo-samples
|
||||||
unread_on: [romm]
|
unread_on: [romm]
|
||||||
destination: fbneo
|
destination: fbneo
|
||||||
|
required: false
|
||||||
source_ref: "source src/burn/snd/samples.cpp:21-35"
|
source_ref: "source src/burn/snd/samples.cpp:21-35"
|
||||||
|
|
||||||
notes: |
|
notes: |
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
|
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
|
||||||
# the site's build rewrites this line there (scripts/sitebootstrap.py).
|
# the site's build rewrites this line there (scripts/sitebootstrap.py).
|
||||||
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
|
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
|
||||||
$defaultInstallSha256 = "57e3cb6739a701181908773e603f17d2b10e1b0e2a5cde5cc4d5c97426da5dd4"
|
$defaultInstallSha256 = "3a78bf2e5a910d0f5c21bc2dc490aa600fc3273c56ae01e9ce5061d9b3578f07"
|
||||||
$maximumInstallerBytes = 2MB
|
$maximumInstallerBytes = 2MB
|
||||||
$installerExit = 0
|
$installerExit = 0
|
||||||
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
|
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
|
||||||
|
|||||||
+25
-8
@@ -3724,6 +3724,8 @@ def _check_data_directory(entry: object, where: str) -> None:
|
|||||||
values = entry.get(field, [])
|
values = entry.get(field, [])
|
||||||
if not isinstance(values, list) or not all(isinstance(v, str) for v in values):
|
if not isinstance(values, list) or not all(isinstance(v, str) for v in values):
|
||||||
raise ValueError(f"{where}.{field} is invalid")
|
raise ValueError(f"{where}.{field} is invalid")
|
||||||
|
if entry.get("optional", True) is not True:
|
||||||
|
raise ValueError(f"{where}.optional is invalid")
|
||||||
files = entry.get("files")
|
files = entry.get("files")
|
||||||
if not isinstance(files, dict) or not files or len(files) > MAX_MANIFEST_FILES:
|
if not isinstance(files, dict) or not files or len(files) > MAX_MANIFEST_FILES:
|
||||||
raise ValueError(f"{where}.files is invalid")
|
raise ValueError(f"{where}.files is invalid")
|
||||||
@@ -7393,11 +7395,16 @@ def _install_data_member(
|
|||||||
scratch.unlink(missing_ok=True)
|
scratch.unlink(missing_ok=True)
|
||||||
|
|
||||||
|
|
||||||
def select_data_directories(manifest: dict, files: list[dict], narrowed: bool) -> list[dict]:
|
def select_data_directories(manifest: dict, files: list[dict], narrowed: bool,
|
||||||
"""The data trees this install keeps: all, or those of a kept system."""
|
required_only: bool = False) -> list[dict]:
|
||||||
entries = manifest.get("data_directories") or []
|
"""The data trees this install keeps: all, or those of a kept system.
|
||||||
|
--required-only leaves out a tree every core reading it runs without
|
||||||
|
(`optional`): a GBA and a SNES game took FBNeo's cheats and samples,
|
||||||
|
3,472 files no game opened."""
|
||||||
|
entries = [e for e in manifest.get("data_directories") or []
|
||||||
|
if not (required_only and e.get("optional"))]
|
||||||
if not narrowed:
|
if not narrowed:
|
||||||
return list(entries)
|
return entries
|
||||||
kept = {system for f in files for system in entry_systems(f)}
|
kept = {system for f in files for system in entry_systems(f)}
|
||||||
return [e for e in entries if kept & set(e.get("systems") or [])]
|
return [e for e in entries if kept & set(e.get("systems") or [])]
|
||||||
|
|
||||||
@@ -8824,7 +8831,8 @@ def _prompt_custom_selection(
|
|||||||
if bios_path is not None and not dry_run and current != INSTALLED_ONLY:
|
if bios_path is not None and not dry_run and current != INSTALLED_ONLY:
|
||||||
kept = menu_choice(files, omitted, installed, current, False)[0]
|
kept = menu_choice(files, omitted, installed, current, False)[0]
|
||||||
kept_trees = select_data_directories({"data_directories": trees}, kept,
|
kept_trees = select_data_directories({"data_directories": trees}, kept,
|
||||||
narrowed or current is not None)
|
narrowed or current is not None,
|
||||||
|
isinstance(current, GamesChoice) and current.required)
|
||||||
if kept and all_in_place(kept, kept_trees, bios_path):
|
if kept and all_in_place(kept, kept_trees, bios_path):
|
||||||
# Read before the menu, as the screen reads before it asks: a
|
# Read before the menu, as the screen reads before it asks: a
|
||||||
# rerun was offered an install that installs nothing, then told
|
# rerun was offered an install that installs nothing, then told
|
||||||
@@ -8953,7 +8961,8 @@ def _print_menu_head(
|
|||||||
# The trees of the systems kept: 2636 data files of blueMSX, Dolphin
|
# The trees of the systems kept: 2636 data files of blueMSX, Dolphin
|
||||||
# and PPSSPP were counted for every --system tried.
|
# and PPSSPP were counted for every --system tried.
|
||||||
kept_trees = select_data_directories({"data_directories": trees}, shown,
|
kept_trees = select_data_directories({"data_directories": trees}, shown,
|
||||||
narrowed or current is not None)
|
narrowed or current is not None,
|
||||||
|
isinstance(current, GamesChoice) and current.required)
|
||||||
data = sum(len(entry.get("files") or {}) for entry in kept_trees)
|
data = sum(len(entry.get("files") or {}) for entry in kept_trees)
|
||||||
data_size = sum(meta.get("size", 0) for entry in kept_trees
|
data_size = sum(meta.get("size", 0) for entry in kept_trees
|
||||||
for meta in (entry.get("files") or {}).values())
|
for meta in (entry.get("files") or {}).values())
|
||||||
@@ -9764,6 +9773,12 @@ def games_setups(index: dict, plat: str, bios_path: Path, os_type: str = "") ->
|
|||||||
if not named:
|
if not named:
|
||||||
above = card_root_above(bios_path)
|
above = card_root_above(bios_path)
|
||||||
named = above[0] if above else ""
|
named = above[0] if above else ""
|
||||||
|
if not named:
|
||||||
|
# --dest on a handheld's games part from a computer (ArkOS's
|
||||||
|
# EASYROMS/bios): detection never ran there, and the card's own rom
|
||||||
|
# folders sit beside the BIOS folder.
|
||||||
|
part = games_part(bios_path.parent)
|
||||||
|
named = part.name if part else ""
|
||||||
key = _setup_key(named) if named else ""
|
key = _setup_key(named) if named else ""
|
||||||
found = [name for name in sorted(setups) if key and (name == key or name.startswith(key + "-"))]
|
found = [name for name in sorted(setups) if key and (name == key or name.startswith(key + "-"))]
|
||||||
if not found and plat in setups:
|
if not found and plat in setups:
|
||||||
@@ -15671,7 +15686,8 @@ def _install(args: argparse.Namespace, real_stdout: TextIO) -> None:
|
|||||||
!= len(manifest.get("files", [])) + len(variants if case_kept else [])
|
!= len(manifest.get("files", [])) + len(variants if case_kept else [])
|
||||||
or games_applied
|
or games_applied
|
||||||
)
|
)
|
||||||
data_dirs = select_data_directories(manifest, files, narrowed)
|
data_dirs = select_data_directories(manifest, files, narrowed,
|
||||||
|
bool(args.required_only))
|
||||||
# The kinds as the plan and the menu head say them (parts_words),
|
# The kinds as the plan and the menu head say them (parts_words),
|
||||||
# the data files of the folders kept among them: this head said
|
# the data files of the folders kept among them: this head said
|
||||||
# BIOS files and game data beside a plan of three kinds, neither
|
# BIOS files and game data beside a plan of three kinds, neither
|
||||||
@@ -21812,7 +21828,8 @@ def _plan_data(state: TuiState, check: dict) -> tuple[int, int | None]:
|
|||||||
if not _tui_estimating(state):
|
if not _tui_estimating(state):
|
||||||
data = check.get("data_missing", 0)
|
data = check.get("data_missing", 0)
|
||||||
return data, check.get("data_bytes") if data else None
|
return data, check.get("data_bytes") if data else None
|
||||||
trees = select_data_directories(state.manifest or {}, _choice_entries(state), True)
|
required = any(flag == "--required-only" for flag, _value in tui_flags(state))
|
||||||
|
trees = select_data_directories(state.manifest or {}, _choice_entries(state), True, required)
|
||||||
sizes = [meta.get("size", 0) for entry in trees for meta in (entry.get("files") or {}).values()]
|
sizes = [meta.get("size", 0) for entry in trees for meta in (entry.get("files") or {}).values()]
|
||||||
return len(sizes), sum(sizes)
|
return len(sizes), sum(sizes)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
|
|||||||
# curl or wget stop on a cut transfer before the hash is read: the site's
|
# curl or wget stop on a cut transfer before the hash is read: the site's
|
||||||
# build rewrites this line there (scripts/sitebootstrap.py).
|
# build rewrites this line there (scripts/sitebootstrap.py).
|
||||||
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
|
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
|
||||||
DEFAULT_INSTALL_SHA256="57e3cb6739a701181908773e603f17d2b10e1b0e2a5cde5cc4d5c97426da5dd4"
|
DEFAULT_INSTALL_SHA256="3a78bf2e5a910d0f5c21bc2dc490aa600fc3273c56ae01e9ce5061d9b3578f07"
|
||||||
MAX_INSTALLER_BYTES=2097152
|
MAX_INSTALLER_BYTES=2097152
|
||||||
|
|
||||||
cleanup() {
|
cleanup() {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "amberelec",
|
"platform": "amberelec",
|
||||||
"display_name": "AmberELEC",
|
"display_name": "AmberELEC",
|
||||||
"version": "prerelease-20261019_1835",
|
"version": "prerelease-20261019_1835",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "",
|
"base_destination": "",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -77381,7 +77381,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -77615,7 +77616,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -77988,7 +77990,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "batocera",
|
"platform": "batocera",
|
||||||
"display_name": "Batocera",
|
"display_name": "Batocera",
|
||||||
"version": "43.1",
|
"version": "43.1",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -225291,7 +225291,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -225525,7 +225526,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"save_directory": {
|
"save_directory": {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "emudeck",
|
"platform": "emudeck",
|
||||||
"display_name": "EmuDeck",
|
"display_name": "EmuDeck",
|
||||||
"version": "2.7EA",
|
"version": "2.7EA",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -123400,7 +123400,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -123634,7 +123635,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -124007,7 +124009,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "lrps2",
|
"ref": "lrps2",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "emuelec",
|
"platform": "emuelec",
|
||||||
"display_name": "EmuELEC",
|
"display_name": "EmuELEC",
|
||||||
"version": "4.8",
|
"version": "4.8",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "",
|
"base_destination": "",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -83639,7 +83639,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -83873,7 +83874,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -84246,7 +84248,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
+5
-3
@@ -6,7 +6,7 @@
|
|||||||
"platform": "knulli",
|
"platform": "knulli",
|
||||||
"display_name": "KNULLI",
|
"display_name": "KNULLI",
|
||||||
"version": "20260511",
|
"version": "20260511",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -157933,7 +157933,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -158167,7 +158168,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "lrps2",
|
"ref": "lrps2",
|
||||||
|
|||||||
+7
-4
@@ -6,7 +6,7 @@
|
|||||||
"platform": "lakka",
|
"platform": "lakka",
|
||||||
"display_name": "Lakka",
|
"display_name": "Lakka",
|
||||||
"version": "v6.1",
|
"version": "v6.1",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "system",
|
"base_destination": "system",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -130677,7 +130677,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -130911,7 +130912,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -131284,7 +131286,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "yaps2-resources",
|
"ref": "yaps2-resources",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "myminui",
|
"platform": "myminui",
|
||||||
"display_name": "MyMinUI",
|
"display_name": "MyMinUI",
|
||||||
"version": "2026-08-09",
|
"version": "2026-08-09",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "",
|
"base_destination": "",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -18958,7 +18958,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-cheats",
|
"ref": "fbneo-cheats",
|
||||||
@@ -32688,7 +32689,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -32922,7 +32924,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -33156,7 +33159,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
+5
-3
@@ -6,7 +6,7 @@
|
|||||||
"platform": "nextui",
|
"platform": "nextui",
|
||||||
"display_name": "NextUI",
|
"display_name": "NextUI",
|
||||||
"version": "2026-10-20",
|
"version": "2026-10-20",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "",
|
"base_destination": "",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -19366,7 +19366,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -19600,7 +19601,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "recalbox",
|
"platform": "recalbox",
|
||||||
"display_name": "Recalbox",
|
"display_name": "Recalbox",
|
||||||
"version": "10.1.1",
|
"version": "10.1.1",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -62834,7 +62834,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -63068,7 +63069,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"save_directory": {
|
"save_directory": {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "retroarch",
|
"platform": "retroarch",
|
||||||
"display_name": "RetroArch",
|
"display_name": "RetroArch",
|
||||||
"version": "v1.22.2",
|
"version": "v1.22.2",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "system",
|
"base_destination": "system",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -140789,7 +140789,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -141023,7 +141024,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -141396,7 +141398,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "ppsspp-assets",
|
"ref": "ppsspp-assets",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "retrobat",
|
"platform": "retrobat",
|
||||||
"display_name": "RetroBat",
|
"display_name": "RetroBat",
|
||||||
"version": "8.3.1",
|
"version": "8.3.1",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -89076,7 +89076,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -89310,7 +89311,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -89683,7 +89685,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"save_directory": {
|
"save_directory": {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "retrodeck",
|
"platform": "retrodeck",
|
||||||
"display_name": "RetroDECK",
|
"display_name": "RetroDECK",
|
||||||
"version": "0.10.10b",
|
"version": "0.10.10b",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "",
|
"base_destination": "",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -153141,7 +153141,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -153375,7 +153376,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -153748,7 +153750,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "yaps2-resources",
|
"ref": "yaps2-resources",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "retropie",
|
"platform": "retropie",
|
||||||
"display_name": "RetroPie",
|
"display_name": "RetroPie",
|
||||||
"version": "4.8.12",
|
"version": "4.8.12",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "BIOS",
|
"base_destination": "BIOS",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -146474,7 +146474,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -146708,7 +146709,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -147081,7 +147083,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "yaps2-resources",
|
"ref": "yaps2-resources",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"platform": "rocknix",
|
"platform": "rocknix",
|
||||||
"display_name": "ROCKNIX",
|
"display_name": "ROCKNIX",
|
||||||
"version": "20261001",
|
"version": "20261001",
|
||||||
"generated": "2026-11-05T23:59:37Z",
|
"generated": "2026-11-06T07:21:27Z",
|
||||||
"base_destination": "bios",
|
"base_destination": "bios",
|
||||||
"detect": [
|
"detect": [
|
||||||
{
|
{
|
||||||
@@ -109453,7 +109453,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 5083767
|
"archive_size": 5083767,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "fbneo-samples",
|
"ref": "fbneo-samples",
|
||||||
@@ -109687,7 +109688,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 0,
|
"strip_components": 0,
|
||||||
"archive_size": 53006540
|
"archive_size": 53006540,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "freeintv-overlays",
|
"ref": "freeintv-overlays",
|
||||||
@@ -110060,7 +110062,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"strip_components": 1,
|
"strip_components": 1,
|
||||||
"archive_size": 21311170
|
"archive_size": 21311170,
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ref": "lrps2",
|
"ref": "lrps2",
|
||||||
|
|||||||
@@ -452,6 +452,11 @@
|
|||||||
},
|
},
|
||||||
"description": "Platform systems whose cores read the tree."
|
"description": "Platform systems whose cores read the tree."
|
||||||
},
|
},
|
||||||
|
"optional": {
|
||||||
|
"type": "boolean",
|
||||||
|
"const": true,
|
||||||
|
"description": "Every core reading the tree runs without it (required: false in its profile): --required-only leaves it out."
|
||||||
|
},
|
||||||
"files": {
|
"files": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
|
|||||||
@@ -518,7 +518,8 @@ def _data_directory_members(
|
|||||||
gets it from the tree's archive.
|
gets it from the tree's archive.
|
||||||
|
|
||||||
``refs_out``, when given, maps each yielded destination to
|
``refs_out``, when given, maps each yielded destination to
|
||||||
(registry key, system ids, directory destination), for the manifest.
|
(registry key, system ids, directory destination, whether the core
|
||||||
|
needs the tree), for the manifest.
|
||||||
|
|
||||||
These are not BIOS and carry no hash of their own: they are whole
|
These are not BIOS and carry no hash of their own: they are whole
|
||||||
trees an emulator reads, refreshed from upstream, so what ships is
|
trees an emulator reads, refreshed from upstream, so what ships is
|
||||||
@@ -532,7 +533,8 @@ def _data_directory_members(
|
|||||||
ref_key = dd.get("ref", "")
|
ref_key = dd.get("ref", "")
|
||||||
if not ref_key or not data_registry or ref_key not in data_registry:
|
if not ref_key or not data_registry or ref_key not in data_registry:
|
||||||
continue
|
continue
|
||||||
if required_only and dd.get("required") is False:
|
needed = dd.get("required") is not False
|
||||||
|
if required_only and not needed:
|
||||||
continue
|
continue
|
||||||
if ref_key in installed_data_refs(platform_name):
|
if ref_key in installed_data_refs(platform_name):
|
||||||
continue
|
continue
|
||||||
@@ -567,7 +569,7 @@ def _data_directory_members(
|
|||||||
):
|
):
|
||||||
del reclaim[full]
|
del reclaim[full]
|
||||||
if refs_out is not None:
|
if refs_out is not None:
|
||||||
refs_out[full] = (ref_key, systems, dd_prefix)
|
refs_out[full] = (ref_key, systems, dd_prefix, needed)
|
||||||
yield src, full
|
yield src, full
|
||||||
continue
|
continue
|
||||||
if full in seen_destinations or (
|
if full in seen_destinations or (
|
||||||
@@ -581,7 +583,7 @@ def _data_directory_members(
|
|||||||
if case_insensitive:
|
if case_insensitive:
|
||||||
seen_lower.add(full.lower())
|
seen_lower.add(full.lower())
|
||||||
if refs_out is not None:
|
if refs_out is not None:
|
||||||
refs_out[full] = (ref_key, systems, dd_prefix)
|
refs_out[full] = (ref_key, systems, dd_prefix, needed)
|
||||||
yield src, full
|
yield src, full
|
||||||
|
|
||||||
|
|
||||||
@@ -4910,7 +4912,7 @@ def generate_manifest(
|
|||||||
# Phase 3: data directories. They are not files of the collection: the
|
# Phase 3: data directories. They are not files of the collection: the
|
||||||
# installer fetches each from its source archive and keeps the members
|
# installer fetches each from its source archive and keeps the members
|
||||||
# whose hash the list below records, the same tree the pack carries.
|
# whose hash the list below records, the same tree the pack carries.
|
||||||
data_refs: dict[str, tuple[str, tuple[str, ...], str]] = {}
|
data_refs: dict[str, tuple[str, tuple[str, ...], str, bool]] = {}
|
||||||
reclaim = {full: path for full, (path, _size) in cache_held.items()}
|
reclaim = {full: path for full, (path, _size) in cache_held.items()}
|
||||||
data_members = list(_data_directory_members(
|
data_members = list(_data_directory_members(
|
||||||
pack_systems, data_registry, platform_name, base_dest,
|
pack_systems, data_registry, platform_name, base_dest,
|
||||||
@@ -5021,7 +5023,7 @@ def generate_manifest(
|
|||||||
|
|
||||||
def _manifest_data_directories(
|
def _manifest_data_directories(
|
||||||
members: list[tuple[str, str]],
|
members: list[tuple[str, str]],
|
||||||
refs: dict[str, tuple[str, tuple[str, ...], str]],
|
refs: dict[str, tuple[str, tuple[str, ...], str, bool]],
|
||||||
registry: dict,
|
registry: dict,
|
||||||
base_dest: str,
|
base_dest: str,
|
||||||
) -> list[dict]:
|
) -> list[dict]:
|
||||||
@@ -5034,11 +5036,14 @@ def _manifest_data_directories(
|
|||||||
changed since is refused rather than installed. archive_size is the
|
changed since is refused rather than installed. archive_size is the
|
||||||
size of the archive refresh_data_dirs last downloaded, what fetching
|
size of the archive refresh_data_dirs last downloaded, what fetching
|
||||||
the tree costs: a tarball whose tree is 10 KB is a download of 21 MB.
|
the tree costs: a tarball whose tree is 10 KB is a download of 21 MB.
|
||||||
|
``optional`` marks a tree every core reading it runs without
|
||||||
|
(``required: false``): install.py --required-only leaves it out, as the
|
||||||
|
pack built with --required-only does.
|
||||||
"""
|
"""
|
||||||
grouped: dict[tuple[str, str], dict] = {}
|
grouped: dict[tuple[str, str], dict] = {}
|
||||||
versions: dict[str, dict[str, dict]] = {}
|
versions: dict[str, dict[str, dict]] = {}
|
||||||
for src, full in members:
|
for src, full in members:
|
||||||
ref, systems, prefix = refs[full]
|
ref, systems, prefix, needed = refs[full]
|
||||||
entry = registry.get(ref, {})
|
entry = registry.get(ref, {})
|
||||||
key = (ref, prefix)
|
key = (ref, prefix)
|
||||||
group = grouped.get(key)
|
group = grouped.get(key)
|
||||||
@@ -5072,11 +5077,19 @@ def _manifest_data_directories(
|
|||||||
size = versions[str(recorded)].get(ref, {}).get("archive_size")
|
size = versions[str(recorded)].get(ref, {}).get("archive_size")
|
||||||
if isinstance(size, int) and size > 0:
|
if isinstance(size, int) and size > 0:
|
||||||
group["archive_size"] = size
|
group["archive_size"] = size
|
||||||
|
if needed:
|
||||||
|
group["needed"] = True
|
||||||
group["systems"].extend(s for s in systems if s not in group["systems"])
|
group["systems"].extend(s for s in systems if s not in group["systems"])
|
||||||
rel = full[len(prefix):].lstrip("/") if prefix else full
|
rel = full[len(prefix):].lstrip("/") if prefix else full
|
||||||
hashes = compute_hashes(src, frozenset({"sha1"}))
|
hashes = compute_hashes(src, frozenset({"sha1"}))
|
||||||
group["files"][rel] = {"sha1": hashes["sha1"], "size": os.path.getsize(src)}
|
group["files"][rel] = {"sha1": hashes["sha1"], "size": os.path.getsize(src)}
|
||||||
return [grouped[key] for key in sorted(grouped)]
|
trees = []
|
||||||
|
for key in sorted(grouped):
|
||||||
|
group = grouped[key]
|
||||||
|
if not group.pop("needed", False):
|
||||||
|
group["optional"] = True
|
||||||
|
trees.append(group)
|
||||||
|
return trees
|
||||||
|
|
||||||
|
|
||||||
def _manifest_core_index(
|
def _manifest_core_index(
|
||||||
|
|||||||
@@ -6923,9 +6923,11 @@ class RequiredOnlyReachesDataDirectories(unittest.TestCase):
|
|||||||
|
|
||||||
def test_every_tree_walk_reads_the_flag(self):
|
def test_every_tree_walk_reads_the_flag(self):
|
||||||
source = (ROOT / "scripts" / "generate_pack.py").read_text(encoding="utf-8")
|
source = (ROOT / "scripts" / "generate_pack.py").read_text(encoding="utf-8")
|
||||||
self.assertEqual(
|
# The pack's walk and the manifest's, which records the flag for
|
||||||
source.count('if required_only and dd.get("required") is False:'), 2
|
# install.py --required-only.
|
||||||
)
|
self.assertEqual(source.count('if required_only and dd.get("required") is False:'), 1)
|
||||||
|
self.assertIn('needed = dd.get("required") is not False\n if required_only and not needed:',
|
||||||
|
source)
|
||||||
self.assertIn("seen_parents, required_only=required_only,", source)
|
self.assertIn("seen_parents, required_only=required_only,", source)
|
||||||
self.assertIn("data_refs, required_only=required_only,", source)
|
self.assertIn("data_refs, required_only=required_only,", source)
|
||||||
|
|
||||||
|
|||||||
@@ -3880,6 +3880,20 @@ class DataDirectoriesAreInstalled(unittest.TestCase):
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def test_required_only_leaves_out_an_optional_tree(self):
|
||||||
|
"""A GBA and a SNES game with --for-games --required-only took
|
||||||
|
FBNeo's cheats and samples, 3,472 files no game opened."""
|
||||||
|
cheats = {**self._entry(), "ref": "fbneo-cheats", "systems": ["snes"], "optional": True}
|
||||||
|
sys_tree = {**self._entry(), "systems": ["snes"]}
|
||||||
|
manifest = {"data_directories": [cheats, sys_tree]}
|
||||||
|
files = [{"dest": "a.rom", "systems": ["snes"]}]
|
||||||
|
self.assertEqual(install.select_data_directories(manifest, files, True), [cheats, sys_tree])
|
||||||
|
self.assertEqual(install.select_data_directories(manifest, files, True, True), [sys_tree])
|
||||||
|
self.assertEqual(install.select_data_directories(manifest, files, False, True), [sys_tree])
|
||||||
|
install._check_data_directory(cheats, "data_directories[0]")
|
||||||
|
with self.assertRaises(ValueError):
|
||||||
|
install._check_data_directory({**cheats, "optional": False}, "data_directories[0]")
|
||||||
|
|
||||||
def test_the_archive_is_drawn_and_counted(self):
|
def test_the_archive_is_drawn_and_counted(self):
|
||||||
"""82 MB of archives came with no progress line, and the run ended
|
"""82 MB of archives came with no progress line, and the run ended
|
||||||
on "310.5 KB downloaded", the BIOS files alone."""
|
on "310.5 KB downloaded", the BIOS files alone."""
|
||||||
|
|||||||
@@ -12912,6 +12912,18 @@ class DriveIsACardByItsFiles(unittest.TestCase):
|
|||||||
self.assertEqual([install.card_system(mount) for mount in mounts],
|
self.assertEqual([install.card_system(mount) for mount in mounts],
|
||||||
[None, None, None])
|
[None, None, None])
|
||||||
|
|
||||||
|
def test_a_dest_on_a_games_part_reads_its_rom_folders(self):
|
||||||
|
"""--dest EASYROMS/bios --for-games from a computer: detection never
|
||||||
|
ran on the card, the generic RetroArch folders were tried, and the
|
||||||
|
run kept every file of the list."""
|
||||||
|
arkos = games_part(self.root / "media" / "EASYROMS")
|
||||||
|
index = {"setups": {"arkos": {}, "retroarch": {}}}
|
||||||
|
with mock.patch.object(install, "_mount_points", return_value=frozenset()), \
|
||||||
|
mock.patch.object(install, "_drive_not_removable", return_value=False):
|
||||||
|
self.assertEqual(install.games_setups(index, "retroarch", arkos / "bios"), ["arkos"])
|
||||||
|
self.assertEqual(install.games_setups(index, "retroarch", self.root / "bios"),
|
||||||
|
["retroarch"])
|
||||||
|
|
||||||
def test_a_card_beside_a_data_drive_comes_first(self):
|
def test_a_card_beside_a_data_drive_comes_first(self):
|
||||||
"""The ArkOS card and the data drive mounted,
|
"""The ArkOS card and the data drive mounted,
|
||||||
the data drive sorted first and took Enter. The card comes first in
|
the data drive sorted first and took Enter. The card comes first in
|
||||||
|
|||||||
+6
-4
@@ -405,7 +405,7 @@ lists record these files as omitted.
|
|||||||
|
|
||||||
<!-- generated: dry-run -->
|
<!-- generated: dry-run -->
|
||||||
|
|
||||||
A RetroArch dry run into an empty folder, with the list of 2026-11-05, printed this:
|
A RetroArch dry run into an empty folder, with the list of 2026-11-06, printed this:
|
||||||
|
|
||||||
```
|
```
|
||||||
Fetching file index for retroarch...
|
Fetching file index for retroarch...
|
||||||
@@ -435,7 +435,7 @@ the installer can fetch them.
|
|||||||
<!-- generated: run-date -->
|
<!-- generated: run-date -->
|
||||||
|
|
||||||
Each line a first install prints, and what it means. The run below is a
|
Each line a first install prints, and what it means. The run below is a
|
||||||
Batocera install into an empty folder, from the list of 2026-11-05.
|
Batocera install into an empty folder, from the list of 2026-11-06.
|
||||||
The figures change with each release.
|
The figures change with each release.
|
||||||
<!-- /generated: run-date -->
|
<!-- /generated: run-date -->
|
||||||
|
|
||||||
@@ -531,7 +531,7 @@ would save, once that saving is over half.
|
|||||||
|
|
||||||
<!-- generated: bulk-hint -->
|
<!-- generated: bulk-hint -->
|
||||||
|
|
||||||
RetroArch with `--system sony-playstation`, from the list of 2026-11-05:
|
RetroArch with `--system sony-playstation`, from the list of 2026-11-06:
|
||||||
|
|
||||||
```
|
```
|
||||||
duckstation pulls 316.5 MB of this 329.0 MB download for sony-playstation. --core pcsx1 keeps 11.0 MB of it and saves 318.0 MB (96%).
|
duckstation pulls 316.5 MB of this 329.0 MB download for sony-playstation. --core pcsx1 keeps 11.0 MB of it and saves 318.0 MB (96%).
|
||||||
@@ -876,7 +876,9 @@ BIOS sets of its parent chain (`neogeo.zip` for `mslug.zip`).
|
|||||||
|
|
||||||
A game that is not recognised gets every BIOS of its system, and the run names
|
A game that is not recognised gets every BIOS of its system, and the run names
|
||||||
it. So does an arcade set the core does not know. **Only what starts**
|
it. So does an arcade set the core does not know. **Only what starts**
|
||||||
(`--required-only`) leaves out the files the cores mark optional.
|
(`--required-only`) leaves out the files the cores mark optional, and the data
|
||||||
|
folders every core reading them runs without (FinalBurn Neo's cheats and
|
||||||
|
samples).
|
||||||
|
|
||||||
The games are read without hashing whole discs, and a cache keeps what was
|
The games are read without hashing whole discs, and a cache keeps what was
|
||||||
read, so a second run over the same card reads only new files. It is a
|
read, so a second run over the same card reads only new files. It is a
|
||||||
|
|||||||
Reference in new issue
Block a user