diff --git a/README.md b/README.md index ef5ea3ee..a5456f89 100644 --- a/README.md +++ b/README.md @@ -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* diff --git a/install.ps1 b/install.ps1 index 8b8de9a6..fb7d9bda 100644 --- a/install.ps1 +++ b/install.ps1 @@ -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 } diff --git a/install.py b/install.py index e4df7bd5..986d2133 100644 --- a/install.py +++ b/install.py @@ -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}" 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}" + if place.by_core: + where += f"{os.sep}" print(f" {_plural(len(saved), 'file')} read from {display}'s save directory " f"go to {where}") return files, [] diff --git a/install.sh b/install.sh index f549bae5..376ff2e1 100755 --- a/install.sh +++ b/install.sh @@ -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() { diff --git a/install/batocera.json b/install/batocera.json index d76c18d3..af2fbd2a 100644 --- a/install/batocera.json +++ b/install/batocera.json @@ -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 + } } \ No newline at end of file diff --git a/install/emudeck.json b/install/emudeck.json index 2ce25594..291dc93e 100644 --- a/install/emudeck.json +++ b/install/emudeck.json @@ -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", diff --git a/install/knulli.json b/install/knulli.json index 3cbed21a..9f5369c6 100644 --- a/install/knulli.json +++ b/install/knulli.json @@ -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 + } } \ No newline at end of file diff --git a/install/recalbox.json b/install/recalbox.json index 6697dd3a..81f34562 100644 --- a/install/recalbox.json +++ b/install/recalbox.json @@ -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 + } } \ No newline at end of file diff --git a/install/retrobat.json b/install/retrobat.json index 86f7b95f..26af92f9 100644 --- a/install/retrobat.json +++ b/install/retrobat.json @@ -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 + } } \ No newline at end of file diff --git a/install/retrodeck.json b/install/retrodeck.json index e0ab413a..20449a45 100644 --- a/install/retrodeck.json +++ b/install/retrodeck.json @@ -292,108 +292,12 @@ "source": "bios/dc/dc_nvmem.bin" } ], - "total_files": 8575, - "total_size": 8549443983, - "pack_files": 8577, - "pack_size": 8549443983, - "total_omitted": 70, + "total_files": 8631, + "total_size": 8602988730, + "pack_files": 8633, + "pack_size": 8602988730, + "total_omitted": 41, "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" - ] - }, - { - "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" - ] - }, - { - "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", @@ -401,7 +305,7 @@ "name": "clientca.pem", "system": "", "required": false, - "reason": "no_save_directory", + "reason": "no_save_system", "cores": [ "ishiiruka" ] @@ -413,7 +317,7 @@ "name": "clientcakey.pem", "system": "", "required": false, - "reason": "no_save_directory", + "reason": "no_save_system", "cores": [ "ishiiruka" ] @@ -425,7 +329,7 @@ "name": "rootca.pem", "system": "", "required": false, - "reason": "no_save_directory", + "reason": "no_save_system", "cores": [ "ishiiruka" ] @@ -437,7 +341,7 @@ "name": "sd.raw", "system": "", "required": false, - "reason": "no_save_directory", + "reason": "no_save_system", "cores": [ "ishiiruka" ] @@ -449,7 +353,7 @@ "name": "SYSCONF", "system": "", "required": false, - "reason": "no_save_directory", + "reason": "no_save_system", "cores": [ "ishiiruka" ] @@ -461,126 +365,11 @@ "name": "setting.txt", "system": "", "required": false, - "reason": "no_save_directory", + "reason": "no_save_system", "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" - ] - }, - { - "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", @@ -588,7 +377,7 @@ "name": "aes_keys.txt", "system": "", "required": false, - "reason": "no_save_directory", + "reason": "no_save_system", "cores": [ "trident" ] @@ -600,7 +389,7 @@ "name": "seeddb.bin", "system": "", "required": false, - "reason": "no_save_directory", + "reason": "no_save_system", "cores": [ "trident" ] @@ -965,142 +754,6 @@ "gzdoom" ], "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" - ], - "systems": [ - "commodore-amiga" - ], - "held": true } ], "core_names": { @@ -57039,6 +56692,468 @@ "sinclair-zx-spectrum" ] }, + { + "dest": "amiga/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/fsuae/Kickstarts/amiga-os-204.rom", + "sha1": "c5839f5cb98a7a8947065c3ed2f14f5f42e334a1", + "sha256": "d0b70e8a1772614b897f92c33cb299bed3fc8e3de488fc12f67f97fc2486eb79", + "size": 524288, + "repo_path": "bios/Commodore/Amiga/amiga-os-204.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/fsuae/Kickstarts/amiga-os-204.rom", + "sha1": "c5839f5cb98a7a8947065c3ed2f14f5f42e334a1", + "sha256": "d0b70e8a1772614b897f92c33cb299bed3fc8e3de488fc12f67f97fc2486eb79", + "size": 524288, + "repo_path": "bios/Commodore/Amiga/amiga-os-204.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/fsuae/Kickstarts/amiga-os-204.rom", + "sha1": "c5839f5cb98a7a8947065c3ed2f14f5f42e334a1", + "sha256": "d0b70e8a1772614b897f92c33cb299bed3fc8e3de488fc12f67f97fc2486eb79", + "size": 524288, + "repo_path": "bios/Commodore/Amiga/amiga-os-204.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/fsuae/Kickstarts/amiga-os-205.rom", + "sha1": "02843c4253bbd29aba535b0aa3bd9a85034ecde4", + "sha256": "8d57d6e9d976df42d91ff9d10a5eedaede1a00e3b4b34cad750ca5ff7229f28a", + "size": 524288, + "repo_path": "bios/Commodore/Amiga/amiga-os-205-a600.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/fsuae/Kickstarts/amiga-os-205.rom", + "sha1": "02843c4253bbd29aba535b0aa3bd9a85034ecde4", + "sha256": "8d57d6e9d976df42d91ff9d10a5eedaede1a00e3b4b34cad750ca5ff7229f28a", + "size": 524288, + "repo_path": "bios/Commodore/Amiga/amiga-os-205-a600.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/fsuae/Kickstarts/amiga-os-205.rom", + "sha1": "02843c4253bbd29aba535b0aa3bd9a85034ecde4", + "sha256": "8d57d6e9d976df42d91ff9d10a5eedaede1a00e3b4b34cad750ca5ff7229f28a", + "size": 524288, + "repo_path": "bios/Commodore/Amiga/amiga-os-205-a600.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/fsuae/Kickstarts/amiga-os-120.rom", + "sha1": "11f9e62cf299f72184835b7b2a70a16333fc0d88", + "sha256": "87cddb1f499e32758de20145e73031a84bab299e3f6e5c8487e76d02b2ee9d16", + "size": 262144, + "repo_path": "bios/Commodore/Amiga/amiga-os-120.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/fsuae/Kickstarts/amiga-os-120.rom", + "sha1": "11f9e62cf299f72184835b7b2a70a16333fc0d88", + "sha256": "87cddb1f499e32758de20145e73031a84bab299e3f6e5c8487e76d02b2ee9d16", + "size": 262144, + "repo_path": "bios/Commodore/Amiga/amiga-os-120.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/fsuae/Kickstarts/amiga-os-120.rom", + "sha1": "11f9e62cf299f72184835b7b2a70a16333fc0d88", + "sha256": "87cddb1f499e32758de20145e73031a84bab299e3f6e5c8487e76d02b2ee9d16", + "size": 262144, + "repo_path": "bios/Commodore/Amiga/amiga-os-120.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/fsuae/Kickstarts/cd32fmv.rom", + "sha1": "03ca81c7a7b259cf64bc9582863eca0f6529f435", + "sha256": "680e654880c891a3b03e6107ed30b10903efca16c1dac1b4c8e7835f4e37acb6", + "size": 262144, + "repo_path": "bios/Commodore/Amiga/cd32fmv.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/fsuae/Kickstarts/cd32fmv.rom", + "sha1": "03ca81c7a7b259cf64bc9582863eca0f6529f435", + "sha256": "680e654880c891a3b03e6107ed30b10903efca16c1dac1b4c8e7835f4e37acb6", + "size": 262144, + "repo_path": "bios/Commodore/Amiga/cd32fmv.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/fsuae/Kickstarts/cd32fmv.rom", + "sha1": "03ca81c7a7b259cf64bc9582863eca0f6529f435", + "sha256": "680e654880c891a3b03e6107ed30b10903efca16c1dac1b4c8e7835f4e37acb6", + "size": 262144, + "repo_path": "bios/Commodore/Amiga/cd32fmv.rom", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/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" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, { "dest": "bios/fuse/48.rom", "sha1": "5ea7c2b824672e914525d1d5c419d71b84a426a2", @@ -105534,6 +105649,64 @@ ], "executable": true }, + { + "dest": "n3ds/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": "n3ds/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": "n3ds/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": "n3ds/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": "bios/cromwell_1024.bin", "sha1": "4e1c2c2ee308ca4591542b3ca48653f65fae6e0f", @@ -106204,6 +106377,107 @@ } ] }, + { + "dest": "arcade/hiscore.dat", + "sha1": "7381472bf046126257e51a0124e4553282f020e5", + "sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5", + "size": 322458, + "repo_path": "bios/Arcade/Arcade/hiscore.dat", + "cores": [ + "fbalpha2012" + ], + "systems": [ + "arcade" + ], + "root": "save" + }, + { + "dest": "cps/hiscore.dat", + "sha1": "7381472bf046126257e51a0124e4553282f020e5", + "sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5", + "size": 322458, + "repo_path": "bios/Arcade/Arcade/hiscore.dat", + "cores": [ + "fbalpha2012", + "fbalpha2012_cps3" + ], + "systems": [ + "arcade" + ], + "root": "save" + }, + { + "dest": "cps1/hiscore.dat", + "sha1": "7381472bf046126257e51a0124e4553282f020e5", + "sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5", + "size": 322458, + "repo_path": "bios/Arcade/Arcade/hiscore.dat", + "cores": [ + "fbalpha2012" + ], + "systems": [ + "arcade" + ], + "root": "save" + }, + { + "dest": "cps2/hiscore.dat", + "sha1": "7381472bf046126257e51a0124e4553282f020e5", + "sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5", + "size": 322458, + "repo_path": "bios/Arcade/Arcade/hiscore.dat", + "cores": [ + "fbalpha2012" + ], + "systems": [ + "arcade" + ], + "root": "save" + }, + { + "dest": "cps3/hiscore.dat", + "sha1": "7381472bf046126257e51a0124e4553282f020e5", + "sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5", + "size": 322458, + "repo_path": "bios/Arcade/Arcade/hiscore.dat", + "cores": [ + "fbalpha2012", + "fbalpha2012_cps3" + ], + "systems": [ + "arcade" + ], + "root": "save" + }, + { + "dest": "fba/hiscore.dat", + "sha1": "7381472bf046126257e51a0124e4553282f020e5", + "sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5", + "size": 322458, + "repo_path": "bios/Arcade/Arcade/hiscore.dat", + "cores": [ + "fbalpha2012", + "fbalpha2012_cps3" + ], + "systems": [ + "arcade" + ], + "root": "save" + }, + { + "dest": "mame/hiscore.dat", + "sha1": "7381472bf046126257e51a0124e4553282f020e5", + "sha256": "9d44fc928c0df41debad1b86739bd6ca96a5891b3b499f6fb3d7e9ea95ca8de5", + "size": 322458, + "repo_path": "bios/Arcade/Arcade/hiscore.dat", + "cores": [ + "fbalpha2012" + ], + "systems": [ + "arcade" + ], + "root": "save" + }, { "dest": "bios/fba2012/samples/dkong.zip", "sha1": "764ec667084bc237c1de6bd1db7541ad8cb59975", @@ -106565,6 +106839,48 @@ "commodore-c64" ] }, + { + "dest": "amiga/fsuae/Kickstarts/rom.key", + "sha1": "801bbab32e3d37386dd1636d4f1d6fa7e21d5874", + "sha256": "baf2366ae04337d37e7b37ebfb5cd7af7e4ffddeb6b017bf2e5fec43d87764e0", + "size": 2069, + "repo_path": "bios/Commodore/Amiga/rom.key", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga1200/fsuae/Kickstarts/rom.key", + "sha1": "801bbab32e3d37386dd1636d4f1d6fa7e21d5874", + "sha256": "baf2366ae04337d37e7b37ebfb5cd7af7e4ffddeb6b017bf2e5fec43d87764e0", + "size": 2069, + "repo_path": "bios/Commodore/Amiga/rom.key", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, + { + "dest": "amiga600/fsuae/Kickstarts/rom.key", + "sha1": "801bbab32e3d37386dd1636d4f1d6fa7e21d5874", + "sha256": "baf2366ae04337d37e7b37ebfb5cd7af7e4ffddeb6b017bf2e5fec43d87764e0", + "size": 2069, + "repo_path": "bios/Commodore/Amiga/rom.key", + "cores": [ + "fsuae" + ], + "systems": [ + "commodore-amiga" + ], + "root": "save" + }, { "dest": "bios/fuse/128p-0.rom", "sha1": "d07fcdeca892ee80494d286ea9ea5bf3928a1aca", @@ -113371,6 +113687,34 @@ ], "category": "game_data" }, + { + "dest": "n3ds/Emulator Files/sysdata/aes_keys.txt", + "sha1": "29556640b022cbfaf427874695838b43a5e8aff4", + "sha256": "0d866e062cf62275fbb291ba44af253e67fdc5bd76c7640b6c4a9dfe742510d9", + "size": 7357, + "repo_path": "bios/Nintendo/3DS/aes_keys.txt", + "cores": [ + "panda3ds" + ], + "systems": [ + "nintendo-3ds" + ], + "root": "save" + }, + { + "dest": "n3ds/Emulator Files/sysdata/seeddb.bin", + "sha1": "9e2c006997761082be87cf316e57c4da5cddbc62", + "sha256": "ff485c60090185aff05354ece01f86b61f6020332bed0f9090c58d4678e5a180", + "size": 53264, + "repo_path": "bios/Nintendo/3DS/Citra/sysdata/seeddb.bin", + "cores": [ + "panda3ds" + ], + "systems": [ + "nintendo-3ds" + ], + "root": "save" + }, { "dest": "bios/mda.rom", "sha1": "c2a8b10808bf51a3c123ba3eb1e9dd608231916f", @@ -115924,6 +116268,90 @@ "j2me" ] }, + { + "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": "bios/KROM1.BIN", "sha1": "f4c74086a83b728b1c1af3a021a60efa80eff5a4", @@ -122197,5 +122625,10 @@ "sony-playstation-2" ] } - ] + ], + "save_directory": { + "folder": "saves", + "by_core": false, + "by_system": true + } } \ No newline at end of file diff --git a/platforms/_registry.yml b/platforms/_registry.yml index e3ffbad6..90d660fd 100644 --- a/platforms/_registry.yml +++ b/platforms/_registry.yml @@ -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/ 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/ 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). + # 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/ 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). 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\ (saves\\ - # 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\ 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). 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\\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/ 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/ 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 diff --git a/platforms/batocera.yml b/platforms/batocera.yml index fcf06b16..636ec81a 100644 --- a/platforms/batocera.yml +++ b/platforms/batocera.yml @@ -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 diff --git a/platforms/knulli.yml b/platforms/knulli.yml index 45e00ab0..947545a9 100644 --- a/platforms/knulli.yml +++ b/platforms/knulli.yml @@ -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 diff --git a/platforms/recalbox.yml b/platforms/recalbox.yml index ad54a51e..13249dcd 100644 --- a/platforms/recalbox.yml +++ b/platforms/recalbox.yml @@ -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 diff --git a/platforms/retrobat.yml b/platforms/retrobat.yml index d0adca3d..b4dbadaf 100644 --- a/platforms/retrobat.yml +++ b/platforms/retrobat.yml @@ -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 diff --git a/platforms/retrodeck.yml b/platforms/retrodeck.yml index 3506c588..f59aa340 100644 --- a/platforms/retrodeck.yml +++ b/platforms/retrodeck.yml @@ -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 diff --git a/schemas/install-manifest.schema.json b/schemas/install-manifest.schema.json index 41882b9b..dee48ee1 100644 --- a/schemas/install-manifest.schema.json +++ b/schemas/install-manifest.schema.json @@ -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 / 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 } } } diff --git a/schemas/platform.schema.json b/schemas/platform.schema.json index b6007472..f652fba7 100644 --- a/schemas/platform.schema.json +++ b/schemas/platform.schema.json @@ -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.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//)", diff --git a/scripts/generate_pack.py b/scripts/generate_pack.py index f10c97b2..c43bdb81 100644 --- a/scripts/generate_pack.py +++ b/scripts/generate_pack.py @@ -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, diff --git a/scripts/packextras.py b/scripts/packextras.py index 1dcd773d..5895ad7b 100644 --- a/scripts/packextras.py +++ b/scripts/packextras.py @@ -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 = { diff --git a/scripts/packpaths.py b/scripts/packpaths.py index 54fb0eb5..3673628e 100644 --- a/scripts/packpaths.py +++ b/scripts/packpaths.py @@ -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 /, RetroArch's sort_savefiles_enable. + ``by_system`` is set when the launcher hands a core /, the system it was launched for (Batocera's + /userdata/saves/): 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: diff --git a/scripts/packreadme.py b/scripts/packreadme.py index 11fffe12..2cdeb8ed 100644 --- a/scripts/packreadme.py +++ b/scripts/packreadme.py @@ -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 = ( diff --git a/scripts/scraper/batocera_scraper.py b/scripts/scraper/batocera_scraper.py index 14df84a4..dd166749 100644 --- a/scripts/scraper/batocera_scraper.py +++ b/scripts/scraper/batocera_scraper.py @@ -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/ 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}") ) diff --git a/scripts/scraper/knulli_scraper.py b/scripts/scraper/knulli_scraper.py index 9cda899b..7c293690 100644 --- a/scripts/scraper/knulli_scraper.py +++ b/scripts/scraper/knulli_scraper.py @@ -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/, 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 diff --git a/scripts/scraper/recalbox_scraper.py b/scripts/scraper/recalbox_scraper.py index b8ce473c..84ef8dfb 100644 --- a/scripts/scraper/recalbox_scraper.py +++ b/scripts/scraper/recalbox_scraper.py @@ -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/ + (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(), } diff --git a/scripts/scraper/retrobat_scraper.py b/scripts/scraper/retrobat_scraper.py index c0bd706e..720ec618 100644 --- a/scripts/scraper/retrobat_scraper.py +++ b/scripts/scraper/retrobat_scraper.py @@ -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\\ 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)), } diff --git a/scripts/scraper/retrodeck_scraper.py b/scripts/scraper/retrodeck_scraper.py index 22261886..4b6797d9 100644 --- a/scripts/scraper/retrodeck_scraper.py +++ b/scripts/scraper/retrodeck_scraper.py @@ -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/, the system's 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), } diff --git a/scripts/validate_schemas.py b/scripts/validate_schemas.py index d04e5827..165f71d1 100644 --- a/scripts/validate_schemas.py +++ b/scripts/validate_schemas.py @@ -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: , by_core: }" + "{folder: , by_core: , by_system: , " + "by_core_for: []}" + ) + 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) diff --git a/scripts/verify.py b/scripts/verify.py index 1800f56c..8e509567 100644 --- a/scripts/verify.py +++ b/scripts/verify.py @@ -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", } diff --git a/tests/test_save_root.py b/tests/test_save_root.py index 68489e00..f3c7eebc 100644 --- a/tests/test_save_root.py +++ b/tests/test_save_root.py @@ -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/, RetroBat's + saves\\ 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 = ( + "3ds" + "azahar" + "" + "citra-qt" + "" + ) + 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 = ( + "n3ds%ROMPATH%/n3ds" + "%EMULATOR_AZAHAR% %ROM%" + "%EMULATOR_RETROARCH% -L " + "%CORE_RETROARCH%/citra_libretro.so %ROM%" + "" + "" + ) + 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: diff --git a/wiki/adding-a-platform.md b/wiki/adding-a-platform.md index f5f30c74..8b6411fc 100644 --- a/wiki/adding-a-platform.md +++ b/wiki/adding-a-platform.md @@ -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 / 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 diff --git a/wiki/installer.md b/wiki/installer.md index 3d74d79e..4ed40c06 100644 --- a/wiki/installer.md +++ b/wiki/installer.md @@ -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: diff --git a/wiki/profiling.md b/wiki/profiling.md index d2d6c6ae..7b976038 100644 --- a/wiki/profiling.md +++ b/wiki/profiling.md @@ -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/` 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