Files
libretro/schemas/platform.schema.json
T
Abdessamad Derraz cedeee2254 refactor: one meaning for copy records
A copies record names its files under search_dir, the folder the code
copies from, and passes_to is the target, as the schema and RetroPie,
RetroDECK and AmberELEC already write it. KNULLI listed patches.zip
under the BIOS folder it is copied into, and KNULLI and RetroBat wrote
the target as prose with the condition. The condition of a copy now
goes in depends_on_option. Only launcher records change in knulli.yml
and retrobat.yml.
2026-11-09 17:58:37 +01:00

577 lines
19 KiB
JSON

{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://abdess.github.io/retrobios/api/v1/schemas/platform.schema.json",
"title": "Platform Configuration",
"description": "Schema for retrogaming platform BIOS configuration files",
"type": "object",
"additionalProperties": false,
"required": [
"platform"
],
"properties": {
"inherits": {
"type": "string",
"description": "Parent platform config to inherit from (e.g., 'retroarch')"
},
"platform": {
"type": "string",
"description": "Platform display name"
},
"version": {
"type": "string",
"description": "Platform version"
},
"dat_version": {
"type": "string"
},
"cores": {
"oneOf": [
{
"type": "string"
},
{
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
}
]
},
"standalone_cores": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true
},
"dual_mode_cores": {
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"description": "Emulators of standalone_cores the platform also launches as a libretro core: both layouts get their files"
},
"libretro_systems": {
"type": "object",
"description": "libretro core name -> the systems the platform's system list offers it for, as the launcher names them. A launcher handing each core <save directory>/<system> (save_directory.by_system in the registry) places a file the core reads below its save directory once in each of these folders",
"additionalProperties": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string",
"minLength": 1,
"pattern": "^[^/\\\\]+$"
}
}
},
"core_system_dirs": {
"type": "object",
"description": "The libretro system directory the platform hands each core, keyed by that directory relative to the pack root. A platform that declares it gives a core no other directory: the core's files are placed below each directory listed for it, and a core listed nowhere gets none (MinUI hands each launch tag its own Bios/<TAG>/)",
"additionalProperties": {
"type": "object",
"additionalProperties": false,
"required": [
"cores",
"source_ref"
],
"properties": {
"cores": {
"type": "array",
"minItems": 1,
"uniqueItems": true,
"items": {
"type": "string"
},
"description": "Libretro cores the platform starts with this directory, by the name of their .so"
},
"devices": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
},
"description": "Devices whose build ships a launcher for this directory"
},
"source_ref": {
"type": "string",
"description": "file:line of the launcher that names the core, at the revision `source` pins"
}
}
}
},
"core_repositories": {
"type": "object",
"description": "Repositories each core of core_system_dirs is built from, read from the platform's build recipes",
"additionalProperties": {
"type": "array",
"uniqueItems": true,
"items": {
"type": "string"
}
}
},
"system_directory_ref": {
"type": "string",
"description": "file:line, at the revision `source` pins, of the code that sets the system directory core_system_dirs lists"
},
"homepage": {
"type": "string",
"format": "uri",
"description": "Platform homepage URL"
},
"source": {
"type": "string",
"description": "URL to source BIOS requirements list"
},
"base_destination": {
"type": "string",
"description": "Base directory for BIOS files on this platform"
},
"core_destination": {
"type": "string",
"minLength": 1,
"description": "With an empty base_destination, the directory core files go under (AmberELEC and EmuELEC declare bios/, neogeo/ and ports/ from /storage/roms, and their cores read bios/)"
},
"hash_type": {
"type": "string",
"enum": [
"sha1",
"md5",
"crc32",
"sha256"
],
"description": "Primary hash algorithm used by this platform"
},
"hash_rule": {
"type": "string",
"enum": [
"size_and_any_hash"
],
"description": "How a digest-mode frontend accepts a file when it is not one digest: size_and_any_hash requires the declared size, then any one of md5, sha1 and crc32 (RomM)"
},
"verification_mode": {
"type": "string",
"enum": [
"existence",
"md5",
"sha1"
],
"default": "existence",
"description": "How the platform verifies BIOS at runtime: existence (file exists), md5 (checks MD5 hash), sha1 (checks SHA1 hash)"
},
"systems": {
"type": "object",
"description": "Systems/consoles supported by this platform",
"additionalProperties": {
"$ref": "#/$defs/system"
}
},
"launchers": {
"type": "array",
"description": "What the platform's own launch code looks for and hands to each emulator or core, read by its scraper at the revision `source` pins",
"items": {
"$ref": "#/$defs/launcher"
}
},
"overrides": {
"type": "object",
"additionalProperties": false,
"description": "Override inherited system configs",
"properties": {
"systems": {
"type": "object",
"additionalProperties": {
"$ref": "#/$defs/system"
}
}
}
}
},
"$defs": {
"launcher": {
"type": "object",
"additionalProperties": false,
"required": [
"emulator",
"build",
"kind",
"names",
"source_ref"
],
"properties": {
"emulator": {
"type": "string",
"description": "Emulator or core as the platform names it (comma-separated when one code path serves several)"
},
"build": {
"type": "string",
"enum": [
"standalone",
"libretro"
]
},
"kind": {
"type": "string",
"enum": [
"names_searched",
"fixed_name",
"core_option",
"passes_path",
"links",
"copies",
"moves",
"scans_dir",
"package"
],
"description": "names_searched: tries the names in order, first found wins. fixed_name: writes or opens one path per name. core_option: sets a core option whose value names the file. passes_path: hands over a directory. links, copies: links or copies a file to where the emulator reads it (a copy names its files under search_dir, the folder it copies from, passes_to is the target, and the case that skips it is in depends_on_option). moves: moves a file the user left in one folder to the folder the launcher links from. scans_dir: the emulator picks from a directory. package: names no file, records what a package builds (`repo`) and the systems it registers (`systems`)"
},
"package": {
"type": "string",
"description": "The platform package whose script this record comes from, when the platform installs emulators as packages"
},
"repo": {
"type": "string",
"description": "What the package fetches and builds, as its script declares it: method, URL, then branch or commit"
},
"systems": {
"type": "array",
"items": {
"type": "string"
},
"description": "Systems the package registers, under the platform's own names, in the order the script adds them"
},
"slot": {
"type": "string",
"description": "The key the launcher files this list under, such as a region or a machine"
},
"names": {
"type": "array",
"items": {
"type": "string"
},
"description": "Names relative to search_dir, in the order the code tries or writes them. A {X} placeholder is expanded from `expands`"
},
"expands": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
},
"description": "Values a placeholder in `names` takes, in the order the code tries them for each name"
},
"case_insensitive": {
"type": "boolean",
"description": "Whether the launcher matches names regardless of case"
},
"search_dir": {
"type": "string",
"description": "Directory the launcher looks in, as the code resolves it"
},
"passes_to": {
"type": "string",
"description": "Where the found file is handed to the emulator: config key, command-line flag or core option"
},
"fails_when_missing": {
"oneOf": [
{
"type": "boolean"
},
{
"type": "string"
}
],
"description": "False when the launcher starts without the file, else the message it raises"
},
"fails_scope": {
"type": "string",
"enum": [
"emulator"
],
"description": "emulator: the failure is raised only when every record of this emulator with the same source_ref found nothing"
},
"depends_on_option": {
"type": "string",
"description": "Options or conditions in the launcher code that decide whether this record applies"
},
"device": {
"type": "string",
"description": "Devices whose shipped config this record reads, comma-separated, set only where the configs of a package differ between devices"
},
"source_ref": {
"type": "string",
"description": "path:lines in the platform's repository at the pinned revision"
}
}
},
"system": {
"type": "object",
"additionalProperties": false,
"properties": {
"core": {
"type": "string",
"description": "Emulator core name"
},
"cores": {
"type": "array",
"items": {"type": "string"},
"uniqueItems": true,
"description": "The emulators and cores the platform's system list offers this system, as the platform writes them, in its order"
},
"manufacturer": {
"type": "string",
"description": "Hardware manufacturer"
},
"name": {
"type": "string"
},
"native_id": {
"type": "string"
},
"dat_version": {
"type": "string",
"description": "Version of the DAT file used as source for BIOS hashes"
},
"source": {
"type": "string",
"description": "URL or reference to the source of BIOS requirements"
},
"release_year": {
"type": "integer",
"minimum": 1970,
"maximum": 2030,
"description": "Console release year"
},
"docs": {
"type": "string",
"format": "uri",
"description": "Documentation URL"
},
"includes": {
"type": "array",
"items": {
"type": "string"
},
"description": "Shared BIOS groups to include (from _shared.yml)"
},
"data_directories": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"ref"
],
"properties": {
"ref": {
"type": "string"
},
"destination": {
"type": "string"
},
"required": {
"type": "boolean",
"description": "false when the core runs without the tree; --required-only leaves it out"
}
}
}
},
"files": {
"type": "array",
"items": {
"$ref": "#/$defs/bios_file"
},
"description": "BIOS files required for this system"
},
"native_check": {
"type": "object",
"additionalProperties": false,
"description": "EmuDeck: the shape of the shell check written for this system",
"properties": {
"kind": {
"type": "string",
"enum": [
"md5",
"file-exists"
]
},
"function": {
"type": "string"
},
"var": {
"type": "string"
},
"array": {
"type": "string"
},
"firmware": {
"type": "string"
},
"keys": {
"type": "string"
}
}
}
}
},
"bios_file": {
"type": "object",
"additionalProperties": false,
"required": [
"name",
"destination"
],
"properties": {
"name": {
"type": "string",
"description": "BIOS filename"
},
"sha1": {
"type": "string",
"pattern": "^[a-f0-9]{40}$",
"description": "SHA1 hash"
},
"md5": {
"type": "string",
"pattern": "^[a-fA-F0-9]{32}(,[a-fA-F0-9]{32})*$",
"description": "MD5 hash (comma-separated for multi-hash)"
},
"sha256": {
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "SHA256 hash"
},
"crc32": {
"type": "string",
"pattern": "^[a-f0-9A-F0-9]{8}$",
"description": "CRC32 hash"
},
"size": {
"type": "integer",
"minimum": 0,
"description": "File size in bytes"
},
"destination": {
"type": "string",
"description": "Destination path relative to base_destination"
},
"required": {
"type": "boolean",
"default": true,
"description": "Whether this BIOS is required for the core to function"
},
"extract": {
"type": "boolean",
"default": false,
"description": "Extract ZIP contents instead of copying the ZIP"
},
"storage": {
"type": "string",
"enum": [
"embedded",
"external",
"user_provided",
"large_file",
"release"
],
"default": "embedded",
"description": "Storage tier: embedded (in repo), external (download at build), user_provided (manual)"
},
"source_url": {
"type": "string",
"format": "uri",
"description": "Download URL for external storage tier"
},
"instructions": {
"type": "string",
"description": "Human-readable instructions (for user_provided or context)"
},
"zipped_file": {
"type": "string",
"description": "If set, the MD5 hash refers to this file inside the ZIP, not the ZIP itself"
},
"native_system": {
"type": "string",
"description": "System id the platform itself uses for this file"
},
"mirror_of": {
"type": "string",
"description": "Native system whose entry this one repeats. The platform's own file does not carry the copy"
},
"curated": {
"type": "boolean",
"description": "Added by our scraper from the cores' source, not declared in the platform's own file"
},
"shared_group": {
"type": "string",
"description": "Set on load, never written in a platform file: the entry joined the system from this group of _shared.yml, named by the system's includes. The platform's own file does not carry it"
},
"zip_digest": {
"const": "composite",
"description": "Set on load, never written in a platform file: the md5 of this ZIP is the md5 of its members concatenated in name order, as Recalbox computes it, never the md5 of the archive bytes"
},
"native_name": {
"type": "string",
"description": "Display name the platform gives its own system"
},
"group": {
"type": "string",
"description": "RetroBat: files sharing a group are alternatives. One held is enough and the others are reported OPTIONAL"
},
"md5_list": {
"type": "boolean",
"description": "Batocera: the platform writes md5 as a list of strings, any of which matches. md5 holds the items comma-joined, in order"
},
"alt_md5": {
"type": "string",
"pattern": "^[a-fA-F0-9]{32}(,[a-fA-F0-9]{32})*$",
"description": "Second accepted MD5 (Batocera altmd5, ROCKNIX altmd5)"
},
"core": {
"type": "string",
"description": "Cores the platform names for this file (comma-separated)"
},
"note": {
"type": "string",
"description": "Free-text note the platform attaches to this file"
},
"description": {
"type": "string",
"description": "Description the platform attaches to this file"
},
"hash_match_mandatory": {
"type": "boolean",
"description": "Recalbox: a hash mismatch is an error, not a warning"
},
"mandatory_declared": {
"type": "boolean",
"description": "Recalbox: mandatory was stated explicitly, not defaulted"
},
"required_label": {
"type": "string",
"description": "RetroDECK: the requirement wording, which is free text"
},
"component": {
"type": "string",
"description": "RetroDECK: the component whose manifest declares this file"
},
"alt_paths": {
"type": "array",
"items": {
"type": "string"
},
"description": "Further paths the platform accepts for the same file"
},
"native_path": {
"type": "string",
"description": "How the platform itself writes this file reference"
}
}
}
}
}