Files
libretro/schemas/install-manifest.schema.json
T
Abdessamad Derraz 05f3f5c702 feat: honour the boards a folder offers a core on
ROCKNIX writes some add_emu_core calls under a case on DEVICE, and the
rom folders file keeps that branch as the offer's `when` (uae4arm for
amiga, emulators/package.mk:188). A board's core list names such a core
when another folder offers it there, so --target placed its files in a
folder the board does not offer it for.

offer_boards() reads `when` and board_defaults against the platform's
targets, aliases included. A board build (generate_pack and generate
--manifest with --target, verify --target) carries the board in the
config (TARGET_KEY), and content_folder_tags leaves out the pairs the
board is not offered. A manifest for every board lists in
offered_boards each profile placed in such a folder, and install.py
--target drops its files there on the other boards.

Manifests: no file moves. The cores ROCKNIX offers under a device case
read no file beside the game today, so no manifest carries
offered_boards yet.
2026-11-11 13:46:57 +01:00

1190 lines
45 KiB
JSON

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://abdess.github.io/retrobios/api/v1/schemas/install-manifest.schema.json",
"title": "RetroBIOS installer manifest",
"type": "object",
"additionalProperties": false,
"required": [
"manifest_version",
"source",
"regions",
"platform",
"display_name",
"version",
"generated",
"base_destination",
"detect",
"standalone_copies",
"total_files",
"total_size",
"total_omitted",
"omitted_files",
"files"
],
"properties": {
"manifest_version": {
"const": 2,
"description": "Format version of the manifest. install.py refuses a version it does not know."
},
"source": {
"enum": [
"full",
"platform",
"truth"
],
"description": "Which files the pack was built from: full (the platform's list plus the files its cores load), platform (the list alone) or truth (the cores' files alone)."
},
"regions": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"description": "Region priority the manifest was narrowed to, best first. Empty when it was not narrowed."
},
"target": {
"type": "string",
"minLength": 1,
"description": "Hardware target this manifest was filtered for, absent when unfiltered"
},
"categorized": {
"description": "Every game data file carries category: game_data. Without it the list records no category, and the installer refuses --no-game-data.",
"const": true
},
"no_game_data": {
"description": "Built without game data, absent when the game data is listed",
"const": true
},
"platform": {
"type": "string",
"minLength": 1,
"description": "Registry key of the platform (batocera)."
},
"display_name": {
"type": "string",
"minLength": 1,
"description": "Name the site shows for the platform."
},
"version": {
"type": "string",
"minLength": 1,
"description": "Version of the platform's own list this manifest was built from, as the platform YAML records it (inherits: resolved): the release tag the scraper read (Batocera 43.1, Recalbox 10.1.1). A list kept on a branch with no release records what the scraper pinned instead: MinUI, MyMinUI and NextUI the date of the pinned commit, MiSTer the timestamp of the BiosDB it read. RetroArch and Lakka name the RetroArch release current when System.dat was read at its pinned commit, RetroPie the __version of RetroPie-Setup at its pinned commit."
},
"generated": {
"type": "string",
"format": "date-time",
"description": "When the manifest was written."
},
"base_destination": {
"type": "string",
"description": "The BIOS folder entries are written below, as the platform names it. Empty when entries start one level higher (RetroDECK)."
},
"detect": {
"type": "array",
"items": {
"type": "object"
},
"description": "Rules install.py follows to find this setup and its BIOS folder on a machine, one per method and operating system."
},
"standalone_copies": {
"type": "array",
"items": {
"type": "object"
},
"description": "Files install.py also copies into the folders of standalone emulators it finds, or a note it prints when their folder exists."
},
"total_files": {
"type": "integer",
"minimum": 0,
"description": "Number of entries in files."
},
"total_size": {
"type": "integer",
"minimum": 0,
"description": "Bytes of the files in files."
},
"pack_files": {
"description": "Files the platform's pack holds once extracted: this list, the data directories and the pack's own documents.",
"type": "integer",
"minimum": 0
},
"pack_size": {
"description": "Bytes those files occupy once extracted.",
"type": "integer",
"minimum": 0
},
"total_omitted": {
"type": "integer",
"minimum": 0,
"description": "Number of entries in omitted_files."
},
"core_names": {
"description": "Each core the platform runs or a file names, with the other names it goes by upstream (the buildbot's mednafen_psx for beetle_psx), empty when it has none.",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"uniqueItems": true
}
},
"downloaded_cores": {
"description": "Each core only the platform's RetroArch core downloader brings, with the boards and board aliases whose downloader offers it. install.py --target keeps the files of such a core on those boards only.",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"uniqueItems": true
}
},
"offered_boards": {
"description": "Each core a roms folder of the platform offers on some boards only, with the folder (below the roms root, or the install tree) and the boards and board aliases it is offered on. install.py --target keeps the core's files in that folder on those boards only.",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["root", "folder", "boards"],
"properties": {
"root": {"enum": ["roms", "install"]},
"folder": {"type": "string", "minLength": 1},
"boards": {
"type": "array",
"items": {"type": "string", "minLength": 1},
"uniqueItems": true
}
}
}
}
},
"system_cores": {
"description": "Each platform system with the cores whose presence keeps it. A system absent here is kept whatever cores are available.",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"uniqueItems": true
}
},
"system_titles": {
"description": "Each system id with the name a person reads for it, the one the site prints (Sony PlayStation). A system the site cannot name is absent.",
"type": "object",
"additionalProperties": {
"type": "string",
"minLength": 1
}
},
"system_names": {
"description": "Each platform system with the names the platform's own file gives it (native_system), which the installer accepts for --system.",
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"uniqueItems": true
}
},
"omitted_files": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"dest",
"name",
"system",
"required",
"reason",
"cores"
],
"properties": {
"dest": {
"type": "string",
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$)).+$",
"description": "Where the file would go, below base_destination, below the save directory when root is save, below the roms folder when root is roms, in an emulator folder when root is emulators (its key first), or in the emulator's own folder when root is emulator."
},
"name": {
"type": "string",
"minLength": 1,
"description": "File name the declaration gives."
},
"system": {
"type": "string",
"description": "System id of the declaration. Empty when the core's file names none."
},
"required": {
"type": "boolean",
"description": "The platform or the core needs the file to run, as the declaration says."
},
"reason": {
"enum": [
"hash_mismatch",
"not_found",
"external",
"user_provided",
"no_platform_slug",
"below_platform_folder",
"no_save_directory",
"no_core_folder",
"no_save_system",
"outside_bios_folder",
"no_roms_directory",
"no_emulators_directory",
"no_configs_directory"
],
"description": "Why the file is left out, as a code. enumDescriptions gives the meaning of each code, in the order of enum.",
"enumDescriptions": [
"The platform checks the hash and the only copy held contradicts the one it declares, so the frontend would refuse it.",
"The collection holds no copy the declaration accepts.",
"The declaration keeps the file outside the repository (storage: external). The pack builder downloads it from its own address, the installer does not.",
"The user supplies the file (storage: user_provided). The pack writes its instructions in its place.",
"The platform keeps one folder per system and has none for the system the core's file belongs to.",
"The platform lists each system folder flat (firmware_folder_flat) and the file would sit in a subfolder it does not read.",
"The core reads the file below the save directory and the platform has no save directory a pack can fill.",
"The frontend sorts saves by core and the core's profile does not name its folder (core_folder).",
"The launcher gives each system its own save folder and no system of the platform runs the core.",
"The platform runs the emulator from a folder outside the BIOS tree and links none of the BIOS tree where the emulator reads this file (root: emulator).",
"The platform's launcher runs the file from its roms folder (root: roms) and the run cannot tell where that folder is: the BIOS folder is not the one the platform keeps in it.",
"The platform's launcher runs the file from one of its emulator folders (root: emulators) and the run cannot place it there: the BIOS folder is not the one beside the platform's launcher config, or that config sets the folder.",
"The platform's launcher starts the emulator from a folder of its configs folder (root: configs) and the run cannot tell where that folder is: the BIOS folder is not the one the platform keeps beside it."
]
},
"category": {
"description": "game_data: a game's own data, not firmware. Absent on firmware.",
"const": "game_data"
},
"held": {
"description": "The pack builder holds this file and the installer cannot download it. Region narrowing counts it held, as the builder does, so it displaces the same fallback.",
"const": true
},
"cores": {
"oneOf": [
{
"type": "null"
},
{
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
}
],
"description": "Profiles whose core wants the file. Null for a file the platform's own list declares."
},
"regions": {
"description": "The regions the emulator code selects the file for. Absent when it never competes.",
"type": "array",
"items": {
"type": "string",
"enum": [
"argentina",
"asia",
"asia-ntsc",
"asia-pal",
"australia",
"brazil",
"canada",
"china",
"denmark",
"europe",
"finland",
"france",
"germany",
"greece",
"hong-kong",
"india",
"italy",
"japan",
"latin-america",
"mexico",
"netherlands",
"new-zealand",
"north-america",
"norway",
"oceania",
"poland",
"portugal",
"russia",
"singapore",
"south-korea",
"spain",
"sweden",
"taiwan",
"uk",
"world"
]
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"region_groups": {
"description": "Groups the file competes in as a core extra, whatever systems are chosen.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"region_system_groups": {
"description": "Groups the file competes in as the platform's own declaration: present only when that system is kept.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"systems": {
"description": "Every platform system that declares the file, for the installer's --system.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"priority": {
"description": "The rank the code searches the file at, lower first: a world file withdraws an unmatched regional one only when it ranks no worse.",
"type": "integer"
},
"declared_in": {
"description": "The platform systems declaring the file, when fewer than `systems`, which also names the systems whose cores read it there.",
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"uniqueItems": true
},
"alternatives": {
"description": "Cores claiming this destination behind the platform's own declaration, in the order the pack builder tries them. A narrowing that drops every declaring system takes the first whose cores remain.",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"cores"
],
"properties": {
"cores": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true,
"description": "Profiles of the cores that claim the destination together."
}
}
}
},
"root": {
"description": "save: dest is relative to the save directory the frontend hands the core (RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY), not to the BIOS directory. emulator: dest is the path the emulator reads in its own folder, which the platform keeps outside the BIOS tree (reason outside_bios_folder). roms: dest is relative to the platform's roms folder (roms_directory). emulators: dest is the emulator folder's key then the path in it (emulators_directory). configs: dest is relative to the frontend's configs folder (configs_directory). Absent for a file of the BIOS tree.",
"enum": [
"save",
"emulator",
"roms",
"emulators",
"configs"
]
},
"core_folder": {
"description": "The core's library_name, the folder a frontend sorting saves by core (RetroArch's sort_savefiles_enable) inserts between its save directory and dest. Only with root: save. Absent on a save entry when the core reads the same place sorted or not.",
"type": "string",
"minLength": 1,
"pattern": "^[^/\\\\]+$"
}
}
},
"description": "Files the pack needs and the repository cannot serve, with the reason."
},
"files": {
"type": "array",
"items": {
"$ref": "#/$defs/file"
},
"description": "Every file the installer fetches, one entry per destination."
},
"case_variants": {
"description": "Files the folded list serves under another case, installed only where the target directory keeps case.",
"type": "array",
"items": {
"$ref": "#/$defs/file"
}
},
"data_directories": {
"description": "Data trees the pack carries, rebuilt by the installer from their source archive. Each file is kept only when its sha1 matches.",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"ref",
"dest",
"url",
"type",
"systems",
"files"
],
"properties": {
"ref": {
"type": "string",
"description": "Key of the data directory in platforms/_data_dirs.yml."
},
"dest": {
"type": "string",
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$)).*$",
"description": "Folder below base_destination the tree is rebuilt in. Empty for base_destination itself."
},
"url": {
"type": "string",
"pattern": "^https://",
"description": "HTTPS address of the source archive the installer downloads."
},
"type": {
"enum": [
"zip",
"tarball"
],
"description": "Format of the source archive: zip, or tarball (gzip)."
},
"strip_components": {
"type": "integer",
"minimum": 0,
"description": "With type zip: leading path parts dropped from each member."
},
"archive_size": {
"type": "integer",
"minimum": 1,
"description": "Bytes of the source archive when it was last downloaded: what fetching the tree costs. Absent when not recorded."
},
"source_path": {
"type": "string",
"description": "With type tarball: only members below this path are kept, relative to it."
},
"exclude": {
"type": "array",
"items": {
"type": "string"
},
"description": "First path parts left out of the tree."
},
"systems": {
"type": "array",
"items": {
"type": "string"
},
"description": "Platform systems whose cores read the tree."
},
"optional": {
"type": "boolean",
"const": true,
"description": "Every core reading the tree runs without it (required: false in its profile): --required-only leaves it out."
},
"cores": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"description": "The cores that read the tree, when no platform system declares it: an install for the games of a card keeps it only when its plan runs one of them."
},
"files": {
"type": "object",
"additionalProperties": {
"type": "object",
"additionalProperties": false,
"required": [
"sha1",
"size"
],
"properties": {
"sha1": {
"type": "string",
"pattern": "^[a-f0-9]{40}$",
"description": "SHA1 the file must have."
},
"size": {
"type": "integer",
"minimum": 0,
"description": "Bytes of the file."
}
}
},
"description": "Every file of the tree by its path below dest. A member whose sha1 differs is refused."
}
}
}
},
"save_directory": {
"description": "Where the platform keeps the save directory its frontend hands a core, present when an entry carries root: save. folder is the pack folder holding those files and the save directory's default place beside the BIOS directory, and by_core says the frontend appends each core's library_name (core_folder).",
"type": "object",
"additionalProperties": false,
"required": [
"folder",
"by_core"
],
"properties": {
"folder": {
"type": "string",
"pattern": "^[^/\\\\.][^/\\\\]*(/[^/\\\\.][^/\\\\]*)*$",
"description": "Pack folder holding the save entries, also the save directory's default place beside the BIOS directory."
},
"by_core": {
"type": "boolean",
"description": "true when the frontend inserts each core's library_name (core_folder) below the save directory."
},
"by_system": {
"description": "true when the platform's launcher hands each core <save directory>/<system> at each launch (Batocera, RetroBat). Each dest then starts with that system's folder, and no frontend config read at install time changes it.",
"const": true
}
}
},
"roms_directory": {
"description": "Where the platform keeps its roms root, present when an entry carries root: roms. from_bios is that root relative to the BIOS folder (\".\" for the folder itself, else one or two \"..\" then plain names), as platforms/romfolders/<platform>.yml records it from the OS's own source (roms_root.from_bios). It is followed only from a BIOS folder named bios_folder (the platform's base_destination). Any other leaves root: roms entries out (no_roms_directory).",
"type": "object",
"additionalProperties": false,
"required": [
"bios_folder",
"from_bios"
],
"properties": {
"bios_folder": {
"description": "Name of the BIOS folder from_bios starts from, the platform's base_destination.",
"type": "string",
"minLength": 1,
"pattern": "^[^/\\\\]+$"
},
"from_bios": {
"description": "The roms root relative to that BIOS folder.",
"type": "string",
"pattern": "^(\\.|\\.\\.(/\\.\\.)?(/[^/\\\\:.][^/\\\\:]*)*)$",
"maxLength": 1024
}
}
},
"emulators_directory": {
"description": "Where the platform keeps its emulator folders, present when an entry carries root: emulators. Paths are relative to the folder holding the BIOS folder, which is named bios_folder. searched are the places the launcher tries for a key, in order, default the one the installer creates when none exists, and config the launcher's key=value file: a key it sets moves the folder, and its files are left out (no_emulators_directory).",
"type": "object",
"additionalProperties": false,
"required": [
"bios_folder",
"searched",
"default",
"config"
],
"properties": {
"bios_folder": {
"description": "Name of the BIOS folder. The other paths are relative to the folder holding it.",
"type": "string",
"minLength": 1,
"pattern": "^[^/\\\\]+$"
},
"searched": {
"description": "The places the launcher tries for an emulator key, in order, {key} standing for it.",
"type": "array",
"minItems": 1,
"items": {
"type": "string",
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$)).*\\{key\\}.*$"
}
},
"default": {
"description": "The place the installer creates when none of searched exists.",
"type": "string",
"pattern": "\\{key\\}"
},
"config": {
"description": "The launcher's key=value file, a key of which moves the folder.",
"type": "string",
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$)).+$"
}
}
},
"configs_directory": {
"description": "Where the frontend keeps its emulators' configs, present when an entry carries root: configs. from_bios is that folder relative to the BIOS folder, as the platform's own path code builds it (Batocera's batoceraPaths CONFIGS, ../system/configs), with the rules of roms_directory.from_bios. It is followed only from a BIOS folder named bios_folder. Any other leaves root: configs entries out (no_configs_directory).",
"type": "object",
"additionalProperties": false,
"required": [
"bios_folder",
"from_bios"
],
"properties": {
"bios_folder": {
"description": "Name of the BIOS folder from_bios starts from, the platform's base_destination.",
"type": "string",
"minLength": 1,
"pattern": "^[^/\\\\]+$"
},
"from_bios": {
"description": "The configs folder relative to that BIOS folder.",
"type": "string",
"pattern": "^(\\.|\\.\\.(/\\.\\.)?(/[^/\\\\:.][^/\\\\:]*)*)$",
"maxLength": 1024
}
}
}
},
"$defs": {
"file": {
"type": "object",
"additionalProperties": false,
"required": [
"dest",
"sha1",
"sha256",
"size",
"repo_path",
"cores"
],
"properties": {
"dest": {
"type": "string",
"pattern": "^(?!/)(?!.*(?:^|/)\\.\\.(?:/|$)).+$",
"description": "Path below base_destination, below the save directory when root is save, below the roms folder when root is roms, below the configs folder when root is configs, or in an emulator folder when root is emulators (its key first)."
},
"sha1": {
"type": "string",
"pattern": "^[a-f0-9]{40}$",
"description": "SHA1 of the copy the repository serves. The installer checks it after download."
},
"sha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA256 of the same copy."
},
"size": {
"type": "integer",
"minimum": 0,
"description": "Bytes of the same copy."
},
"repo_path": {
"type": "string",
"description": "Path in the repository. Fetched from `https://raw.githubusercontent.com/Abdess/retrobios/<ref>/<repo_path>`, ref being main unless RETROBIOS_REF names a tag."
},
"cores": {
"oneOf": [
{
"type": "null"
},
{
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
}
],
"description": "Profiles whose core brings the file into the pack. Null for a file the platform's own list declares."
},
"storage": {
"const": "release",
"description": "release when the file is a large-files release asset."
},
"release_asset": {
"type": "string",
"pattern": "^[^/\\\\]+$",
"description": "Asset of the large-files release, fetched from `https://github.com/Abdess/retrobios/releases/download/large-files/<asset>` instead of repo_path."
},
"systems": {
"description": "Every platform system that declares the file, for the installer's --system.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"regions": {
"description": "The regions the emulator code selects the file for. Absent when it never competes.",
"type": "array",
"items": {
"type": "string",
"enum": [
"argentina",
"asia",
"asia-ntsc",
"asia-pal",
"australia",
"brazil",
"canada",
"china",
"denmark",
"europe",
"finland",
"france",
"germany",
"greece",
"hong-kong",
"india",
"italy",
"japan",
"latin-america",
"mexico",
"netherlands",
"new-zealand",
"north-america",
"norway",
"oceania",
"poland",
"portugal",
"russia",
"singapore",
"south-korea",
"spain",
"sweden",
"taiwan",
"uk",
"world"
]
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"region_groups": {
"description": "Groups the file competes in as a core extra, whatever systems are chosen.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"region_system_groups": {
"description": "Groups the file competes in as the platform's own declaration: present only when that system is kept.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"priority": {
"description": "The rank the code searches the file at, lower first: a world file withdraws an unmatched regional one only when it ranks no worse.",
"type": "integer"
},
"alternatives": {
"description": "Copies other cores read at this destination when they disagree on its content, in the order the pack builder tries them. A narrowing that drops the entry's cores takes the first whose cores remain.",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"sha1",
"sha256",
"size",
"repo_path",
"cores"
],
"properties": {
"sha1": {
"type": "string",
"pattern": "^[a-f0-9]{40}$",
"description": "SHA1 of this copy."
},
"sha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA256 of this copy."
},
"size": {
"type": "integer",
"minimum": 0,
"description": "Bytes of this copy."
},
"repo_path": {
"type": "string",
"description": "Path of this copy in the repository, fetched as the entry's repo_path is."
},
"storage": {
"const": "release",
"description": "release when this copy is a large-files release asset."
},
"release_asset": {
"type": "string",
"pattern": "^[^/\\\\]+$",
"description": "Asset of the large-files release holding this copy, fetched instead of repo_path."
},
"cores": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true,
"description": "Profiles whose core reads this copy."
},
"executable": {
"type": "boolean",
"description": "The repository keeps this copy executable."
}
}
}
},
"slot_choices": {
"description": "On a platform file a core's own source contradicts while the frontend only checks the path: the copy each core's presence puts there, in the order the pack builder settles the slot. A narrowing serves the first whose cores remain. One naming only cores, or none remaining, leaves `declared_choices`.",
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"cores"
],
"properties": {
"sha1": {
"type": "string",
"pattern": "^[a-f0-9]{40}$",
"description": "SHA1 of this copy."
},
"sha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA256 of this copy."
},
"size": {
"type": "integer",
"minimum": 0,
"description": "Bytes of this copy."
},
"repo_path": {
"type": "string",
"description": "Path of this copy in the repository, fetched as the entry's repo_path is."
},
"storage": {
"const": "release",
"description": "release when this copy is a large-files release asset."
},
"release_asset": {
"type": "string",
"pattern": "^[^/\\\\]+$",
"description": "Asset of the large-files release holding this copy, fetched instead of repo_path."
},
"cores": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true,
"description": "Profiles whose presence puts this copy in the slot."
},
"executable": {
"type": "boolean",
"description": "The repository keeps this copy executable."
}
}
}
},
"declared_choices": {
"description": "The platform's own answer at the destination by the declaring systems that remain, in the order the pack builder takes the declarations. A narrowing serves the first whose systems remain.",
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"sha1",
"sha256",
"size",
"repo_path",
"systems"
],
"properties": {
"sha1": {
"type": "string",
"pattern": "^[a-f0-9]{40}$",
"description": "SHA1 of this copy."
},
"sha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA256 of this copy."
},
"size": {
"type": "integer",
"minimum": 0,
"description": "Bytes of this copy."
},
"repo_path": {
"type": "string",
"description": "Path of this copy in the repository, fetched as the entry's repo_path is."
},
"storage": {
"const": "release",
"description": "release when this copy is a large-files release asset."
},
"release_asset": {
"type": "string",
"pattern": "^[^/\\\\]+$",
"description": "Asset of the large-files release holding this copy, fetched instead of repo_path."
},
"executable": {
"type": "boolean",
"description": "The repository keeps this copy executable."
},
"systems": {
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"minItems": 1,
"uniqueItems": true,
"description": "Platform systems whose declaration this copy answers."
}
}
}
},
"category": {
"description": "game_data: a game's own data, not firmware. Absent on firmware. The installer's --no-game-data leaves these out, as a pack built with --no-game-data does.",
"const": "game_data"
},
"executable": {
"description": "The repository keeps the file executable, and the installer gives it the execute bits the umask allows.",
"type": "boolean"
},
"declared_in": {
"description": "The platform systems declaring the file, when fewer than `systems`, which also names the systems whose cores read it there.",
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"uniqueItems": true
},
"absent_claims": {
"description": "Cores that want this destination and have nothing held, after the cores served here: a narrowing that keeps none of those takes the first named one as a file left out, as a pack built for it lists it.",
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"system",
"required",
"reason",
"cores"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"description": "File name the declaration gives."
},
"system": {
"type": "string",
"description": "System id of the declaration. Empty when the core's file names none."
},
"required": {
"type": "boolean",
"description": "The platform or the core needs the file to run, as the declaration says."
},
"reason": {
"enum": [
"hash_mismatch",
"not_found",
"external",
"user_provided",
"no_platform_slug",
"below_platform_folder"
],
"description": "Why the file is left out, as a code. enumDescriptions gives the meaning of each code, in the order of enum.",
"enumDescriptions": [
"The platform checks the hash and the only copy held contradicts the one it declares, so the frontend would refuse it.",
"The collection holds no copy the declaration accepts.",
"The declaration keeps the file outside the repository (storage: external). The pack builder downloads it from its own address, the installer does not.",
"The user supplies the file (storage: user_provided). The pack writes its instructions in its place.",
"The platform keeps one folder per system and has none for the system the core's file belongs to.",
"The platform lists each system folder flat (firmware_folder_flat) and the file would sit in a subfolder it does not read."
]
},
"cores": {
"oneOf": [
{
"type": "null"
},
{
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
}
],
"description": "Profiles whose core wants the file. Null for a file the platform's own list declares."
},
"regions": {
"description": "The regions the emulator code selects the file for. Absent when it never competes.",
"type": "array",
"items": {
"type": "string",
"enum": [
"argentina",
"asia",
"asia-ntsc",
"asia-pal",
"australia",
"brazil",
"canada",
"china",
"denmark",
"europe",
"finland",
"france",
"germany",
"greece",
"hong-kong",
"india",
"italy",
"japan",
"latin-america",
"mexico",
"netherlands",
"new-zealand",
"north-america",
"norway",
"oceania",
"poland",
"portugal",
"russia",
"singapore",
"south-korea",
"spain",
"sweden",
"taiwan",
"uk",
"world"
]
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"region_groups": {
"description": "Groups the file competes in as a core extra, whatever systems are chosen.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"region_system_groups": {
"description": "Groups the file competes in as the platform's own declaration: present only when that system is kept.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"systems": {
"description": "Every platform system that declares the file, for the installer's --system.",
"type": "array",
"items": {
"type": "string",
"minLength": 1,
"maxLength": 256
},
"minItems": 1,
"maxItems": 1000,
"uniqueItems": true
},
"priority": {
"description": "The rank the code searches the file at, lower first: a world file withdraws an unmatched regional one only when it ranks no worse.",
"type": "integer"
},
"declared_in": {
"description": "The platform systems declaring the file, when fewer than `systems`, which also names the systems whose cores read it there.",
"type": "array",
"items": {
"type": "string",
"minLength": 1
},
"uniqueItems": true
}
}
}
},
"root": {
"description": "save: dest is relative to the save directory the frontend hands the core (RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY), not to the BIOS directory. roms: dest is relative to the platform's roms folder, which roms_directory locates (a file its launcher runs from there, ROCKNIX's roms/pico-8). emulators: dest is the key of an emulator folder of the platform, then the path in it, located by emulators_directory (RetroBat's emulators/pico8). configs: dest is relative to the frontend's configs folder, which configs_directory locates (Batocera starts shadPS4 from configs/shadps4). Absent for a file of the BIOS tree.",
"enum": [
"save",
"roms",
"emulators",
"configs"
]
},
"core_folder": {
"description": "The core's library_name, the folder a frontend sorting saves by core (RetroArch's sort_savefiles_enable) inserts between its save directory and dest. Only with root: save. Absent on a save entry when the core reads the same place sorted or not.",
"type": "string",
"minLength": 1,
"pattern": "^[^/\\\\]+$"
}
},
"oneOf": [
{
"required": [
"release_asset"
]
},
{
"properties": {
"repo_path": {
"type": "string",
"pattern": "^bios/",
"description": "Without release_asset, the copy is served from the repository's bios/ tree."
}
},
"not": {
"required": [
"release_asset"
]
}
}
]
}
},
"description": "What a platform's pack installs, one file per entry, as install.py reads it. The platform's list says what the setup checks, this list says what the pack writes: the list's files plus every file the setup's cores load."
}