Skip to content
Back to skills

Retrobat Layout

ASecurity

RetroBat's on-disk layout and integration seams - folder tree, es_systems.cfg, es_savestates.cfg, es_settings.cfg precedence, ES event hooks, and the ES menu entry. Use when reading or writing anything inside a RetroBat install.

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added October 15, 2026
documentationgoapi

Works with

  • api

Security analysis

A100/100

Pro scans all 6 files and shows the line behind each finding

Scanned October 15, 2026

npx -y skills add Spinnich/rommbat --skill retrobat-layout --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Retrobat Layout?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Retrobat Layout
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/spinnich-retrobat-layout/badge)](https://www.skillsdirectory.com/skills/spinnich-retrobat-layout)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: retrobat-layout
description: RetroBat's on-disk layout and integration seams - folder tree, es_systems.cfg, es_savestates.cfg, es_settings.cfg precedence, ES event hooks, and the ES menu entry. Use when reading or writing anything inside a RetroBat install.
---

# RetroBat layout

RomMBat integrates purely through seams RetroBat already has. **Do not fork RetroBat.**

## Map

This file holds the tree, BIOS and systems. The rest is in topic files beside it, by section:

| Section                                                                                                                                                    | File                                       |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| [es_savestates.cfg is the authority on save states](savestates.md#es_savestatescfg-is-the-authority-on-save-states)                                        | [savestates.md](savestates.md)             |
| [es_settings.cfg is how you configure emulators](settings.md#es_settingscfg-is-how-you-configure-emulators)                                                | [settings.md](settings.md)                 |
| [The window in which `es_settings.cfg` can be written](settings.md#the-window-in-which-es_settingscfg-can-be-written)                                      | [settings.md](settings.md)                 |
| [Controller input: read `es_input.cfg`, never detect a layout](input.md#controller-input-read-es_inputcfg-never-detect-a-layout)                           | [input.md](input.md)                       |
| [The ES menu entry is two files, and one of them is somebody else's](emulationstation.md#the-es-menu-entry-is-two-files-and-one-of-them-is-somebody-elses) | [emulationstation.md](emulationstation.md) |
| [Event hooks](emulationstation.md#event-hooks)                                                                                                             | [emulationstation.md](emulationstation.md) |
| [The EmulationStation HTTP API](emulationstation.md#the-emulationstation-http-api)                                                                         | [emulationstation.md](emulationstation.md) |
| [RetroBat's scraper settings are settings RomMBat should read](media.md#retrobats-scraper-settings-are-settings-rommbat-should-read)                       | [media.md](media.md)                       |
| [gamelist.xml](media.md#gamelistxml)                                                                                                                       | [media.md](media.md)                       |

## Tree

| Path                                        | Use                                                   |
| ------------------------------------------- | ----------------------------------------------------- |
| `roms/<system>/`                            | ROMs. Folder names come from `es_systems.cfg`         |
| `roms/<system>/gamelist.xml`                | Metadata ES reads directly                            |
| `roms/<system>/images`, `videos`, `manuals` | Media siblings, named after the ROM file              |
| `saves/`                                    | Emulator save output                                  |
| `bios/`                                     | BIOS and firmware, and much else. See below           |
| `emulationstation/.emulationstation/`       | ES home: `es_settings.cfg`, `scripts/`, themes        |
| `system/es_menu/*.menu`                     | How RetroBat registers launchable apps in the ES menu |
| `system/version.info`                       | The version, used for the compatibility gate          |

Locate the root by walking up from `AppContext.BaseDirectory` to a marker
(`retrobat.ini`, `emulationstation/`, `roms/`). Registry lookups are a fallback for fixed
installs only, never the primary path.

## bios/ is a shared tree, and RomMBat owns almost none of it

**The requirements manifest is not a file in the install.** `batocera-systems.json` ships as a
.NET string resource inside `emulationstation/batocera-systems.exe`, byte-identical to
`reference/batocera-systems.json` apart from a trailing newline (RB-379). So the "read the live copy"
rule below has no live copy to read: the manifest is bundled at `data/retrobat/bios.json`,
generated by `tools/build-bios-manifest.py`. An entry carrying `supplement` is one RetroBat lists
under a sibling system, copied onto a system whose row was measured reading it (`gb` takes
`sgb`'s four and `gbc`'s boot ROM, RB-293).

Measured on a real install, `bios/` holds **4,683 files and 373 MB before RomMBat writes
anything** (RB-380): `dolphin-emu` 2,508 files, `mame` 858 (776 of them software-list XML), `nxengine`
436, blueMSX's `Machines` 296, plus openMSX's whole user directory **including its save
states**. Exactly 3 files sat at a path the manifest names carrying the md5 it names.

So the rules here are stricter than under `roms/`:

- **Never overwrite.** A file at a required path whose md5 disagrees is reported and left
  exactly as it is. A BIOS the user plays with beats the manifest's idea of the right one.
- **Never delete.** A file with the right md5 that RomMBat did not download is adopted as a
  fact, not as something it may later remove. Firmware rows carry no `rom_id`, which is what
  keeps eviction away from them at the schema level.
- **Everything lands under `bios/`.** Six manifest entries name `emulators/` paths; all six
  are hashless and therefore unreachable through an md5 join, and the prefix is enforced anyway.
- **Destination paths go six segments deep** and one md5 can owe three of them
  (`coleco.rom`, `colecovision.rom`, `openMSX/share/systemroms/coleco.rom`). The path is the
  key; the md5 is not.
- **180 of the 354 requirements carry no md5 at all**, and 30 systems have nothing else. Those
  are unverifiable, which is a third state beside matched and missing, and reporting them as
  missing tells a user to hunt for a file RomMBat could not recognize if they already had it.
  One absent from disk, where the library holds a file under its exact name, stays
  `Unverifiable` with `BiosStep.SameName` set: a lead the report prints, never a fetch.

## es_systems.cfg is the authority on systems and extensions

Read the **live** copy, not the vendored template: it reflects that machine's actual
configuration. Each `<system>` carries `<name>`, `<fullname>`, `<manufacturer>`,
`<hardware>`, `<release>`, `<path>`, `<extension>` and `<command>`.

**The folder is `<path>`, not `<name>`.** They are different vocabularies and five systems
in the shipped 8.3.0 file disagree: `gw` writes to `gameandwatch`, `powerbomberman` to `pb`,
`casloopy` to `loopy`, `Windows` to `windows`, and `starship` is used **twice**, for
`ghostship` and `starship`, so `<name>` is not even unique. Three entries own no folder under
`roms/` (`library`, `screenshots`, and `retrobat` at `system/es_menu`) and `mess` declares no
path; none is a sync target (RB-69). `~` expands to `<root>/emulationstation`, so the
ubiquitous `~\..\roms\<folder>` resolves to `<root>/roms/<folder>`. Match
case-insensitively, and parse it as XML: `arcade` and `kodi` sit inside comments, which a
regex over `<system>` would wrongly pick up.

`<extension>` is **a note, never a sync filter**. It is a union across every emulator the
system offers (`nes` lists `.wad`; one `psx` emulator reads `.chd` and another does not), so it
cannot say whether the running emulator opens a file, only whether ES lists it. RomMBat syncs
every member and reports the ones the list omits as unlisted in ES. It also moves between patch
releases: 8.2.1 added `.decomp` to eleven systems and `.zar` to
`ps4`, which is the concrete reason the list is read live rather than bundled. Never cache a
per-system extension set across runs.

`<manufacturer>`, `<hardware>` and `<release>` let the platform rollout order be derived
rather than hand-maintained.

Files in this skill

  • SKILL.md7.9 KB
  • emulationstation.md11.6 KB
  • input.md10.6 KB
  • media.md10.7 KB
  • savestates.md12 KB
  • settings.md8.6 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.