Crear un tema de Recalbox

45 páginas · 8 secciones
FRENESDE Mostrar todo Página a página Crear mi tema

¿Qué es un tema?

Lo que un tema cambia, y lo que no cambia.

Un tema de Recalbox viste la interfaz: la lista de tus sistemas al arrancar, la de tus juegos, los menús, el salvapantallas.

Lo que un tema decide

Lo que un tema no decide

El principio, en una frase

Recalbox lee archivos XML que declaran componentes — una imagen, un texto, una lista — cada uno con su posición, su tamaño y su apariencia.

<image name="fond">
  <pos>0 0</pos>
  <size>1 1</size>
  <path>./data/fond.jpg</path>
</image>

El estudio escribe estos archivos por ti. Esta documentación explica la sintaxis completa: debe permitirte escribir un tema enteramente a mano si lo deseas.


El tema mínimo que funciona

Las cuatro vistas, en un solo archivo.

Un tema encaja siempre de la misma manera, y es el plan de toda esta documentación:

un tema contiene vistas — una pantalla cada una; una vista contiene componentes — una imagen, un texto, una lista; un componente lleva propiedades — su posición, su tamaño, su color.

Aquí tienes un tema completo y funcional: están las cuatro vistas. Crea una carpeta mon-theme/ en /recalbox/share/themes/, pon dentro este theme.xml, y aparecerá en la lista de temas.

<?xml version="1.0" encoding="UTF-8"?>
<theme name="Mi Tema" version="1.0" author="Yo"
       recalbox="10.0" compatibility="hdmi,crt" resolutions="hd,fhd">

  <!-- ── 1. LA LISTA DE SISTEMAS ─────────────────────────────── -->
  <view name="system">
    <box name="fond" extra="true">
      <pos>0 0</pos><size>1 1</size>
      <color>101820</color><zIndex>1</zIndex>
    </box>

    <carousel name="systemcarousel">
      <type>horizontal</type>
      <pos>0 0.35</pos><size>1 0.3</size>
      <logoSize>0.2 0.12</logoSize>
      <maxLogoCount>5</maxLogoCount>
    </carousel>

    <image name="logo"/>

    <text name="systemInfo">
      <pos>0.5 0.75</pos><origin>0.5 0.5</origin>
      <fontSize>0.03</fontSize><color>8A92A6</color>
      <alignment>center</alignment>
      <backgroundColor>00000000</backgroundColor>
    </text>
  </view>

  <!-- ── 2. LA LISTA DE JUEGOS ───────────────────────────────── -->
  <view name="detailed">
    <box name="fond" extra="true">
      <pos>0 0</pos><size>1 1</size>
      <color>101820</color><zIndex>1</zIndex>
    </box>

    <textlist name="gamelist">
      <pos>0.05 0.15</pos><size>0.42 0.75</size>
      <primaryColor>C6CBD8</primaryColor>
      <secondaryColor>8A92A6</secondaryColor>
      <selectedColor>101820</selectedColor>
      <selectorColor>4FE3C1</selectorColor>
      <fontSize>0.035</fontSize>
    </textlist>

    <image name="md_image">
      <pos>0.74 0.4</pos><origin>0.5 0.5</origin>
      <maxSize>0.4 0.45</maxSize>
    </image>

    <text name="md_description">
      <pos>0.54 0.68</pos><size>0.4 0.22</size>
      <fontSize>0.024</fontSize><color>A0A8BA</color>
    </text>
  </view>

  <!-- ── 3. EL ESTILO DE LOS MENÚS ───────────────────────────── -->
  <view name="menu">
    <menuBackground>
      <color>101820F0</color>
    </menuBackground>
    <menuText>
      <fontSize>0.038</fontSize>
      <color>C6CBD8</color>
      <selectedColor>101820</selectedColor>
      <selectorColor>4FE3C1</selectorColor>
    </menuText>
  </view>

  <!-- ── 4. EL SALVAPANTALLAS ────────────────────────────────── -->
  <view name="gameclip">
    <extras>
      <text name="titre">
        <pos>0.06 0.86</pos>
        <text>${game.name}</text>
        <fontSize>0.05</fontSize><color>FFFFFF</color>
      </text>
    </extras>
  </view>
</theme>

Lo que hay que observar

Aquí todo cabe en un solo archivo, para poder leerlo de un vistazo. En cuanto el tema crece, se divide — ver Dividir el tema.


Crear tu primer tema

El camino a seguir — con el estudio, o a mano.

El resultado es el mismo: una carpeta de tema. Dos caminos para llegar.

Con el estudio

  1. Parte de una plantilla. La página en blanco es el peor punto de partida. Una plantilla llega con sus componentes ya colocados: tú los sustituyes.
  2. Elige tus resoluciones de pantalla — HD 16:9, CRT 4:3, pantalla vertical (TATE). Lo que cabe en una pantalla ancha no cabe en un televisor de tubo. Empieza por una sola, añade las demás después.
  3. Coloca tus componentes: arrástralos desde la columna izquierda, ajústalos en la derecha.
  4. Cambia de sistema en Opciones de la vista y mira: el error más frecuente es un tema ajustado en una sola máquina que se rompe en las demás. No todos los logotipos tienen la misma forma, ni todos los nombres la misma longitud.
  5. Exporta, copia la carpeta a tu máquina, pruébalo — ver Probar el tema.

A mano

  1. Parte de un tema existente. Abre uno, léelo: es la forma más rápida de entender cómo se hace. El tema oficial de Recalbox es un buen comienzo.
  2. Crea la carpeta y su theme.xml — el único archivo obligatorio. Ver Carpetas y archivos.
  3. Anuncia lo que cubres en la etiqueta <theme>: compatibility para los tipos de pantalla, resolutions para las resoluciones. Estos dos atributos encienden los pictogramas del gestor de temas, y anunciarlos mal es prometer lo que el tema no cumple. Ver La cabecera.
  4. Escribe tus vistas, una por pantalla, y divide en varios archivos en cuanto crezca — ver El tema mínimo que funciona, luego Dividir el tema.
  5. Sirve las demás pantallas con condiciones en lugar de copiarlo todo: <include if="crt">.
  6. Copia la carpeta a tu máquina y pruébalo — y lee themes.log al primer componente invisible.

En ambos casos acecha el mismo error: comprobar solo en TU pantalla y TU sistema.


Carpetas y archivos

Una sola regla, y mucha libertad.

Un tema es una carpeta colocada en /recalbox/share/themes/.

📁 mon-theme/ 📄 theme.xml 📁 views/ 📁 data/ 📁 data/fonts/ …ordenados como quieras OBLIGATORIO sin él, el tema no existe libre ningún nombre, ningún reparto impuesto la única regla: una carpeta, y un theme.xml en su raíz

La única regla

Esa carpeta debe contener un archivo theme.xml.

Eso es todo. theme.xml es el punto de entrada: Recalbox lo busca en la raíz de la carpeta, y si no está, el tema no existe.

Nada más es obligatorio. Ni nombres de subcarpetas, ni división, ni organización. Puedes escribir un tema entero en ese único archivo.

Dividir, porque es más práctico

Un tema serio pronto alcanza miles de líneas. Así que se divide en varios archivos XML, ordenados como quieras, que theme.xml incluye:

mon-theme/
  theme.xml            ← el único nombre impuesto
  variables.xml
  views/
    system.xml
    detailed.xml
    menu.xml
  data/
    fonts/
    images/

Esos nombres son tuyos: llámalos como quieras. La costumbre, tanto en los temas publicados como en las exportaciones del estudio, es escribirlos en inglésviews/, data/, fonts/ — porque es el idioma de las etiquetas que contienen.

El mecanismo de inclusión se explica en Dividir el tema.

Las rutas

Una ruta escrita en un archivo es relativa a ese archivo. En cuanto se divide en subcarpetas, eso se convierte en una fuente de errores.

Pasa por ${root}, que siempre designa la raíz del tema:

<path>${root}/data/images/fond.jpg</path>   <!-- ✅ funciona desde cualquier archivo -->
<path>../data/images/fond.jpg</path>        <!-- frágil: depende de dónde se escriba la línea -->

La cabecera: la etiqueta <theme>

Lo que identifica tu tema — y va SOLO en theme.xml.

<theme> es la raíz de todo archivo XML de un tema. Pero sus atributos de identidad solo tienen sentido en theme.xml: ese es el archivo que lee el gestor de temas para saber de qué se trata.

Para recordar En theme.xml, rellénalos todos: sin ellos, tu tema aparece sin nombre, sin versión, y el gestor no sabe en qué pantallas funciona. En los demás archivos, escribe <theme> desnudo: repetirlos no aporta nada y puede sembrar confusión.

Los atributos

AtributoFunciónEjemploSi falta
nameNombre mostrado en la lista de temasname="Mi Tema"el nombre de la carpeta
versionVersión del temaversion="1.2"no se muestra
authorEl autorauthor="Benoît"no se muestra
recalboxVersión mínima de Recalbox exigidarecalbox="10.0"todas las versiones
compatibilityTipos de pantalla cubiertos: hdmi, crt, jamma, tatecompatibility="hdmi,crt"hdmi
resolutionsResoluciones cubiertas: qvga, vga, hd, fhdresolutions="hd,fhd"fhd,hd

compatibility y resolutions son exactamente los pictogramas que muestra el gestor de temas: HDMI / CRT / JAMMA / TATE por un lado, SD 240p / SD+ 480p / HD 720p / FULLHD 1080p por el otro. Anunciarlos mal es prometer lo que el tema no cumple.

⚠️ Sin ellos, tu tema no puede publicarse en el gestor de temas: el repositorio oficial exige un nombre, una versión y un autor. Ver Compartir el tema.

Los dos casos

En theme.xmlla etiqueta completa:

<theme name="Mi Tema" version="1.2" author="Benoît"
       recalbox="10.0" compatibility="hdmi,crt" resolutions="hd,fhd">
  …
</theme>

En todos los demás archivos del tema — la etiqueta desnuda:

<theme>
  <view name="system"> … </view>
</theme>

Dividir el tema: <include>

Un tema serio no cabe en un solo archivo.

<include> carga otro archivo en ese punto exacto, como si su contenido estuviera copiado ahí.

<include>${root}/views/system.xml</include>
<include path="${root}/views/detailed.xml" />

Las dos escrituras funcionan: la ruta como contenido de la etiqueta, o como atributo path.

El orden importa

Recalbox lee de arriba abajo, y dos componentes con el mismo nombre se sustituyen: gana el último.

base.xml fondo = azul rouge.xml fondo = rojo el fondo es ROJO leído de arriba abajo: dos componentes con el mismo nombre se reemplazan, gana el ÚLTIMO ese es todo el mecanismo de las sobrecapas — y por tanto de las opciones

Ese es todo el mecanismo de las capas — y así se construyen las opciones del tema: cada elección es un archivo cargado encima, que solo redefine lo que cambia. Ver Qué es una opción.

<include>${root}/views/base.xml</include>       <!-- pinta el fondo de azul -->
<include>${root}/options/rouge.xml</include>     <!-- lo repinta de rojo -->

Incluir bajo condición

Un <include> acepta if=, como un componente: el archivo solo se carga si la condición es verdadera.

<include if="crt">${root}/views/system-crt.xml</include>

Así se sirve una disposición distinta según la pantalla, sin duplicar todo lo demás. La lista de condiciones está en Mostrar bajo condición.


Los componentes libres: extra="true" y <extras>

Por qué un componente que añades no se muestra — y las dos formas de declararlo.

Dos familias de componentes

En una vista, Recalbox distingue:

Un componente libre debe declararse como tal

Un componente libre colocado directamente en la vista no se dibuja: la máquina solo construye los elementos marcados extra. Dos escrituras posibles, y hacen exactamente lo mismo:

<image name="monLogo" extra="true">…</image>
<extras>
    <image name="monLogo">…</image>
    <text name="maMention">…</text>
</extras>

<extras> es un contenedor: cada uno de sus hijos recibe extra="true", de una vez. Es más corto y más legible en cuanto hay varios componentes — es lo que escribe el estudio.

Lo que hay que recordar

En el estudio no tienes que hacer nada: los componentes que añades se escriben automáticamente dentro de <extras>, y los elementos reservados fuera.


Tus propias variables: <variables>

Lo que se escribe en el archivo: la etiqueta, las reglas de nombre, el alcance.

Esta página describe lo que se escribe en el archivo. Para crearlas sin escribir una línea de XML, ver Tus variables a medida, en «Los datos dinámicos».

Es el mecanismo más útil de un tema serio, y sin embargo el menos conocido.

<variables>
  <variable name="CouleurPrincipale" value="2E447C" />
  <variable name="PoliceTitre"       value="${root}/data/fonts/Exo2.otf" />
  <variable name="Alpha50"           value="80" />
</variables>

Después, en cualquier parte del tema:

<box name="fond">
  <color>${CouleurPrincipale}</color>
</box>
<text name="titre">
  <fontPath>${PoliceTitre}</fontPath>
  <color>${CouleurPrincipale}${Alpha50}</color>
</text>

Cambia el valor en un solo sitio, y todo el tema le sigue. Es lo que hace posibles las opciones de color: un archivo de capa redefine la variable, y nada más.

Las reglas

  <variable name="CheminLogo" value="${root}/data/logos/${system.name}.svg" />
  <variables if="crt">
    <variable name="TailleTitre" value="0.09" />
  </variables>

⚠️ El bloque se declara arriba del todo

<variables> vale para todo lo que se lee DESPUÉS de él.

Recalbox sustituye cada ${nom} a medida que lee los archivos. Una variable declarada en lo alto del tema vale por tanto en todas partes; declarada en medio, solo vale para lo que sigue.

De ahí la regla, válida para todos los temas: el bloque de variables primero, antes de las vistas, antes de todo lo demás.

Una variable redefinida más adelante sustituye a la anterior para el resto de la lectura — eso es lo que permite a una elección de opción recolorear todo un tema, siempre que se cargue antes de las vistas. Ver Declarar una opción.

Dónde declararlas

En theme.xml, antes de los <include> que las usan: el motor lee las variables de un archivo antes de tratar sus inclusiones.

La costumbre, tomada del tema oficial, es darles su propio archivovariables.xml — incluido el primero de todos:

<include>${root}/variables.xml</include>

Las tres formas de escribir una propiedad

Etiqueta, etiqueta con valor, o atributo — y por qué lo cambia todo.

Una misma propiedad puede escribirse de tres maneras. Son equivalentes… salvo en un punto decisivo.

1. Como etiqueta hija

<image name="fond">
  <path>./data/fond.jpg</path>
</image>

La forma histórica. La más legible en cuanto un componente tiene varias propiedades.

2. Como etiqueta hija con atributo value

<image name="fond">
  <path value="./data/fond.jpg" />
</image>

Estrictamente equivalente a la primera.

3. Como atributo del componente

<image name="fond" path="./data/fond.jpg" pos="0 0" size="1 1" />

Todo cabe en una línea. Muy práctico para los componentes simples.

La diferencia que cuenta

Solo las formas 1 y 2 aceptan una condición sobre UNA propiedad.

<image name="fond">
  <path if="crt">./data/fond-crt.jpg</path>
  <path if="!crt">./data/fond-hd.jpg</path>
</image>

Imposible en la forma 3: if= en la etiqueta madre condicionaría el componente entero, no una de sus propiedades.

Se mezclan libremente

Este es el punto importante: no tienes que elegir una forma y atenerte a ella. El lector de Recalbox acepta las tres, incluso dentro del mismo componente.

<image name="fond" pos="0 0" size="1 1" zIndex="1">
  <path if="crt">${root}/images/fond-crt.jpg</path>
  <path if="!crt">${root}/images/fond-hd.jpg</path>
  <color value="FFFFFFC0" />
</image>

Tres escrituras en el mismo componente: los valores simples como atributos en la primera línea, la que tiene variantes como etiquetas condicionales, y una última como etiqueta con value. Es perfectamente válido, y es incluso lo que se escribe en la práctica.

➡️ Regla simple: un solo valor → atributo; variantes → etiqueta hija.


Ratio, porcentaje o píxeles

Las tres escrituras aceptadas para una posición o un tamaño.

Varias propiedades se escriben con dos números separados por un espacio: x y. Es el caso de pos, size, maxSize, origin, rotationOrigin, logoSize y reflection.

Cada número acepta tres escrituras, y se pueden mezclar en la misma pareja.

EscrituraEjemploQué significa
Ratio (por defecto)0.5 0.25una proporción de la pantalla, de 0 a 1
Porcentaje50% 25%lo mismo, escrito de otra forma
Píxeles960p 270ppíxeles reales, sufijo p
<pos>0.5 0.5</pos>      <!-- el centro -->
<pos>50% 50%</pos>      <!-- exactamente igual -->
<pos>960p 540p</pos>    <!-- el centro… solo de una pantalla 1920×1080 -->

Ratio o porcentaje: preferibles

x es una proporción del ancho, y de la altura. Un componente en 0.5 0.5 está en el centro de un 1920×1080 igual que de un 640×480. Eso es lo que permite a un tema caber en varias pantallas.

Los píxeles: una posición fija

Un píxel es un píxel. 960p son 960 píxeles desde el borde izquierdo, y punto.

No se adapta a nada: en una pantalla de menos de 960 píxeles de ancho, el componente queda fuera de la pantalla. Es una posición absoluta, lo contrario del ratio.

Los píxeles solo se justifican para lo que debe quedarse fijo sea cual sea la resolución: el grosor de un filete, un desplazamiento de unos puntos. Para todo lo demás, usa el ratio.

El caso particular de fontSize

fontSize solo toma un número, y su unidad depende de su valor:

ValorQué significa
< 1una proporción del lado corto de la pantalla — 0.05 = 5 % de la altura en 16:9
>= 1un tamaño de referencia 240p, que Recalbox multiplica según la pantalla

Por encima de 1, el valor no son píxeles. Es un tamaño pensado para una pantalla de 240 líneas, multiplicado un escalón en cada salto de resolución: ×1 hasta 288 píxeles de lado corto, ×2 hasta 576, ×4 en 1080p. <fontSize>8</fontSize> hace por tanto 16 píxeles en una pantalla 480p y 32 píxeles en 1080p. La misma regla vale en todas partes — textos del menú incluidos.

<fontSize>0.045</fontSize>   <!-- 4,5 % del lado corto: se adapta en todas partes, preferible -->
<fontSize>8</fontSize>       <!-- tamaño «240p»: 16 px en 480p, 32 px en 1080p -->

Posición, tamaño, origen, rotación

Colocar un componente exactamente donde se quiere.

pos y origin van siempre juntos

Es el punto que hay que entender antes que nada, porque los dos no hablan de lo mismo:

posdónde, en la PANTALLA, se coloca el componente. originqué punto DEL COMPONENTE se coloca en ese sitio.

Uno es una posición en la pantalla, el otro un punto del componente. Es el encuentro de ambos lo que decide dónde aparece el componente.


pos — una posición en la pantalla

<pos>0.1 0.2</pos>

Estos dos números se miden desde la esquina superior izquierda de la pantalla: 0 0 es esa esquina, 1 1 la esquina inferior derecha.

Lo más sencillo es leerlos como porcentajes — es exactamente lo mismo: 0.1 = 10 %, 0.2 = 20 %, 0.5 = 50 %. Así que pos 0.1 0.2 es 10 % del ancho y 20 % de la altura.

la pantalla, sea cual sea su resolución 00 10 01 11 pos 0.1 0.2 0.1 → 10 % de la largeur 0.2 → 20 % de la hauteur todo se mide desde la esquina superior izquierda de la PANTALLA

pos no dice nada del componente en sí: es un simple punto en la pantalla. Lo que decide qué parte del componente se posa ahí es origin.


origin — qué punto DEL COMPONENTE

origin responde a la otra mitad de la pregunta: ahora que sabemos dónde en la pantalla, ¿qué parte del componente viene a posarse ahí?

Estos nueve valores son los más corrientes, pero cualquier pareja entre 0 y 1 funciona:

tu componente000.501000.50.50.510.5010.5111los nueve valores posibles de origin

Por defecto, origin vale 0 0 — la esquina superior izquierda del componente. Por eso un componente sin origin se extiende hacia la derecha y hacia abajo desde su pos.

El ejemplo que lo aclara todo

Tomemos una imagen apaisada en una pantalla 16:9:

<pos>0.5 0.5</pos>
<origin>1 1</origin>

pos 0.5 0.5 es el centro de la pantalla. Se podría creer que la imagen quedará centrada. No lo está: origin 1 1 designa la esquina inferior derecha de la imagen, y es esa esquina la que se posa en el centro.

la pantalla (16:9) tu imagen (horizontal) origin 1 1 la esquina inferior derecha de la imagen… pos 0.5 0.5 …colocado en el centro de la pantalla ➜ la imagen NO está centrada: queda arriba y a la izquierda del centro.

La imagen queda por tanto entera arriba a la izquierda del centro.

Para centrar de verdad

<pos>0.5 0.5</pos>
<origin>0.5 0.5</origin>

Esta vez es el centro de la imagen lo que se posa en el centro de la pantalla.

La tabla completa

originEl punto del componente posado sobre pos
0 0esquina superior izquierda — el valor por defecto
0.5 0centro del borde superior
1 0esquina superior derecha
0 0.5centro del borde izquierdo
0.5 0.5el centro
1 0.5centro del borde derecho
0 1esquina inferior izquierda
0.5 1centro del borde inferior
1 1esquina inferior derecha

Para qué sirve realmente

Sin origin, todo componente se coloca por su esquina superior izquierda: para centrar algo habría que calcular 0.5 − ancho/2, y recalcular cada vez que el ancho cambia.

Con origin, ya no se calcula nada:

Lo que se quiereposorigin
centrado en pantalla0.5 0.50.5 0.5
pegado al borde derecho1 …1 …
pegado al borde inferior… 1… 1
centrado abajo0.5 10.5 1

Es especialmente útil para un logotipo de sistema, cuyo ancho cambia de una máquina a otra: con origin, queda alineado pase lo que pase.


size — el tamaño impuesto

<size>0.3 0.2</size>

El componente hace exactamente ese tamaño. Para una imagen, eso significa que se deforma para llenar la caja.

Dar solo uno

Pon 0 en el otro: la dimensión que falta se calcula para conservar las proporciones.

<size>0.3 0</size>   <!-- 30 % de ancho, altura proporcional -->

⚠️ No es lo mismo que keepratio o maxSize, aunque ambos conserven las proporciones:

EscrituraLo que se garantiza
size 0.3 0el ancho hace exactamente 30 %; la altura sigue, sea cual sea — puede desbordar
maxSize 0.3 0.2la imagen cabe en la caja: gana la dimensión más restrictiva, el ancho puede por tanto reducirse

Dicho de otro modo: size con un cero impone una restricción, maxSize impone dos.

maxSize — el tamaño máximo, sin deformar

<maxSize>0.3 0.2</maxSize>
size 0.3 0.2 la imagen LLENA la caja… imagen estirada ➜ deformada maxSize 0.3 0.2 …la imagen CABE en la caja imagen entera ➜ proporciones conservadas queda hueco arriba y abajo el marco punteado amarillo = la caja pedida, en ambos casos

La imagen se agranda o se reduce conservando sus proporciones para caber en la caja. Por tanto rara vez ocupa toda su superficie.

Para un logotipo de sistema, casi siempre lo que hace falta es maxSize. Los logotipos no tienen la misma forma de una máquina a otra: con size, algunos quedarían aplastados.

size acompañado de keepratio da el mismo resultado que maxSize — y suele ser la escritura preferida, porque dice el tamaño deseado en lugar de un límite:

<size>0.3 0.2</size>
<keepratio>true</keepratio>   <!-- ⚠️ todo en minúsculas -->

maxSize solo existe en image y video.

rotation y rotationOrigin

<rotation>90</rotation>
<rotationOrigin>0.5 0.5</rotationOrigin>

rotation está en grados, sentido horario. rotationOrigin designa el punto alrededor del cual pivota el componente, en sus propias proporciones. Sin rotationOrigin, el pivote es la esquina superior izquierda (0 0) — escribe 0.5 0.5 para girar alrededor del centro.

La rotación se aplica a las imágenes, los bloques de color, los vídeos y los bloques Markdown. Un texto girado se dibuja con inclinaciones pequeñas pero desaparece a 90°; un texto deslizante girado solo dibuja su fondo, nunca su texto. Para un título vertical, pasa por una imagen o un bloque Markdown.

rotationOrigin 0.5 0.5 gira sobre su centro rotationOrigin 0 0 gira sobre su esquina superior izquierda rotation 20 — en grados, sentido horario

La profundidad (zIndex) y el apagado (disabled) tienen su propia página: Profundidad y visibilidad.


Profundidad y visibilidad

Qué pasa delante de qué, y cómo apagar un componente.

Dos propiedades que todo componente acepta, y que no hablan ni de posición ni de tamaño: cuál pasa delante de la otra, y cuál no se muestra en absoluto.

zIndex — las capas

<zIndex>40</zIndex>

Es un sistema de capas, exactamente como en un programa de dibujo: cada componente es una hoja, y zIndex dice en qué orden se apilan. Cuanto mayor es el número, más cerca de ti está el componente.

barra de ayuda50textos y logotipos40velo de legibilidad20decorado10fondo1zIndex

Los componentes reservados tienen sus valores por defecto, y los componentes libres reciben 10 si no dices nada. Deja hueco entre los tuyos — 10, 20, 30 — para poder deslizar uno en medio más adelante.

disabled — apagar un componente

<disabled>true</disabled>

El componente se lee pero no se muestra. Práctico para ocultar un componente reservado que no se quiere, sin tener que redefinirlo por completo.

⚠️ Ni carousel ni textlist lo aceptan.


Los colores y los degradados

RRGGBB, transparencia, y las ocho esquinas.

La escritura

Un color se escribe en hexadecimal, sin almohadilla:

<color>2E447C</color>       <!-- opaco -->
<color>2E447C80</color>     <!-- medio transparente -->

Los valores de transparencia más útiles

El código de un color lo conoce todo el mundo. Los dos caracteres de la opacidad, mucho menos:

OpacidadEscribirOpacidadEscribir
0 % — invisible0060 %99
10 %1A70 %B3
20 %3375 %BF
25 %4080 %CC
30 %4D90 %E6
40 %6695 %F2
50 %80100 % — opacoFF

El cálculo, si tu valor no está: el porcentaje × 255, escrito en hexadecimal.

Los degradados

box e image aceptan un color por borde o por esquina. Basta con dar dos para obtener un degradado.

colorTop colorBottom degradado vertical colorLeft colorRight degradado horizontal colorTopLeft colorBottomRight degradado por las cuatro esquinas basta con dar DOS colores para obtener un degradado
PropiedadEfecto
colorTop + colorBottomdegradado vertical
colorLeft + colorRightdegradado horizontal
colorTopLeft, colorTopRight, colorBottomLeft, colorBottomRightdegradado en las cuatro esquinas
<box name="ombre-du-haut">
  <pos>0 0</pos>
  <size>1 0.3</size>
  <colorTop>00000080</colorTop>
  <colorBottom>00000000</colorBottom>
</box>

Un degradado del negro medio transparente al transparente total: el clásico velo bajo el que un título sigue siendo legible sea cual sea la imagen de detrás.

Teñir una imagen

En un componente image, color no rellena: multiplica la imagen. Una imagen blanca toma por tanto exactamente el color dado — así se recolorea un icono sin rehacer el archivo.

<image name="etoile">
  <path>${root}/data/arts/etoile-blanche.svg</path>
  <color>FFC24B</color>      <!-- la estrella se vuelve dorada -->
</image>

Condicionar, traducir, regionalizar

Un valor distinto según la pantalla, la máquina o el idioma.

Una condición sobre una propiedad

<text name="titre">
  <fontSize if="crt">0.09</fontSize>
  <fontSize if="!crt">0.05</fontSize>
  <color>FFFFFF</color>
</text>

Un solo componente, dos tamaños según la pantalla. La lista de condiciones está en la página Mostrar bajo condición.

Una condición sobre el componente entero

<image name="filtre" if="crt">
  <path>${root}/data/arts/scanlines.png</path>
</image>

El componente solo existe si la condición es verdadera. La lista completa está en Mostrar bajo condición, y Combinar varias condiciones explica y, o y los paréntesis.

ifexists e ifnotexists

Estos dos no comprueban la máquina sino la presencia de un archivo:

<image name="jaquette">
  <path ifexists="${game.media.imagepath}">${game.media.imagepath}</path>
  <path ifnotexists="${game.media.imagepath}">${root}/images/pas-dimage.png</path>
</image>

Es la forma limpia de gestionar los juegos sin carátula — sin eso la casilla queda vacía.

Traducir un texto

Basta un sufijo de idioma en la propiedad:

<text name="bienvenue">
  <text>Bienvenue</text>
  <text.en>Welcome</text.en>
  <text.es>Bienvenido</text.es>
</text>

Recalbox toma la variante que corresponde, y la versión sin sufijo si ninguna corresponde.

Lo que acepta un sufijo

SufijoA qué apunta
.fr .es .deel idioma de la máquina, en minúsculas
.fr_FRel idioma y el país
.US .EU .JPla región, en MAYÚSCULAS

La región

Es lo que permite escribir «Genesis» en Estados Unidos y «Mega Drive» en Europa. El mismo mecanismo que el idioma, con un sufijo en mayúsculas — es lo que emplea el tema oficial de Recalbox:

<box name="fond"
     color.US="2E447C"
     color.EU="7C2E44"
     color.JP="447C2E" />

Los tres valores son US, EU y JP. Una propiedad sin sufijo vale para todas las regiones.

⚠️ Siempre hay una región activa. En una máquina nueva es US: lo que escribas sin sufijo es lo que verá la mayoría, y .EU o .JP solo sirven para apartarse de ello.

La región se cambia en la máquina, en las propiedades de la interfaz — y Recalbox relee entonces el tema entero, como con una opción. El estudio ofrece la misma elección, para ver lo que verá cada público.

Sobre qué funciona: sobre TODO

No existe ninguna lista de propiedades traducibles. El sufijo se examina en cada propiedad antes incluso de que el motor sepa de cuál se trata — así que todas lo aceptan:

<text name="titre" text.fr="Bienvenue" text.es="Bienvenido" />
<image name="logo" path.US="genesis.png" path.EU="megadrive.png" />
<text name="mention" fontSize.de="0.03" />        <!-- el alemán es más largo -->
<box name="bandeau" color.JP="D62828" />

Las dos escrituras lo admiten — como atributo (size.fr="…") igual que como subnodo (<size.fr>…</size.fr>) — e incluso el nombre de la etiqueta (<text.fr name="…">). Vale también para el title y el help de una opción.

⚠️ La versión localizada gana definitivamente. En cuanto se ha aplicado una variante, la versión sin sufijo de la misma propiedad se rechaza, incluso en un archivo leído después. Una capa no puede por tanto «retomar el control» de una propiedad ya localizada: debe aportar su propia variante localizada.

Cargar un texto desde un archivo

text, scrolltext y markdown aceptan path en lugar de text: el contenido se lee entonces del archivo. Práctico para un texto largo de presentación.

<markdown name="apropos">
  <path>${root}/data/textes/apropos.md</path>
</markdown>

Nombrar y reutilizar

El nombre de un componente, y cómo crear varios de una vez.

Dos cosas que no hay que confundir

<image name="mon-fond">

Dos componentes con el mismo name en la misma vista son uno solo: el segundo completa o sustituye al primero. Es intencionado — es el mecanismo de las capas — pero es una fuente de errores cuando se nombran dos decorados «fond» sin pensarlo.

Crear varios componentes de una vez

<box name="bande1, bande2, bande3, bande4">
  <size>0.01 1</size>
  <color>FFFFFF20</color>
</box>

Cuatro componentes, mismas propiedades. Queda darles su posición individual más adelante:

<box name="bande1"><pos>0.90 0</pos></box>
<box name="bande2"><pos>0.92 0</pos></box>

Modificar sin reescribirlo todo

Como gana el último, basta con redeclarar la única propiedad que cambia:

<include>${root}/views/base.xml</include>

<view name="system">
  <box name="fond"><color>7C2E44</color></box>   <!-- el resto se conserva -->
</view>

Todos los componentes

Lo que existe, y lo que sabe hacer cada uno.

Un componente se declara por su tipo — el nombre de la etiqueta. Un tipo que no está en esta lista es ignorado por Recalbox y señalado en el registro.

Mostrar algo

TipoLo que hace
textun texto, en una o varias líneas
scrolltextun texto que se desplaza cuando es demasiado largo
markdownun texto con formato (negrita, títulos, listas)
imageuna imagen
videoun vídeo
boxun bloque de color, o un degradado
datetimeuna fecha
ratinguna puntuación, en estrellas
soundun sonido (no muestra nada)

Listas y navegación

TipoLo que hace
textlistla lista de juegos
carouselel carrusel de sistemas
helpsystemla barra de ayuda de abajo de la pantalla

Estilo de los menús

Estos nueve no se colocan: ajustan el aspecto de los menús que Recalbox construye por sí mismo.

menuBackground · menuIcons · menuText · menuTextSmall · menuSection · menuSwitch · menuSlider · menuButton · menuSize

Estilo del teclado virtual

keyboard tampoco se coloca: da sus colores y su fuente al teclado que Recalbox abre para una búsqueda o una entrada de texto. Se configura en Componentes globales.

Cuidado con las mayúsculas

Los nombres distinguen mayúsculas y minúsculas. menuswitch no funciona, hay que escribir menuSwitch. Una sola propiedad es la excepción, escrita toda en minúsculas: keepratio.


text, scrolltext, markdown

Las tres maneras de mostrar texto.

text — el texto normal (18 propiedades)

<text name="titre">
  <pos>0.06 0.08</pos>
  <size>0.5 0.1</size>
  <text>${system}</text>
  <fontPath>${root}/data/fonts/Exo2.otf</fontPath>
  <fontSize>0.05</fontSize>
  <color>FFFFFF</color>
  <alignment>left</alignment>
  <forceUppercase>true</forceUppercase>
</text>
PropiedadTipoFunción
pos size origin rotation rotationOriginparcolocación — ver Posición, tamaño, origen
texttextoel contenido, variables incluidas
pathrutalee el contenido desde un archivo, en lugar de text
fontPathrutala fuente
fontSizenúmero< 1 = proporción de la altura de pantalla, >= 1 = píxeles
fontStyletextonormal, bold, italic, bolditalic
colorcolorel color del texto
backgroundColorcolorun fondo detrás del texto
alignmenttextover más abajo
forceUppercasesí/notodo en mayúsculas
lineSpacingnúmeroel interlineado, 1.2 por defecto
multilinesí/nopermitir los saltos de línea
zIndexnúmerola profundidad
disabledsí/noapagar el componente

alignment actúa sobre dos ejes

El valor combina la horizontal y la vertical.

Nueve posiciones, trece maneras de escribirlas — cuatro valores son sinónimos:

PosiciónEscribirSinónimo
arriba-izquierdatopleft
arriba-centrotopcentertop
arriba-derechatopright
centro-izquierdacenterleftleft
centrocenter
centro-derechacenterrightright
abajo-izquierdabottomleft
abajo-centrobottomcenterbottom
abajo-derechabottomright

⚠️ Un valor desconocido no conserva la alineación anterior: vuelve a centro-izquierda, el valor por defecto.

toplefttopcenter= toptoprightcenterleft= leftcentercenterright= rightbottomleftbottomcenter= bottombottomrightel texto se coloca dentro de su caja `size` — sin size, la alineación no tiene sobre qué actuar

El texto se alinea dentro de su caja size: sin size, la alineación no tiene sobre qué actuar.


scrolltext — el texto que se desplaza (16 propiedades)

Las mismas propiedades que text, sin multiline ni lineSpacing. El texto se desplaza horizontalmente cuando desborda su caja.

<scrolltext name="titre-long">
  <size>0.4 0.06</size>
  <text>${game.name}</text>
  <fontSize>0.04</fontSize>
</scrolltext>

Reservado a los valores cuya longitud no controlas — un nombre de juego, un desarrollador.


markdown — el texto con formato (15 propiedades)

<markdown name="synopsis">
  <pos>0.06 0.5</pos>
  <size>0.4 0.35</size>
  <text>${game.synopsis}</text>
  <fontSize>0.028</fontSize>
  <color>C6CBD8</color>
</markdown>

Las mismas propiedades que text, sin fontStyle, backgroundColor ni multiline.

Entiende un formato sencillo en el texto: **negrita**, *cursiva*, # título, listas con guiones. Útil para una sinopsis o una página « acerca de ».

⚠️ markdown no se desplaza: un texto más largo que su caja queda cortado.


image y video

Mostrar una imagen o un vídeo, y teñirlos.

image (21 propiedades)

<image name="jaquette">
  <pos>0.75 0.4</pos>
  <origin>0.5 0.5</origin>
  <maxSize>0.35 0.4</maxSize>
  <path>${game.media.imagepath}</path>
  <zIndex>30</zIndex>
</image>
PropiedadTipoFunción
pos size origin rotation rotationOriginparcolocación
maxSizepartamaño máximo sin deformación — ver Posición, tamaño
keepratiosí/noconservar las proporciones (⚠️ todo en minúsculas)
pathrutael archivo de imagen
tilesí/norepetir la imagen en mosaico en lugar de estirarla
colorcolortiñe la imagen (multiplicación)
colorTop colorBottom colorLeft colorRightcolortinte en degradado
colorTopLeft colorTopRight colorBottomLeft colorBottomRightcolortinte por las cuatro esquinas
reflectionparun reflejo bajo la imagen: opacidad inicial y final
zIndex disabledprofundidad, apagado

Formatos

PNG, JPG y SVG. SVG recomendado para los logotipos: queda nítido a cualquier tamaño.

tile — la textura repetida

<image name="grille">
  <size>1 1</size>
  <path>${root}/data/arts/motif.png</path>
  <tile>true</tile>
</image>

La imagen conserva su tamaño original y se repite hasta cubrir la caja.

reflection

<reflection>0.5 0.0</reflection>

Añade un reflejo invertido bajo la imagen, del 50 % de opacidad arriba al 0 % abajo.


video (15 propiedades)

<video name="md_video">
  <pos>0.75 0.4</pos>
  <origin>0.5 0.5</origin>
  <maxSize>0.35 0.3</maxSize>
  <delay>1.5</delay>
  <loops>0</loops>
</video>

Las mismas propiedades de colocación que image, más:

PropiedadTipoFunción
delaynúmerosegundos antes de que arranque el vídeo
loopsnúmeronúmero de reproducciones; 0 = en bucle
animationstextoel efecto de aparición
linktextovincular la reproducción a otro componente
reflectionparel reflejo, como en image

video no acepta ni tile ni los colores de tinte.

Un delay de uno o dos segundos evita que el vídeo se dispare en cada juego por el que solo pasas al recorrer la lista.


box — el bloque de color

Fondos, velos, bandas y degradados.

El componente más sencillo, y uno de los más útiles: fondos, velos, bandas, separadores. 16 propiedades.

<box name="fond" extra="true">
  <pos>0 0</pos>
  <size>1 1</size>
  <color>101820</color>
  <zIndex>1</zIndex>
</box>
PropiedadFunción
pos size origin rotation rotationOrigincolocación
colorcolor liso
colorTop colorBottomdegradado vertical
colorLeft colorRightdegradado horizontal
colorTopLeft colorTopRight colorBottomLeft colorBottomRightdegradado por las cuatro esquinas
zIndex disabledprofundidad, apagado

Nada de path: un box no muestra ninguna imagen. Para un fondo con imagen, usa image.

El velo de legibilidad

El caso de uso más frecuente: hacer legible un texto sobre cualquier imagen.

<box name="voile-du-bas" extra="true">
  <pos>0 0.7</pos>
  <size>1 0.3</size>
  <colorTop>00000000</colorTop>
  <colorBottom>000000C0</colorBottom>
  <zIndex>20</zIndex>
</box>

De transparente a negro al 75 %: la parte baja de la pantalla se oscurece progresivamente, y el texto colocado encima queda legible sea cual sea el material gráfico de detrás.

Una banda fina

<box name="filet" extra="true">
  <pos>0.06 0.18</pos>
  <size>0.3 2p</size>
  <color>FFFFFF40</color>
</box>

2p = dos píxeles de alto, sea cual sea la resolución: uno de los raros casos donde la unidad en píxeles es la elección correcta.


textlist — la lista de juegos

La lista donde eliges tu juego: sus colores, su resaltador, su fuente.

⚠️ Esta lista no se coloca donde quieras. textlist solo existe en la vista Juegos, bajo el nombre reservado gamelist. En otro lugar — o con otro nombre — no se construye, y no puedes añadir una segunda.

Las propiedades (19)

<textlist name="gamelist">
  <pos>0.05 0.2</pos>
  <size>0.4 0.7</size>
  <primaryColor>C6CBD8</primaryColor>
  <secondaryColor>8A92A6</secondaryColor>
  <selectedColor>101820</selectedColor>
  <selectorColor>4FE3C1</selectorColor>
  <selectorHeight>0.055</selectorHeight>
  <fontSize>0.035</fontSize>
  <horizontalMargin>0.01</horizontalMargin>
</textlist>
PropiedadFunción
pos size origincolocación
primaryColorel color de los juegos
secondaryColorel color de las carpetas
selectedColorel color del texto de la línea elegida
selectorColorel color del resaltador
selectorImagePathuna imagen de resaltador, en lugar del color
selectorImageTilerepetir esa imagen en mosaico
selectorHeightla altura del resaltador
selectorOffsetYsu desplazamiento vertical
fontPath fontSizela fuente
alignmentla alineación de las líneas
horizontalMarginel margen izquierdo y derecho
forceUppercasetodo en mayúsculas
lineSpacingel interlineado — es él quien espacia las líneas
scrollSoundel sonido reproducido al desplazarse
zIndexla profundidad
Sonic the Hedgehog ▸ Una carpeta Streets of Rage 2 Golden Axe Gunstar Heroes primaryColor los juegos secondaryColor las CARPETAS (¡no una línea de cada dos!) selectorColor el resaltador selectedColor el TEXTO de la línea elegida selectorHeight el error clásico: creer que secondaryColor alterna una línea de cada dos

⚠️ Nada de disabled: una lista de juegos no se apaga.

primaryColor y secondaryColor son la fuente de confusión más frecuente: el segundo no es el color alterno de una línea de cada dos, es el color de las carpetas.


carousel — el carrusel de sistemas

La cinta que hace desfilar los sistemas: dirección, tamaño de los logotipos, y el modo texto.

El carrusel muestra los sistemas, logotipo a logotipo. Solo existe en la vista Sistemas, bajo el nombre reservado systemcarousel, y el motor solo construye uno. En otro lugar, o con otro nombre, no se construye en absoluto.

type acepta horizontal (por defecto), vertical y vertical_wheel — la rueda. No existe rueda horizontal: cualquier otro valor vuelve silenciosamente a horizontal.

<carousel name="systemcarousel">
  <type>vertical</type>
  <pos>0 0</pos>
  <size>0.25 1</size>
  <color>00000020</color>
  <logoSize>0.12 0.075</logoSize>
  <logoScale>1.5</logoScale>
  <maxLogoCount>7</maxLogoCount>
  <logoAlignment>center</logoAlignment>
  <defaultTransition>instant</defaultTransition>
</carousel>
PropiedadFunción
typehorizontal, vertical, vertical_wheel
pos size origincolocación
colorel fondo del carrusel
logoSizeel tamaño de un logotipo (par)
logoScaleel agrandamiento del logotipo elegido
logoRotation logoRotationOriginla rotación de los logotipos (ruedas)
logoAlignmentla alineación de los logotipos en su casilla
maxLogoCountcuántos logotipos visibles a la vez
defaultTransitionfade o instant; cualquier otro valor da slide
fontPath fontSize fontColorla fuente del modo texto
forceUppercaselos nombres de sistemas en mayúsculas
textOnlyescribir los nombres en lugar de los logotipos
primaryColor secondaryColorel color de los nombres
selectedColorel color del nombre elegido
selectorColor selectorHeightel resaltador del modo texto
selectorOffsetX selectorOffsetYsu desplazamiento
textOffsetXel desplazamiento del texto
lineSpacing horizontalMargininterlineado y márgenes del modo texto
zIndexla profundidad
color — el fondo del carrusel elegido logoSize × logoScale maxLogoCount — cuántos se ven solo el logotipo elegido está a tamaño completo: los demás se reducen

⚠️ Nada de disabled: el carrusel no se apaga.

⚠️ maxLogoCount no es un número de logotipos mostrados. Solo dirige el espaciado y el centrado: el motor dibuja más, que desbordan y quedan recortados. Y el valor se redondea al entero — un decimal (2.5) es por tanto inútil.


En la sección Lista de sistemas, « QUÉ DESFILA » elige entre:

⚠️ No es una cuarta dirección de desplazamiento: el modo texto se combina con horizontal, vertical y rueda. Un carrusel de nombres puede por tanto desfilar en cualquier dirección.

En modo texto, la fuente, su tamaño y su color se configuran en la sección Texto. Se añaden dos desplazamientos propios del carrusel:

<carousel name="systemcarousel" type="vertical">
  <textOnly>true</textOnly>
  <textOffsetX>0.02</textOffsetX>
</carousel>

Disponible a partir de Recalbox 10.1. En una máquina más antigua, textOnly se ignora y el carrusel muestra los logotipos.


rating — la puntuación en estrellas

La nota del juego, dibujada en estrellas: las dos imágenes que la componen.

Las propiedades (9)

<rating name="md_rating">
  <pos>0.06 0.72</pos>
  <size>0.12 0.024</size>
  <filledPath>${root}/data/arts/etoile-pleine.svg</filledPath>
  <unfilledPath>${root}/data/arts/etoile-vide.svg</unfilledPath>
</rating>
PropiedadFunción
pos size origin rotation rotationOrigincolocación
filledPathla imagen de estrella llena
unfilledPathla imagen de estrella vacía
zIndex disabledprofundidad, apagado

size designa el conjunto de las cinco estrellas. Un ancho de cinco veces el alto da estrellas cuadradas.

Nada de color: para cambiar el tinte, cambia las imágenes — o proporciona imágenes blancas y tíñelas… cosa que rating no permite. Hacen falta por tanto dos archivos.


datetime — una fecha

La fecha de salida de un juego, o la de la última partida.

Un datetime muestra una fecha que Recalbox conoce, nunca un texto libre. Su nombre dice qué fecha — md_releasedate la salida del juego, md_lastplayed la última partida — y su propiedad display dice en qué forma escribirla.

<datetime name="md_releasedate">
  <pos>0.06 0.66</pos>
  <fontSize>0.028</fontSize>
  <color>C6CBD8</color>
  <display>date</display>
</datetime>

display — la forma de la fecha

EscribirLo que se muestra
date1991/06/23
dateTime1991/06/23 14:05:30
year1991
time14:05:30
realTimela hora actual — no una fecha del juego
RelativeToNow« hace 3 días »

⚠️ Las mayúsculas cuentan. datetime no funciona, hay que escribir dateTime; relativeToNow tampoco, hay que escribir RelativeToNow. Un valor desconocido conserva la forma anterior y acaba en themes.log.

Las propiedades (12)

PropiedadFunción
pos size origincolocación
displayla forma de la fecha
color backgroundColorlos colores
fontPath fontSizela fuente
alignment forceUppercaseel formato
zIndex disabledprofundidad, apagado

⚠️ Un datetime sin color es invisible: es el único componente que pone el color a cero en lugar de conservar el anterior. Y de alignment, solo se conserva la parte horizontal — la vertical queda siempre centrada.

Un juego sin fecha muestra una línea vacía: es el dato lo que falta, no el tema.


sound — la música del tema

Una pista, o una carpeta de pistas, reproducida durante la navegación.

Un sound no se dibuja: no tiene ni posición, ni tamaño, ni profundidad. Lleva una ruta, y nada más.

Dos nombres, dos comportamientos:

NombreLo que hace la máquina
bgsoundreproduce esa pista
directoryelige al azar en esa carpeta

⚠️ La máquina solo lo lee en la vista Sistemas. Colocado en otro lugar, no suena nunca. En cambio, un archivo de sistema puede redefinirlo: así es como se da una música por sistema.

La música propia del usuario, si la hay, tiene prioridad sobre la del tema.


helpsystem — la barra de ayuda

Los 32 iconos de botones, uno a uno.

La barra de abajo de la pantalla que recuerda para qué sirven los botones. 38 propiedades: seis de formato, y 32 iconos.

Recalbox decide por sí mismo lo que anuncia la barra, pantalla a pantalla, y traduce cada etiqueta. Tu tema solo fija la forma: la colocación, la fuente, los colores, y la imagen de cada pictograma.

<helpsystem name="help">
  <pos>0.02 0.955</pos>
  <fontPath>${root}/data/fonts/Exo2.otf</fontPath>
  <fontSize>0.025</fontSize>
  <textColor>C6CBD8</textColor>
  <iconColor>FFFFFF</iconColor>
  <iconA>${root}/data/arts/boutons/a.svg</iconA>
  <iconB>${root}/data/arts/boutons/b.svg</iconB>
</helpsystem>

El formato

PropiedadFunción
pos sizecolocación
textColorel color de las etiquetas
iconColorel tinte de los iconos — proporciónalos en blanco
fontPath fontSizela fuente

Los 32 iconos

Reemplazar un icono es opcional: Recalbox proporciona los suyos. Solo redefines los que quieres.

DireccionesiconUpDown, iconLeftRight, iconUpDownLeftRight

BotonesiconA, iconB, iconX, iconY

GatillosiconL, iconR, iconL2, iconR2, iconL3, iconR3, iconLR, iconL2R2, iconL3R3

SistemaiconStart, iconSelect, iconHotkey

Combinaciones hotkeyiconHkA, iconHkB, iconHkX, iconHkY, iconHkL, iconHkR, iconHkLeftRight

JoysticksiconJ1UpDown, iconJ1LeftRight, iconJ1UpDownLeftRight, iconJ2UpDown, iconJ2LeftRight, iconJ2UpDownLeftRight

Una combinación son dos pictogramas

Cuando la ayuda trata de una combinación, Recalbox dibuja iconHotkey, luego la tecla.

[HK] [A]  Lanzar el juego

iconHkA es por tanto la imagen del botón A usado en combinación — no un dibujo de « HK + A ». Pon ahí un botón normal: el atajo ya está delante.

iconHotkey cuenta doble: aparece delante de cada combinación de la barra. Es el icono que pulir primero si tu tema muestra alguna.

El nombre es impuesto: help

Recalbox busca el componente llamado help, y solo ese. <helpsystem name="barre"> existirá en tu archivo sin dirigir nunca nada.

La barra se configura vista a vista

Recalbox relee el <helpsystem> de la vista en cada cambio de pantalla, y vuelve a partir de sus propios iconos. Lo que una vista no declara vuelve por tanto al valor por defecto de Recalbox — nunca a lo que otra vista había configurado.

Dos maneras de hacerlo:

Proporciona iconos blancos y usa iconColor: un solo juego de archivos basta entonces para todas las variantes de color de tu tema.

Ofrecer varios juegos de iconos

Es lo que hacen los grandes temas: un juego SNES, un juego Xbox, un juego PlayStation… y el usuario elige en Menú → Interfaz → Tema.

Cada juego es un archivo que solo contiene el <helpsystem> y sus imágenes:

<!-- ./options/icones-snes.xml -->
<theme>
  <view name="system, detailed, menu">
    <helpsystem name="help">
      <iconA>${root}/data/icones/snes/a.svg</iconA>
      <iconB>${root}/data/icones/snes/b.svg</iconB>
    </helpsystem>
  </view>
</theme>

Y se ofrecen así, sin declarar nada más:

<include subset="iconset" name="1 - SNES">${root}/options/icones-snes.xml</include>
<include subset="iconset" name="2 - Xbox">${root}/options/icones-xbox.xml</include>

iconset es un nombre reservado: Recalbox muestra « SELECT THEME'S ICONSET », traducido al idioma de la máquina. No hace falta ninguna etiqueta <subset> para nombrarlo.


El estilo de los menús

Los nueve componentes que ajustan los menús de Recalbox.

Recalbox construye sus menús por sí mismo: su contenido no te pertenece. El tema solo ajusta su aspecto, mediante nueve componentes que no se colocan.

menuBackground (3)

<menuBackground>
  <color>101820F0</color>
  <path>${root}/data/arts/cadre-menu.png</path>
  <fadePath>${root}/data/arts/voile.png</fadePath>
</menuBackground>
PropiedadFunción
colorel color del marco — tiñe la imagen si se da path
pathla imagen del marco
fadePathla imagen de velo que oscurece la vista de detrás

menuText (6) — las líneas del menú

PropiedadFunción
fontPath fontSizela fuente
colorel texto de las líneas
selectedColorel texto de la línea elegida
selectorColorel resaltador
separatorColorlos filetes entre líneas

menuTextSmall (5) — el texto pequeño

fontPath, fontSize, color, selectedColor, selectorColor. Usado para los valores de ajuste y las listas desplegables.

menuSection (5) — los títulos de sección

fontPath, fontSize, color, selectedColor, alignment.

menuSize (1)

<menuSize><height>0.85</height></menuSize>

La altura máxima del marco del menú, en proporción de la pantalla. Es la única medida que un tema impone a los menús.

menuSwitch (2) — los interruptores

pathOn, pathOff — las dos imágenes de un ajuste sí/no.

menuSlider (1) — los deslizadores

path — la imagen del cursor.

menuButton (2) — los botones

path, filledPath — el estado normal y el pulsado.

menuIcons (23) — los iconos de sección

Un icono por sección del menú:

iconSystem · iconUpdates · iconThemes · iconGames · iconUI · iconTate · iconControllers · iconSound · iconNetwork · iconScraper · iconBios · iconDownload · iconLicense · iconAdvanced · iconArcade · iconKodi · iconCardReader · iconRecalboxRGBDual · iconQuit · iconRestart · iconShutdown · iconFastShutdown · iconList

⚠️ iconList va en singular, a diferencia de la sección « Listas » que representa. En plural, se ignora.


El estilo del teclado virtual

Los colores y la fuente del teclado que se abre para buscar un juego o escribir un texto.

Como los menús, no se coloca: el teclado decide su propia geometría, el tema solo elige sus colores y su fuente.

Se abre sobre la pantalla en la que estás, sea cual sea — así que se configura una sola vez, en Componentes globales.

PropiedadLo que pinta
keyColorel fondo de cada tecla en reposo
keySelectedColorla tecla en la que estás
keyTextColorla letra escrita en la tecla
keyDisabledColorla letra de un carácter que la entrada rechaza
keyModifierColorMayús / Ctrl / Alt pulsado para una sola tecla
keyModifierLockedColorMayús / Ctrl / Alt bloqueado
keyTitleColorel título encima del teclado
keyEditTextColorel texto que se está escribiendo
fontPathla fuente — el tamaño lo sigue decidiendo el teclado

Tres teclados, y el usuario elige

El tema no decide cuál se muestra: es un ajuste de la consola. Y no todos leen tus colores.

Configura por tanto primero los cuatro que leen todos: tu estilo se mantendrá sea cual sea el teclado.

Lo que escribe

<view name="system, basic, detailed, menu, gameclip">
    <keyboard name="keyboard">
        <keyColor>1B1D22</keyColor>
        <keySelectedColor>4FE3C1</keySelectedColor>
        <keyTextColor>FFFFFF</keyTextColor>
        <keyTitleColor>FFFFFF</keyTitleColor>
        <keyEditTextColor>FFFFFF</keyEditTextColor>
    </keyboard>
</view>

El name debe ser exactamente keyboard, y no acepta ni pos ni size.

Disponible a partir de Recalbox 10.1. En una máquina más antigua, el bloque se ignora y el teclado conserva sus colores de fábrica.


⚠️ La regla más importante

Por qué tu componente no aparece.

Esta es la causa del « he puesto mi imagen y no la veo ».

Una vista solo dibuja dos cosas:

  1. sus componentes reservados, que construye ella misma;
  2. los componentes marcados extra="true".

Un componente libre sin extra no aparece nunca.

extra="true" → dibujado tu componente sin extra → invisible nada el motor solo dibuja sus componentes reservados + los marcados extra
<view name="system">
  <image name="mon-decor" extra="true">      <!-- ✅ se muestra -->
    <path>${root}/data/arts/decor.png</path>
  </image>

  <image name="autre-decor">                  <!-- ❌ invisible -->
    <path>${root}/data/arts/decor.png</path>
  </image>
</view>

La otra escritura, equivalente, es agruparlos:

<view name="system">
  <extras>
    <image name="mon-decor"> … </image>
    <text name="ma-legende"> … </text>
  </extras>
</view>

Solo SEIS tipos pueden colocarse libremente

La fábrica de componentes libres solo sabe construir estos:

✅ Utilizable como extra❌ Rechazado
image · box · video · text · scrolltext · markdowntextlist · carousel · datetime · rating · sound · helpsystem · keyboard · container · ninepatch · todos los menu*

Un tipo rechazado escribe en el registro Extra type unknown: Rating y no se dibuja nada.

➡️ rating, datetime, textlist y carousel solo se usan bajo su nombre reservado, en una vista que los prevé. No puedes añadir una segunda puntuación ni una segunda lista.

➡️ ninepatch no tiene nombre reservado en ninguna parte: rechazado como componente libre, y ninguna vista lo construye. Es por tanto inutilizable en la práctica, pese a estar presente en el motor.

➡️ container tampoco se coloca, pero no es inútil: el motor lo aplica por encima de otro componente. En la lista de juegos, md_description declarado como <text> ajusta a la vez el marco desplazable que lo rodea — pos, size y zIndex van al marco, el resto al texto. Nunca lo escribes tú mismo.

Otros tres límites

La excepción

helpsystem sigue funcionando incluso escrito en un bloque <extras>: la vista lo encuentra por su nombre. La advertencia del registro no tiene consecuencias.


La vista system — las máquinas

El carrusel, el logotipo, la línea de información.

La primera pantalla: la lista de tus máquinas.

Los componentes reservados

NombreTipoFunción
systemcarouselcarouselel carrusel — uno solo, no renombrable
logoimageel logotipo del sistema en el carrusel
systemInfotextla línea « 510 juegos disponibles, 13 favoritos »
bgsoundsoundla música de fondo del tema
directorysoundla carpeta de músicas del tema

bgsound y directory son los únicos nombres que <sound> acepta, y únicamente en esta vista.

Dos trampas

systemInfo tiene un fondo gris por defecto. Para quitarlo:

<text name="systemInfo">
  <backgroundColor>00000000</backgroundColor>
</text>

El carrusel es único. Un segundo <carousel> se lee sin error pero no se dibuja nunca.

El logotipo por defecto

Cuando el tema no proporciona un logotipo, Recalbox busca el suyo en este orden:

<sistema>-<idioma_PAIS>.svg   →   <sistema>-<idioma>.svg
      →   <sistema>-<region>.svg   →   <sistema>.svg

Es lo que permite tener un logotipo « Genesis » en Estados Unidos y « Mega Drive » en Europa sin escribir nada.

El carrusel en detalle

PropiedadPor defectoPrecisión
typehorizontalhorizontal, vertical, vertical_wheel; cualquier otro valor vuelve a horizontal
logoSizecalculadoproporción de la pantalla, no del carrusel
logoScale1.2agrandamiento del logotipo elegido
maxLogoCount3redondeado al entero — un decimal no sirve de nada
colortransparenteel fondo del carrusel

El espaciado de los logotipos se calcula así:

espaciado = (longitud − logoSize × maxLogoCount) / maxLogoCount + logoSize

donde longitud es size.y en vertical, size.x en horizontal.


La vista detailed — los juegos

La lista, la ficha del juego, y sus treinta componentes reservados.

La lista de juegos de un sistema, con la ficha del juego señalado.

Es la vista de todas las listas de juegos: la vista basic nunca es solicitada por el motor, y la vista de arcade reutiliza detailed.

La lista y los medios

NombreTipoFunción
gamelisttextlistla lista de juegos
logoimageel logotipo del sistema
md_imageimagela carátula
default_image_pathimagela imagen de reemplazo cuando el juego no tiene carátula
md_videovideoel vídeo de vista previa
md_region1md_region4imagelas cuatro banderas de región del juego

En md_image, el path escrito en el tema se ignora: la imagen viene del juego. En los md_region*, solo se leen pos, size, zIndex y path.

La información del juego

NombreTipo
md_descriptiontext, markdown o scrolltext — a elegir
md_folder_nametext
md_ratingrating
md_releasedate, md_lastplayeddatetime
md_developer, md_publisher, md_genre, md_players, md_playcount, md_favoritetext

Las etiquetas

md_lbl_rating, md_lbl_releasedate, md_lbl_developer, md_lbl_publisher, md_lbl_genre, md_lbl_players, md_lbl_lastplayed, md_lbl_playcount, md_lbl_favorite

⚠️ Su texto es impuesto. Recalbox escribe « Nota: », « Salió el: », « Desarrollador: »… traducidos al idioma de la máquina, después de aplicar el tema. Un text= en el tema se sobrescribe. Ajustas su formato, nunca su contenido.

Del mismo modo, los valores md_* aceptan todas las propiedades salvo text: su contenido viene del juego.

Los colores de la lista

gamelist usa cinco colores, de los cuales tres no son tematizables:

LíneaColor
un juegoprimaryColor
una carpetasecondaryColor
un juego atenuadocalculado: primaryColor con la opacidad dividida por dos
una carpeta atenuadacalculado igual
el fondo de un encabezado de ordenaciónimpuesto

Componentes presentes pero inertes

template_flag, template_genre y template_players son leídos por el motor pero nunca usados: los colores de las decoraciones no son tematizables. No pierdas tiempo con ellos.


La vista gameclip — el salvapantallas

Lo que se muestra cuando la máquina no hace nada.

El salvapantallas lanza fragmentos de juegos. El tema lo viste alrededor.

Lo que es tematizable

Esta vista se construye casi por completo a partir de tus extras: coloca tus componentes con extra="true" y se muestran.

Un solo componente reservado es tematizable aquí: el vídeo. Los componentes de información (md_rating, md_developer, md_genre…) existen en esta vista pero están desactivados del lado del tema: a diferencia de detailed, no puedes darles formato.

➡️ Para mostrar el nombre o el desarrollador del juego en el salvapantallas, coloca tus propios text con las variables:

<view name="gameclip">
  <extras>
    <text name="titre">
      <pos>0.06 0.85</pos>
      <text>${game.name}</text>
      <fontSize>0.05</fontSize>
      <color>FFFFFF</color>
    </text>
    <text name="editeur">
      <pos>0.06 0.91</pos>
      <text>${game.developer} · ${game.releasedate}</text>
      <fontSize>0.03</fontSize>
    </text>
  </extras>
</view>

Las variables del juego funcionan aquí

El contexto de esta vista contiene el sistema Y el juego: todas las ${game.*} se resuelven. Es lo que hace interesante vestir el salvapantallas.


La vista menu — los menús

Lo que un tema puede, y no puede, cambiar en los menús.

Recalbox construye sus menús por sí mismo: su contenido, su orden y sus etiquetas no te pertenecen.

Lo que el tema proporciona son estilos — y una sola medida.

<view name="menu">
  <menuBackground>
    <color>101820F0</color>
    <path>${root}/data/arts/cadre.png</path>
  </menuBackground>

  <menuText>
    <fontPath>${root}/data/fonts/Exo2.otf</fontPath>
    <fontSize>0.038</fontSize>
    <color>C6CBD8</color>
    <selectedColor>101820</selectedColor>
    <selectorColor>4FE3C1</selectorColor>
    <separatorColor>FFFFFF20</separatorColor>
  </menuText>

  <menuSize><height>0.85</height></menuSize>
</view>

Los nueve componentes disponibles se describen en El estilo de los menús.

Lo que no puedes hacer

En qué hay que pensar

Los menús se muestran por encima de la vista actual. El velo (fadePath de menuBackground) oscurece lo que hay detrás: sin él, un menú con fondo transparente se vuelve ilegible sobre un tema claro.


Una capa presente en todas las vistas

Un decorado común escrito una sola vez, en lugar de copiarlo en cada vista.

El problema

Un velo catódico, un logotipo de marca, un marco: lo quieres en la lista de sistemas y en la lista de juegos y en el menú. Copiarlo en cada vista funciona… hasta el día en que modificas solo uno. Los demás se quedan atrás, y nada lo señala.

La solución

Clic derecho en la capa (o el del inspector) → « Presente en todas las vistas ».

La capa sale de su vista y se une a las capas comunes: ya no hay más que una, compartida. Ajustarla desde donde sea la ajusta en todas partes.

Para dar marcha atrás: « Conservar solo en esta vista ».

Lo que escribe en el tema

Un solo bloque, cuyo nombre enumera las vistas:

<!-- global.xml -->
<view name="system, basic, detailed, menu, gameclip">
    <extras>
        <image name="voileCRT" extra="true">…</image>
    </extras>
</view>

La máquina corta ese nombre por las comas y coloca el elemento en cada vista. El archivo se carga antes que las vistas: lo que vale en todas partes es una base, que una vista aún puede corregir.

No confundir

« Duplicar hacia otra disposición… » es otra cosa: copia la capa en otra disposición de la misma vista (por ejemplo « Vertical izquierda » y « Horizontal »), y las dos copias son después independientes.

⚠️ El nombre de vista menu se escribe porque el tema lo pide, pero el motor no lee allí ningún componente libre: la capa no se ve en los menús.

Al importar, un tema que ya escribe un bloque que cubre todas las vistas recupera su capa común. Un bloque que solo cubre una parte queda repartido por vista: solo vale allí donde el tema lo puso.


Usar las variables

Mostrar el nombre de un juego, elegir una imagen según el sistema.

Una variable se escribe ${…} y Recalbox la reemplaza en el momento de mostrar.

<text name="titre">
  <text>Bienvenue sur ${system}</text>
</text>

→ « Bienvenue sur Super Nintendo ».

En una ruta de imagen: lo más útil

<image name="console" extra="true">
  <path>${root}/data/arts/consoles/${system.name}.png</path>
</image>

Una sola línea, y cada sistema muestra su propia imagen. Basta con que los archivos lleven el nombre interno del sistema: snes.png, megadrive.png

Dónde funciona cada variable

Es la regla que más sorprende, y viene del motor:

FamiliaVistas donde se resuelve
${system…}Sistemas y Lista de juegos — una lista siempre pertenece a un sistema
${game…}Lista de juegos y Salvapantallas — allí donde hay un juego señalado
${recalbox…} ${settings…} ${hardware…} ${display…}en todas partes

Una variable empleada donde no existe no se reemplaza: el texto en bruto se muestra tal cual, ${game.name} incluido. El studio solo propone las que funcionan en la vista actual.

Cuando la línea resaltada no es un juego

En la lista de juegos, el cursor no recorre solo juegos: también pasa por las carpetas y por los encabezados de ordenación, esos intertítulos que Recalbox añade en cuanto la lista se ordena de otra forma que no sea alfabética. Las ${game…} siguen respondiendo, pero describen entonces una línea que no tiene juego:

Línea resaltada${game.name}${game.releasedate}${game.file.name}
un juegosu nombresu fecha de salidael archivo de la rom
una carpetael nombre de la carpetaDESCONOCIDOel nombre de la carpeta
un encabezado de ordenaciónnadaDESCONOCIDOnada

Un componente que muestra un dato del juego ya no tiene nada que decir en esas líneas — y aun así sigue en pantalla, encima del nombre de la carpeta que Recalbox escribe en ese mismo momento. Limítelo a las líneas de juego:

<text name="sortie" extra="true" showIf="game">
  <text>Salida: ${game.releasedate}</text>
</text>

El estudio se encarga de ello: en cuanto un componente emplea un dato del juego, su visibilidad pasa a «un juego». La pestaña Visibilidad del componente permite volver a abrirla a las carpetas y a los encabezados cuando así se desee.

${root} — para no olvidar nunca

${root} designa la raíz del tema seleccionado. Sin él, las rutas son relativas al archivo que las escribe, y tu tema se rompe en cuanto se guarda de otra manera.

<path>${root}/data/arts/fond.jpg</path>     <!-- ✅ -->
<path>../data/arts/fond.jpg</path>          <!-- frágil -->

Las antiguas variables $…

En temas viejos te cruzarás con variables sin llaves:

AntiguaLo que daEquivalente actual
$systemel nombre corto — « snes »${system.name}
$themela carpeta del tema${root}

⚠️ $system y ${system} no dan lo mismo: la primera devuelve « snes », la segunda « Super Nintendo ». Todavía se aceptan, pero están obsoletas: escribe ya solo la forma con llaves.

El sorteo

<path>${random.between(fond1.jpg,fond2.jpg,fond3.jpg)}</path>
<fontSize>${random.range(1,10)}</fontSize>

random.between elige un valor al azar de la lista, random.range un número entre dos límites. El sorteo tiene lugar al cargar el tema, no en cada visualización.


Todas las variables

La lista completa, y dónde funciona cada una.

Aquí están todas las variables que Recalbox sabe reemplazar, relevadas en el motor.

Una variable se escribe ${…} y Recalbox la sustituye al mostrarla.

El sistema

Qué escribirQué esQué devuelveDónde
${system}Nombre del sistemaEl nombre completo — p. ej. « Sega Megadrive »Sistemas, Juegos
${system.input.keyboard}¿Teclado necesario?mandatory · recommended · optional · noSistemas, Juegos
${system.input.mouse}¿Ratón necesario?mandatory · recommended · optional · noSistemas, Juegos
${system.input.pad}¿Mando necesario?mandatory · recommended · optional · noJuegos, Sistemas
${system.logo}Logotipo del sistemaLa ruta del logotipo proporcionado por RecalboxSistemas, Juegos
${system.manufacturer}FabricanteP. ej. « Sega », « Nintendo ». Vacío si se desconoceSistemas, Juegos
${system.name}Nombre corto del sistemaSistemas, Juegos
${system.releasedate}Año de salidaAño y mes — p. ej. « 1988-10 »Sistemas, Juegos
${system.type}Tipo de máquina (nombre técnico)arcade · console · handheld · computer · engine · port · fantasy · virtual · virtual-arcadeSistemas, Juegos
${system.type.name}Tipo de máquinaEl mismo, en claro: « Home Console », « handheld Console », « Arcade »…Sistemas, Juegos

El juego

Qué escribirQué esQué devuelveDónde
${game.developer}DesarrolladorP. ej. « Konami ». « UNKNOWN » si faltaSalvapantallas, Juegos
${game.file.name}Nombre del archivoEl nombre del archivo, extensión incluidaSalvapantallas, Juegos
${game.file.path}Ruta completa del archivoLa ruta completa del archivoSalvapantallas, Juegos
${game.file.stem}Nombre del archivo (sin extensión)El nombre del archivo, sin extensiónSalvapantallas, Juegos
${game.genre.normalized}Género (nombre técnico)El género normalizado, en inglés — « Platform », « Shoot’em Up », « Racing »…Salvapantallas, Juegos
${game.genre.raw}GéneroEl género tal como está escrito en la ficha del juegoSalvapantallas, Juegos
${game.isadult}¿Reservado a adultos?yes o noSalvapantallas, Juegos
${game.isfavorite}¿Es un favorito?yes o no (nunca true/false)Juegos, Salvapantallas
${game.ishidden}¿Está oculto?yes o noSalvapantallas, Juegos
${game.islastversion}¿Es la última versión?yes o noSalvapantallas, Juegos
${game.isnotagame}¿No es un juego?yes o noSalvapantallas, Juegos
${game.ispreinstalled}¿Está preinstalado?yes o noSalvapantallas, Juegos
${game.license}LicenciaLa licencia, a menudo vacíaSalvapantallas, Juegos
${game.name}Nombre del juegoEl nombre del juegoSalvapantallas, Juegos
${game.players}Número de jugadores« 1 », « 2 », « 1-4 », « 4+ »…Salvapantallas, Juegos
${game.players.max}Jugadores — máximoUn número — p. ej. « 4 »Salvapantallas, Juegos
${game.players.min}Jugadores — mínimoUn número — p. ej. « 1 »Salvapantallas, Juegos
${game.publisher}EditorP. ej. « Sega ». « UNKNOWN » si faltaSalvapantallas, Juegos
${game.releasedate}Fecha de salidaFecha ISO — p. ej. « 1991-06-23 ». « UNKNOWN » si faltaSalvapantallas, Juegos
${game.synopsis}DescripciónEl texto de presentación, a menudo largoSalvapantallas, Juegos

Puntuación y estadísticas

Qué escribirQué esQué devuelveDónde
${game.lastplayed}Última partidaFecha ISO, o « NEVER » si nunca se ha jugadoSalvapantallas, Juegos
${game.rating.10}Puntuación (sobre 10)Un entero de 0 a 10Salvapantallas, Juegos
${game.rating.100}Puntuación (sobre 100)Un entero de 0 a 100Salvapantallas, Juegos
${game.rating.5}Puntuación (sobre 5)Un entero de 0 a 5 — no estrellasSalvapantallas, Juegos
${game.timesplayed}Número de partidasUn número de partidasSalvapantallas, Juegos
${game.totalplayed}Tiempo de juego totalUna duración — p. ej. « 3h 12m ». « NONE » si es ceroSalvapantallas, Juegos

Imágenes y vídeo del juego

Qué escribirQué esQué devuelveDónde
${game.media.boxpath}Caja (box art)Juegos, Salvapantallas
${game.media.imagepath}Carátula / imagenLa ruta de la carátula. Vacía si el juego no tiene — ver ifexistsSalvapantallas, Juegos
${game.media.thumbpath}MiniaturaLa ruta de la miniaturaSalvapantallas, Juegos
${game.media.videopath}VídeoLa ruta del vídeoSalvapantallas, Juegos

Soporte del juego

Qué escribirQué esQué devuelveDónde
${game.support.index}Índice del soporteEl número del disco — vacío si solo hay unoSalvapantallas, Juegos
${game.support.number}Número del soporteTodo junto — p. ej. « 2A/3 »Salvapantallas, Juegos
${game.support.side}Cara del soporteLa cara del soporte — A, B…Salvapantallas, Juegos
${game.support.total}Número de soportesEl número de soportes. « UNKNOWN » si se desconoceSalvapantallas, Juegos
${game.support.type}Tipo de soporteCartridge · CD/DVD · Harddisk · Files · Tape · Quick Disc · 3" Floppy · 3".5 Floppy · 5".25 Floppy · PCB · UnknownSalvapantallas, Juegos

Sistema del juego

Qué escribirQué esQué devuelveDónde
${game.system}Nombre del sistema del juegoEl nombre completo del sistema del juegoSalvapantallas, Juegos
${game.system.input.keyboard}Teclado exigido por el sistema del juegomandatory · recommended · optional · noSalvapantallas, Juegos
${game.system.input.mouse}Ratón exigido por el sistema del juegomandatory · recommended · optional · noSalvapantallas, Juegos
${game.system.input.pad}Mando exigido por el sistema del juegomandatory · recommended · optional · noSalvapantallas, Juegos
${game.system.logo}Logotipo del sistema del juegoLa ruta de su logotipoSalvapantallas, Juegos
${game.system.manufacturer}Fabricante del sistema del juegoSu fabricanteSalvapantallas, Juegos
${game.system.name}Nombre corto del sistema del juegoSu nombre internoSalvapantallas, Juegos
${game.system.releasedate}Año del sistema del juegoSu año de salidaSalvapantallas, Juegos
${game.system.type}Tipo del sistema del juego (nombre técnico)Como ${system.type}: console · handheld · arcade…Salvapantallas, Juegos
${game.system.type.name}Tipo del sistema del juegoEl mismo, en claroSalvapantallas, Juegos

Emulador

Qué escribirQué esQué devuelveDónde
${game.emulator.compatibility}Compatibilidadunknown · low · average · good · high · perfectSalvapantallas, Juegos
${game.emulator.extensions}Extensiones admitidasLas extensiones admitidas — p. ej. « .bin .gen .md »Salvapantallas, Juegos
${game.emulator.hasnetplay}¿Compatible con juego en línea?yes o noSalvapantallas, Juegos
${game.emulator.hassoftpatching}¿Acepta parches?yes o noSalvapantallas, Juegos
${game.emulator.islibretro}¿Es un núcleo Libretro?yes o noSalvapantallas, Juegos
${game.emulator.name}Nombre del emuladorP. ej. « libretro picodrive »Salvapantallas, Juegos
${game.emulator.speed}Velocidadunknown · low · average · good · high · perfectSalvapantallas, Juegos

La máquina y sus ajustes

Qué escribirQué esQué devuelveDónde
${display.overscan}¿Overscan?yes o noSalvapantallas, Sistemas, Menú, Juegos
${random.between(a,b,c)}Un valor al azar entre…uno de los valores dadosen todas partes
${random.range(1,10)}Un número al azar entre…un entero entre los dos límitesen todas partes
${display.resolution}Resoluciónfhd (1080p y más) · hd (720p) · vga · qvgaSistemas, Menú, Juegos, Salvapantallas
${display.tate}¿Pantalla vertical (TATE)?yes o noSalvapantallas, Sistemas, Menú, Juegos
${display.tateleft}¿Vertical hacia la izquierda?yes o noSalvapantallas, Sistemas, Menú, Juegos
${display.tateright}¿Vertical hacia la derecha?yes o noMenú, Juegos, Salvapantallas, Sistemas
${hardware.board}Modelo de máquinaEl modelo — « RPi 5 », « PC x64 », « RG351P/M »…Salvapantallas, Sistemas, Menú, Juegos
${hardware.crt}¿Pantalla CRT?yes o noSalvapantallas, Sistemas, Menú, Juegos
${hardware.isanbernic}¿Es una Anbernic?yes o noSalvapantallas, Sistemas, Menú, Juegos
${hardware.isodroid}¿Es una Odroid?yes o noSalvapantallas, Sistemas, Menú, Juegos
${hardware.ispc}¿Es un PC?yes o noSistemas, Menú, Juegos, Salvapantallas
${hardware.ispi}¿Es una Raspberry Pi?yes o noSalvapantallas, Sistemas, Menú, Juegos
${hardware.jamma}¿Mueble Jamma?yes o noSalvapantallas, Sistemas, Menú, Juegos
${recalbox.built}Fecha de compilaciónLa fecha de compilaciónMenú, Juegos, Salvapantallas, Sistemas
${recalbox.version}Versión de RecalboxP. ej. « 10.0 »Salvapantallas, Sistemas, Menú, Juegos
${root}Carpeta del temaLa raíz del tema seleccionado — hay que ponerla delante de todas tus rutasSalvapantallas, Sistemas, Menú, Juegos
${settings.language}IdiomaEl idioma solo — p. ej. « fr »Salvapantallas, Sistemas, Menú, Juegos
${settings.locale}Idioma y paísIdioma y país — p. ej. « fr_FR »Salvapantallas, Sistemas, Menú, Juegos
${settings.region}Región elegidaeu · us · jpSistemas, Menú, Juegos, Salvapantallas
${settings.timezone}Zona horariaP. ej. « Europe/Paris »Salvapantallas, Sistemas, Menú, Juegos

Tus variables a medida

Tus propios valores con nombre — un color, una fuente — creados desde el studio.

Las variables de la página anterior son las de Recalbox: ${system}, ${game.developer}… Vienen dadas, tú solo las empleas.

Estas son las tuyas. Le das un nombre a un valor — un color, una fuente, una ruta — empleas ese nombre en todas partes, y el día que cambias el valor, todo el tema le sigue. Es lo que hace posibles las opciones de color: una elección redefine la variable, y nada más.

Crearlas en el studio

  1. abre Variables en la barra de herramientas: el panel se abre a la derecha;
  2. + Nueva variable, dale un nombre, y di qué es — un color (obtienes el selector, transparencia incluida), una fuente (elegida entre las del tema), u otro valor (un texto, una ruta, u otra variable);
  3. en un campo de color, el pequeño { } pegado al campo propone las tuyas, y en la lista de fuentes aparecen al principio.

El studio muestra bajo el campo el valor calculado: una variable que emplea otra se relee de un vistazo.

A mano, sin el studio

Se escriben en un bloque <variables>. La etiqueta, las reglas de nombre, el alcance y las condiciones se explican en Tus propias variables, en « La estructura de un tema ».


Mostrar bajo condición

Las 26 condiciones: la máquina, la pantalla, y el sistema mostrado.

Una condición if= hace aparecer un componente solo en ciertos casos.

<image name="fond" if="crt">…</image>

Se combinan con ! (no), & (y), | (o) — o, si prefieres las palabras, not, and, or: if="crt and not tate". Ver Combinar varias condiciones.

⚠️ Un identificador ausente de esta lista es ignorado por Recalbox y aparece como desconocido en themes.log.

En todas partes — la máquina y la pantalla

CondiciónVerdadera cuando…
hd fhd vga qvgala pantalla tiene esa resolución
crtla pantalla es un tubo de rayos catódicos
overscanla imagen desborda (CRT sin Jamma)
tate tateleft taterightla pantalla es vertical
jamma bartopla máquina es una recreativa
ispc ispi isodroid isanbernicla máquina es de ese modelo
nomenulos menús están desactivados

Solo donde se muestra un sistema

Estas ocho consultan el sistema actual. Solo valen en la vista Sistemas y en la Lista de juegos — en el resto no hay sistema, y la condición es siempre falsa.

CondiciónVerdadera cuando…
console handheld computer arcade engine port fantasyel sistema es de ese tipo
virtuales un sistema automático (Favoritos, Jugados recientemente, Todos los juegos…)
favoritees el sistema automático Favoritos
lastplayedes el sistema automático Jugados recientemente

⚠️ favorite no dice que el juego resaltado sea un favorito: habla del sistema. No existe ninguna condición sobre un juego ni sobre una carpeta — para reaccionar al contenido de un juego, usa sus variables (${game.isfavorite}) o ifexists.


Combinar varias condiciones

Y, O, « eso no », y los grupos entre paréntesis.

Una etiqueta por condición

Eliges una condición de la lista, y se convierte en una etiqueta. El pequeño botón delante dice en qué sentido cuenta:

Sobre una etiqueta ya puesta, ese mismo botón invierte el sentido; el ✕ la quita.

Los grupos

Un grupo es un paréntesis. Dentro, dices si hacen falta todas las condiciones, o al menos una. Entre dos grupos, la misma pregunta: Y u O.

Tres escrituras para los mismos operadores

Lo que se quiere decirSignoCon todas las letras
y&AND
o|OR
no!NOT

Las dos escrituras se mezclan, y las mayúsculas no importan en absoluto: if="crt AND !tate" equivale a if="crt & !tate".

⚠️ && y || no funcionan. Dos signos seguidos son un error de sintaxis, y una expresión con error vale falso: el componente desaparece sin que nada lo diga en la pantalla.

Ejemplo: « en una pantalla catódica, y en arcade o en favoritos » se escribe

crt & (arcade | favorite)

⚠️ El orden de los grupos cuenta

La máquina lee de izquierda a derecha, sin prioridad. a | b & c vale ahí (a | b) & c, y no a | (b & c). Por eso el studio pone sistemáticamente los paréntesis: lo que lees es exactamente lo que la máquina entenderá.

Dentro de un mismo grupo, en cambio, el orden no importa nada: « no Full HD y arcade » dice lo mismo que « arcade y no Full HD ».

Una condición se escribe en dos sitios

La misma condición, sobre el componente o sobre una sola de sus propiedades, no dice lo mismo:

<image name="filtre" if="crt">…</image>      <!-- ① el componente SOLO existe en un CRT -->

<text name="titre">                          <!-- ② el componente existe siempre… -->
  <fontSize if="crt">0.09</fontSize>         <!--    …pero su tamaño cambia en un CRT -->
  <fontSize if="!crt">0.05</fontSize>
</text>

① sobre el componente: aparece, o no existe en absoluto. ② sobre una propiedad: el componente siempre está ahí, solo cambia uno de sus valores.

En el studio, es el mismo botón y la misma ventana en ambos casos — lo que construyes aquí sirve allá de forma idéntica.


Los sistemas

Los nombres internos esperados en tus carpetas y tus archivos.

Cada sistema tiene varios nombres, y no hay que confundirlos:

La carpeta que debe crear en su tema lleva el nombre de ${system.name}. Algunos sistemas son una excepción: se enumeran debajo de su tabla.

Las máquinas (121)

Sistema${system.name}${system}${system.manufacturer}${system.type}
240ptestsuite240ptestsuite240ptestsuitevirtualvirtual
Acorn BBC MicrobbcmicroAcorn BBC MicroAcorncomputer
Amiga AGAamiga1200Amiga AGACommodorecomputer
Amiga CD32amigacd32Amiga CD32Commodoreconsole
Amiga CDTVamigacdtvAmiga CDTVCommodoreconsole
Amiga ECS/OCSamiga600Amiga ECS/OCSCommodorecomputer
Amstrad GX4000gx4000Amstrad GX4000Amstradconsole
AmstradCPCamstradcpcAmstradCPCAmstradcomputer
Apple IIapple2Apple IIApplecomputer
Apple IIGSapple2gsApple IIGSApplecomputer
Apple MacintoshmacintoshApple MacintoshApplecomputer
ArduboyarduboyArduboyfantasyfantasy
Atari 2600atari2600Atari 2600Atariconsole
Atari 5200atari5200Atari 5200Atariconsole
Atari 7800atari7800Atari 7800Atariconsole
Atari 8bitsatari800Atari 8bitsAtaricomputer
Atari JaguarjaguarAtari JaguarAtariconsole
Atari STataristAtari STAtaricomputer
ColecovisioncolecovisionColecovisionColecoconsole
Commodore 64c64Commodore 64Commodorecomputer
Commodore VIC-20vic20Commodore VIC-20Commodorecomputer
DaphnedaphneDaphneDaphnearcade
DICEdiceDICEDICEarcade
Dos (x86)dosDos (x86)IBMcomputer
Dragon 32/64dragonDragon 32/64DragonDatacomputer
EasyRPGeasyrpgEasyRPGvirtualengine
Elektronika BKbkElektronika BKElektronikacomputer
Epoch Cassette VisioncassettevisionEpoch Cassette VisionEpochconsole
Exelvision EXL 100exl100Exelvision EXL 100Exelvisioncomputer
Fairchild Channel FchannelfFairchild Channel FFairchildconsole
Family Computer Disk SystemfdsFamily Computer Disk SystemNintendoconsole
FinalBurn NeofbneoFinalBurn NeoFBNarcade
Game and WatchgwGame and WatchNintendohandheld
Game BoygbGame BoyNintendohandheld
Game Boy AdvancegbaGame Boy AdvanceNintendohandheld
Game Boy ColorgbcGame Boy ColorNintendohandheld
GameCubegamecubeGameCubeNintendoconsole
Infocom Z-MachinezmachineInfocom Z-MachineInfocomengine
LowRes NXlowresnxLowRes NXvirtualfantasy
LutrolutroLutrovirtualfantasy
LynxlynxLynxAtarihandheld
MamemameMameMamearcade
Mattel IntellivisionintellivisionMattel IntellivisionMattelconsole
MegaDuckmegaduckMegaDuckWelbackhandheld
MGT SAM CoupésamcoupeMGT SAM CoupéMGTcomputer
MoonlightmoonlightMoonlightNVidiavirtual
MSX1msx1MSX1Microsoftcomputer
MSX2msx2MSX2Microsoftcomputer
MSXturboRmsxturborMSXturboRMicrosoftcomputer
NEC PC-88pc88NEC PC-88NECcomputer
NEC PC-98pc98NEC PC-98NECcomputer
NEC PC-FXpcfxNEC PC-FXNECconsole
Neo-Geo AESneogeoNeo-Geo AESSNKconsole
Neo-Geo CDneogeocdNeo-Geo CDSNKconsole
Neo-Geo PocketngpNeo-Geo PocketSNKhandheld
Neo-Geo Pocket ColorngpcNeo-Geo Pocket ColorSNKhandheld
Nintendo 64n64Nintendo 64Nintendoconsole
Nintendo 64DD64ddNintendo 64DDNintendoconsole
Nintendo DSndsNintendo DSNintendohandheld
Nintendo Entertainment SystemnesNintendo Entertainment SystemNintendoconsole
Odyssey2o2emOdyssey2Magnavoxconsole
OpenBORopenborOpenBORSenile Teamengine
Oric/AtmosoricatmosOric/AtmosTangerinecomputer
Othello MultivisionmultivisionOthello MultivisionTsukudaconsole
PalmpalmPalmPalmhandheld
Panasonic 3DO3doPanasonic 3DOPanasonicconsole
PC EnginepcenginePC EngineNECconsole
PC Engine CDpcenginecdPC Engine CDNECconsole
Philips CD-IcdiPhilips CD-IPhillipsconsole
Philips P2000Tp2000tPhilips P2000TPhilipscomputer
Philips VG 5000vg5000Philips VG 5000Philipscomputer
PICO-8pico8PICO-8virtualfantasy
Pocket Challenge v2pcv2Pocket Challenge v2Benessehandheld
Pokémon MinipokeminiPokémon MiniNintendohandheld
Sammy AtomiswaveatomiswaveSammy AtomiswaveSammyarcade
SatellaviewsatellaviewSatellaviewNintendoconsole
ScreenshotsimageviewerScreenshotsvirtualvirtual
ScummVMscummvmScummVMLudvig Strigeusengine
Sega 32Xsega32xSega 32XSegaconsole
Sega CDsegacdSega CDSegaconsole
Sega DreamcastdreamcastSega DreamcastSegaconsole
Sega Game GeargamegearSega Game GearSegahandheld
Sega Master System / Mark IIImastersystemSega Master System / Mark IIISegaconsole
Sega MegadrivemegadriveSega MegadriveSegaconsole
Sega Model3model3Sega Model3Segaarcade
Sega NAOMInaomiSega NAOMISegaarcade
Sega NAOMI 2naomi2Sega NAOMI 2Segaarcade
Sega NAOMI GD-ROM SystemnaomigdSega NAOMI GD-ROM SystemSegaarcade
Sega PicopicoSega PicoSegaconsole
Sega SaturnsaturnSega SaturnSegaconsole
Sega SG1000sg1000Sega SG1000Segaconsole
Sharp X1x1Sharp X1Sharpcomputer
Sharp X68000x68000Sharp X68000Sharpcomputer
SolarussolarusSolarusSolarusengine
Sony Playstation 1psxSony Playstation 1Sonyconsole
Sony Playstation 2ps2Sony Playstation 2Sonyconsole
Sony Playstation PortablepspSony Playstation PortableSonyhandheld
SpectravideospectravideoSpectravideoSpectravideocomputer
ST-VstvST-VSegaarcade
SuFami TurbosufamiSuFami TurboBandaiconsole
Super Cassette VisionscvSuper Cassette VisionEpochconsole
Super Nintendo Entertainment SystemsnesSuper Nintendo Entertainment SystemNintendoconsole
SupergrafxsupergrafxSupergrafxNECconsole
Texas Instrument TI-99/4Ati994aTexas Instrument TI-99/4ATexas Instrumentcomputer
ThomsonthomsonThomsonThomsoncomputer
TIC-80tic80TIC-80portfantasy
TRS-80 Color Computertrs80cocoTRS-80 Color ComputerTandycomputer
UzeboxuzeboxUzeboxportconsole
VectrexvectrexVectrexMBconsole
Videopac+ G7400videopacplusVideopac+ G7400Philipsconsole
Vircon32vircon32Vircon32virtualconsole
Virtual BoyvirtualboyVirtual BoyNintendoconsole
Visual Pinball StandalonevpinballVisual Pinball StandaloneRandy Davisengine
WASM-4wasm4WASM-4Bruno Garciafantasy
Watara SupervisionsupervisionWatara SupervisionWatarahandheld
WiiwiiWiiNintendoconsole
WonderSwanwswanWonderSwanBandaihandheld
WonderSwan ColorwswancWonderSwan ColorBandaihandheld
XboxxboxXboxMicrosoftconsole
ZX81zx81ZX81Sinclaircomputer
ZXSpectrumzxspectrumZXSpectrumSinclaircomputer

Las carpetas que no llevan el nombre del sistema. Para estos, y solo para estos, la carpeta de su tema se llama de otra manera que ${system.name}.

Sistema${system.name}Carpeta a crear
Dos (x86)dospc
GameCubegamecubegc
Odyssey2o2emodyssey2
Oric/Atmosoricatmosoric
Thomsonthomsonto8
WonderSwanwswanwonderswan
WonderSwan Colorwswancwonderswancolor

Los sistemas virtuales (11)

Recalbox los fabrica él mismo, a partir de tus juegos: no tienen archivo de sistema, pero sí tienen una carpeta de tema, y puedes vestirlos como los demás.

Sistema${system.name}${system}${system.type}
PortsportsPortsvirtual
FavoritesfavoritesFavoritesvirtual
Last playedlastplayedLast playedvirtual
All gamesallgamesAll gamesvirtual
MultiplayermultiplayerMultiplayervirtual
ArcadearcadeArcadevirtual-arcade
LightgunlightgunLightgunvirtual
TatetateTatevirtual
DialdialDialvirtual
TrackballtrackballTrackballvirtual
ChallengeschallengesChallengesvirtual

Las carpetas que no llevan el nombre del sistema. Para estos, y solo para estos, la carpeta de su tema se llama de otra manera que ${system.name}.

Sistema${system.name}Carpeta a crear
Last playedlastplayedauto-lastplayed
All gamesallgamesauto-allgames
Multiplayermultiplayerauto-multiplayer
Lightgunlightgunauto-lightgun
Tatetateauto-tate
Dialdialauto-dial
Trackballtrackballauto-trackball
Challengeschallengesauto-challenges

Arcade por fabricante (54) (${system.type} = virtual-arcade)

Sistema${system.name}${system}
Acclaimarcade-manufacturer-acclaimAcclaim
Atariarcade-manufacturer-atariAtari
Atlusarcade-manufacturer-atlusAtlus
Banprestoarcade-manufacturer-banprestoBanpresto
Capcom Cps1arcade-manufacturer-capcom-cps1Capcom Cps1
Capcom Cps2arcade-manufacturer-capcom-cps2Capcom Cps2
Capcom Cps3arcade-manufacturer-capcom-cps3Capcom Cps3
Capcomarcade-manufacturer-capcomCapcom
Cavearcade-manufacturer-caveCave
Data eastarcade-manufacturer-data eastData east
Exidyarcade-manufacturer-exidyExidy
Hng64arcade-manufacturer-hng64Hng64
Igsarcade-manufacturer-igsIgs
Irem M72arcade-manufacturer-irem-m72Irem M72
Irem M92arcade-manufacturer-irem-m92Irem M92
Iremarcade-manufacturer-iremIrem
Itecharcade-manufacturer-itechItech
Jalecoarcade-manufacturer-jalecoJaleco
Kanekoarcade-manufacturer-kanekoKaneko
Konami Gxarcade-manufacturer-konami-gxKonami Gx
Konamiarcade-manufacturer-konamiKonami
Midwayarcade-manufacturer-midwayMidway
Mitchellarcade-manufacturer-mitchellMitchell
Namco Naarcade-manufacturer-namco-naNamco Na
Namco Nbarcade-manufacturer-namco-nbNamco Nb
Namco System1arcade-manufacturer-namco-system1Namco System1
Namco System10arcade-manufacturer-namco-system10Namco System10
Namco System11arcade-manufacturer-namco-system11Namco System11
Namco System12arcade-manufacturer-namco-system12Namco System12
Namco System18arcade-manufacturer-namco-system18Namco System18
Namco System2arcade-manufacturer-namco-system2Namco System2
Namcoarcade-manufacturer-namcoNamco
Neogeoarcade-manufacturer-neogeoNeogeo
Nichibutsuarcade-manufacturer-nichibutsuNichibutsu
Nintendoarcade-manufacturer-nintendoNintendo
Nmkarcade-manufacturer-nmkNmk
Psikyoarcade-manufacturer-psikyoPsikyo
Raizingarcade-manufacturer-raizingRaizing
Sammyarcade-manufacturer-sammySammy
Sega Stvarcade-manufacturer-sega-stvSega Stv
Sega System16arcade-manufacturer-sega-system16Sega System16
Sega System18arcade-manufacturer-sega-system18Sega System18
Sega System32arcade-manufacturer-sega-system32Sega System32
Segaarcade-manufacturer-segaSega
Seibuarcade-manufacturer-seibuSeibu
Setaarcade-manufacturer-setaSeta
Snkarcade-manufacturer-snkSnk
Taito F3arcade-manufacturer-taito-f3Taito F3
Taito Gnetarcade-manufacturer-taito-gnetTaito Gnet
Taitoarcade-manufacturer-taitoTaito
Technosarcade-manufacturer-technosTechnos
Tecmoarcade-manufacturer-tecmoTecmo
Toaplanarcade-manufacturer-toaplanToaplan
Viscoarcade-manufacturer-viscoVisco

Por género (56) (${system.type} = virtual)

Sistema${system.name}${system}
Actiongenre-actionAction
Platformgenre-actionplatformerPlatform
Platform Shootergenre-actionplatformshooterPlatform Shooter
First Person Shootergenre-actionfirstpersonshooterFirst Person Shooter
Shoot'em Upgenre-actionshootemupShoot'em Up
Shoot with Gungenre-actionshootwithgunShoot with Gun
Fightinggenre-actionfightingFighting
Beat'em Allgenre-actionbeatemupBeat'em All
Infiltrationgenre-actionstealthInfiltration
Battle Royalegenre-actionbattleroyaleBattle Royale
Rythm & Musicgenre-actionrythmRythm & Music
Adventuregenre-adventureAdventure
Textual Adventuregenre-adventuretextTextual Adventure
Graphical Adventuregenre-adventuregraphicsGraphical Adventure
Visual Novelgenre-adventurevisualnovelsVisual Novel
Interactive Moviegenre-adventureinteractivemovieInteractive Movie
Real Time 3D Adventuregenre-adventurerealtime3dReal Time 3D Adventure
Survivalgenre-adventuresurvivalhorrorSurvival
RPGgenre-rpgRPG
Action RPGgenre-rpgactionAction RPG
MMORPGgenre-rpgmmoMMORPG
Dungeon Crawlergenre-rpgdungeoncrawlerDungeon Crawler
Tactical RPGgenre-rpgtacticalTactical RPG
JRPGgenre-rpgjapaneseJRPG
Party based RPGgenre-rpgfirstpersonpartybasedParty based RPG
Simulationgenre-simulationSimulation
Build & Managementgenre-simulationbuildandmanagementBuild & Management
Life Simulationgenre-simulationlifeLife Simulation
Fishing & Huntinggenre-simulationfishandhuntFishing & Hunting
Vehicle Simulationgenre-simulationvehicleVehicle Simulation
Science Fiction Simulationgenre-simulationscifiScience Fiction Simulation
Strategygenre-strategyStrategy
eXplore, eXpand, eXploit & eXterminategenre-strategy4xeXplore, eXpand, eXploit & eXterminate
Artillerygenre-strategyartilleryArtillery
Auto-battlergenre-strategyautobattlerAuto-battler
Multiplayer Online Battle Arenagenre-strategymobaMultiplayer Online Battle Arena
Real Time Strategygenre-strategyrtsReal Time Strategy
Turn Based Strategygenre-strategytbsTurn Based Strategy
Tower Defensegenre-strategytowerdefenseTower Defense
Wargamegenre-strategywargameWargame
Sportsgenre-sportsSports
Racinggenre-sportracingRacing
Sport Simulationgenre-sportsimulationSport Simulation
Competition Sportgenre-sportcompetitiveCompetition Sport
Fighting/Violent Sportgenre-sportfightFighting/Violent Sport
Pinballgenre-pinballPinball
Board gamegenre-boardBoard game
Casual gamegenre-casualCasual game
Digital Cardsgenre-digitalcardDigital Cards
Puzzle & Logicgenre-puzzleandlogicPuzzle & Logic
Multiplayer Party Gamegenre-partyMultiplayer Party Game
Triviagenre-triviaTrivia
Casinogenre-casinoCasino
Multi Game Compilationgenre-compilationMulti Game Compilation
Demo from Demo Screnegenre-demosceneDemo from Demo Screne
Educativegenre-educativeEducative

Las fuentes

Las de la máquina, y las tuyas.

Una fuente viene de dos sitios, y eso cambia lo que hay que entregar.

Las de la máquina

<fontPath>:/ubuntu_condensed.ttf</fontPath>

El :/ designa los recursos de EmulationStation. Nada que copiar en tu tema: el archivo está presente en todas las Recalbox.

Las tuyas

<fontPath>${root}/data/fonts/Exo2.otf</fontPath>

El archivo debe estar en tu tema, y se entregará con él. TTF y OTF funcionan.

El tamaño

fontSize cambia de unidad según su valor: por debajo de 1, es una proporción de la altura de la pantalla; a partir de 1, son píxeles. Todo se explica en Proporción, porcentaje o píxeles. Prefiere la proporción: 0.045 da la misma proporción en todas partes.

Las fuentes de píxeles

f8bitfortressplus solo es nítida a tamaños múltiplos de 7 en píxeles. Entre esos valores, se emborrona. Es cierto para toda fuente dibujada píxel a píxel: si añades una, comprueba a qué tamaños queda limpia.

fontStyle

normal · bold · italic · bolditalic

⚠️ Solo funciona si la fuente contiene esos gruesos. Una fuente entregada en un solo archivo « Regular » no se volverá negrita: hay que proporcionar el archivo « Bold » y designarlo con su propio fontPath.

Incluidas con Recalbox

Nada que copiar en tu tema.

FuenteQué escribir
Ubuntu Condensed:/ubuntu_condensed.ttf
DejaVu Sans Condensed:/dejavusanscondensed.ttf
Ubuntu Mono:/UbuntuMonoR.ttf
8-bit Fortress Plus — fuente de píxeles, nítida en múltiplos de 7:/f8bitfortressplus.ttf

Qué es una opción

Ofrecer elecciones al usuario de tu tema.

Una opción es una propiedad que el usuario encontrará en los menús de su máquina: « Colores del tema: Azul / Verde / Rojo », « Filtro retro: CRT / scanlines / ninguno ».

Es lo que distingue un tema rico de un tema congelado.

Lo que una opción hace de verdad

Una opción no es un interruptor « mostrar u ocultar ». Es un archivo cargado por encima del tema, que redefine lo que quiere: un color, una fuente, una disposición entera.

En los temas oficiales, la inmensa mayoría de las opciones solo cambian colores — a menudo redefiniendo una simple <variable>. Las ocultaciones son raras.

Una opción actúa sobre todas las vistas a la vez: es una propiedad del tema, no de una vista.

Las opciones del tema oficial

recalbox-next-2025 propone diez, lo que da una buena idea de lo que se hace:

OpciónLo que cambia
systemViewla disposición de la lista de sistemas
gameListla de la lista de juegos
gameclipviewla del salvapantallas
SysInfosla información de los sistemas: completa, mínima, oculta
gameInfosla información de los juegos
colorTheme12 paletas de colores
shaderel filtro retro: CRT, scanlines, panal, ninguno
shadowel sombreado
bandslas bandas de color: finas, gruesas, ninguna
iconesetThemelos iconos de la barra de ayuda: 8 juegos

Declarar una opción: <subset>

La sintaxis exacta, en dos tiempos.

Una opción se construye en dos tiempos: se declara, y luego se enumeran sus elecciones.

<subset subset="colorTheme" declara el GRUPO + su título <include … name="1 - Azul"> <include … name="2 - Rojo"> cada elección = un archivo cargado por encima Ajustes ▸ Tema Colores del tema ◁ Azul ▷ lo que ve el usuario en su máquina el prefijo « 1 - » sirve para ORDENAR las elecciones: no se muestra

1. Declarar el grupo

<subset subset="colorTheme"
        title="THEME : Colors"      title.fr="THÈME : Couleurs"
        help="Choose the color set"  help.fr="Choisissez la palette" />
AtributoFunción
subsetel identificador del grupo — es él quien enlaza las elecciones entre sí
titleel rótulo que el usuario lee en el menú
helpla frase de explicación bajo el rótulo

title y help aceptan un sufijo de idioma: title.fr, title.es… La versión sin sufijo sirve de repliegue.

2. Enumerar las elecciones

Cada elección es un <include> que lleva el mismo 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>
AtributoFunción
subseta qué grupo pertenece esta elección
nameel rótulo de la elección en la lista (traducible: name.fr)

La elección « ninguno »

Un <include> vacío da la opción « ninguno » — útil para dejar el tema en su estado original:

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

Proponer una elección solo en ciertas pantallas

<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>

El usuario solo ve las elecciones pertinentes para su material. Así es como el filtro retro no aparece en una pantalla catódica, que no lo necesita.

El contenido de un archivo de elección

Es un archivo de tema ordinario, que solo redefine lo que cambia:

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

Tres líneas útiles, y todo el tema pasa al rojo — a condición de haber construido el tema sobre variables en lugar de sobre colores escritos en duro.

⚠️ Las opciones se cargan ANTES que las vistas. Una variable vale para lo que se lee después de ella: es por ahí por donde debe pasar la elección para que las vistas la aprovechen.

El orden a escribir en theme.xml:

<theme name="Mon Thème" …>
  <include>${root}/variables.xml</include>      <!-- 1. los valores por defecto -->
  <include>${root}/options.xml</include>        <!-- 2. la elección los redefine -->
  <include>${root}/views/system.xml</include>   <!-- 3. las vistas, que los emplean -->
</theme>

Lo que ocurre cuando la persona cambia de elección

Recalbox relee el tema entero — todos los archivos, desde theme.xml, con la nueva elección activa. Por eso aparece en ese momento un breve « Actualizando el tema… ».

Una opción que solo cambia colores redefine únicamente variables. Es la manera más corta de escribir un juego de colores — y la principal razón para usar <variables>.


El orden de las elecciones

El prefijo numérico — y por qué no se muestra.

Recalbox no conserva el orden en el que escribes tus <include>. Ordena las elecciones él mismo, en dos tiempos:

  1. si TODAS las elecciones tienen un número al principio de su name, ordena por ese número;
  2. si no, ordena por orden alfabético del name.

Por eso se numera.

La buena escritura

<include subset="bands" name="1 - Thin"   name.fr="1 - Fines">…</include>
<include subset="bands" name="2 - Thick"  name.fr="2 - Épaisses">…</include>
<include subset="bands" name="3 - None"   name.fr="3 - Aucune">…</include>

El prefijo no se muestra. Recalbox lo detecta, lo usa para ordenar, y luego lo quita antes de mostrar el rótulo. El usuario lee « Finas », « Gruesas », « Ninguna ».

Lo que el motor acepta como prefijo

Un número, luego un espacio, un guion o un punto, todo en los ocho primeros caracteres. Estas tres escrituras funcionan:

1 - Finas
1. Finas
1 Finas

La trampa

La ordenación numérica solo se emplea si todas las elecciones están numeradas. Un solo olvido, y Recalbox vuelve al orden alfabético — tus elecciones se reordenan solas, sin mensaje.

<include subset="bands" name="1 - Fines">…</include>
<include subset="bands" name="2 - Épaisses">…</include>
<include subset="bands" name="Aucune">…</include>     <!-- ❌ rompe la ordenación de los tres -->

El nombre de los ARCHIVOS, en cambio, es libre

No confundir: el número va en el atributo name, no en el nombre del archivo. Recalbox nunca mira cómo se llama tu archivo.

options/
  bandes/
    fines.xml        ← nómbralos como quieras
    epaisses.xml
    aucune.xml

Lo que cuenta: una carpeta por opción, y nombres que digan lo que hacen.


Probar tu tema

Copiarlo en la máquina, y leer el registro si algo falla.

Un tema solo se juzga encendido, en una pantalla. La vista previa del studio es fiel, pero nada sustituye a la máquina.

  1. Exportar el tema desde el studio;
  2. copiar la carpeta en /recalbox/share/themes/;
  3. en la máquina: Menú → Propiedades de la interfaz → Tema, y elegir el tuyo.

📄 El registro: themes.log

Es el primer sitio que hay que mirar cuando algo no se muestra.

/recalbox/share/system/logs/themes.log

Anota, con archivo y línea como respaldo:

Un componente invisible sin nada en el registro casi siempre significa que falta extra="true": ver La regla más importante.


Compartir tu tema

Proponer tu tema al gestor de temas de Recalbox, desde el estudio.

Recalbox tiene un gestor de temas: los temas se instalan desde ahí, sin copiar nada a mano. Para que un tema entre, hay que proponerlo — y todo se hace desde este estudio.

📘 Ya no hay repositorio que bifurcar, ni merge request, ni archivo que escribir: el estudio prepara el paquete, toma las capturas y lo envía todo por ti.

Proponer tu tema

Dos puertas, un mismo destino:

En ambos casos describes tu tema en unos pocos campos y lo envías. Ya está.

⚠️ Hace falta tener el derecho. Proponer un tema está abierto a los roles que el equipo ha designado en el Discord de Recalbox: si el botón no aparece, es que todavía te falta.

Lo que el estudio hace por ti

⚠️ Tu archivo se envía tal cual. El estudio solo lo mira para tomar las capturas; nunca lo reescribe. Tus carpetas, tus nombres de archivo, tu organización: nada se mueve.

Lo que ocurre después

  1. tu tema pasa a votación — los creadores de temas lo miran pantalla por pantalla y dan su opinión, con un comentario si quieren;
  2. un administrador decide. El voto orienta, no decide: nadie se publica por un recuento;
  3. aceptado, el tema entra en el gestor de temas y todas las Recalbox lo ven. Rechazado, recibes un motivo — lo suficiente para corregirlo y volver a proponerlo.

Lo sigues todo desde «Mis temas»: la tarjeta de tu tema muestra «solicitud pendiente», y la pestaña «Publicar» te enseña el recuento de votos y lo que te han escrito (sin los nombres).

Actualizar un tema ya publicado

El mismo camino: vuelve a proponer tu tema, con un número de versión más alto.

⚠️ Una actualización no vuelve a pasar por la votación — es tu tema, conoces su estado. Solo espera a que un administrador la ponga en línea. Nadie tiene que reinstalar nada: el gestor de temas les ofrece la actualización.

Lo que hace que te rechacen