feat: place save files in each system folder

This commit is contained in:
Abdessamad Derraz committed 2026-10-22 22:23:02 +02:00
commit 8d0cd27103
33 files changed
+6017 -1913

No files matched your search

+7 -7
View File
@@ -106,21 +106,21 @@ Full list with per-file details: **[https://abdess.github.io/retrobios/](https:/
| Platform | On its BIOS list | Files its emulators load | Checked by |
|----------|-----------------:|-------------------------:|------------|
| AmberELEC | 414/434 | 4,551/4,663 | MD5 hash |
| Batocera | 353/353 | 13,943/15,053 | MD5 hash |
| Batocera | 353/353 | 13,958/15,053 | MD5 hash |
| BizHawk | 118/118 | - | SHA1 hash |
| EmuDeck | 168/168 | 8,158/8,272 | MD5 hash |
| EmuDeck | 168/168 | 8,195/8,272 | MD5 hash |
| EmuELEC | 544/572 | 4,597/9,956 | MD5 hash |
| KNULLI | 290/290 | 8,892/15,114 | MD5 hash |
| KNULLI | 290/290 | 8,915/15,114 | MD5 hash |
| Lakka | 532/532 | 7,682/7,742 | file presence |
| MiSTer FPGA | 81/81 | - | MD5 hash |
| MinUI | 0/0 | 78/79 | file presence |
| MyMinUI | 0/0 | 347/356 | file presence |
| NextUI | 0/0 | 343/349 | file presence |
| ROCKNIX | 38/38 | 7,078/8,397 | MD5 hash |
| Recalbox | 351/351 | 2,748/2,933 | MD5 hash |
| Recalbox | 351/351 | 2,762/2,933 | MD5 hash |
| RetroArch | 526/526 | 7,691/7,733 | file presence |
| RetroBat | 348/348 | 4,729/9,218 | MD5 hash |
| RetroDECK | 2,007/2,008 | 6,258/6,547 | MD5 hash |
| RetroBat | 348/348 | 4,752/9,218 | MD5 hash |
| RetroDECK | 2,007/2,008 | 6,287/6,547 | MD5 hash |
| RetroPie * | 532/532 | 7,858/12,489 | file presence |
| RomM | 383/383 | 83/860 | MD5 hash |
@@ -209,4 +209,4 @@ The scripts and tooling are released under the [MIT License](LICENSE).
The BIOS and firmware files are not covered by that license: they are third-party system software, preserved and provided for personal backup, archival, and interoperability with emulation software. [NOTICE](NOTICE) sets out their status and how to ask for a file to be removed.
The reasoning, and where it is weakest, is in [the project's legal position](https://abdess.github.io/retrobios/wiki/legal/).
*Auto-generated on 2026-10-22T17:48:21Z*
*Auto-generated on 2026-10-22T19:15:47Z*
+1 -1
View File
@@ -11,7 +11,7 @@
$ErrorActionPreference = "Stop"
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
$defaultInstallSha256 = "b574c5beb84e9988a53a742f1abf0ad98fcb23dae961facef98c955856380704"
$defaultInstallSha256 = "ad3b338a8f709be45352a12bd9c6a6250819a8fb9afd19498e24f41e3f062d20"
$maximumInstallerBytes = 2MB
$installerExit = 0
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
+42 -15
View File
@@ -107,6 +107,7 @@ OMISSION_REASONS = {
"below_platform_folder": "below the platform folder",
"no_save_directory": "no save directory",
"no_core_folder": "no core folder",
"no_save_system": "no system runs the core",
}
# What a file is when it is not firmware, as the manifest's category field
# says, and as the installer words it. Firmware carries no category.
@@ -2447,6 +2448,15 @@ def _entry_path(root: Path, entry: dict) -> Path:
return _destination_path(*_entry_place(root, entry))
def _entry_key(entry: dict) -> str:
"""What tells one entry of the list from another: its dest, below the
BIOS folder or below the save directory. KNULLI lists its own
fbneo/hiscore.dat in the BIOS tree and FB Alpha 2012's below the save
directory, two files under one dest. NUL never appears in a dest."""
dest = str(entry.get("dest"))
return f"save\0{dest}" if entry.get("root") == "save" else dest
def _check_root(entry: dict, dest: str) -> None:
"""root is absent or save, and core_folder one folder name of a save entry."""
root = entry.get("root")
@@ -2480,9 +2490,10 @@ def _check_save_directory(data: dict) -> None:
return
if (
not isinstance(layout, dict)
or set(layout) != {"folder", "by_core"}
or set(layout) - {"by_system"} != {"folder", "by_core"}
or not isinstance(layout["by_core"], bool)
or len(_safe_relative_path(layout["folder"], "save_directory.folder").parts) != 1
or layout.get("by_system", True) is not True
or not _safe_relative_path(layout["folder"], "save_directory.folder").parts
):
raise ValueError("invalid save_directory")
if layout["by_core"]:
@@ -2625,9 +2636,10 @@ def _check_entry(
if not isinstance(entry, dict):
raise ValueError(f"{where} must be an object")
dest = str(_safe_relative_path(entry.get("dest"), f"{where}.dest"))
if dest in seen_destinations:
key = _entry_key({**entry, "dest": dest})
if key in seen_destinations:
raise ValueError(f"duplicate manifest destination: {dest}")
seen_destinations.add(dest)
seen_destinations.add(key)
_check_root(entry, dest)
size = _check_download(entry, where, dest)
@@ -2762,9 +2774,10 @@ def _validate_manifest(data: object, plat: str) -> dict:
entry.get("dest"), f"omitted_files[{index}].dest"
)
)
if dest in seen_destinations or dest in seen_omitted:
key = _entry_key({**entry, "dest": dest})
if key in seen_destinations or key in seen_omitted:
raise ValueError(f"duplicate or conflicting omitted destination: {dest}")
seen_omitted.add(dest)
seen_omitted.add(key)
_check_omission(entry, dest)
_check_root(entry, dest)
claims = entry.get("alternatives", [])
@@ -3197,7 +3210,7 @@ def region_drops(
systems: list[str] | None = None,
held: set[str] | None = None,
) -> set[str]:
"""Destinations a region priority list withdraws.
"""Destinations a region priority list withdraws, as _entry_key spells them.
The pack builder's rule (region.resolve_region_drops), replayed over the
groups the manifest records. Per group, the best-ranked regional file
@@ -3231,7 +3244,7 @@ def region_drops(
if not isinstance(priority, int) or isinstance(priority, bool):
priority = None
for group in joined:
groups.setdefault(group, []).append((set(regions), entry["dest"], priority))
groups.setdefault(group, []).append((set(regions), _entry_key(entry), priority))
keep: set[str] = set()
drop: set[str] = set()
for group_id, members in groups.items():
@@ -3304,10 +3317,12 @@ def narrow(
# answers the request but takes no installable file's place, unless
# the builder holds it (held: true) and only this download lacks it:
# the pack drops the fallback it displaces, and so does this.
held = {f["dest"] for f in files} | {o["dest"] for o in omitted if o.get("held")}
held = {_entry_key(f) for f in files} | {
_entry_key(o) for o in omitted if o.get("held")
}
dropped = region_drops(files + omitted, regions, systems, held)
files = [f for f in files if f["dest"] not in dropped]
omitted = [o for o in omitted if o["dest"] not in dropped]
files = [f for f in files if _entry_key(f) not in dropped]
omitted = [o for o in omitted if _entry_key(o) not in dropped]
if systems:
wanted = set(systems)
files = [f for f in files if _chosen(f, wanted)]
@@ -3488,8 +3503,12 @@ def save_directory_for(
default (config.def.h:1099). savefiles_in_content_dir and
sort_savefiles_by_content_enable put the directory beside each game: no
single place then. Without a config, the BIOS folder standing at its
default name puts the save directory beside it, as the pack lays them out.
``override`` (--save-dir) names the directory itself.
default name puts the save directory beside it, as the pack lays them out,
and a list whose dests start above the BIOS folder (RetroDECK) puts it
in the folder the run installs to. ``override`` (--save-dir) names the directory itself. A launcher that
writes the save directory at each launch, one folder per system
(by_system: Batocera, RetroBat), is not read from any retroarch.cfg:
the one on disk holds the last launch's system.
"""
layout = manifest.get("save_directory")
if not layout:
@@ -3497,7 +3516,7 @@ def save_directory_for(
folder = layout["folder"]
listed = bool(layout["by_core"])
by_core = listed
found = _RETROARCH_CONFIGS.get(bios_path)
found = None if layout.get("by_system") else _RETROARCH_CONFIGS.get(bios_path)
if found is not None:
cfg_path, app_dir = found
for key in ("savefiles_in_content_dir", "sort_savefiles_by_content_enable"):
@@ -3518,6 +3537,10 @@ def save_directory_for(
base = manifest.get("base_destination") or ""
if base and bios_path.name == base:
return SavePlace(bios_path.parent / folder, by_core, listed)
if not base:
# The dests start below the folder holding the BIOS folder
# (RetroDECK's ~/retrodeck holds bios/ and saves/).
return SavePlace(bios_path / folder, by_core, listed)
return (f"{bios_path} is not the frontend's default BIOS folder: "
"name its save directory with --save-dir")
@@ -3537,7 +3560,11 @@ def place_save_entries(
place = save_directory_for(bios_path, manifest, override)
if isinstance(place, SavePlace):
_SAVE_DIRS[bios_path] = place
where = f"{place.directory}{os.sep}<core>" if place.by_core else str(place.directory)
where = str(place.directory)
if (manifest.get("save_directory") or {}).get("by_system"):
where += f"{os.sep}<system>"
if place.by_core:
where += f"{os.sep}<core>"
print(f" {_plural(len(saved), 'file')} read from {display}'s save directory "
f"go to {where}")
return files, []
+1 -1
View File
@@ -18,7 +18,7 @@ esac
TEMP_INSTALLER=""
TEMP_DIRECTORY=""
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
DEFAULT_INSTALL_SHA256="b574c5beb84e9988a53a742f1abf0ad98fcb23dae961facef98c955856380704"
DEFAULT_INSTALL_SHA256="ad3b338a8f709be45352a12bd9c6a6250819a8fb9afd19498e24f41e3f062d20"
MAX_INSTALLER_BYTES=2097152
cleanup() {
+331 -198
View File
@@ -274,11 +274,11 @@
}
}
],
"total_files": 14508,
"total_size": 9590599187,
"pack_files": 14510,
"pack_size": 9590599187,
"total_omitted": 415,
"total_files": 14531,
"total_size": 9893543681,
"pack_files": 14533,
"pack_size": 9893543681,
"total_omitted": 400,
"omitted_files": [
{
"dest": "AUDIO.APC",
@@ -500,19 +500,6 @@
],
"category": "game_data"
},
{
"dest": "FB Alpha 2012/hiscore.dat",
"root": "save",
"core_folder": "FB Alpha 2012",
"name": "hiscore.dat",
"system": "arcade",
"required": false,
"reason": "no_save_directory",
"cores": [
"fbalpha2012"
],
"held": true
},
{
"dest": "GAMEMAPS.APC",
"name": "GAMEMAPS.APC",
@@ -1085,97 +1072,6 @@
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVSHARED.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVSHARED.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "System BIOS image",
"name": "System BIOS image",
@@ -1604,94 +1500,6 @@
],
"category": "game_data"
},
{
"dest": "dolphin-emu/User/GBA/gba_bios.bin",
"root": "save",
"core_folder": "dolphin-emu",
"name": "gba_bios.bin",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gba"
],
"held": true
},
{
"dest": "dolphin-emu/User/Load/WiiSD.raw",
"root": "save",
"core_folder": "dolphin-emu",
"name": "WiiSD.raw",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/clientca.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "clientca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/clientcakey.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "clientcakey.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/rootca.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "rootca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/shared2/sys/SYSCONF",
"root": "save",
"core_folder": "dolphin-emu",
"name": "SYSCONF",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/title/00000001/00000002/data/setting.txt",
"root": "save",
"core_folder": "dolphin-emu",
"name": "setting.txt",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "doom2bfg.wad",
"name": "doom2bfg.wad",
@@ -178536,6 +178344,220 @@
"triforce"
]
},
{
"dest": "gamecube/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "wii/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "wii/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "wii/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "wii/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "gamecube/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "wii/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "wii/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "wii/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube",
"triforce"
],
"root": "save"
},
{
"dest": "GC/dsp_rom.bin",
"sha1": "3c6cc6e04fdd0b2a392d7a6ed769455444846be7",
@@ -179622,6 +179644,28 @@
}
]
},
{
"dest": "fbneo/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "neogeo/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "fba2012/samples/dkong.zip",
"sha1": "764ec667084bc237c1de6bd1db7541ad8cb59975",
@@ -242619,6 +242663,90 @@
"squirreljme"
]
},
{
"dest": "atari2600/stella/KVS1.WAV",
"sha1": "b094c2c1fca81a0e531e0541f302346150ec4604",
"sha256": "8bf8d878db407cc81b4c8a05069d3aa35e0e7bff803112d4d0eba637d60fe12c",
"size": 3436329,
"repo_path": "bios/Atari/2600/KVS1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS2.WAV",
"sha1": "8b83b2eea01b3e08ceb885aeb153d4084bddb63c",
"sha256": "d031b9534ba75d870365657f578ed18c0cc513ebe9b253be7d80114c7ae4210d",
"size": 2086275,
"repo_path": "bios/Atari/2600/KVS2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS3.WAV",
"sha1": "86896a1e272d8715489de9b407f0b8a42f82d4a0",
"sha256": "4e47d32533feebfa9625ea818183edcd519b8cb6516bf3db11dc9a01ada6878b",
"size": 3720920,
"repo_path": "bios/Atari/2600/KVS3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB1.WAV",
"sha1": "6a582aebcefd6e2a97bdd8968202aab9851a889c",
"sha256": "968937d09e17ca059cdc5f092161ba172c56ff31bc945e381638c79bf7a7e4e2",
"size": 4219542,
"repo_path": "bios/Atari/2600/KVB1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB2.WAV",
"sha1": "60a425c6bde3226ab731995562716321be20fc49",
"sha256": "6ac885493469e68992b0d272264b4b0947e7d6a5c6fd0170c65299acc386c122",
"size": 9593878,
"repo_path": "bios/Atari/2600/KVB2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB3.WAV",
"sha1": "5e34125c4d6c209b21d1c892f3df0ec1644fd0d8",
"sha256": "76acf3b4e607cc851c625d455ced2b099dc394460d8716c02420904960842e34",
"size": 7676992,
"repo_path": "bios/Atari/2600/KVB3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVSHARED.WAV",
"sha1": "9adf10cdf1de833b194c7d8797ad1f041ad98dd3",
"sha256": "589b37725aeb9801868deafa2940c6eacb15430d4051ada7942298561f3014b6",
"size": 3059116,
"repo_path": "bios/Atari/2600/KVSHARED.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "REMOTE1.RTS",
"sha1": "945f1c126de553cd6e11b9c40e9dd05a103ee25a",
@@ -247461,5 +247589,10 @@
"sony-playstation-2"
]
}
]
],
"save_directory": {
"folder": "saves",
"by_core": false,
"by_system": true
}
}
+411 -461
View File
@@ -305,335 +305,12 @@
}
}
],
"total_files": 8207,
"total_size": 7660568116,
"pack_files": 8209,
"pack_size": 7660568116,
"total_omitted": 49,
"total_files": 8239,
"total_size": 7836973672,
"pack_files": 8241,
"pack_size": 7836973672,
"total_omitted": 12,
"omitted_files": [
{
"dest": "Citra/Citra/sysdata/aes_keys.txt",
"root": "save",
"core_folder": "Citra",
"name": "aes_keys.txt",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra"
],
"systems": [
"nintendo-3ds"
],
"held": true
},
{
"dest": "Citra/Citra/sysdata/boot9.bin",
"root": "save",
"core_folder": "Citra",
"name": "boot9.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra"
]
},
{
"dest": "Citra/Citra/sysdata/seeddb.bin",
"root": "save",
"core_folder": "Citra",
"name": "seeddb.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra"
]
},
{
"dest": "Citra/Citra/sysdata/shared_font.bin",
"root": "save",
"core_folder": "Citra",
"name": "shared_font.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra"
]
},
{
"dest": "Citra2018/Citra/sysdata/aes_keys.txt",
"root": "save",
"core_folder": "Citra2018",
"name": "aes_keys.txt",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra2018"
],
"systems": [
"nintendo-3ds"
],
"held": true
},
{
"dest": "Citra2018/Citra/sysdata/shared_font.bin",
"root": "save",
"core_folder": "Citra2018",
"name": "shared_font.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra2018"
]
},
{
"dest": "FB Alpha 2012 CPS-3/hiscore.dat",
"root": "save",
"core_folder": "FB Alpha 2012 CPS-3",
"name": "hiscore.dat",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"fbalpha2012_cps3"
]
},
{
"dest": "FB Alpha 2012/hiscore.dat",
"root": "save",
"core_folder": "FB Alpha 2012",
"name": "hiscore.dat",
"system": "arcade",
"required": false,
"reason": "no_save_directory",
"cores": [
"fbalpha2012"
]
},
{
"dest": "Ishiiruka/User/Wii/clientca.pem",
"root": "save",
"core_folder": "Ishiiruka",
"name": "clientca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"ishiiruka"
]
},
{
"dest": "Ishiiruka/User/Wii/clientcakey.pem",
"root": "save",
"core_folder": "Ishiiruka",
"name": "clientcakey.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"ishiiruka"
]
},
{
"dest": "Ishiiruka/User/Wii/rootca.pem",
"root": "save",
"core_folder": "Ishiiruka",
"name": "rootca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"ishiiruka"
]
},
{
"dest": "Ishiiruka/User/Wii/sd.raw",
"root": "save",
"core_folder": "Ishiiruka",
"name": "sd.raw",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"ishiiruka"
]
},
{
"dest": "Ishiiruka/User/Wii/shared2/sys/SYSCONF",
"root": "save",
"core_folder": "Ishiiruka",
"name": "SYSCONF",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"ishiiruka"
]
},
{
"dest": "Ishiiruka/User/Wii/title/00000001/00000002/data/setting.txt",
"root": "save",
"core_folder": "Ishiiruka",
"name": "setting.txt",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"ishiiruka"
]
},
{
"dest": "Panda3DS/Emulator Files/sysdata/aes_keys.txt",
"root": "save",
"core_folder": "Panda3DS",
"name": "aes_keys.txt",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"panda3ds"
],
"systems": [
"nintendo-3ds"
],
"held": true
},
{
"dest": "Panda3DS/Emulator Files/sysdata/seeddb.bin",
"root": "save",
"core_folder": "Panda3DS",
"name": "seeddb.bin",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"panda3ds"
]
},
{
"dest": "Stella/stella/KVB1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVSHARED.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVSHARED.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Trident/Emulator Files/sysdata/aes_keys.txt",
"root": "save",
"core_folder": "Trident",
"name": "aes_keys.txt",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"trident"
],
"systems": [
"nintendo-3ds"
],
"held": true
},
{
"dest": "Trident/Emulator Files/sysdata/seeddb.bin",
"root": "save",
"core_folder": "Trident",
"name": "seeddb.bin",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"trident"
]
},
{
"dest": "doomu.wad",
"name": "doomu.wad",
@@ -656,139 +333,6 @@
],
"category": "game_data"
},
{
"dest": "fsuae/Kickstarts/amiga-ext-130-cdtv.rom",
"root": "save",
"name": "amiga-ext-130-cdtv.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-ext-310-cd32.rom",
"root": "save",
"name": "amiga-ext-310-cd32.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-120.rom",
"root": "save",
"name": "amiga-os-120.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-130.rom",
"root": "save",
"name": "amiga-os-130.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-204.rom",
"root": "save",
"name": "amiga-os-204.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-205.rom",
"root": "save",
"name": "amiga-os-205.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-310-a1200.rom",
"root": "save",
"name": "amiga-os-310-a1200.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-310-a3000.rom",
"root": "save",
"name": "amiga-os-310-a3000.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-310-a4000.rom",
"root": "save",
"name": "amiga-os-310-a4000.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-310-cd32.rom",
"root": "save",
"name": "amiga-os-310-cd32.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/cd32fmv.rom",
"root": "save",
"name": "cd32fmv.rom",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
]
},
{
"dest": "fsuae/Kickstarts/rom.key",
"root": "save",
"name": "rom.key",
"system": "amiga",
"required": false,
"reason": "no_save_directory",
"cores": [
"fsuae"
],
"held": true
},
{
"dest": "jazz2/Source/Anims.j2a",
"name": "Anims.j2a",
@@ -18673,6 +18217,127 @@
"fmsx"
]
},
{
"dest": "fsuae/Kickstarts/amiga-os-130.rom",
"sha1": "891e9a547772fe0c6c19b610baf8bc4ea7fcb785",
"sha256": "ee05862d8102a08436ac4056da7d549db31625c7d47b24dfb7b3c9a5c113ca53",
"size": 262144,
"repo_path": "bios/Commodore/Amiga/Kickstart-v1.3-rev34.5-1987-Commodore-A500-A1000-A2000-CDTV.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-os-204.rom",
"sha1": "c5839f5cb98a7a8947065c3ed2f14f5f42e334a1",
"sha256": "d0b70e8a1772614b897f92c33cb299bed3fc8e3de488fc12f67f97fc2486eb79",
"size": 524288,
"repo_path": "bios/Commodore/Amiga/amiga-os-204.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-os-205.rom",
"sha1": "02843c4253bbd29aba535b0aa3bd9a85034ecde4",
"sha256": "8d57d6e9d976df42d91ff9d10a5eedaede1a00e3b4b34cad750ca5ff7229f28a",
"size": 524288,
"repo_path": "bios/Commodore/Amiga/amiga-os-205-a600.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-os-120.rom",
"sha1": "11f9e62cf299f72184835b7b2a70a16333fc0d88",
"sha256": "87cddb1f499e32758de20145e73031a84bab299e3f6e5c8487e76d02b2ee9d16",
"size": 262144,
"repo_path": "bios/Commodore/Amiga/amiga-os-120.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-os-310-a1200.rom",
"sha1": "e21545723fe8374e91342617604f1b3d703094f1",
"sha256": "6d43840d4099a74170ea0f0425b6257c3891ebcaa39c4d1840075a9ab22b5707",
"size": 524288,
"repo_path": "bios/Commodore/Amiga/amiga-os-310-a1200.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-os-310-a3000.rom",
"sha1": "f8e210d72b4c4853e0c9b85d223ba20e3d1b36ee",
"sha256": "f2c9307aacb92b203a3135a35185deffad6c66cfa8d79920b235d7cf9a5222c4",
"size": 524288,
"repo_path": "bios/Commodore/Amiga/amiga-os-310-a3000.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-os-310-a4000.rom",
"sha1": "5fe04842d04a489720f0f4bb0e46948199406f49",
"sha256": "71236ed62c85394a3ad7d0d8d65405bac7a10083e06ba6b82120dacc7a00fe9a",
"size": 524288,
"repo_path": "bios/Commodore/Amiga/amiga-os-310-a4000.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-os-310-cd32.rom",
"sha1": "3525be8887f79b5929e017b42380a79edfee542d",
"sha256": "3586355514947b5ab48c8755dc004fab94f188b19e7bce491c8f9693499e830b",
"size": 524288,
"repo_path": "bios/Commodore/Amiga/amiga-os-310-cd32.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-ext-310-cd32.rom",
"sha1": "5bef3d628ce59cc02a66e6e4ae0da48f60e78f7f",
"sha256": "d964826432559994ffe329f643fd4e42dbbff313362d9434945725d7119cae87",
"size": 524288,
"repo_path": "bios/Commodore/Amiga/amiga-ext-310-cd32.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/cd32fmv.rom",
"sha1": "03ca81c7a7b259cf64bc9582863eca0f6529f435",
"sha256": "680e654880c891a3b03e6107ed30b10903efca16c1dac1b4c8e7835f4e37acb6",
"size": 262144,
"repo_path": "bios/Commodore/Amiga/cd32fmv.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fsuae/Kickstarts/amiga-ext-130-cdtv.rom",
"sha1": "7ba40ffa17e500ed9fed041f3424bd81d9c907be",
"sha256": "6e48bb768539e8dae352553e5fdfa860682edaf9e26b105fadd8e26103171765",
"size": 262144,
"repo_path": "bios/Commodore/Amiga/amiga-ext-130-cdtv.rom",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fuse/48.rom",
"sha1": "5ea7c2b824672e914525d1d5c419d71b84a426a2",
@@ -69121,6 +68786,64 @@
],
"executable": true
},
{
"dest": "Citra/sysdata/aes_keys.txt",
"sha1": "29556640b022cbfaf427874695838b43a5e8aff4",
"sha256": "0d866e062cf62275fbb291ba44af253e67fdc5bd76c7640b6c4a9dfe742510d9",
"size": 7357,
"repo_path": "bios/Nintendo/3DS/aes_keys.txt",
"cores": [
"citra",
"citra2018"
],
"systems": [
"nintendo-3ds"
],
"root": "save"
},
{
"dest": "Citra/sysdata/boot9.bin",
"sha1": "5a3d3d6df4743e6b50afe0fc717fa8a12bc888e6",
"sha256": "2f88744feed717856386400a44bba4b9ca62e76a32c715d4f309c399bf28166f",
"size": 65536,
"repo_path": "bios/Nintendo/3DS/boot9.bin",
"cores": [
"citra"
],
"systems": [
"nintendo-3ds"
],
"root": "save"
},
{
"dest": "Citra/sysdata/shared_font.bin",
"sha1": "60022d6d026c8df950722478aab25702a0dfa067",
"sha256": "a06aaf6b50ebc38ebdccc59b913d4a1c0cc7005289957530acaaf78ffc49dddd",
"size": 3145728,
"repo_path": "bios/Nintendo/3DS/Citra/sysdata/shared_font.bin",
"cores": [
"citra",
"citra2018"
],
"systems": [
"nintendo-3ds"
],
"root": "save"
},
{
"dest": "Citra/sysdata/seeddb.bin",
"sha1": "9e2c006997761082be87cf316e57c4da5cddbc62",
"sha256": "ff485c60090185aff05354ece01f86b61f6020332bed0f9090c58d4678e5a180",
"size": 53264,
"repo_path": "bios/Nintendo/3DS/Citra/sysdata/seeddb.bin",
"cores": [
"citra"
],
"systems": [
"nintendo-3ds"
],
"root": "save"
},
{
"dest": "switch/title.keys",
"sha1": "bfee8e708dc4c8f27bfe51a12d57caaa0b7f74de",
@@ -69851,6 +69574,18 @@
"smsplus"
]
},
{
"dest": "hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012",
"fbalpha2012_cps3"
],
"root": "save"
},
{
"dest": "fba2012/samples/dkong.zip",
"sha1": "764ec667084bc237c1de6bd1db7541ad8cb59975",
@@ -70622,6 +70357,17 @@
"frodo"
]
},
{
"dest": "fsuae/Kickstarts/rom.key",
"sha1": "801bbab32e3d37386dd1636d4f1d6fa7e21d5874",
"sha256": "baf2366ae04337d37e7b37ebfb5cd7af7e4ffddeb6b017bf2e5fec43d87764e0",
"size": 2069,
"repo_path": "bios/Commodore/Amiga/rom.key",
"cores": [
"fsuae"
],
"root": "save"
},
{
"dest": "fuse/128p-0.rom",
"sha1": "d07fcdeca892ee80494d286ea9ea5bf3928a1aca",
@@ -71058,6 +70804,92 @@
"nintendo-gamecube"
]
},
{
"dest": "User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"ishiiruka"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"ishiiruka"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "User/Wii/sd.raw",
"sha1": "8c8134f08b2e3baa603206ede30d3935365009b8",
"sha256": "5709657d763f510f58792ca3ba080b0f663ec922149aa3ef5a0a4495ebabf8a6",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/sd.raw",
"cores": [
"ishiiruka"
],
"systems": [
"nintendo-gamecube"
],
"storage": "release",
"release_asset": "sd.raw",
"root": "save"
},
{
"dest": "User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"ishiiruka"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"ishiiruka"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"ishiiruka"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "jazz2/Source/AnimsSw.j2a",
"sha1": "133392a2c638d17796c6f510cf94ec391cc4c407",
@@ -91320,6 +91152,36 @@
],
"category": "game_data"
},
{
"dest": "Emulator Files/sysdata/aes_keys.txt",
"sha1": "29556640b022cbfaf427874695838b43a5e8aff4",
"sha256": "0d866e062cf62275fbb291ba44af253e67fdc5bd76c7640b6c4a9dfe742510d9",
"size": 7357,
"repo_path": "bios/Nintendo/3DS/aes_keys.txt",
"cores": [
"panda3ds",
"trident"
],
"systems": [
"nintendo-3ds"
],
"root": "save"
},
{
"dest": "Emulator Files/sysdata/seeddb.bin",
"sha1": "9e2c006997761082be87cf316e57c4da5cddbc62",
"sha256": "ff485c60090185aff05354ece01f86b61f6020332bed0f9090c58d4678e5a180",
"size": 53264,
"repo_path": "bios/Nintendo/3DS/Citra/sysdata/seeddb.bin",
"cores": [
"panda3ds",
"trident"
],
"systems": [
"nintendo-3ds"
],
"root": "save"
},
{
"dest": "64DD_IPL.bin",
"sha1": "bf861922dcb78c316360e3e742f4f70ff63c9bc3",
@@ -94409,6 +94271,90 @@
"squirreljme"
]
},
{
"dest": "stella/KVS1.WAV",
"sha1": "b094c2c1fca81a0e531e0541f302346150ec4604",
"sha256": "8bf8d878db407cc81b4c8a05069d3aa35e0e7bff803112d4d0eba637d60fe12c",
"size": 3436329,
"repo_path": "bios/Atari/2600/KVS1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "stella/KVS2.WAV",
"sha1": "8b83b2eea01b3e08ceb885aeb153d4084bddb63c",
"sha256": "d031b9534ba75d870365657f578ed18c0cc513ebe9b253be7d80114c7ae4210d",
"size": 2086275,
"repo_path": "bios/Atari/2600/KVS2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "stella/KVS3.WAV",
"sha1": "86896a1e272d8715489de9b407f0b8a42f82d4a0",
"sha256": "4e47d32533feebfa9625ea818183edcd519b8cb6516bf3db11dc9a01ada6878b",
"size": 3720920,
"repo_path": "bios/Atari/2600/KVS3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "stella/KVB1.WAV",
"sha1": "6a582aebcefd6e2a97bdd8968202aab9851a889c",
"sha256": "968937d09e17ca059cdc5f092161ba172c56ff31bc945e381638c79bf7a7e4e2",
"size": 4219542,
"repo_path": "bios/Atari/2600/KVB1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "stella/KVB2.WAV",
"sha1": "60a425c6bde3226ab731995562716321be20fc49",
"sha256": "6ac885493469e68992b0d272264b4b0947e7d6a5c6fd0170c65299acc386c122",
"size": 9593878,
"repo_path": "bios/Atari/2600/KVB2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "stella/KVB3.WAV",
"sha1": "5e34125c4d6c209b21d1c892f3df0ec1644fd0d8",
"sha256": "76acf3b4e607cc851c625d455ced2b099dc394460d8716c02420904960842e34",
"size": 7676992,
"repo_path": "bios/Atari/2600/KVB3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "stella/KVSHARED.WAV",
"sha1": "9adf10cdf1de833b194c7d8797ad1f041ad98dd3",
"sha256": "589b37725aeb9801868deafa2940c6eacb15430d4051ada7942298561f3014b6",
"size": 3059116,
"repo_path": "bios/Atari/2600/KVSHARED.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "sgb.sfc",
"sha1": "973e10840db683cf3faf61bd443090786b3a9f04",
@@ -100395,6 +100341,10 @@
]
}
],
"save_directory": {
"folder": "saves/retroarch/saves",
"by_core": false
},
"case_variants": [
{
"dest": "np2kai/2608_BD.WAV",
+361 -246
View File
@@ -29,11 +29,11 @@
}
],
"standalone_copies": [],
"total_files": 9375,
"total_size": 9410194263,
"pack_files": 9377,
"pack_size": 9410194263,
"total_omitted": 418,
"total_files": 9402,
"total_size": 9716410642,
"pack_files": 9404,
"pack_size": 9716410642,
"total_omitted": 399,
"omitted_files": [
{
"dest": "AUDIO.APC",
@@ -112,54 +112,6 @@
],
"category": "game_data"
},
{
"dest": "Citra/Citra/sysdata/aes_keys.txt",
"root": "save",
"core_folder": "Citra",
"name": "aes_keys.txt",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra"
]
},
{
"dest": "Citra/Citra/sysdata/boot9.bin",
"root": "save",
"core_folder": "Citra",
"name": "boot9.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra"
]
},
{
"dest": "Citra/Citra/sysdata/seeddb.bin",
"root": "save",
"core_folder": "Citra",
"name": "seeddb.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra"
]
},
{
"dest": "Citra/Citra/sysdata/shared_font.bin",
"root": "save",
"core_folder": "Citra",
"name": "shared_font.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"citra"
]
},
{
"dest": "DARK.GOB",
"name": "DARK.GOB",
@@ -303,19 +255,6 @@
],
"category": "game_data"
},
{
"dest": "FB Alpha 2012/hiscore.dat",
"root": "save",
"core_folder": "FB Alpha 2012",
"name": "hiscore.dat",
"system": "arcade",
"required": false,
"reason": "no_save_directory",
"cores": [
"fbalpha2012"
],
"held": true
},
{
"dest": "GAMEMAPS.APC",
"name": "GAMEMAPS.APC",
@@ -888,97 +827,6 @@
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVSHARED.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVSHARED.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "System BIOS image",
"name": "System BIOS image",
@@ -1407,94 +1255,6 @@
],
"category": "game_data"
},
{
"dest": "dolphin-emu/User/GBA/gba_bios.bin",
"root": "save",
"core_folder": "dolphin-emu",
"name": "gba_bios.bin",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gba"
],
"held": true
},
{
"dest": "dolphin-emu/User/Load/WiiSD.raw",
"root": "save",
"core_folder": "dolphin-emu",
"name": "WiiSD.raw",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/clientca.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "clientca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/clientcakey.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "clientcakey.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/rootca.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "rootca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/shared2/sys/SYSCONF",
"root": "save",
"core_folder": "dolphin-emu",
"name": "SYSCONF",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/title/00000001/00000002/data/setting.txt",
"root": "save",
"core_folder": "dolphin-emu",
"name": "setting.txt",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "doom2bfg.wad",
"name": "doom2bfg.wad",
@@ -111162,6 +110922,50 @@
],
"category": "game_data"
},
{
"dest": "3ds/Citra/sysdata/aes_keys.txt",
"sha1": "29556640b022cbfaf427874695838b43a5e8aff4",
"sha256": "0d866e062cf62275fbb291ba44af253e67fdc5bd76c7640b6c4a9dfe742510d9",
"size": 7357,
"repo_path": "bios/Nintendo/3DS/aes_keys.txt",
"cores": [
"citra"
],
"root": "save"
},
{
"dest": "3ds/Citra/sysdata/boot9.bin",
"sha1": "5a3d3d6df4743e6b50afe0fc717fa8a12bc888e6",
"sha256": "2f88744feed717856386400a44bba4b9ca62e76a32c715d4f309c399bf28166f",
"size": 65536,
"repo_path": "bios/Nintendo/3DS/boot9.bin",
"cores": [
"citra"
],
"root": "save"
},
{
"dest": "3ds/Citra/sysdata/shared_font.bin",
"sha1": "60022d6d026c8df950722478aab25702a0dfa067",
"sha256": "a06aaf6b50ebc38ebdccc59b913d4a1c0cc7005289957530acaaf78ffc49dddd",
"size": 3145728,
"repo_path": "bios/Nintendo/3DS/Citra/sysdata/shared_font.bin",
"cores": [
"citra"
],
"root": "save"
},
{
"dest": "3ds/Citra/sysdata/seeddb.bin",
"sha1": "9e2c006997761082be87cf316e57c4da5cddbc62",
"sha256": "ff485c60090185aff05354ece01f86b61f6020332bed0f9090c58d4678e5a180",
"size": 53264,
"repo_path": "bios/Nintendo/3DS/Citra/sysdata/seeddb.bin",
"cores": [
"citra"
],
"root": "save"
},
{
"dest": "Citra/sysdata/aes_keys.txt",
"sha1": "29556640b022cbfaf427874695838b43a5e8aff4",
@@ -111700,6 +111504,206 @@
"dolphin"
]
},
{
"dest": "gamecube/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "wii/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "gamecube/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "GC/dsp_rom.bin",
"sha1": "3c6cc6e04fdd0b2a392d7a6ed769455444846be7",
@@ -112676,6 +112680,28 @@
}
]
},
{
"dest": "fbneo/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "neogeo/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "fba2012/samples/dkong.zip",
"sha1": "764ec667084bc237c1de6bd1db7541ad8cb59975",
@@ -163565,6 +163591,90 @@
"squirreljme"
]
},
{
"dest": "atari2600/stella/KVS1.WAV",
"sha1": "b094c2c1fca81a0e531e0541f302346150ec4604",
"sha256": "8bf8d878db407cc81b4c8a05069d3aa35e0e7bff803112d4d0eba637d60fe12c",
"size": 3436329,
"repo_path": "bios/Atari/2600/KVS1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS2.WAV",
"sha1": "8b83b2eea01b3e08ceb885aeb153d4084bddb63c",
"sha256": "d031b9534ba75d870365657f578ed18c0cc513ebe9b253be7d80114c7ae4210d",
"size": 2086275,
"repo_path": "bios/Atari/2600/KVS2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS3.WAV",
"sha1": "86896a1e272d8715489de9b407f0b8a42f82d4a0",
"sha256": "4e47d32533feebfa9625ea818183edcd519b8cb6516bf3db11dc9a01ada6878b",
"size": 3720920,
"repo_path": "bios/Atari/2600/KVS3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB1.WAV",
"sha1": "6a582aebcefd6e2a97bdd8968202aab9851a889c",
"sha256": "968937d09e17ca059cdc5f092161ba172c56ff31bc945e381638c79bf7a7e4e2",
"size": 4219542,
"repo_path": "bios/Atari/2600/KVB1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB2.WAV",
"sha1": "60a425c6bde3226ab731995562716321be20fc49",
"sha256": "6ac885493469e68992b0d272264b4b0947e7d6a5c6fd0170c65299acc386c122",
"size": 9593878,
"repo_path": "bios/Atari/2600/KVB2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB3.WAV",
"sha1": "5e34125c4d6c209b21d1c892f3df0ec1644fd0d8",
"sha256": "76acf3b4e607cc851c625d455ced2b099dc394460d8716c02420904960842e34",
"size": 7676992,
"repo_path": "bios/Atari/2600/KVB3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVSHARED.WAV",
"sha1": "9adf10cdf1de833b194c7d8797ad1f041ad98dd3",
"sha256": "589b37725aeb9801868deafa2940c6eacb15430d4051ada7942298561f3014b6",
"size": 3059116,
"repo_path": "bios/Atari/2600/KVSHARED.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "REMOTE1.RTS",
"sha1": "945f1c126de553cd6e11b9c40e9dd05a103ee25a",
@@ -168249,5 +168359,10 @@
"sony-playstation-2"
]
}
]
],
"save_directory": {
"folder": "saves",
"by_core": false,
"by_system": true
}
}
+295 -185
View File
@@ -279,103 +279,12 @@
}
}
],
"total_files": 3370,
"total_size": 4356797363,
"pack_files": 3372,
"pack_size": 4356797363,
"total_omitted": 28,
"total_files": 3391,
"total_size": 4659096941,
"pack_files": 3393,
"pack_size": 4659096941,
"total_omitted": 14,
"omitted_files": [
{
"dest": "Stella/stella/KVB1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVSHARED.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVSHARED.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "caesar3/The_empire.555",
"name": "The_empire.555",
@@ -475,94 +384,6 @@
],
"category": "game_data"
},
{
"dest": "dolphin-emu/User/GBA/gba_bios.bin",
"root": "save",
"core_folder": "dolphin-emu",
"name": "gba_bios.bin",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gba"
],
"held": true
},
{
"dest": "dolphin-emu/User/Load/WiiSD.raw",
"root": "save",
"core_folder": "dolphin-emu",
"name": "WiiSD.raw",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/clientca.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "clientca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/clientcakey.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "clientcakey.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/rootca.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "rootca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/shared2/sys/SYSCONF",
"root": "save",
"core_folder": "dolphin-emu",
"name": "SYSCONF",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/title/00000001/00000002/data/setting.txt",
"root": "save",
"core_folder": "dolphin-emu",
"name": "setting.txt",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "doomu.wad",
"name": "doomu.wad",
@@ -34198,6 +34019,206 @@
"dolphin"
]
},
{
"dest": "gamecube/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "wii/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "gamecube/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "gamecube/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "wii/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gamecube"
],
"root": "save"
},
{
"dest": "GC/dsp_rom.bin",
"sha1": "3c6cc6e04fdd0b2a392d7a6ed769455444846be7",
@@ -38332,6 +38353,90 @@
"scummvm"
]
},
{
"dest": "atari2600/stella/KVS1.WAV",
"sha1": "b094c2c1fca81a0e531e0541f302346150ec4604",
"sha256": "8bf8d878db407cc81b4c8a05069d3aa35e0e7bff803112d4d0eba637d60fe12c",
"size": 3436329,
"repo_path": "bios/Atari/2600/KVS1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS2.WAV",
"sha1": "8b83b2eea01b3e08ceb885aeb153d4084bddb63c",
"sha256": "d031b9534ba75d870365657f578ed18c0cc513ebe9b253be7d80114c7ae4210d",
"size": 2086275,
"repo_path": "bios/Atari/2600/KVS2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS3.WAV",
"sha1": "86896a1e272d8715489de9b407f0b8a42f82d4a0",
"sha256": "4e47d32533feebfa9625ea818183edcd519b8cb6516bf3db11dc9a01ada6878b",
"size": 3720920,
"repo_path": "bios/Atari/2600/KVS3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB1.WAV",
"sha1": "6a582aebcefd6e2a97bdd8968202aab9851a889c",
"sha256": "968937d09e17ca059cdc5f092161ba172c56ff31bc945e381638c79bf7a7e4e2",
"size": 4219542,
"repo_path": "bios/Atari/2600/KVB1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB2.WAV",
"sha1": "60a425c6bde3226ab731995562716321be20fc49",
"sha256": "6ac885493469e68992b0d272264b4b0947e7d6a5c6fd0170c65299acc386c122",
"size": 9593878,
"repo_path": "bios/Atari/2600/KVB2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB3.WAV",
"sha1": "5e34125c4d6c209b21d1c892f3df0ec1644fd0d8",
"sha256": "76acf3b4e607cc851c625d455ced2b099dc394460d8716c02420904960842e34",
"size": 7676992,
"repo_path": "bios/Atari/2600/KVB3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVSHARED.WAV",
"sha1": "9adf10cdf1de833b194c7d8797ad1f041ad98dd3",
"sha256": "589b37725aeb9801868deafa2940c6eacb15430d4051ada7942298561f3014b6",
"size": 3059116,
"repo_path": "bios/Atari/2600/KVSHARED.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "id1/pak0.pak",
"sha1": "36b42dc7b6313fd9cabc0be8b9e9864840929735",
@@ -43913,5 +44018,10 @@
"sony-playstation-2"
]
}
]
],
"save_directory": {
"folder": "saves",
"by_core": false,
"by_system": true
}
}
+539 -298
View File
@@ -284,11 +284,11 @@
}
}
],
"total_files": 5146,
"total_size": 8009125130,
"pack_files": 5148,
"pack_size": 8009125130,
"total_omitted": 178,
"total_files": 5187,
"total_size": 8450820256,
"pack_files": 5189,
"pack_size": 8450820256,
"total_omitted": 155,
"omitted_files": [
{
"dest": "AR6002G.ROM",
@@ -332,93 +332,6 @@
],
"category": "game_data"
},
{
"dest": "Azahar/Azahar/nand/private/movable.sed",
"root": "save",
"core_folder": "Azahar",
"name": "movable.sed",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"azahar"
]
},
{
"dest": "Azahar/Azahar/nand/rw/sys/LocalFriendCodeSeed_B",
"root": "save",
"core_folder": "Azahar",
"name": "LocalFriendCodeSeed_B",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"azahar"
]
},
{
"dest": "Azahar/Azahar/nand/rw/sys/SecureInfo_A",
"root": "save",
"core_folder": "Azahar",
"name": "SecureInfo_A",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"azahar"
]
},
{
"dest": "Azahar/Azahar/sysdata/keys.txt",
"root": "save",
"core_folder": "Azahar",
"name": "keys.txt",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"azahar"
],
"held": true
},
{
"dest": "Azahar/Azahar/sysdata/otp.bin",
"root": "save",
"core_folder": "Azahar",
"name": "otp.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"azahar"
],
"held": true
},
{
"dest": "Azahar/Azahar/sysdata/seeddb.bin",
"root": "save",
"core_folder": "Azahar",
"name": "seeddb.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"azahar"
],
"held": true
},
{
"dest": "Azahar/Azahar/sysdata/shared_font.bin",
"root": "save",
"core_folder": "Azahar",
"name": "shared_font.bin",
"system": "nintendo-3ds",
"required": false,
"reason": "no_save_directory",
"cores": [
"azahar"
]
},
{
"dest": "BIOSDSI7.ROM",
"name": "BIOSDSI7.ROM",
@@ -578,32 +491,6 @@
"cxbx-reloaded"
]
},
{
"dest": "FB Alpha 2012 CPS-3/hiscore.dat",
"root": "save",
"core_folder": "FB Alpha 2012 CPS-3",
"name": "hiscore.dat",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"fbalpha2012_cps3"
],
"held": true
},
{
"dest": "FB Alpha 2012/hiscore.dat",
"root": "save",
"core_folder": "FB Alpha 2012",
"name": "hiscore.dat",
"system": "arcade",
"required": false,
"reason": "no_save_directory",
"cores": [
"fbalpha2012"
],
"held": true
},
{
"dest": "GANIM.BS6",
"name": "GANIM.BS6",
@@ -835,97 +722,6 @@
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVB3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVB3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS1.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS1.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS2.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS2.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVS3.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVS3.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "Stella/stella/KVSHARED.WAV",
"root": "save",
"core_folder": "Stella",
"name": "KVSHARED.WAV",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"stella"
],
"category": "game_data"
},
{
"dest": "TD.GRP",
"name": "TD.GRP",
@@ -1277,94 +1073,6 @@
],
"category": "game_data"
},
{
"dest": "dolphin-emu/User/GBA/gba_bios.bin",
"root": "save",
"core_folder": "dolphin-emu",
"name": "gba_bios.bin",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
],
"systems": [
"nintendo-gba"
],
"held": true
},
{
"dest": "dolphin-emu/User/Load/WiiSD.raw",
"root": "save",
"core_folder": "dolphin-emu",
"name": "WiiSD.raw",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/clientca.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "clientca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/clientcakey.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "clientcakey.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/rootca.pem",
"root": "save",
"core_folder": "dolphin-emu",
"name": "rootca.pem",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/shared2/sys/SYSCONF",
"root": "save",
"core_folder": "dolphin-emu",
"name": "SYSCONF",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "dolphin-emu/User/Wii/title/00000001/00000002/data/setting.txt",
"root": "save",
"core_folder": "dolphin-emu",
"name": "setting.txt",
"system": "",
"required": false,
"reason": "no_save_directory",
"cores": [
"dolphin"
]
},
{
"dest": "doom2bfg.wad",
"name": "doom2bfg.wad",
@@ -11653,6 +11361,17 @@
"xegs"
]
},
{
"dest": "3ds/Azahar/sysdata/keys.txt",
"sha1": "5288772be438b86978a801e6dcb14228ad3a20af",
"sha256": "ea8b3d7c752d85f2326b9bfa01615414ab34ba052f87481b0ff4003fd887e50a",
"size": 7424,
"repo_path": "bios/Other/azaharplus/sysdata/keys.txt",
"cores": [
"azahar"
],
"root": "save"
},
{
"dest": "sysdata/keys.txt",
"sha1": "5288772be438b86978a801e6dcb14228ad3a20af",
@@ -40473,6 +40192,72 @@
"sega-saturn"
]
},
{
"dest": "3ds/Azahar/sysdata/shared_font.bin",
"sha1": "60022d6d026c8df950722478aab25702a0dfa067",
"sha256": "a06aaf6b50ebc38ebdccc59b913d4a1c0cc7005289957530acaaf78ffc49dddd",
"size": 3145728,
"repo_path": "bios/Nintendo/3DS/Citra/sysdata/shared_font.bin",
"cores": [
"azahar"
],
"root": "save"
},
{
"dest": "3ds/Azahar/sysdata/seeddb.bin",
"sha1": "9e2c006997761082be87cf316e57c4da5cddbc62",
"sha256": "ff485c60090185aff05354ece01f86b61f6020332bed0f9090c58d4678e5a180",
"size": 53264,
"repo_path": "bios/Nintendo/3DS/Citra/sysdata/seeddb.bin",
"cores": [
"azahar"
],
"root": "save"
},
{
"dest": "3ds/Azahar/sysdata/otp.bin",
"sha1": "49489245b400f62c62faf1736b7f0a70714d3c49",
"sha256": "e2f1810ceff3d1fd4f1c08ffc1f4d47aa8efca551edd24cd5686205c71a3b13b",
"size": 256,
"repo_path": "bios/Nintendo/3DS/otp.bin",
"cores": [
"azahar"
],
"root": "save"
},
{
"dest": "3ds/Azahar/nand/private/movable.sed",
"sha1": "6620b0a0c79dfe80be682fbd5c31c152ab570899",
"sha256": "5c024772c93d5b491398873b05be69a178d8a5208152d60ea2c006dfdbb2ce00",
"size": 320,
"repo_path": "bios/Nintendo/3DS/Citra/nand/private/movable.sed",
"cores": [
"azahar"
],
"root": "save"
},
{
"dest": "3ds/Azahar/nand/rw/sys/SecureInfo_A",
"sha1": "ff52883a0f61afcbbb3f8e59b9327ac52050e9a7",
"sha256": "5eda7e8951c48fc0913445fc844fa1caafcf226f82c0d06341e7e5fa39ae033e",
"size": 273,
"repo_path": "bios/Nintendo/3DS/Citra/nand/rw/sys/SecureInfo_A",
"cores": [
"azahar"
],
"root": "save"
},
{
"dest": "3ds/Azahar/nand/rw/sys/LocalFriendCodeSeed_B",
"sha1": "3011ae55c3dc70203fd62aad98bf485e55d018ff",
"sha256": "086e900d21c6ae3f892db284359315cb5ec44bb3939f2fb3187d212f5be3ac61",
"size": 272,
"repo_path": "bios/Nintendo/3DS/Citra/nand/rw/sys/LocalFriendCodeSeed_B",
"cores": [
"azahar"
],
"root": "save"
},
{
"dest": "sysdata/shared_font.bin",
"sha1": "60022d6d026c8df950722478aab25702a0dfa067",
@@ -42161,6 +41946,306 @@
"triforce"
]
},
{
"dest": "gamecube/dolphin-emu/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "triforce/dolphin-emu/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "wii/dolphin-emu/User/GBA/gba_bios.bin",
"sha1": "300c20df6731a33952ded8c436f7f186d25d3492",
"sha256": "fd2547724b505f487e6dcb29ec2ecff3af35a841a77ab2e85fd87350abd36570",
"size": 16384,
"repo_path": "bios/Nintendo/Game Boy Advance/GBA_bios.rom",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/dolphin-emu/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "triforce/dolphin-emu/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "wii/dolphin-emu/User/Wii/shared2/sys/SYSCONF",
"sha1": "3256c026284a24fb99d2ec1558d95db3b5dcc2e9",
"sha256": "a8ec1ec377ee3a3c93a27f74dadf9edf95112ce167fc23d1abdbeb4fa15eb179",
"size": 16384,
"repo_path": "bios/Nintendo/Wii/SYSCONF",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/dolphin-emu/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "triforce/dolphin-emu/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "wii/dolphin-emu/User/Wii/title/00000001/00000002/data/setting.txt",
"sha1": "077a31ce116de322f089a627c5eb7ff5c2236a5d",
"sha256": "5e17f8bc2444048c944e92a4f3b2a89a6f7f06398a17b2552be8d32e52c6f9db",
"size": 256,
"repo_path": "bios/Nintendo/Wii/setting.txt",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/dolphin-emu/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "triforce/dolphin-emu/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "wii/dolphin-emu/User/Load/WiiSD.raw",
"sha1": "90d83d6c084deceeeb0466ac00723723ccfd0c6d",
"sha256": "6ea30c50325dba6adeaf0b5841956a7074534cf2aac5ff4160d5279226f56047",
"size": 134217728,
"repo_path": "bios/Nintendo/Wii/WiiSD.raw",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"storage": "release",
"release_asset": "WiiSD.raw",
"root": "save"
},
{
"dest": "gamecube/dolphin-emu/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "triforce/dolphin-emu/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "wii/dolphin-emu/User/Wii/clientca.pem",
"sha1": "4b937d4e81de11574b926386dd5f768aa23bf177",
"sha256": "229ec678525e060588e8ea23e5459ec14af3c2ebb7b9e69ec46b0faf011730d9",
"size": 1005,
"repo_path": "bios/Nintendo/Wii/clientca.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/dolphin-emu/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "triforce/dolphin-emu/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "wii/dolphin-emu/User/Wii/clientcakey.pem",
"sha1": "a2c11886e6d12a135e1d5eb50d5fe92e028577d9",
"sha256": "723be9b32c3afb83a4a3757adf352529e90c0ad6fad52509963ba8942ae625df",
"size": 609,
"repo_path": "bios/Nintendo/Wii/clientcakey.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "gamecube/dolphin-emu/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "triforce/dolphin-emu/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "wii/dolphin-emu/User/Wii/rootca.pem",
"sha1": "b5229455dd26c1f53c73060e9089b391389e1f75",
"sha256": "c5b0f8dfcec6b9ed2ac38b8bc69a4db7c209dc177d243c8df2bddf9e39171e5f",
"size": 897,
"repo_path": "bios/Nintendo/Wii/rootca.pem",
"cores": [
"dolphin"
],
"systems": [
"triforce"
],
"root": "save"
},
{
"dest": "GC/USA/IPL.bin",
"sha1": "ef9194ab4804aa0aa8540d846caf291b28331165",
@@ -43040,6 +43125,73 @@
"ep128emu_core"
]
},
{
"dest": "cave/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "cps1/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "cps2/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "cps3/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012",
"fbalpha2012_cps3"
],
"root": "save"
},
{
"dest": "fbneo/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "neogeo/hiscore.dat",
"sha1": "7381472bf046126257e51a0124e4553282f020e5",
"sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5",
"size": 322458,
"repo_path": "bios/Arcade/Arcade/hiscore.dat",
"cores": [
"fbalpha2012"
],
"root": "save"
},
{
"dest": "fba2012/samples/dkong.zip",
"sha1": "764ec667084bc237c1de6bd1db7541ad8cb59975",
@@ -94958,6 +95110,90 @@
"release_asset": "audioremaster.bin",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS1.WAV",
"sha1": "b094c2c1fca81a0e531e0541f302346150ec4604",
"sha256": "8bf8d878db407cc81b4c8a05069d3aa35e0e7bff803112d4d0eba637d60fe12c",
"size": 3436329,
"repo_path": "bios/Atari/2600/KVS1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS2.WAV",
"sha1": "8b83b2eea01b3e08ceb885aeb153d4084bddb63c",
"sha256": "d031b9534ba75d870365657f578ed18c0cc513ebe9b253be7d80114c7ae4210d",
"size": 2086275,
"repo_path": "bios/Atari/2600/KVS2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVS3.WAV",
"sha1": "86896a1e272d8715489de9b407f0b8a42f82d4a0",
"sha256": "4e47d32533feebfa9625ea818183edcd519b8cb6516bf3db11dc9a01ada6878b",
"size": 3720920,
"repo_path": "bios/Atari/2600/KVS3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB1.WAV",
"sha1": "6a582aebcefd6e2a97bdd8968202aab9851a889c",
"sha256": "968937d09e17ca059cdc5f092161ba172c56ff31bc945e381638c79bf7a7e4e2",
"size": 4219542,
"repo_path": "bios/Atari/2600/KVB1.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB2.WAV",
"sha1": "60a425c6bde3226ab731995562716321be20fc49",
"sha256": "6ac885493469e68992b0d272264b4b0947e7d6a5c6fd0170c65299acc386c122",
"size": 9593878,
"repo_path": "bios/Atari/2600/KVB2.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVB3.WAV",
"sha1": "5e34125c4d6c209b21d1c892f3df0ec1644fd0d8",
"sha256": "76acf3b4e607cc851c625d455ced2b099dc394460d8716c02420904960842e34",
"size": 7676992,
"repo_path": "bios/Atari/2600/KVB3.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "atari2600/stella/KVSHARED.WAV",
"sha1": "9adf10cdf1de833b194c7d8797ad1f041ad98dd3",
"sha256": "589b37725aeb9801868deafa2940c6eacb15430d4051ada7942298561f3014b6",
"size": 3059116,
"repo_path": "bios/Atari/2600/KVSHARED.WAV",
"cores": [
"stella"
],
"root": "save",
"category": "game_data"
},
{
"dest": "pcsx2x6/TeknoParrot/bios/COH-H31100.rom0",
"sha1": "9a67e2d344b1132a183881c267463078b220ed21",
@@ -99224,5 +99460,10 @@
"namco-system246"
]
}
]
],
"save_directory": {
"folder": "saves",
"by_core": false,
"by_system": true
}
}
+794 -361
View File
File diff suppressed because it is too large. Load diff
+90 -11
View File
@@ -493,12 +493,20 @@ platforms:
source_url: https://raw.githubusercontent.com/batocera-linux/batocera.linux/master/package/batocera/core/batocera-scripts/scripts/batocera-systems
source_format: python_dict
hash_type: md5
# The libretro launcher hands each core /userdata/saves/<system> with
# sort_savefiles_enable off (python-src/batocera-launch-libretro/
# batocera_launch_libretro/emulator.py:754-757 at 8bbc0d6e, saves_dir in
# python-src/batocera-launch/batocera_launch/emulator.py:251-252 at
# d30617e5): one folder per launched system, no single place.
save_directory: null
# configgen hands each libretro core /userdata/saves/<system> at every
# launch, with sort_savefiles_enable off (package/batocera/core/
# batocera-configgen/configgen/configgen/generators/libretro/
# libretroConfig.py:225-228 and batoceraPaths.py:22 at batocera-43.1).
# <system> is the ES system name (Emulator.py:119, args.system), so a
# file is placed once below each system es_systems.yml offers the core
# for (libretro_systems in batocera.yml). The pack keeps them in
# userdata-saves/: batocera-systems lists bios/saves/dolphin-emu/
# Triforce/segaboot.gcm, so saves/ already belongs to the BIOS tree.
save_directory:
folder: saves
by_core: false
by_system: true
pack_folder: userdata-saves
schedule: weekly
target_scraper: batocera_targets
target_source: https://github.com/batocera-linux/batocera.linux
@@ -524,6 +532,16 @@ platforms:
hash_type: md5
# Bios.cpp:64-68 hashes a .zip with Zip::Md5Composite, never its bytes
zip_digest: composite
# configgen hands each libretro core /recalbox/share/saves/<system> at
# every launch, with sort_savefiles_enable off (projects/configgen/
# configgen/generators/libretro/libretroRetroarch.py:338, 347-348 and
# 419-420, recalboxFiles.py:84 at 10.1.1). <system> is the name the
# system.ini gives, so a file is placed once below each system offering
# the core (libretro_systems in recalbox.yml).
save_directory:
folder: saves
by_core: false
by_system: true
schedule: monthly
target_scraper: recalbox_targets
target_source: https://gitlab.com/recalbox/recalbox/-/tree/master/configs
@@ -552,11 +570,20 @@ platforms:
hash_type: md5
# Windows: names differing only by case land on one file.
case_insensitive_fs: true
# emulatorLauncher hands a libretro core saves\<system> (saves\<system>\
# LR-amiberry for amiberry, saves\ for mame), sorted by core for dolphin
# only (emulatorLauncher/Generators/LibRetro.Generator.cs:1128-1131 and
# 1305-1315 at 7f8dc28a): one folder per launched system, no single place.
save_directory: null
# emulatorLauncher hands each libretro core saves\<system> at every
# launch, saves\ beside bios\ (emulatorLauncher.cfg in retrobat 8.3.1),
# and sorts saves by core for dolphin alone (CoreSaveSort)
# (emulatorLauncher/Generators/LibRetro.Generator.cs:1128-1132, 1304-1315
# and 2707 at 48cdc616). <system> is the ES system name, so a file is
# placed once below each system es_systems.cfg offers the core for
# (libretro_systems in retrobat.yml). mame (saves\) and amiberry
# (saves\<system>\LR-amiberry) differ, and neither profile has a file
# read below the save directory.
save_directory:
folder: saves
by_core: false
by_system: true
by_core_for: [dolphin]
schedule: weekly
target_scraper: null
target_source: null
@@ -591,6 +618,16 @@ platforms:
hash_type: md5
# Windows: names differing only by case land on one file.
case_insensitive_fs: true
# RetroArch_setupSaves points savefile_directory at
# $savesPath/retroarch/saves (functions/EmuScripts/emuDeckRetroArch.sh:236
# at dddb3022), savesPath ~/Emulation/saves beside biosPath
# ~/Emulation/bios (functions/helperFunctions.sh:347-348). The shipped
# retroarch.cfg turns savefiles_in_content_dir and both sort options off
# (configs/org.libretro.RetroArch/config/retroarch/retroarch.cfg:3135,
# 3176-3177): one folder for every core.
save_directory:
folder: saves/retroarch/saves
by_core: false
schedule: weekly
target_scraper: emudeck_targets
target_source: https://github.com/dragoonDorise/EmuDeck
@@ -669,6 +706,20 @@ platforms:
source_url: https://github.com/RetroDECK/components
source_format: github_component_manifests
hash_type: md5
# savefile_directory is $saves_path, ~/retrodeck/saves beside
# ~/retrodeck/bios (retroarch/component_prepare.sh:27 and 44 at
# components fcd0d729), and RetroArch sorts saves by content, not by
# core (retroarch/rd_assets/rd_config/retroarch.cfg:3233-3234 and
# 3275-3276). RetroArch 1.22.2 appends the name of the folder holding
# the ROM (runloop.c:8205-8209 and 8249-8258 at 69a4f0ea): saves/<ROM
# folder> for a ROM at the top of its system folder, the folder of each
# system whose ES-DE command loads the core (libretro_systems in
# retrodeck.yml, from RetroDECK/ES-DE resources/systems/linux/
# es_systems.xml at 15e1b236, the release RetroDECK takes as latest).
save_directory:
folder: saves
by_core: false
by_system: true
schedule: monthly
contributed_by:
- username: monster-penguin
@@ -705,6 +756,11 @@ platforms:
source_url: https://raw.githubusercontent.com/rommapp/romm/master/backend/models/fixtures/known_bios_files.json
source_format: json
hash_type: sha1
# Cores run in the browser through EmulatorJS: the save file lives in
# the Emscripten filesystem and goes through RomM's save API
# (frontend/src/views/Player/EmulatorJS/utils.ts:409-426 at 5.4.0).
# Nothing a user installs reaches it.
save_directory: null
schedule: monthly
contributed_by:
- username: PixNyb
@@ -765,6 +821,11 @@ platforms:
extract_to: /storage/roms/bios/
logo: https://avatars.githubusercontent.com/u/163176886
scraper: rocknix
# Every device's retroarch.cfg sets savefiles_in_content_dir (for
# instance projects/ROCKNIX/packages/emulators/libretro/retroarch/
# sources/RK3566/retroarch.cfg:664-665 at 20261001) and setsettings.sh
# leaves it: saves sit beside each game, no single place.
save_directory: null
schedule: weekly
target_scraper: rocknix_targets
target_source: https://github.com/ROCKNIX/distribution/blob/next/projects/ROCKNIX/packages/virtual/emulators/package.mk
@@ -793,6 +854,10 @@ platforms:
source_url: https://github.com/AmberELEC/AmberELEC/blob/dev/packages/amberelec/sources/scripts/batocera-systems
source_format: python_dict
hash_type: md5
# retroarch.cfg sets savefiles_in_content_dir (packages/games/tools/
# retroarch/sources/retroarch.cfg:567-568 at a21975bf) and
# setsettings.py leaves it: saves sit beside each game, no single place.
save_directory: null
schedule: monthly
target_scraper: null
target_source: null
@@ -830,6 +895,10 @@ platforms:
source_url: https://github.com/EmuELEC/EmuELEC/blob/master/packages/sx05re/emuelec/bin/batocera/batocera-systems
source_format: python_dict
hash_type: md5
# savefile_directory stays commented out (packages/sx05re/libretro_base/
# retroarch/package.mk:115 at v4.8) and setsettings.sh never sets it, so
# RetroArch saves beside each game: no single place.
save_directory: null
schedule: monthly
target_scraper: null
target_source: null
@@ -858,6 +927,16 @@ platforms:
source_url: https://github.com/knulli-cfw/knulli-linux/blob/knulli-main/package/system/knulli-scripts/scripts/knulli-systems
source_format: python_dict
hash_type: md5
# configgen hands each libretro core /userdata/saves/<system> at every
# launch, with sort_savefiles_enable off (package/system/knulli-configgen/
# configgen/configgen/generators/libretro/libretroConfig.py:240-243 and
# batoceraPaths.py:22 at 20260511), as Batocera's does: a file is placed
# once below each system es_systems.yml offers the core for
# (libretro_systems in knulli.yml).
save_directory:
folder: saves
by_core: false
by_system: true
schedule: monthly
target_scraper: null
target_source: null
+401
View File
@@ -5813,6 +5813,407 @@ dual_mode_cores:
- scummvm
- stella
- tic80
libretro_systems:
"81":
- zx81
a5200:
- atari5200
applewin:
- apple2
arduous:
- arduboy
atari800:
- atari5200
- atari800
beetle-saturn:
- saturn
bennugd:
- bennugd
bk:
- bk
blastem:
- megadrive
bluemsx:
- colecovision
- msx1
- msx2
- msx2+
- msxturbor
- spectravideo
boom3:
- doom3
bsnes:
- sgb-msu1
- snes
- snes-msu1
bsnes_hd:
- sgb-msu1
- snes
- snes-msu1
cap32:
- amstradcpc
- gx4000
desmume:
- nds
dice:
- dice
dolphin:
- gamecube
- wii
dosbox_pure:
- dos
easyrpg:
- easyrpg
emuscv:
- scv
ep128emu-core:
- enterprise
- tvc
fake08:
- pico8
fbalpha:
- fbneo
- neogeo
fbneo:
- fbneo
- neogeo
fceumm:
- fds
- nes
flycast:
- atomiswave
- dreamcast
- naomi
- naomi2
- systemsp
flycastvl:
- atomiswave
- dreamcast
- naomi
fmsx:
- msx1
- msx2
- msx2+
freechaf:
- channelf
freeintv:
- intellivision
freej2me:
- j2me
fuse:
- zxspectrum
gambatte:
- gb
- gbc
gearcoleco:
- colecovision
gearsystem:
- gamegear
- mastersystem
- multivision
- sg1000
genesisplusgx:
- gamegear
- mastersystem
- megacd
- megadrive
- megadrive-msu
- pico
- sg1000
genesisplusgx-expanded:
- megadrive
genesisplusgx-wide:
- megadrive
- megadrive-msu
- pico
gong:
- gong
gpsp:
- gba
gw:
- gameandwatch
handy:
- lynx
hatari:
- atarist
hatarib:
- atarist
holani:
- lynx
imame4all:
- mame
- neogeo
kronos:
- saturn
lowresnx:
- lowresnx
lutro:
- lutro
mame:
- adam
- advision
- apfm1000
- apple2
- arcadia
- archimedes
- astrocade
- atom
- bbcmicro
- beena
- bk
- camplynx
- cave3rd
- cdi
- cgenie
- coco
- crvision
- ctvboy
- dragon64
- electron
- enterprise
- fm7
- fmtowns
- gaelco
- gamate
- gameandwatch
- gamecom
- gamepock
- gmaster
- gp32
- laser310
- lcdgames
- loopy
- macintosh
- mame
- mc10
- megaduck
- model2
- mz2000
- mz2500
- mz700
- mz800
- mz80k
- namco22
- neogeo
- oricatmos
- pc60
- pc80
- pcw
- pdp1
- pv1000
- pv2000
- rx78
- samcoupe
- sc3000
- segaai
- socrates
- supracan
- sv8000
- ti99
- trs80
- tutor
- tvc
- tvgames
- uzebox
- vc4000
- vectrex
- vgmplay
- vis
- vsmile
- xegs
mame078plus:
- mame
- neogeo
mednafen_lynx:
- lynx
mednafen_ngp:
- ngp
- ngpc
mednafen_psx:
- psx
mednafen_supergrafx:
- supergrafx
mednafen_wswan:
- wswan
- wswanc
melonds:
- nds
melondsds:
- nds
mesen:
- fds
- nes
mesen-s:
- gb
- gbc
- satellaview
- sgb
- snes
mgba:
- gb
- gba
- gbc
- sgb
minivmac:
- macintosh
mrboom:
- mrboom
mupen64plus-next:
- n64
- n64dd
neocd:
- neogeocd
nestopia:
- fds
- nes
np2kai:
- pc98
nxengine:
- cavestory
o2em:
- odyssey2
- videopacplus
opera:
- 3do
parallel_n64:
- n64
- n64dd
pce:
- pcengine
- pcenginecd
pce_fast:
- pcengine
- pcenginecd
pcfx:
- pcfx
pcsx2:
- ps2
pcsx_rearmed:
- psx
pd777:
- cassettevision
picodrive:
- gamegear
- mastersystem
- megacd
- megadrive
- pico
- sega32x
play:
- ps2
pocketsnes:
- satellaview
- snes
- snes-msu1
pokemini:
- pokemini
potator:
- supervision
ppsspp:
- psp
prboom:
- prboom
prosystem:
- atari7800
puae:
- amiga1200
- amiga500
- amigacd32
- amigacdtv
puae2021:
- amiga1200
- amiga500
- amigacd32
- amigacdtv
px68k:
- x68000
quasi88:
- pc88
reminiscence:
- reminiscence
same_cdi:
- cdi
sameduck:
- megaduck
scummvm:
- scummvm
smsplus:
- gamegear
- mastersystem
snes9x:
- satellaview
- snes
- snes-msu1
- sufami
snes9x_next:
- snes
squirreljme:
- j2me
stella:
- atari2600
stella2014:
- atari2600
superbroswar:
- superbroswar
swanstation:
- psx
tgbdual:
- gb2players
- gbc2players
theodore:
- thomson
tic80:
- tic80
tyrquake:
- quake
uae4arm:
- amiga1200
- amiga500
- amigacd32
- amigacdtv
uzem:
- uzebox
vb:
- virtualboy
vba-m:
- gb
- gba
- gbc
vecx:
- vectrex
vemulator:
- vemulator
vice_x128:
- c128
vice_x64:
- c64
vice_x64sc:
- c64
vice_xpet:
- pet
vice_xplus4:
- cplus4
vice_xscpu64:
- c64
vice_xvic:
- c20
vircon32:
- vircon32
virtualjaguar:
- jaguar
- jaguarcd
vitaquake2:
- quake2
wasm4:
- wasm4
x1:
- x1
xrick:
- xrick
yabasanshiro:
- saturn
zc210:
- zc210
launchers:
- emulator: duckstation
build: standalone
+379
View File
@@ -5015,3 +5015,382 @@ dual_mode_cores:
- scummvm
- stella
- yabasanshiro
libretro_systems:
"81":
- zx81
a5200:
- atari5200
applewin:
- apple2
arduous:
- arduboy
atari800:
- atari5200
- atari800
beetle-saturn:
- saturn
bennugd:
- bennugd
blastem:
- megadrive
bluemsx:
- colecovision
- msx1
- msx2
- msx2+
- msxturbor
- spectravideo
boom3:
- doom3
bsnes:
- sgb-msu1
- snes
- snes-msu1
bsnes_hd:
- sgb-msu1
- snes
- snes-msu1
cap32:
- amstradcpc
- gx4000
citra:
- 3ds
desmume:
- nds
dice:
- dice
dolphin:
- gamecube
- wii
dosbox_pure:
- dos
easyrpg:
- easyrpg
emuscv:
- scv
fake08:
- pico8
fbalpha:
- fbneo
- neogeo
fbneo:
- fbneo
- neogeo
fceumm:
- fds
- nes
flycast:
- atomiswave
- dreamcast
- naomi
- naomi2
- systemsp
flycast-xtreme:
- atomiswave
- dreamcast
- naomi
- naomi2
- systemsp
flycastvl:
- atomiswave
- dreamcast
- naomi
fmsx:
- msx1
- msx2
- msx2+
freechaf:
- channelf
freeintv:
- intellivision
freej2me:
- j2me
fuse:
- zxspectrum
gambatte:
- gb
- gbc
gearsystem:
- gamegear
- mastersystem
- multivision
- sg1000
genesisplusgx:
- gamegear
- mastersystem
- megadrive
- msu-md
- pico
- segacd
- sg1000
genesisplusgx-expanded:
- megadrive
genesisplusgx-wide:
- megadrive
- msu-md
- pico
geolith:
- fbneo
- neogeo
gong:
- gong
gpsp:
- gba
gw:
- gameandwatch
handy:
- lynx
hatari:
- atarist
hatarib:
- atarist
holani:
- lynx
imame4all:
- mame
- neogeo
kronos:
- saturn
lowresnx:
- lowresnx
lutro:
- lutro
mame:
- adam
- advision
- apfm1000
- apple2
- apple2gs
- arcadia
- archimedes
- astrocde
- atom
- bbc
- camplynx
- cdi
- coco
- crvision
- electron
- fm7
- fmtowns
- gamate
- gameandwatch
- gamecom
- gamepock
- gmaster
- gp32
- laser310
- lcdgames
- macintosh
- mame
- megaduck
- namco22
- neogeo
- pdp1
- plugnplay
- pv1000
- socrates
- supracan
- ti99
- tutor
- vc4000
- vgmplay
- vis
- vsmile
- xegs
mame0139:
- mame
- neogeo
mame078plus:
- mame
- neogeo
mednafen_lynx:
- lynx
mednafen_ngp:
- ngp
- ngpc
mednafen_psx:
- psx
mednafen_supergrafx:
- supergrafx
mednafen_wswan:
- wswan
- wswanc
melonds:
- nds
melondsds:
- nds
mesen:
- fds
- nes
mesen-s:
- gb
- gbc
- satellaview
- sgb
- snes
mgba:
- gb
- gba
- gbc
- sgb
minivmac:
- macintosh
mrboom:
- mrboom
mupen64plus-next:
- n64
- n64dd
neocd:
- neogeocd
nestopia:
- fds
- nes
np2kai:
- pc98
nxengine:
- cavestory
o2em:
- o2em
- videopacplus
openlara:
- traider1
opera:
- 3do
parallel_n64:
- n64
- n64dd
pce:
- pcengine
- pcenginecd
pce_fast:
- pcengine
- pcenginecd
pcfx:
- pcfx
pcsx2:
- ps2
pcsx_rearmed:
- psx
picodrive:
- gamegear
- mastersystem
- megadrive
- pico
- sega32x
- segacd
play:
- ps2
pocketsnes:
- satellaview
- snes
- snes-msu1
pokemini:
- pokemini
potator:
- supervision
ppsspp:
- psp
prboom:
- prboom
prosystem:
- atari7800
puae:
- amiga1200
- amiga500
- amigacd32
- amigacdtv
puae2021:
- amiga1200
- amiga500
- amigacd32
- amigacdtv
px68k:
- x68000
quasi88:
- pc88
reminiscence:
- reminiscence
same_cdi:
- cdi
sameduck:
- megaduck
scummvm:
- scummvm
smsplus:
- gamegear
- mastersystem
snes9x:
- satellaview
- snes
- snes-msu1
- sufami
snes9x_next:
- snes
squirreljme:
- j2me
stella:
- atari2600
stella2014:
- atari2600
superbroswar:
- superbroswar
swanstation:
- psx
tgbdual:
- gb2players
- gbc2players
theodore:
- thomson
tic80:
- tic80
tyrquake:
- quake
uae4arm:
- amiga1200
- amiga500
- amigacd32
- amigacdtv
uzem:
- uzebox
vb:
- virtualboy
vba-m:
- gb
- gba
- gbc
vecx:
- vectrex
vemulator:
- vemulator
vice_x128:
- c128
vice_x64:
- c64
vice_x64sc:
- c64
vice_xpet:
- pet
vice_xplus4:
- cplus4
vice_xscpu64:
- c64
vice_xvic:
- c20
vircon32:
- vircon32
virtualjaguar:
- jaguar
- jaguarcd
vitaquake2:
- quake2
wasm4:
- wasm4
x1:
- x1
xrick:
- xrick
yabasanshiro:
- saturn
zc210:
- zc210
+425
View File
@@ -3409,6 +3409,431 @@ systems:
mandatory_declared: true
native_name: ST-V
native_id: stv
libretro_systems:
"2048":
- "2048"
"81":
- zx81
a5200:
- atari5200
amiberry:
- amiga1200
- amiga600
- amigacd32
- amigacdtv
applewin:
- apple2
arduous:
- arduboy
atari800:
- atari5200
- atari800
b2:
- bbcmicro
bk:
- bk
bluemsx:
- colecovision
- msx1
- msx2
- msxturbor
- multivision
- sg1000
- spectravideo
boom3:
- doom3
bsnes:
- gb
- gbc
- satellaview
- snes
bsneshd:
- satellaview
- snes
cannonball:
- outrun
cap32:
- amstradcpc
- gx4000
cdi2015:
- cdi
craft:
- minecraft
crocods:
- amstradcpc
desmume:
- nds
dice:
- dice
dinothawr:
- dinothawr
dirksimple:
- daphne
dolphin:
- gamecube
- wii
dosbox_pure:
- dos
easyrpg:
- easyrpg
ecwolf:
- wolfenstein3d
eightyone:
- zx81
- zxspectrum
emuscv:
- scv
exel-hence:
- exl100
fake08:
- pico8
fbneo:
- channelf
- colecovision
- fbneo
- fds
- gamegear
- mastersystem
- megadrive
- msx1
- neogeo
- neogeocd
- nes
- ngp
- pcengine
- sg1000
- supergrafx
- zxspectrum
fceumm:
- fds
- nes
flycast:
- 240ptestsuite
- atomiswave
- dreamcast
- naomi
- naomigd
flycast-next:
- atomiswave
- dreamcast
- naomi
- naomi2
- naomigd
fmsx:
- msx1
- msx2
freechaf:
- channelf
freeintv:
- intellivision
fuse:
- zxspectrum
gambatte:
- 240ptestsuite
- gb
- gbc
gearcoleco:
- colecovision
geargrafx:
- pcengine
- pcenginecd
- supergrafx
gearsystem:
- gamegear
- mastersystem
- multivision
- sg1000
genesisplusgx:
- 240ptestsuite
- gamegear
- mastersystem
- megadrive
- segacd
- sg1000
genesisplusgx_ex:
- megadrive
genesisplusgxwide:
- megadrive
geolith:
- neogeo
- neogeocd
gong:
- gong
gpsp:
- gba
gw:
- gw
handy:
- lynx
hatari:
- atarist
hatarib:
- atarist
holani:
- lynx
hypseus_singe:
- daphne
imageviewer:
- imageviewer
kronos:
- saturn
- stv
lowresnx:
- lowresnx
lutro:
- lutro
m2000:
- p2000t
mame0258:
- mame
mame0278:
- mame
mame2000:
- mame
- neogeo
mame2003:
- mame
- neogeo
mame2003_plus:
- mame
- neogeo
mame2010:
- mame
- neogeo
mame2015:
- mame
- neogeo
mame2016:
- neogeo
mednafen_lynx:
- lynx
mednafen_ngp:
- ngp
- ngpc
mednafen_pce_fast:
- pcengine
- pcenginecd
mednafen_pcfx:
- pcfx
mednafen_psx:
- psx
mednafen_psx_hw:
- psx
mednafen_saturn:
- saturn
mednafen_stv:
- stv
mednafen_supafaust:
- snes
mednafen_supergrafx:
- 240ptestsuite
- pcengine
- pcenginecd
- supergrafx
mednafen_vb:
- virtualboy
mednafen_wswan:
- pcv2
- wswan
- wswanc
melonds:
- nds
mesen:
- fds
- nes
mesen_s:
- gb
- gbc
- satellaview
- snes
meteor:
- gba
mgba:
- 240ptestsuite
- gb
- gba
- gbc
minivmac:
- macintosh
mojozork:
- zmachine
mrboom:
- mrboom
mu:
- palm
mupen64plus:
- n64
mupen64plus_next:
- 64dd
- n64
neocd:
- neogeocd
nestopia:
- 240ptestsuite
- fds
- nes
np2kai:
- pc98
nxengine:
- cavestory
o2em:
- o2em
- videopacplus
opera:
- 3do
parallel_n64:
- 64dd
- n64
pcsx2:
- ps2
pcsx_rearmed:
- psx
pd777:
- cassettevision
picodrive:
- gamegear
- mastersystem
- megadrive
- pico
- sega32x
- segacd
- sg1000
pokemini:
- pokemini
potator:
- supervision
ppsspp:
- psp
prboom:
- doom
prosystem:
- atari7800
ps2:
- ps2
puae:
- amiga1200
- amiga600
- amigacd32
- amigacdtv
puae2021:
- amiga1200
- amiga600
- amigacd32
- amigacdtv
px68k:
- x68000
quasi88:
- pc88
quicknes:
- nes
race:
- ngp
- ngpc
rb5000:
- vg5000
reminiscence:
- flashback
retro8:
- pico8
retrodream:
- dreamcast
same_cdi:
- cdi
sameboy:
- gb
- gbc
sameduck:
- megaduck
scummvm:
- scummvm
snes9x:
- 240ptestsuite
- satellaview
- snes
- sufami
snes9x2002:
- snes
snes9x2005:
- snes
snes9x2010:
- snes
stella:
- atari2600
stella2014:
- atari2600
stonesoup:
- dungeoncrawlstonesoup
sugarbox2:
- amstradcpc
- gx4000
swanstation:
- 240ptestsuite
- psx
tamalibretro:
- tamagotchi
tgbdual:
- gb
- gbc
theodore:
- thomson
thepowdertoy:
- thepowdertoy
tic80:
- tic80
tyrquake:
- quake
uae4all:
- amiga600
uae4arm:
- amiga1200
- amiga600
- amigacd32
- amigacdtv
uzem:
- uzebox
vecx:
- vectrex
vice_x128:
- c64
vice_x64:
- c64
vice_x64sc:
- c64
vice_xcbm2:
- c64
vice_xcbm5x0:
- c64
vice_xpet:
- c64
vice_xplus4:
- c64
vice_xscpu64:
- c64
vice_xvic:
- c64
- vic20
vircon32:
- vircon32
virtualjaguar:
- jaguar
vitaquake2:
- quake2
vitaquake3:
- quake3
vitavoyager:
- startrekvoyager
wasm4:
- wasm4
x1:
- x1
xrick:
- rickdangerous
yabasanshiro:
- saturn
yabause:
- saturn
ymir:
- saturn
launchers:
- emulator: hatari
build: standalone
+472
View File
@@ -3047,6 +3047,478 @@ systems:
native_path: bios/mame/hash/xegs.xml
native_name: Atari XEGS
name: Atari XEGS
libretro_systems:
"81":
- zx81
DoubleCherryGB:
- gb
- gb2players
- gbc
- gbc2players
a5200:
- atari5200
amiarcadia:
- arcadia
- vc4000
amiberry:
- amiga1200
- amiga4000
- amiga500
- amigacd32
- amigacdtv
applewin:
- apple2
ardens:
- arduboy
arduous:
- arduboy
atari800:
- atari5200
- atari800
azahar:
- 3ds
b2:
- bbcmicro
bennugd:
- bennugd
bk:
- bk
bluemsx:
- colecovision
- msx1
- msx2
- msx2+
- msxturbor
- spectravideo
boom3:
- doom3
boom3_xp:
- doom3
bsnes:
- gb
- sgb-msu1
- snes
- snes-msu1
- sufami
bsnes-jg:
- snes
bsnes_hd_beta:
- sgb-msu1
- snes
- snes-msu1
cannonball:
- cannonball
cap32:
- amstradcpc
- gx4000
crocods:
- amstradcpc
desmume:
- nds
desmume2015:
- nds
dice:
- dice
dinothawr:
- dinothawr
dolphin:
- gamecube
- triforce
- wii
dosbox_pure:
- dos
doukutsu_rs:
- cavestory
easyrpg:
- easyrpg
ecwolf:
- ecwolf
emuscv:
- scv
ep128emu_core:
- enterprise
fake08:
- pico8
fbalpha:
- cave
- cps1
- cps2
- cps3
- fbneo
- neogeo
fbalpha2012:
- cave
- cps1
- cps2
- cps3
- fbneo
fbalpha2012_cps1:
- cps1
fbalpha2012_cps2:
- cps2
fbalpha2012_cps3:
- cps3
fbalpha2012_neogeo:
- fbneo
- neogeo
fbneo:
- cave
- colecovision
- cps1
- cps2
- cps3
- fbneo
- gamegear
- mastersystem
- megadrive
- msx1
- msx2
- msx2+
- msxturbor
- neogeo
- neogeocd
- pcengine
- pcenginecd
- supergrafx
- zx81
- zxspectrum
fceumm:
- fds
- nes
flycast:
- atomiswave
- dreamcast
- naomi
- naomi2
freechaf:
- channelf
freeintv:
- intellivision
freej2me:
- j2me
frodo:
- c64
fuse:
- zx81
- zxspectrum
gambatte:
- gb
- gbc
gearcoleco:
- adam
- colecovision
geargrafx:
- supergrafx
gearsystem:
- gamegear
- mastersystem
- multivision
- sg1000
genesis_plus_gx:
- gamegear
- mastersystem
- megacd
- megadrive
- megadrive-msu
- sg1000
genesis_plus_gx_expanded:
- megadrive-msu
genesis_plus_gx_wide:
- megacd
- megadrive
- megadrive-msu
geolith:
- neogeo
gpsp:
- gba
gw:
- gw
- lcdgames
handy:
- lynx
hatari:
- atarist
hatarib:
- atarist
holani:
- lynx
imageviewer:
- screenshots
jollycv:
- colecovision
- crvision
kronos:
- saturn
- segastv
lowresnx:
- lowresnx
lutro:
- lutro
m2000:
- p2000t
mame:
- adam
- advision
- apfm1000
- apple2
- apple2gs
- aquarius
- arcadia
- archimedes
- astrocade
- atom
- bbcmicro
- camplynx
- casloopy
- cave
- cdi
- coco
- crvision
- electron
- fm7
- fmtowns
- gaelco
- gamate
- gamecom
- gamepock
- gmaster
- gp32
- gw
- hbmame
- lcdgames
- mame
- megaduck
- model2
- neogeo64
- odyssey2
- oricatmos
- pegasus
- pv1000
- scv
- segastv
- supracan
- ti99
- tutor
- tvgames
- vc4000
- vg5k
- vsmile
- xegs
- zinc
mame2000:
- mame
mame2003:
- mame
- segastv
mame2003_midway:
- mame
mame2003_plus:
- cave
- mame
- segastv
mame2010:
- mame
- segastv
mame2014:
- gaelco
- mame
- segastv
mame2016:
- cave
- gaelco
- mame
- neogeo64
- segastv
mednafen_gba:
- gba
mednafen_lynx:
- lynx
mednafen_ngp:
- ngp
- ngpc
mednafen_pce:
- pcengine
- pcenginecd
mednafen_pce_fast:
- pcengine
- pcenginecd
mednafen_pcfx:
- pcfx
mednafen_psx_hw:
- psx
mednafen_saturn:
- saturn
mednafen_snes:
- snes
mednafen_supergrafx:
- supergrafx
mednafen_vb:
- virtualboy
mednafen_wswan:
- wswan
- wswanc
melonds:
- nds
melondsds:
- nds
mesen:
- fds
- nes
mesen-s:
- gb
- satellaview
- sgb
- snes
- snes-msu1
mgba:
- gba
- sgb
mupen64plus_next:
- n64
- n64dd
nekop2:
- pc98
neocd:
- neogeocd
nestopia:
- fds
- nes
noods:
- nds
np2kai:
- pc98
nxengine:
- cavestory
o2em:
- odyssey2
openlara:
- openlara
opera:
- 3do
parallel_n64:
- n64
- n64dd
pcsx2:
- ps2
pcsx_rearmed:
- psx
pd777:
- cassettevision
picodrive:
- gamegear
- mastersystem
- megacd
- megadrive
- sega32x
pocketcdg:
- karaoke
pokemini:
- pokemini
potator:
- supervision
ppsspp:
- psp
prboom:
- doom
prosystem:
- atari7800
puae:
- amiga1200
- amiga4000
- amiga500
- amigacd32
- amigacdtv
px68k:
- x68000
quasi88:
- pc88
race:
- ngp
- ngpc
reminiscence:
- reminiscence
retro8:
- pico8
same_cdi:
- cdi
sameboy:
- gb
- gb2players
- gbc
- gbc2players
sameduck:
- megaduck
scummvm:
- scummvm
snes9x:
- satellaview
- snes
- snes-msu1
- sufami
snes9x2005:
- snes
stella:
- atari2600
stella2014:
- atari2600
- atari5200
superbroswar:
- superbroswar
supermodel:
- model3
swanstation:
- psx
tgbdual:
- gb
- gb2players
- gbc
- gbc2players
theodore:
- thomson
tic80:
- tic80
tyrquake:
- quake
uzem:
- uzebox
vecx:
- vectrex
vice_x128:
- c128
vice_x64:
- c64
vice_x64sc:
- c64
vice_xpet:
- pet
vice_xplus4:
- c16
- cplus4
vice_xvic:
- c20
vircon32:
- vircon32
virtualjaguar:
- jaguar
- jaguarcd
vitaquake2:
- quake2
vitaquake2-rogue:
- quake2
vitaquake2-xatrix:
- quake2
vitaquake2-zaero:
- quake2
wasm4:
- wasm4
x1:
- x1
yabasanshiro:
- saturn
ymir:
- saturn
zc255:
- zeldaclassic
launchers:
- emulator: amiberry
build: standalone
+635
View File
@@ -16040,6 +16040,641 @@ systems:
native_system: coco
component: xroar
description: Generic disk ROM
libretro_systems:
"81":
- zx81
DoubleCherryGB:
- gb
- gbc
a5200:
- atari5200
amiarcadia:
- arcadia
amiberry:
- amiga
- amiga1200
- amiga600
- amigacd32
- cdtv
applewin:
- apple2
ardens:
- arduboy
arduous:
- arduboy
atari800:
- atari5200
- atari800
- atarixe
azahar:
- n3ds
b2:
- bbcmicro
blastem:
- colecovision
- gamegear
- genesis
- mark3
- mastersystem
- megacd
- megacdjp
- megadrive
- megadrivejp
- sega32x
- sega32xjp
- sega32xna
- segacd
- sg-1000
bluemsx:
- colecovision
- msx
- msx1
- msx2
- msxturbor
- sg-1000
- spectravideo
boom3:
- doom
boom3_xp:
- doom
bsnes:
- gb
- gbc
- satellaview
- sfc
- snes
- snesna
- sufami
bsnes-jg:
- satellaview
- sfc
- snes
- snesna
- sufami
bsnes_hd_beta:
- satellaview
- sfc
- snes
- snesna
- sufami
bsnes_mercury_accuracy:
- satellaview
- sfc
- snes
- snesna
- sufami
cannonball:
- ports
cap32:
- amstradcpc
- gx4000
cdi2015:
- cdimono1
cemu:
- wiiu
chailove:
- chailove
citra:
- n3ds
citra2018:
- n3ds
clownmdemu:
- megacd
- megacdjp
- segacd
craft:
- ports
crocods:
- amstradcpc
- gx4000
desmume:
- nds
desmume2015:
- nds
dice:
- arcade
- mame
dirksimple:
- daphne
- laserdisc
dolphin:
- gc
- wii
dosbox_core:
- dos
- pc
dosbox_pure:
- dos
- pc
- windows3x
- windows9x
dosbox_svn:
- dos
- pc
easyrpg:
- easyrpg
ecwolf:
- ports
fbalpha2012:
- arcade
- cps
- cps1
- cps2
- cps3
- fba
- mame
fbalpha2012_cps1:
- cps
- cps1
- fba
fbalpha2012_cps2:
- cps
- cps2
- fba
fbalpha2012_cps3:
- cps
- cps3
- fba
fbalpha2012_neogeo:
- fba
fbneo:
- arcade
- cps
- cps1
- cps2
- cps3
- fbneo
- mame
- neogeo
- neogeocd
- neogeocdjp
fceumm:
- famicom
- fds
- nes
flycast:
- arcade
- atomiswave
- consolearcade
- dreamcast
- mame
- naomi
- naomi2
- naomigd
fmsx:
- msx
- msx1
- msx2
freechaf:
- channelf
freeintv:
- intellivision
frodo:
- c64
fsuae:
- amiga
- amiga1200
- amiga600
fuse:
- zxspectrum
gambatte:
- gb
- gbc
gearboy:
- gb
- gbc
gearcoleco:
- colecovision
geargrafx:
- pcengine
- pcenginecd
- supergrafx
- tg-cd
- tg16
gearsystem:
- gamegear
- mark3
- mastersystem
- multivision
- sg-1000
genesis-plus-gx-expanded-rom-size-paprium:
- megadrive
- megadrivejp
genesis_plus_gx:
- gamegear
- genesis
- mark3
- mastersystem
- megacd
- megacdjp
- megadrive
- megadrivejp
- segacd
- sg-1000
genesis_plus_gx_wide:
- gamegear
- genesis
- mark3
- mastersystem
- megacd
- megacdjp
- megadrive
- megadrivejp
- segacd
- sg-1000
geolith:
- arcade
- mame
- neogeo
- neogeocd
- neogeocdjp
gpsp:
- gba
gw:
- gameandwatch
- lcdgames
handy:
- atarilynx
hatari:
- atarist
hatari2014:
- atarist
hbmame:
- arcade
- mame
holani:
- atarilynx
irogb:
- gb
- gbc
jollycv:
- colecovision
- crvision
kronos:
- arcade
- consolearcade
- mame
- saturn
- saturnjp
- stv
lowresnx:
- lowresnx
lutro:
- lutro
mame:
- apple2
- apple2gs
- arcade
- arcadia
- astrocde
- atari7800
- channelf
- consolearcade
- cps
- cps1
- cps2
- cps3
- crvision
- daphne
- fmtowns
- gamate
- gameandwatch
- gamecom
- gmaster
- intellivision
- laserdisc
- lcdgames
- mame
- megaduck
- model2
- neogeo
- odyssey2
- pv1000
- scv
- stv
- supervision
- supracan
- vectrex
- videopac
- vsmile
mame2000:
- arcade
- cps
- cps1
- cps2
- cps3
- mame
mame2003:
- arcade
- cps
- cps1
- cps2
- cps3
- mame
mame2003_plus:
- arcade
- cps
- cps1
- cps2
- cps3
- mame
mame2010:
- arcade
- cps
- cps1
- cps2
- cps3
- mame
mednafen_lynx:
- atarilynx
mednafen_ngp:
- ngp
- ngpc
mednafen_pce:
- pcengine
- pcenginecd
- supergrafx
- tg-cd
- tg16
mednafen_pce_fast:
- pcengine
- pcenginecd
- tg-cd
- tg16
mednafen_pcfx:
- pcfx
mednafen_psx:
- psx
mednafen_psx_hw:
- psx
mednafen_saturn:
- saturn
- saturnjp
mednafen_supafaust:
- sfc
- snes
- snesna
mednafen_supergrafx:
- pcengine
- pcenginecd
- supergrafx
- tg-cd
- tg16
mednafen_vb:
- virtualboy
mednafen_wswan:
- wonderswan
- wonderswancolor
melonds:
- nds
melondsds:
- nds
mesen:
- famicom
- fds
- nes
mesen-s:
- gb
- gbc
- satellaview
- sfc
- sgb
- snes
- snesna
mesen2:
- famicom
- fds
- gamegear
- gb
- gba
- gbc
- mark3
- mastersystem
- nes
- pcengine
- pcenginecd
- satellaview
- sfc
- sgb
- snes
- snesna
- supergrafx
- tg-cd
- tg16
- wonderswan
- wonderswancolor
mess2015:
- mess
mgba:
- gb
- gba
- gbc
- sgb
mojozork:
- zmachine
mrboom:
- ports
mu:
- palm
mupen64plus_next:
- n64
- n64dd
nekop2:
- pc98
neocd:
- neogeocd
- neogeocdjp
nestopia:
- famicom
- fds
- nes
noods:
- gba
np2kai:
- pc98
nxengine:
- ports
o2em:
- odyssey2
- videopac
openlara:
- ports
opera:
- 3do
panda3ds:
- n3ds
parallel_n64:
- n64
- n64dd
pcee2:
- ps2
pcsx2:
- ps2
pcsx_rearmed:
- psx
picodrive:
- gamegear
- genesis
- mark3
- mastersystem
- megacd
- megacdjp
- megadrive
- megadrivejp
- sega32x
- sega32xjp
- sega32xna
- segacd
pokemini:
- pokemini
potator:
- supervision
ppsspp:
- psp
prboom:
- doom
prosystem:
- atari7800
puae:
- amiga
- amiga1200
- amiga600
- amigacd32
- cdtv
puae2021:
- amiga
- amiga1200
- amiga600
- amigacd32
- cdtv
px68k:
- x68000
quasi88:
- pc88
quicknes:
- famicom
- nes
race:
- ngp
- ngpc
retro8:
- pico8
rustynes:
- famicom
- fds
- nes
same_cdi:
- cdimono1
sameboy:
- gb
- gbc
- sgb
sameduck:
- megaduck
scummvm:
- scummvm
skyemu:
- gb
- gba
- gbc
smsplus:
- gamegear
- mark3
- mastersystem
snes9x:
- satellaview
- sfc
- snes
- snesna
- sufami
snes9x2005_plus:
- satellaview
- sfc
- snes
- snesna
- sufami
snes9x2010:
- satellaview
- sfc
- snes
- snesna
- sufami
squirreljme:
- j2me
stella:
- atari2600
stella2014:
- atari2600
stella2023:
- atari2600
superbroswar:
- ports
supermodel:
- arcade
- mame
swanstation:
- psx
tgbdual:
- gb
- gbc
theodore:
- moto
- to8
tia:
- atari2600
tic80:
- tic80
tyrquake:
- quake
uzem:
- uzebox
vba_next:
- gba
vbam:
- gb
- gba
- gbc
vecx:
- vectrex
vice_x128:
- c64
vice_x64:
- c64
vice_x64sc:
- c64
vice_xplus4:
- plus4
vice_xscpu64:
- c64
vice_xvic:
- vic20
vircon32:
- vircon32
virtualjaguar:
- atarijaguar
virtualxt:
- dos
- pc
vitaquake2:
- quake
vitaquake2-rogue:
- quake
vitaquake2-xatrix:
- quake
vitaquake2-zaero:
- quake
vitaquake3:
- quake
wasm4:
- wasm4
x1:
- x1
yabasanshiro:
- saturn
- saturnjp
yabause:
- saturn
- saturnjp
launchers:
- emulator: cemu
build: standalone
+7 -2
View File
@@ -177,7 +177,8 @@
"no_platform_slug",
"below_platform_folder",
"no_save_directory",
"no_core_folder"
"no_core_folder",
"no_save_system"
]
},
"category": {
@@ -431,10 +432,14 @@
"properties": {
"folder": {
"type": "string",
"pattern": "^[^/\\\\.][^/\\\\]*$"
"pattern": "^[^/\\\\.][^/\\\\]*(/[^/\\\\.][^/\\\\]*)*$"
},
"by_core": {
"type": "boolean"
},
"by_system": {
"description": "true when the platform's launcher hands each core <save directory>/<system> at each launch (Batocera, RetroBat). Each dest then starts with that system's folder, and no frontend config read at install time changes it.",
"const": true
}
}
}
+14
View File
@@ -53,6 +53,20 @@
"uniqueItems": true,
"description": "Emulators of standalone_cores the platform also launches as a libretro core: both layouts get their files"
},
"libretro_systems": {
"type": "object",
"description": "libretro core name -> the systems the platform's system list offers it for, as the launcher names them. A launcher handing each core <save directory>/<system> (save_directory.by_system in the registry) places a file the core reads below its save directory once in each of these folders",
"additionalProperties": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string",
"minLength": 1,
"pattern": "^[^/\\\\]+$"
}
}
},
"core_system_dirs": {
"type": "object",
"description": "The libretro system directory the platform hands each core, keyed by that directory relative to the pack root. A platform that declares it gives a core no other directory: the core's files are placed below each directory listed for it, and a core listed nowhere gets none (MinUI hands each launch tag its own Bios/<TAG>/)",
+14 -21
View File
@@ -12,7 +12,7 @@ and 3-tier storage (embedded/external/user_provided).
from __future__ import annotations
from collections.abc import Callable, Iterable, Iterator
from collections.abc import Callable, Iterator
from artifacts import _build_timestamp, set_plain_mode
import argparse
@@ -1191,7 +1191,14 @@ 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 ""),
save_layout(config).folder, base_dest,
) if save_count else ""
),
save_by_system=bool(save_count and save_layout(config).by_system),
)
_write_generated_member(zf, "README.txt", readme_text)
@@ -3975,24 +3982,6 @@ def _manifest_core_entries(
return total_size
def _check_save_destinations(files: list[dict], omitted: Iterable[dict]) -> None:
"""Refuse a manifest naming one destination below both directories.
The installer keys every entry by its ``dest``: a file read below the
save directory and one of the BIOS tree written alike would be taken
for one file.
"""
roots: dict[str, set[bool]] = {}
for entry in [*files, *omitted]:
roots.setdefault(entry["dest"], set()).add(entry.get("root") == "save")
clashes = sorted(dest for dest, kinds in roots.items() if len(kinds) > 1)
if clashes:
raise ValueError(
"destinations below both the system and save directories: "
+ ", ".join(clashes[:10])
)
def _manifest_dest_of(full_dest: str, base_dest: str) -> str:
"""A pack destination as the manifest writes it, below base_destination."""
if base_dest and full_dest.startswith(f"{base_dest}/"):
@@ -4598,9 +4587,12 @@ def generate_manifest(
result["data_directories"] = data_directories
saved = [entry for entry in manifest_files if entry.get("root") == "save"]
if saved:
_check_save_destinations(manifest_files, omitted_by_destination.values())
layout = save_layout(config)
result["save_directory"] = {"folder": layout.folder, "by_core": layout.by_core}
if layout.by_system:
# The launcher writes the directory at each launch, one folder
# per system: each dest starts with that folder.
result["save_directory"]["by_system"] = True
if case_insensitive and fold_case is None and any(
d.get("os") not in CASE_FOLDING_OS for d in detect
):
@@ -5061,6 +5053,7 @@ from packextras import ( # noqa: E402,F401
from packreadme import ( # noqa: E402,F401
_build_readme,
_build_agnostic_rename_readme,
save_place,
)
from packverify import ( # noqa: E402,F401
_check_member_hash,
+132 -56
View File
@@ -20,7 +20,7 @@ from common import standalone_set as platform_standalone_set
from common import sanitize_pack_path
from common import size_fits
from validation import deliverable, read_from_save_dir, read_from_system_dir
from packpaths import save_destination, save_layout
from packpaths import libretro_systems, save_destination, save_layout
from region import FILE_GROUP
@@ -67,15 +67,16 @@ def save_entry_fields(fe: dict) -> dict:
def save_manifest_dest(fe: dict) -> str:
"""A manifest dest for a file read below the save directory.
The pack path below the platform's save folder when the file is placed,
the core's own folder first where the frontend sorts saves by core.
The pack path below the platform's save folder when the file is placed
(``save_dest``), the system's folder first where the launcher keeps one
per system, the core's own folder first where the frontend sorts saves
by core.
Without a save folder (an omission), the same shape: the core's folder,
then the path the core reads, so two cores reading one name below their
own folders stay two entries.
"""
pack_path = str(fe.get("pack_path") or "")
if pack_path:
return pack_path.split("/", 1)[1]
if fe.get("save_dest"):
return str(fe["save_dest"])
rel = sanitize_pack_path(fe.get("destination") or fe.get("path") or fe.get("name", ""))
folder = fe.get("core_folder")
return f"{folder}/{rel}" if folder else rel
@@ -324,6 +325,7 @@ def hidden_extras(
lower = set(content) if case_insensitive else set()
prefix = _detect_extras_prefix(config, base_dest)
hidden: dict[tuple[str, str, str], str] = {}
packed_keys: set[tuple[str, str, str]] = set()
extras = _collect_emulator_extras(
config, emulators_dir, db, set() if system_ids else set(shipped),
base_dest, profiles, target_cores=target_cores, include_all=include_all,
@@ -356,13 +358,14 @@ def hidden_extras(
held = (sha1_by_path.get(local) or _file_sha1(local)) if local else None
if reason == "case_twin" and held and content.get(full.lower()) == held:
continue
key = (
fe.get("source_emulator", ""), fe.get("source_name", ""),
fe.get("source_path", ""),
)
if reason is not None:
key = (
fe.get("source_emulator", ""), fe.get("source_name", ""),
fe.get("source_path", ""),
)
hidden.setdefault(key, reason)
continue
packed_keys.add(key)
_register_path(full, seen, parents)
content[full.lower()] = held
if case_insensitive:
@@ -373,7 +376,9 @@ def hidden_extras(
placed_kind[full] = fe.get("category", "bios")
if placed_local is not None and local:
placed_local[full] = local
return hidden
# A file read below a save directory kept per system is packed once per
# system: one copy left out does not leave the file out.
return {key: reason for key, reason in hidden.items() if key not in packed_keys}
def _extra_dest(u: dict) -> str:
@@ -407,7 +412,7 @@ def unplaceable_extras(
if not placement.slug_based and u.get("root") != "save":
continue
dest = _extra_dest(u)
if placement.place(u, dest) is None:
if not placement.places(u, dest):
key = (u.get("emulator", ""), u.get("name", ""), u.get("path") or "")
unplaced[key] = placement.unplaced_reason(u, dest)
return unplaced
@@ -893,6 +898,7 @@ class ExtraPlacement:
self.native_systems = native_slug_systems(config)
self.flat = bool(config.get("firmware_folder_flat"))
self.save = save_layout(config)
self.config = config
self.norm_map = (
{_norm_system_id(sid): sid for sid in self.platform_systems}
if self.slug_based
@@ -911,10 +917,8 @@ class ExtraPlacement:
platform keeping saves beside the content does not have.
"""
if entry.get("root") == "save":
if self.save is None:
return None
full = save_destination(dest, entry.get("core_folder"), self.save)
return (dest, full) if full else None
placed = self.save_places(entry, dest)
return placed[0] if placed else None
if self.slug_based:
slug = _slug_for(
entry, self.profiles, self.platform_systems, self.norm_map,
@@ -925,6 +929,43 @@ class ExtraPlacement:
dest = f"{slug}/{dest}"
return dest, (f"{self.prefix}/{dest}" if self.prefix else dest)
def places(self, entry: dict, dest: str) -> list[tuple[str, str]]:
"""Every (pack-relative, full) destination the pack gives an entry.
One for most entries. A file read below the save directory of a
platform that hands each system a save folder of its own goes once
below each system that runs the core.
"""
if entry.get("root") == "save":
return self.save_places(entry, dest)
placed = self.place(entry, dest)
return [placed] if placed is not None else []
def save_places(self, entry: dict, dest: str) -> list[tuple[str, str]]:
"""The destinations of a file read below the save directory."""
if self.save is None:
return []
names = self.core_names(entry)
sorted_by_core = self.save.sorts(names)
systems = libretro_systems(self.config, names) if self.save.by_system else [""]
placed = []
for system in systems:
full = save_destination(
dest, entry.get("core_folder"), self.save, system, sorted_by_core
)
if full:
placed.append((dest, full))
return placed
def core_names(self, entry: dict) -> set[str]:
"""The names a report entry's core goes by: its profile key and the
upstream names its profile lists."""
key = entry.get("profile") or entry.get("emulator", "")
profile = self.profiles.get(key) or next(
(pp for pp in self.profiles.values() if pp.get("emulator") == key), {}
)
return {str(key), *(str(c) for c in profile.get("cores") or [])} - {""}
def nested(self, dest: str) -> bool:
"""True when the file would sit below a folder the frontend lists flat."""
return self.slug_based and self.flat and "/" in dest
@@ -932,7 +973,13 @@ class ExtraPlacement:
def unplaced_reason(self, entry: dict, dest: str) -> str:
"""Why ``place`` returned None for this entry."""
if entry.get("root") == "save":
return "no_save_directory" if self.save is None else "no_core_folder"
if self.save is None:
return "no_save_directory"
if self.save.by_system and not libretro_systems(
self.config, self.core_names(entry)
):
return "no_save_system"
return "no_core_folder"
return "below_platform_folder" if self.nested(dest) else "no_platform_slug"
@@ -1053,49 +1100,51 @@ def _collect_emulator_extras(
name = archive if archive else u["name"]
dest = _extra_dest(u)
# Slug-based platforms: prefix dest with system slug
placed = placement.place(u, dest)
# Slug-based platforms: prefix dest with system slug. A file read
# below a save directory kept per system goes below each system.
placements = placement.places(u, dest)
save_root = u.get("root") == "save"
if not u["in_repo"]:
if placed is not None:
for placed in placements:
missing = _report_extra(u, name, placed[0])
if u.get("root") == "save":
missing["pack_path"] = placed[1]
if save_root:
_save_fields(missing, placed[1], placement)
absent.append(missing)
continue
if placed is None:
if not placements:
if unplaceable is not None:
reason = placement.unplaced_reason(u, dest)
unplaceable.append(
u if reason == "no_platform_slug" else {**u, "unplaceable": reason}
)
continue
dest, full_dest = placed
if claimants is not None:
claimants[(u.get("emulator", ""), u.get("name", ""), u.get("path") or "")] = (
sanitize_pack_path(dest)
sanitize_pack_path(placements[0][0])
)
candidates = [
_report_extra(c, name, dest) for c in (u, *u.get("other_claims", []))
]
if u.get("root") == "save":
for dest, full_dest in placements:
candidates = [
_report_extra(c, name, dest) for c in (u, *u.get("other_claims", []))
]
if save_root:
for item in candidates:
_save_fields(item, full_dest, placement)
# Where the builder meets each claim: the strongest proof first, the
# report's profile order between equals, archives after loose files.
for item in candidates:
item["pack_path"] = full_dest
# Where the builder meets each claim: the strongest proof first, the
# report's profile order between equals, archives after loose files.
for item in candidates:
item["claim_order"] = (
1, 1 if u.get("archive") else 0, -rank.of_extra(item, full_dest),
item["source_profile"],
)
candidates.sort(key=lambda item: item["claim_order"])
extra, claims = candidates[0], candidates[1:]
if not _take(extra, full_dest, seen_dests, taken):
item["claim_order"] = (
1, 1 if u.get("archive") else 0, -rank.of_extra(item, full_dest),
item["source_profile"],
)
candidates.sort(key=lambda item: item["claim_order"])
extra, claims = candidates[0], candidates[1:]
if not _take(extra, full_dest, seen_dests, taken):
for claim in claims:
_another_claim(taken.get(full_dest), claim)
continue
for claim in claims:
_another_claim(taken.get(full_dest), claim)
continue
for claim in claims:
_another_claim(extra, claim)
extras.append(extra)
_another_claim(extra, claim)
extras.append(extra)
# Second pass: find alternative destinations for files already in the pack.
# A file declared by the platform or emitted above may also be needed at a
@@ -1234,20 +1283,29 @@ class _ClaimRanks:
self._db = db
# Two spellings of one path are one file where the filesystem folds case.
self._key = (lambda dest: dest.lower()) if fold else (lambda dest: dest)
self._placed: dict[int, tuple[str, str] | None] = {}
# An entry can take several destinations: one per system folder of a
# save directory kept per system.
self._placed: dict[int, list[tuple[str, str]]] = {}
counts: dict[str, int] = {}
for u in undeclared:
placed = (
placement.place(u, _extra_dest(u))
if u.get("in_repo") and not u.get("bundled") else None
placement.places(u, _extra_dest(u))
if u.get("in_repo") and not u.get("bundled") else []
)
self._placed[id(u)] = placed
if placed is not None:
key = self._key(placed[1])
for _dest, full in placed:
key = self._key(full)
counts[key] = counts.get(key, 0) + 1 + len(u.get("other_claims", []))
self._contested = {dest for dest, n in counts.items() if n > 1}
self._cache: dict[tuple, int] = {}
def _contests(self, u: dict) -> list[tuple[str, str]]:
"""The entry's destinations another claim also asks for."""
return [
placed for placed in self._placed.get(id(u), [])
if self._key(placed[1]) in self._contested
]
def of_extra(self, extra: dict, full_dest: str) -> int:
if self._key(full_dest) not in self._contested:
return 0
@@ -1275,22 +1333,23 @@ class _ClaimRanks:
first: dict[str, int] = {}
keys: list[tuple[int, int, int]] = []
for position, u in enumerate(undeclared):
placed = self._placed.get(id(u))
if placed is None or self._key(placed[1]) not in self._contested:
contests = self._contests(u)
if not contests:
keys.append((position, 0, position))
continue
group = first.setdefault(self._key(placed[1]), position)
group = first.setdefault(self._key(contests[0][1]), position)
keys.append((group, -self.of_entry(u), position))
order = sorted(range(len(undeclared)), key=keys.__getitem__)
return [undeclared[i] for i in order]
def of_entry(self, u: dict) -> int:
placed = self._placed.get(id(u))
if placed is None or self._key(placed[1]) not in self._contested:
contests = self._contests(u)
if not contests:
return 0
name = u.get("archive") or u["name"]
return max(
self.of_extra(_report_extra(c, name, placed[0]), placed[1])
self.of_extra(_report_extra(c, name, dest), full)
for dest, full in contests
for c in (u, *u.get("other_claims", []))
)
@@ -1300,6 +1359,23 @@ def _names_content(entry: dict) -> bool:
return any(entry.get(field) for field in ("sha1", "md5", "sha256", "crc32"))
def _save_fields(extra: dict, pack_path: str, placement: ExtraPlacement) -> None:
"""Record where a file read below the save directory goes in the pack.
``core_folder`` stays only where the frontend sorts saves by core for
every core, the one setting a frontend config can turn off and the
installer then reads (RetroArch's sort_savefiles_enable). A launcher
writing the save directory at each launch fixes the path the pack
already spells out.
"""
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.in_pack) + 1:]
if not placement.save.by_core:
extra.pop("core_folder", None)
def _report_extra(u: dict, name: str, dest: str) -> dict:
"""The extra a cross-reference entry asks for at its destination."""
extra = {
+73 -15
View File
@@ -6,6 +6,7 @@ on Windows is not a pack."""
from __future__ import annotations
from collections.abc import Iterable
from dataclasses import dataclass
from common import sanitize_pack_path
@@ -17,36 +18,69 @@ class SaveLayout:
"""Where a platform's frontend keeps the save directory it hands a core.
``folder`` names it twice: the folder of the pack that holds the files
read below it, and its default place beside the system directory
(RetroArch's own folder holds system/ and saves/). A pack is extracted
into the system directory, so that folder is moved by hand, and the
installer writes to the save directory the frontend's config names.
read below it, and its default place relative to the folder holding the
system directory (RetroArch's own folder holds system/ and saves/,
EmuDeck's Emulation/ holds bios/ and saves/retroarch/saves/). A pack is
extracted into the system directory, so that folder is moved by hand,
and the installer writes to the save directory the frontend's config
names.
``by_core`` is set when the frontend hands each core <save
directory>/<library_name>, RetroArch's sort_savefiles_enable.
``by_system`` is set when the launcher hands a core <save
directory>/<system>, the system it was launched for (Batocera's
/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. ``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
by any of these names: always where it sorts saves by core, else
only for the cores its launcher sorts (``by_core_for``, RetroBat's
CoreSaveSort)."""
return self.by_core or bool(self.by_core_for & {str(n) for n in names})
def save_layout(config: dict) -> SaveLayout | None:
"""The platform's save directory, or None when it is no fixed place.
Read from the registry's ``save_directory``. A platform that keeps
saves beside the content, or in one folder per launched system, has
none: a file read below it has no single destination.
saves beside the content has none: a file read below it has no single
destination. ``folder`` is a relative path, never one that climbs.
"""
block = config.get("save_directory")
if not isinstance(block, dict):
return None
folder = sanitize_pack_path(str(block.get("folder") or ""))
if not folder or "/" in folder:
raw = str(block.get("folder") or "")
folder = sanitize_pack_path(raw)
if not folder or folder != raw:
return None
return SaveLayout(folder, bool(block.get("by_core")))
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 "")),
)
def save_destination(
path: str, core_folder: str | None, layout: SaveLayout
path: str, core_folder: str | None, layout: SaveLayout, system: str = "",
sorted_by_core: bool | None = None,
) -> str | None:
"""The pack path of a file a core reads below the save directory.
@@ -54,16 +88,40 @@ def save_destination(
is the folder a frontend sorting saves by core inserts: the core's
library_name, empty when it inserts none (an empty library_name, or a
core that reads the same place sorted or not), None when the profile
does not say. None then, where the frontend sorts by core.
does not say. None then, where the frontend sorts by core. ``system``
is the folder a launcher saving by system inserts first, required
where the layout is ``by_system``. ``sorted_by_core`` says whether the
frontend sorts this core's saves, the layout's ``by_core`` by default.
"""
rel = sanitize_pack_path(path)
if not rel:
return None
if layout.by_core and core_folder:
return f"{layout.folder}/{sanitize_pack_path(core_folder)}/{rel}"
if layout.by_core and core_folder is None:
root = layout.in_pack
if layout.by_system:
folder = sanitize_pack_path(system)
if not folder or "/" in folder:
return None
root = f"{root}/{folder}"
by_core = layout.by_core if sorted_by_core is None else sorted_by_core
if by_core and core_folder:
return f"{root}/{sanitize_pack_path(core_folder)}/{rel}"
if by_core and core_folder is None:
return None
return f"{layout.folder}/{rel}"
return f"{root}/{rel}"
def libretro_systems(config: dict, names: Iterable[str]) -> list[str]:
"""The systems a platform runs any of these libretro core names for.
Read from the platform file's ``libretro_systems`` (core -> the systems
whose launch offers it), which the platform's scraper writes from its
system list. Sorted, each once.
"""
table = config.get("libretro_systems") or {}
found: set[str] = set()
for name in names:
found.update(str(system) for system in table.get(str(name)) or [])
return sorted(found)
def core_save_folder(profile: dict) -> str | None:
+57 -13
View File
@@ -116,22 +116,59 @@ def _generic_manual(bios_paths: list[str]) -> str:
)
def _save_section(display: str, folder: str) -> str:
def save_place(extract_to: str, folder: str, base_dest: str) -> str:
"""Where a platform keeps its save directory by default, as the README
names it: ``folder`` beside the BIOS folder the archive is extracted
into (``base_dest`` names it), or inside the folder the archive is
extracted into when the archive holds the BIOS folder itself
(RetroDECK's ~/retrodeck/). A relative BIOS folder (RetroArch's
system/) gives ``folder`` beside it."""
root = extract_to.rstrip("/")
if not base_dest:
return f"{root}/{folder}/" if root else f"{folder}/"
parent = root.rpartition("/")[0]
if parent:
return f"{parent}/{folder}/"
return f"{folder}/ beside {root or base_dest}/"
def _save_section(
display: str, folder: str, place: str = "", by_system: bool = False,
in_frontend_settings: bool = True, in_place: bool = False,
) -> str:
"""Where the files of the pack's save folder go.
Some cores read their system data below the save directory the frontend
hands them, not below the system directory the archive is extracted
into: Azahar keeps its user folder there.
into: Azahar keeps its user folder there. ``place`` is the save
directory's default place (save_place), saves/ beside system/ when not
given. ``by_system`` says the launcher hands each system a folder of
its own, which the archive's folder already holds.
``in_frontend_settings`` points at RetroArch's setting, for a frontend
whose own config names the directory. ``in_place`` says the archive is
extracted into the folder holding the save directory, which then
needs no move.
"""
return (
" Files read from the save directory\n"
" ----------------------------------\n"
f" Some cores read files from {display}'s save directory, not its\n"
f" system directory. The {folder}/ folder of this archive holds them.\n"
f" Move its contents into the save directory ({folder}/ beside\n"
" system/ by default, see Settings > Directory > Save Files), keeping\n"
" the folders it holds. The automatic install writes them there.\n\n"
)
where = place or f"{folder}/ beside system/"
kept = "the folder of each system" if by_system else "the folders it holds"
lines = [
" Files read from the save directory",
" ----------------------------------",
f" Some cores read files from {display}'s save directory, not its",
f" system directory. The {folder}/ folder of this archive holds them.",
]
if in_place:
lines.append(f" Extracted as above, it lands at {where}, where they are read.")
else:
lines += [
" Move its contents into the save directory, keeping",
f" {kept}. By default it is {where}"
+ ("," if in_frontend_settings else "."),
]
if in_frontend_settings:
lines.append(" see Settings > Directory > Save Files.")
lines.append(" The automatic install writes them there.")
return "\n".join(lines) + "\n\n"
def _build_readme(
@@ -152,13 +189,17 @@ def _build_readme(
standalone_copies: list[dict] | None = None,
launch_folders: int = 0,
save_folder: str = "",
save_where: str = "",
save_by_system: bool = False,
) -> str:
"""Build a personalized step-by-step README for each platform pack.
``launch_folders`` counts the folders a platform that hands each core
its own system directory gives them, where it names no system.
``save_folder`` is the pack folder holding files cores read below the
frontend's save directory, empty when the pack holds none.
frontend's save directory, empty when the pack holds none, and
``save_where`` that directory's default place (save_place).
``save_by_system`` is set when the launcher hands each system a folder.
"""
narrowings = narrowings or []
sep = "=" * 50
@@ -189,7 +230,10 @@ def _build_readme(
)
if save_folder:
guide += _save_section(platform_display, save_folder)
guide += _save_section(
platform_display, save_folder, save_where, save_by_system,
in_frontend_settings=not save_by_system, in_place=not base_dest,
)
if regions:
region_help = (
+28
View File
@@ -142,6 +142,29 @@ def es_systems_libretro(text: str) -> set[str]:
return found
def es_systems_libretro_systems(text: str, dropped: set[str]) -> dict[str, list[str]]:
"""libretro core -> the systems es_systems.yml offers it under `libretro:`.
configgen hands a libretro core /userdata/saves/<system> at each launch
(libretroConfig.py: savefile_directory = SAVES / system.name), so a file
a core reads below its save directory sits once in each of these
system folders.
"""
data = yaml_load_upstream(text)
if not isinstance(data, dict):
raise ValueError("es_systems.yml is not a mapping")
found: dict[str, set[str]] = {}
for system, spec in data.items():
emulators = spec.get("emulators") if isinstance(spec, dict) else None
libretro = emulators.get("libretro") if isinstance(emulators, dict) else None
if not isinstance(libretro, dict):
continue
for core, entry in libretro.items():
if isinstance(entry, dict) and str(core) not in dropped:
found.setdefault(str(core), set()).add(str(system))
return {core: sorted(systems) for core, systems in sorted(found.items())}
def es_systems_by_system(
es_systems_text: str, defaults_text: str, dropped: set[str]
) -> dict[str, list[str]]:
@@ -518,6 +541,9 @@ class Scraper(BaseScraper):
)
cores, standalone, dual = self._fetch_cores()
libretro_systems = es_systems_libretro_systems(
self._fetch_text(ES_SYSTEMS_URL.format(tag=self.tag)), _not_cores()
)
result = {
"platform": "Batocera",
"version": self.tag.removeprefix("batocera-"),
@@ -534,6 +560,8 @@ class Scraper(BaseScraper):
if dual:
# Launched both ways: each layout gets its files.
result["dual_mode_cores"] = dual
# The systems each libretro core runs for: its save folders.
result["libretro_systems"] = libretro_systems
result["launchers"] = extract_launchers(
lambda path: self._fetch_text(f"{_RAW_BASE}/{self.tag}/{path}")
)
+4
View File
@@ -38,6 +38,7 @@ from .batocera_scraper import (
_not_cores,
configgen_cores,
es_systems_by_system,
es_systems_libretro_systems,
extract_systems_dict,
platform_systems,
requirements_from_systems,
@@ -120,6 +121,9 @@ class Scraper(BaseScraper):
result["standalone_cores"] = standalone
if dual:
result["dual_mode_cores"] = dual
# configgen hands a libretro core /userdata/saves/<system>, as
# Batocera's does: the systems each core runs for are its save folders.
result["libretro_systems"] = es_systems_libretro_systems(es_systems, dropped)
return result
+28 -1
View File
@@ -167,6 +167,29 @@ def system_ini_libretro(text: str) -> set[str]:
}
def system_ini_name(text: str, folder: str) -> str:
"""The system name a system.ini gives, the one ES passes configgen.
configgen hands a libretro core /recalbox/share/saves/<that name>
(projects/configgen/configgen/generators/libretro/libretroRetroarch.py
savesFolder). The folder name stands in where the file names none.
"""
return _ini_sections(text).get("system", {}).get("name") or folder
def libretro_systems(inis: dict[str, str]) -> dict[str, list[str]]:
"""libretro core -> the systems whose system.ini offers it.
``inis`` maps each system folder to its system.ini.
"""
found: dict[str, set[str]] = {}
for folder, text in inis.items():
name = system_ini_name(text, folder)
for core in system_ini_libretro(text):
found.setdefault(core, set()).add(name)
return {core: sorted(systems) for core, systems in sorted(found.items())}
def system_ini_cores(text: str) -> tuple[set[str], set[str]]:
"""The cores one Recalbox system.ini offers, and those run standalone.
@@ -282,7 +305,10 @@ class Scraper(BaseScraper):
cores: set[str] = set()
standalone: set[str] = set()
libretro: set[str] = set()
for text in self._system_inis(systems):
texts = self._system_inis(systems)
# The systems each libretro core runs for: its save folders.
self.libretro_systems = libretro_systems(dict(zip(systems, texts)))
for text in texts:
found, alone = system_ini_cores(text)
cores |= found
standalone |= alone
@@ -397,6 +423,7 @@ class Scraper(BaseScraper):
# Launched both ways: each layout gets its files.
**({"dual_mode_cores": dual} if dual else {}),
"systems": systems,
"libretro_systems": self.libretro_systems,
"launchers": self._fetch_launchers(),
}
+28
View File
@@ -99,6 +99,31 @@ def es_systems_cores(text: str) -> tuple[set[str], set[str]]:
return cores, standalone
def es_systems_libretro_systems(text: str) -> dict[str, list[str]]:
"""libretro core -> the ES systems es_systems.cfg offers it for.
emulatorLauncher hands a libretro core saves\\<system> at each launch
(LibRetro.Generator.cs Configure: savefile_directory), so a file a core
reads below its save directory sits once in each of these system
folders. A commented-out system is no element and counts for nothing.
"""
from common import parse_untrusted_xml
found: dict[str, set[str]] = {}
for system in parse_untrusted_xml(text, "es_systems.cfg").iter("system"):
name = (system.findtext("name") or "").strip()
if not name:
continue
for emulator in system.iter("emulator"):
if (emulator.get("name") or "").strip() != "libretro":
continue
for core in emulator.iter("core"):
core_name = (core.text or "").strip()
if core_name:
found.setdefault(core_name, set()).add(name)
return {core: sorted(systems) for core, systems in sorted(found.items())}
def launcher_revision(url: str) -> str:
"""The emulatorLauncher commit a source URL is pinned to."""
found = re.search(r"/emulatorlauncher/([0-9a-f]{40})/", url)
@@ -259,6 +284,7 @@ class Scraper(BaseScraper):
es_text = resp.read().decode("utf-8")
cores, standalone = es_systems_cores(es_text)
dual = es_systems_dual(es_text)
libretro_systems = es_systems_libretro_systems(es_text)
except urllib.error.URLError as e:
raise ConnectionError(f"Failed to fetch {es_url}: {e}") from e
if not cores:
@@ -277,6 +303,8 @@ class Scraper(BaseScraper):
# Launched both ways: each layout gets its files.
**({"dual_mode_cores": sorted(dual)} if dual else {}),
"systems": systems,
# The systems each libretro core runs for: its save folders.
"libretro_systems": libretro_systems,
"launchers": fetch_launchers(launcher_revision(self.url)),
}
+48 -4
View File
@@ -39,6 +39,8 @@ try:
BaseScraper,
BiosRequirement,
fetch_branch_head,
fetch_bytes,
fetch_github_latest_version,
github_headers,
requirement_entry,
)
@@ -49,6 +51,8 @@ except ImportError:
BaseScraper,
BiosRequirement,
fetch_branch_head,
fetch_bytes,
fetch_github_latest_version,
github_headers,
requirement_entry,
)
@@ -60,6 +64,38 @@ COMPONENTS_BRANCH = "main"
COMPONENTS_API_URL = "https://api.github.com/repos/" + COMPONENTS_REPO + "/git/trees/{rev}"
RAW_BASE = "https://raw.githubusercontent.com/" + COMPONENTS_REPO + "/{rev}"
SKIP_DIRS = {"archive_later", "archive_old", "automation-tools", ".github"}
# ES-DE's system list as RetroDECK's fork builds it.
ES_DE_REPO = "RetroDECK/ES-DE"
ES_DE_SYSTEMS_URL = (
"https://raw.githubusercontent.com/" + ES_DE_REPO
+ "/{rev}/resources/systems/linux/es_systems.xml"
)
_RETROARCH_CORE = re.compile(r"%CORE_RETROARCH%/([\w.+-]+?)_libretro\.so")
def es_systems_libretro_systems(text: str) -> dict[str, list[str]]:
"""libretro core -> the ROM folders of the systems whose commands load it.
RetroDECK's RetroArch sorts saves by content and not by core
(retroarch/rd_assets/rd_config/retroarch.cfg, sort_savefiles_by_content_enable
and sort_savefiles_enable): a core is handed saves/<folder holding the
ROM>, the system's <path> folder below %ROMPATH%. A commented-out
command is no element and counts for nothing.
"""
from common import parse_untrusted_xml
found: dict[str, set[str]] = {}
for system in parse_untrusted_xml(text, "es_systems.xml").iter("system"):
path = (system.findtext("path") or "").strip().replace("\\", "/")
folder = path.rstrip("/").rsplit("/", 1)[-1]
if not folder or folder.startswith("%"):
continue
for command in system.iter("command"):
match = _RETROARCH_CORE.search(command.text or "")
if match:
found.setdefault(match.group(1), set()).add(folder)
return {core: sorted(folders) for core, folders in sorted(found.items())}
NON_EMULATOR_COMPONENTS = {
"framework",
"es-de",
@@ -468,6 +504,16 @@ class Scraper(BaseScraper):
return requirements
def _fetch_libretro_systems(self) -> dict[str, list[str]]:
"""libretro core -> ROM folders, from the ES-DE build RetroDECK ships.
RetroDECK takes ES-DE's latest release of its fork
(automation-tools/alchemist/desired_versions.sh, ES_DE_DESIRED_VERSION).
"""
tag = fetch_github_latest_version(ES_DE_REPO)
text = fetch_bytes(ES_DE_SYSTEMS_URL.format(rev=tag)).decode("utf-8")
return es_systems_libretro_systems(text)
def generate_platform_yaml(self) -> dict:
reqs = self.fetch_requirements()
manifests = self._get_manifests()
@@ -486,10 +532,6 @@ class Scraper(BaseScraper):
sys_entry = systems.setdefault(req.system, {"files": []})
sys_entry["files"].append(requirement_entry(req))
try:
from .base_scraper import fetch_github_latest_version
except ImportError:
from scraper.base_scraper import fetch_github_latest_version
version = fetch_github_latest_version("RetroDECK/RetroDECK")
return {
@@ -509,6 +551,8 @@ class Scraper(BaseScraper):
# its own, and retroarch is the one that runs cores.
"standalone_cores": [c for c in cores if c != "retroarch"],
"systems": systems,
# The ROM folders each libretro core runs for: its save folders.
"libretro_systems": self._fetch_libretro_systems(),
"launchers": extract_launchers(cores, self.component_file),
}
+65 -7
View File
@@ -395,7 +395,9 @@ def _save_directory_blocks() -> list[str]:
"""Each registry save_directory is null or a folder and a by_core flag.
The folder names the pack folder and the save directory's default place
beside the BIOS directory: one path segment.
beside the BIOS directory: a relative path that never climbs. ``by_system`` (a save
folder per launched system) needs the platform file's libretro_systems,
and ``by_core_for`` names the cores a launcher sorts by core.
"""
registry_path = ROOT / "platforms" / "_registry.yml"
if not registry_path.is_file():
@@ -410,22 +412,76 @@ def _save_directory_blocks() -> list[str]:
if block is None:
continue
folder = block.get("folder") if isinstance(block, dict) else None
sorted_cores = block.get("by_core_for", []) if isinstance(block, dict) else None
if (
not isinstance(block, dict)
or set(block) != {"folder", "by_core"}
or not {"folder", "by_core"} <= set(block) <= {
"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 re.search(r"[/\\]", folder)
or folder in (".", "..")
or "\\" in folder
or any(part in ("", ".", "..") for part in folder.split("/"))
or not isinstance(block.get("by_core"), bool)
or not isinstance(block.get("by_system", False), bool)
or not isinstance(sorted_cores, list)
or not all(isinstance(core, str) and core for core in sorted_cores)
):
out.append(
f"platforms/_registry.yml: {name}.save_directory must be null or "
"{folder: <one path segment>, by_core: <bool>}"
"{folder: <relative path>, by_core: <bool>, by_system: <bool>, "
"by_core_for: [<core>]}"
)
continue
if block.get("by_system") and not _libretro_systems(name):
out.append(
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
try:
config = load_platform_config(platform, str(ROOT / "platforms"))
except FileNotFoundError:
return {}
return config.get("libretro_systems") or {}
def _semantic_install_checks(path: Path, manifest: dict) -> list[str]:
out: list[str] = []
files = manifest.get("files", [])
@@ -439,10 +495,12 @@ def _semantic_install_checks(path: Path, manifest: dict) -> list[str]:
f"{path.relative_to(ROOT)}: total_omitted does not equal "
"len(omitted_files)"
)
destinations = [entry.get("dest") for entry in files]
# One dest below the BIOS folder and one below the save directory are
# two places.
destinations = [(entry.get("root"), entry.get("dest")) for entry in files]
if len(destinations) != len(set(destinations)):
out.append(f"{path.relative_to(ROOT)}: duplicate destinations")
omitted_destinations = [entry.get("dest") for entry in omitted]
omitted_destinations = [(entry.get("root"), entry.get("dest")) for entry in omitted]
if len(omitted_destinations) != len(set(omitted_destinations)):
out.append(f"{path.relative_to(ROOT)}: duplicate omitted destinations")
overlap = set(destinations) & set(omitted_destinations)
+1
View File
@@ -876,6 +876,7 @@ _UNPLACED_REASONS = {
"below_platform_folder": "below the folder the platform lists",
"no_save_directory": "read below a save directory the platform keeps in no fixed place",
"no_core_folder": "read below the save directory and the profile names no library_name",
"no_save_system": "read below a save folder per system and no system runs the core there",
}
+290 -2
View File
@@ -96,7 +96,8 @@ class ThePlatformNamesItsSaveDirectory(unittest.TestCase):
save_layout({"save_directory": {"folder": "saves", "by_core": True}}),
SaveLayout("saves", True),
)
for block in (None, {}, {"folder": ""}, {"folder": "a/b", "by_core": True}):
for block in (None, {}, {"folder": ""}, {"folder": "../b", "by_core": True},
{"folder": "a/../b", "by_core": True}):
with self.subTest(block=block):
self.assertIsNone(save_layout({"save_directory": block}))
self.assertIsNone(save_layout({}))
@@ -126,6 +127,76 @@ class ThePlatformNamesItsSaveDirectory(unittest.TestCase):
# RetroPie inherits RetroArch but keeps saves beside each game.
self.assertIsNone(save_layout(load_platform_config("retropie", platforms)))
def test_each_platform_running_these_cores_says_where(self):
"""The layout read from each platform's launch code, or none where
saves sit beside each game or in a browser."""
from common import load_platform_config
platforms = str(REPO_ROOT / "platforms")
expected = {
"batocera": SaveLayout("saves", False, True, pack_folder="userdata-saves"),
"knulli": SaveLayout("saves", False, True),
"recalbox": SaveLayout("saves", False, True),
"retrodeck": SaveLayout("saves", False, True),
"retrobat": SaveLayout("saves", False, True, frozenset({"dolphin"})),
"emudeck": SaveLayout("saves/retroarch/saves", False),
"rocknix": None, "amberelec": None, "emuelec": None, "romm": None,
"retropie": None,
}
for name, layout in expected.items():
with self.subTest(platform=name):
config = load_platform_config(name, platforms)
self.assertEqual(save_layout(config), layout)
if layout is not None and layout.by_system:
self.assertTrue(config.get("libretro_systems"))
def test_a_save_folder_per_system(self):
layout = SaveLayout("saves", False, True)
self.assertEqual(save_destination("User/GBA/gba_bios.bin", "dolphin-emu", layout,
"gamecube"),
"saves/gamecube/User/GBA/gba_bios.bin")
# The system folder is required, and one folder name.
self.assertIsNone(save_destination("a.bin", "X", layout))
self.assertIsNone(save_destination("a.bin", "X", layout, "a/b"))
# A launcher sorting one core by core (RetroBat's dolphin).
sorted_one = SaveLayout("saves", False, True, frozenset({"dolphin"}))
self.assertTrue(sorted_one.sorts({"dolphin", "dolphin-gui"}))
self.assertFalse(sorted_one.sorts({"stella"}))
self.assertEqual(
save_destination("User/GBA/gba_bios.bin", "dolphin-emu", sorted_one, "wii",
sorted_one.sorts({"dolphin"})),
"saves/wii/dolphin-emu/User/GBA/gba_bios.bin",
)
def test_a_pack_folder_apart_from_the_bios_tree(self):
"""Batocera's BIOS tree has a saves/ of its own: the pack keeps the
save directory's files in another folder, the installer still
writes them to /userdata/saves."""
layout = save_layout({"save_directory": {
"folder": "saves", "by_core": False, "by_system": True,
"pack_folder": "userdata-saves"}})
self.assertEqual(layout.in_pack, "userdata-saves")
self.assertEqual(save_destination("stella/KVS1.WAV", None, layout, "atari2600"),
"userdata-saves/atari2600/stella/KVS1.WAV")
self.assertEqual(SaveLayout("saves", True).in_pack, "saves")
try:
from validate_schemas import _bios_tree_below
except ImportError:
self.skipTest("validate_schemas needs jsonschema")
self.assertEqual(_bios_tree_below("batocera", "saves"),
"saves/dolphin-emu/Triforce/segaboot.gcm")
self.assertEqual(_bios_tree_below("batocera", "userdata-saves"), "")
def test_the_systems_a_core_runs_for(self):
from packpaths import libretro_systems
config = {"libretro_systems": {"dolphin": ["wii", "gamecube"], "fbalpha": ["fbneo"],
"fbalpha2012": ["cps3", "fbneo"]}}
self.assertEqual(libretro_systems(config, ["dolphin"]), ["gamecube", "wii"])
self.assertEqual(libretro_systems(config, ["fbalpha2012", "fbalpha"]),
["cps3", "fbneo"])
self.assertEqual(libretro_systems(config, ["stella"]), [])
class _Fixture(unittest.TestCase):
"""A RetroArch-like platform with a save directory, one without, and a
@@ -300,6 +371,108 @@ class ThePackPlacesThemInTheSaveFolder(_Fixture):
self.assertEqual(set(report["pack_destinations"]), set(record.files))
class AFolderPerSystem(_Fixture):
"""Batocera's launcher hands a core /userdata/saves/<system>, RetroBat's
saves\\<system> with dolphin alone sorted by core: one copy of the file
below each system the platform runs the core for."""
OWN = b"COREY OWN FILE"
def setUp(self) -> None:
super().setUp()
(self.bios / "X" / "own.bin").write_bytes(self.OWN)
sha1 = hashlib.sha1(self.OWN).hexdigest()
self.db["files"][sha1] = {
"path": str(self.bios / "X" / "own.bin"), "name": "own.bin",
"md5": hashlib.md5(self.OWN).hexdigest(), "size": len(self.OWN), "crc32": "",
}
self.db["indexes"]["by_name"]["own.bin"] = [sha1]
(self.emulators / "corey.yml").write_text(yaml.safe_dump({
"emulator": "CoreY", "type": "libretro", "library_name": "CoreY",
"systems": ["test-console"],
"files": [{"name": "own.bin", "path": "own.bin", "load_from": "save_dir",
"required": False, "sha1": sha1}],
}))
system = {"files": [{"name": "keys.txt", "destination": "keys.txt",
"sha1": hashlib.sha1(self.OTHER_KEYS).hexdigest(),
"required": False}]}
for name in ("testbato", "testrb"):
(self.platforms / f"{name}.yml").write_text(yaml.safe_dump({
"platform": name, "verification_mode": "existence",
"base_destination": "bios", "cores": ["corex", "corey"],
"systems": {"test-console": system},
# Two systems run CoreX, none runs CoreY.
"libretro_systems": {"corex": ["sysb", "sysa"], "other": ["sysc"]},
}))
registry = yaml.safe_load((self.platforms / "_registry.yml").read_text())
registry["platforms"]["testbato"] = {"save_directory": {
"folder": "saves", "by_core": False, "by_system": True}}
registry["platforms"]["testrb"] = {"save_directory": {
"folder": "saves", "by_core": False, "by_system": True, "by_core_for": ["corex"]}}
(self.platforms / "_registry.yml").write_text(yaml.safe_dump(registry))
def test_one_copy_below_each_system(self):
names = self.pack("testbato")
saved = sorted(n for n in names if n.startswith("saves/"))
self.assertEqual(saved, ["saves/sysa/CoreX/sysdata/keys.txt",
"saves/sysb/CoreX/sysdata/keys.txt"])
self.assertIn("the folder of each system", self.readme)
report = self.verify("testbato")
written = {n for n in names if n != "README.txt" and not n.endswith("/")}
self.assertEqual(set(report["pack_destinations"]), written)
def test_the_manifest_lists_each_copy(self):
manifest = self.manifest("testbato")
saved = sorted((e["dest"], e.get("core_folder")) for e in manifest["files"]
if e.get("root") == "save")
# The launcher fixes the path: no core folder for the installer to undo.
self.assertEqual(saved, [("sysa/CoreX/sysdata/keys.txt", None),
("sysb/CoreX/sysdata/keys.txt", None)])
self.assertEqual(manifest["save_directory"],
{"folder": "saves", "by_core": False, "by_system": True})
omitted = [(e["dest"], e["reason"]) for e in manifest["omitted_files"]
if e.get("root") == "save"]
self.assertEqual(omitted, [("CoreY/own.bin", "no_save_system")])
for entry in manifest["files"]:
entry["repo_path"] = f"bios/{Path(entry['repo_path']).name}"
install._validate_manifest(manifest, "testbato")
def test_verify_says_why_a_core_without_a_system_is_left_out(self):
report = self.verify("testbato")
entry = next(u for u in report["undeclared_files"] if u["name"] == "own.bin")
self.assertFalse(entry["in_pack"])
self.assertIn("no system runs the core", entry["omitted"])
def test_a_core_the_launcher_sorts(self):
names = self.pack("testrb")
self.assertEqual(sorted(n for n in names if n.startswith("saves/")),
["saves/sysa/CoreX/CoreX/sysdata/keys.txt",
"saves/sysb/CoreX/CoreX/sysdata/keys.txt"])
manifest = self.manifest("testrb")
self.assertEqual(sorted(e["dest"] for e in manifest["files"] if e.get("root") == "save"),
["sysa/CoreX/CoreX/sysdata/keys.txt",
"sysb/CoreX/CoreX/sysdata/keys.txt"])
def test_two_cores_reading_one_path_in_one_folder_share_it(self):
(self.emulators / "corez.yml").write_text(yaml.safe_dump({
"emulator": "CoreZ", "type": "libretro", "library_name": "CoreZ",
"systems": ["test-console"],
"files": [{"name": "keys.txt", "path": "CoreX/sysdata/keys.txt",
"load_from": "save_dir", "required": False,
"sha1": hashlib.sha1(self.KEYS).hexdigest()}],
}))
config = yaml.safe_load((self.platforms / "testbato.yml").read_text())
config["cores"].append("corez")
config["libretro_systems"]["corez"] = ["sysa"]
(self.platforms / "testbato.yml").write_text(yaml.safe_dump(config))
names = self.pack("testbato")
self.assertEqual(names.count("saves/sysa/CoreX/sysdata/keys.txt"), 1)
manifest = self.manifest("testbato")
shared = next(e for e in manifest["files"]
if e["dest"] == "sysa/CoreX/sysdata/keys.txt")
self.assertEqual(sorted(shared["cores"]), ["corex", "corez"])
class TheInstallerFindsTheSaveDirectory(unittest.TestCase):
MANIFEST = {"base_destination": "system",
"save_directory": {"folder": "saves", "by_core": True}}
@@ -349,6 +522,36 @@ class TheInstallerFindsTheSaveDirectory(unittest.TestCase):
self.assertEqual(install.save_directory_for(other, self.MANIFEST, self.root / "s"),
install.SavePlace(self.root / "s", True))
def test_a_launcher_writing_it_per_system_is_not_read_from_a_config(self):
"""Batocera and RetroBat write retroarch.cfg at each launch: the one
on disk names the last system played."""
manifest = {"base_destination": "system",
"save_directory": {"folder": "saves", "by_core": False, "by_system": True}}
other = self.root / "elsewhere"
other.mkdir()
self.cfg.write_text(f'savefile_directory = "{other}"\nsort_savefiles_enable = "true"\n')
install._RETROARCH_CONFIGS[self.bios] = (self.cfg, self.app)
self.assertEqual(install.save_directory_for(self.bios, manifest),
install.SavePlace(self.app / "saves", False, False))
def test_a_list_rooted_above_the_bios_folder(self):
"""RetroDECK's dests start at ~/retrodeck, which holds bios/ and saves/."""
manifest = {"base_destination": "",
"save_directory": {"folder": "saves", "by_core": False, "by_system": True}}
root = self.root / "retrodeck"
self.assertEqual(install.save_directory_for(root, manifest),
install.SavePlace(root / "saves", False, False))
def test_a_save_folder_several_levels_down(self):
"""EmuDeck: ~/Emulation/bios and ~/Emulation/saves/retroarch/saves."""
manifest = {"base_destination": "bios",
"save_directory": {"folder": "saves/retroarch/saves", "by_core": False}}
bios = self.root / "Emulation" / "bios"
self.assertEqual(install.save_directory_for(bios, manifest),
install.SavePlace(self.root / "Emulation" / "saves/retroarch/saves",
False, False))
install._check_save_directory(manifest)
def test_the_entry_path(self):
saves = (self.app / "saves").resolve()
install._SAVE_DIRS[self.bios] = install.SavePlace(self.app / "saves", True)
@@ -403,7 +606,12 @@ class TheManifestBoundary(unittest.TestCase):
("core folder on a BIOS file", self.manifest(
{k: v for k, v in self.ENTRY.items() if k != "root"}, layout)),
("climbing save folder", self.manifest(self.ENTRY, {"folder": "..", "by_core": True})),
("save folder with a path", self.manifest(self.ENTRY, {"folder": "a/b", "by_core": True})),
("save folder climbing inside", self.manifest(
self.ENTRY, {"folder": "a/../b", "by_core": True})),
("by_system not true", self.manifest(
self.ENTRY, {"folder": "saves", "by_core": True, "by_system": False})),
("unknown save_directory key", self.manifest(
self.ENTRY, {"folder": "saves", "by_core": True, "by_game": True})),
("by_core not a flag", self.manifest(self.ENTRY, {"folder": "saves", "by_core": 1})),
("dest without its core folder", self.manifest(
{**self.ENTRY, "dest": "sysdata/keys.txt"}, layout)),
@@ -528,6 +736,86 @@ class TheProfilesFollowTheContract(unittest.TestCase):
self.assertTrue(all(e["root"] == "save" for e in azahar.values()))
class TheScrapersReadTheSystemLists(unittest.TestCase):
"""libretro_systems, read from each platform's own system list."""
def setUp(self) -> None:
sys.path.insert(0, str(REPO_ROOT))
self.addCleanup(sys.path.remove, str(REPO_ROOT))
def test_batocera_and_knulli_es_systems_yml(self):
from scripts.scraper.batocera_scraper import es_systems_libretro_systems
text = (
"gamecube:\n emulators:\n dolphin:\n dolphin: { requireAnyOf: [A] }\n"
" libretro:\n dolphin: { requireAnyOf: [B] }\n"
"wii:\n emulators:\n libretro:\n dolphin: { requireAnyOf: [B] }\n"
" plugin: { requireAnyOf: [C] }\n"
"atari2600:\n emulators:\n libretro:\n stella: { requireAnyOf: [D] }\n"
)
self.assertEqual(es_systems_libretro_systems(text, {"plugin"}),
{"dolphin": ["gamecube", "wii"], "stella": ["atari2600"]})
def test_retrobat_es_systems_cfg(self):
from scripts.scraper.retrobat_scraper import es_systems_libretro_systems
text = (
"<systemList><system><name>3ds</name><emulators>"
"<emulator name=\"libretro\"><cores><core>azahar</core>"
"<!-- <core>citra</core> --></cores></emulator>"
"<emulator name=\"citra-qt\"><cores><core>citra-qt</core></cores></emulator>"
"</emulators></system></systemList>"
)
self.assertEqual(es_systems_libretro_systems(text), {"azahar": ["3ds"]})
def test_recalbox_system_ini(self):
from scripts.scraper.recalbox_scraper import libretro_systems
wii = ("[system]\nname = \"wii\"\n[core.0]\nemulator = \"dolphin-gui\"\n"
"core = \"dolphin-gui\"\n[core.2]\nemulator = \"libretro\"\ncore = \"dolphin\"\n")
nameless = "[core.0]\nemulator = \"libretro\"\ncore = \"stella\"\n"
self.assertEqual(libretro_systems({"wii": wii, "atari2600": nameless}),
{"dolphin": ["wii"], "stella": ["atari2600"]})
def test_retrodeck_es_de_commands(self):
from scripts.scraper.retrodeck_scraper import es_systems_libretro_systems
text = (
"<systemList><system><name>n3ds</name><path>%ROMPATH%/n3ds</path>"
"<command label=\"Azahar (Standalone)\">%EMULATOR_AZAHAR% %ROM%</command>"
"<command label=\"Citra\">%EMULATOR_RETROARCH% -L "
"%CORE_RETROARCH%/citra_libretro.so %ROM%</command>"
"<!-- <command>%EMULATOR_RETROARCH% -L %CORE_RETROARCH%/x_libretro.so</command> -->"
"</system></systemList>"
)
self.assertEqual(es_systems_libretro_systems(text), {"citra": ["n3ds"]})
def test_the_published_platform_files(self):
expected = {
"batocera": {"dolphin": ["gamecube", "wii"], "stella": ["atari2600"]},
"knulli": {"dolphin": ["gamecube", "wii"], "citra": ["3ds"]},
"retrobat": {"azahar": ["3ds"], "dolphin": ["gamecube", "triforce", "wii"]},
"recalbox": {"dolphin": ["gamecube", "wii"], "stella": ["atari2600"]},
"retrodeck": {"citra": ["n3ds"], "stella": ["atari2600"]},
}
for name, cores in expected.items():
table = yaml.safe_load(
(REPO_ROOT / "platforms" / f"{name}.yml").read_text(encoding="utf-8")
)["libretro_systems"]
for core, systems in cores.items():
with self.subTest(platform=name, core=core):
self.assertEqual(table[core], systems)
def test_the_published_batocera_list_places_dolphin_per_system(self):
manifest = json.loads((REPO_ROOT / "install" / "batocera.json").read_text())
self.assertEqual(manifest.get("save_directory"),
{"folder": "saves", "by_core": False, "by_system": True})
dests = {e["dest"] for e in manifest["files"] if e.get("root") == "save"}
for system in ("gamecube", "wii"):
self.assertIn(f"{system}/User/GBA/gba_bios.bin", dests)
self.assertIn("atari2600/stella/KVS1.WAV", dests)
class TheSchemasCarryTheFields(unittest.TestCase):
def test_install_manifest_and_profile_schemas(self):
try:
+19 -2
View File
@@ -226,6 +226,16 @@ platform hands it no folder. `platform_layouts` builds one view per directory,
so the builder, the manifest, verify and slots read the same placement, and the
resolver still looks the collection up by the core's own path.
A launcher that hands each libretro core a save directory per system needs to
know which systems run each core. The scraper writes `libretro_systems`, each
libretro core name with the systems the platform's own list offers it for, under
the name the launcher puts in the path: Batocera and KNULLI from `es_systems.yml`
(`libretro:` entries), RetroBat from `es_systems.cfg`, Recalbox from each
`system.ini`, RetroDECK from the ROM folders of the ES-DE commands that load the
core. With `save_directory.by_system`, a file a core reads below its save
directory goes once below each of those folders, and a core no system runs is
listed as omitted (`no_save_system`).
### Guide text
`platforms/_guides.yml` holds each platform's guide: what it is, where its
@@ -287,9 +297,16 @@ that text belongs in a guide field.
save_directory: # the save directory the frontend hands libretro cores,
folder: saves # where it is one place: the pack folder holding the
by_core: true # files cores read there (load_from: save_dir), its
# default place beside the BIOS folder, and whether
# default place beside the BIOS folder (a relative
# path, saves/retroarch/saves on EmuDeck), and whether
# the frontend appends the core's library_name.
# null when it is one folder per game or system
by_system: true # the launcher hands <folder>/<system> at each launch
# (Batocera, RetroBat): one copy per system in the
# platform file's libretro_systems
by_core_for: [dolphin] # cores the launcher alone sorts by core (RetroBat)
pack_folder: userdata-saves # the pack's folder for them, where the BIOS tree
# already has one named like folder (Batocera)
# null when saves sit beside each game
zip_digest: composite # the frontend hashes a .zip by its members only
firmware_folder_flat: true # the frontend lists each system folder without
# descending into it
+11 -2
View File
@@ -102,8 +102,17 @@ the save directory beside it (`saves`, `/storage/savefiles` on Lakka).
applies, or when `savefiles_in_content_dir` or
`sort_savefiles_by_content_enable` keeps saves beside each game, those files
are left out and the run says why, like the other entries the list cannot
install. Batocera, RetroBat and RetroPie hand each system or game a save folder
of its own: their lists record these files as omitted.
install.
Batocera, KNULLI, Recalbox, RetroBat and RetroDECK write the save directory at
each launch, one folder per system (`by_system` in the file list). Their lists
already name each system's folder (`gamecube/User/GBA/gba_bios.bin`), and the
run writes below the `saves` folder beside the BIOS folder (`/userdata/saves`,
`/recalbox/share/saves`, `~/retrodeck/saves`), never reading a
`retroarch.cfg` that only holds the last launch. EmuDeck's RetroArch config
names `~/Emulation/saves/retroarch/saves`. RetroPie, ROCKNIX, AmberELEC and
EmuELEC keep saves beside each game, and RomM keeps them in the browser: their
lists record these files as omitted.
A RetroArch run into an empty folder printed this on 2026-10-21:
+14 -4
View File
@@ -562,10 +562,20 @@ The save directory itself is the platform's: `save_directory` in
`platforms/_registry.yml` names it where the frontend keeps it in one place.
RetroArch keeps `saves/` beside `system/` and sorts by core, so Azahar's keys
land in `saves/Azahar/Azahar/sysdata/keys.txt`. Lakka keeps
`/storage/savefiles`. Batocera, RetroBat and RetroPie hand each game or system
a folder of its own: those entries are listed as omitted
(`no_save_directory`), never placed in the BIOS tree where the core does not
look.
`/storage/savefiles`, and EmuDeck one unsorted `~/Emulation/saves/retroarch/saves`
for every core.
Batocera, KNULLI, Recalbox, RetroBat and RetroDECK hand a core the save folder
of the system it was launched for (`by_system`): Batocera's configgen writes
`/userdata/saves/<system>` at each launch. The file then goes once below each
system that runs the core there, so libretro Dolphin's `User/GBA/gba_bios.bin`
lands in both `saves/gamecube/User/GBA/` and `saves/wii/User/GBA/` on Batocera.
RetroBat sorts Dolphin's saves by core too, which adds `dolphin-emu/`.
RetroPie, ROCKNIX, AmberELEC and EmuELEC keep saves beside each game, and RomM
runs cores in the browser: no single place exists, so those entries are listed
as omitted (`no_save_directory`), never placed in the BIOS tree where the core
does not look.
### File entry fields