Making a Recalbox theme

45 pages · 8 sections
FRENESDE Show everything Create my theme

Declaring an option: <subset>

The exact syntax, in two steps.

An option is built in two steps: you declare it, then you list its choices.

<subset subset="colorTheme" declares the GROUP + its title <include … name="1 - Blue"> <include … name="2 - Red"> each choice = a file loaded on top Settings ▸ Theme Theme colors ◁ Blue ▷ what the user sees on their machine the “1 - ” prefix is there to ORDER the choices: it is not displayed

1. Declare the group

<subset subset="colorTheme"
        title="THEME : Colors"      title.fr="THÈME : Couleurs"
        help="Choose the color set"  help.fr="Choisissez la palette" />
AttributeRole
subsetthe identifier of the group — it is what ties the choices together
titlethe label the user reads in the menu
helpthe explanation line under the label

title and help accept a language suffix: title.fr, title.es… The version without a suffix serves as the fallback.

2. List the choices

Each choice is an <include> bearing the same subset:

<include subset="colorTheme" name="Blue"  name.fr="Bleu">${root}/options/couleurs/bleu.xml</include>
<include subset="colorTheme" name="Green" name.fr="Vert">${root}/options/couleurs/vert.xml</include>
<include subset="colorTheme" name="Red"   name.fr="Rouge">${root}/options/couleurs/rouge.xml</include>
AttributeRole
subsetwhich group this choice belongs to
namethe choice's label in the list (translatable: name.fr)

The “none” choice

An empty <include> gives the “none” option — useful to leave the theme in its original state:

<include subset="shader" name="None" name.fr="Aucun"></include>

Offering a choice only on certain screens

<include subset="systemView" if="(hd | fhd) and !tate"
         name="Vertical left" name.fr="Vertical gauche">${root}/_views/vertical.xml</include>
<include subset="systemView" if="crt | jamma"
         name="Horizontal">${root}/_views/horizontal.xml</include>

The user only sees the choices relevant to their hardware. That is how the retro filter does not appear on a CRT screen, which does not need it.

The content of a choice file

It is an ordinary theme file, which only redefines what changes:

<?xml version="1.0" encoding="UTF-8"?>
<theme>
  <variables>
    <variable name="CouleurPrincipale" value="7C2E44" />
  </variables>
</theme>

Three useful lines, and the whole theme turns red — provided the theme was built on variables rather than on hard-coded colors.

⚠️ Options load BEFORE the views. A variable applies to what is read after it: that is where the choice must pass for the views to benefit from it.

The order to write in theme.xml:

<theme name="Mon Thème" …>
  <include>${root}/variables.xml</include>      <!-- 1. the default values -->
  <include>${root}/options.xml</include>        <!-- 2. the choice redefines them -->
  <include>${root}/views/system.xml</include>   <!-- 3. the views, which use them -->
</theme>

What happens when the person changes their choice

Recalbox re-reads the whole theme — every file, starting from theme.xml, with the new choice active. That is why a brief “Updating theme…” shows at that moment.

An option that only changes colors redefines variables only. It is the shortest way to write a color set — and the main reason to use <variables>.