¿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
- dónde se colocan los elementos en pantalla, y de qué tamaño;
- qué imágenes se muestran: fondos, logotipos, marcos, ilustraciones;
- los colores y las fuentes, incluidas las de los menús;
- qué se muestra según el contexto: la resolución de la pantalla, el tipo de máquina, el juego resaltado.
Lo que un tema no decide
- el contenido de los menús: Recalbox los construye por sí mismo. Un tema solo ajusta su aspecto;
- los juegos, su información, los emuladores;
- el comportamiento de los botones.
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
extra="true"en el fondo: sin él, no se mostraría. Es la regla que hay que recordar, explicada en La regla más importante;systemcarousel,logo,gamelist,md_imageson nombres reservados: es ese nombre — no el tipo de la etiqueta — lo que los conecta con el motor. Hay una treintena, y cada vista tiene los suyos: la lista completa está en Las vistas y sus componentes;${system}y${game.name}son variables: Recalbox las sustituye al mostrar, por el nombre del sistema actual o del juego resaltado. Es lo que hace vivo un tema sin escribir nada especial — ver Usar las variables;- la vista
menuno se compone: no se coloca nada en ella, se viste lo que Recalbox construye; - la vista
gameclipes el salvapantallas — Recalbox encadena allí extractos de juegos, y el tema apenas añade información sobre el juego mostrado.
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
- 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.
- 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.
- Coloca tus componentes: arrástralos desde la columna izquierda, ajústalos en la derecha.
- 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.
- Exporta, copia la carpeta a tu máquina, pruébalo — ver Probar el tema.
A mano
- 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.
- Crea la carpeta y su
theme.xml— el único archivo obligatorio. Ver Carpetas y archivos. - Anuncia lo que cubres en la etiqueta
<theme>:compatibilitypara los tipos de pantalla,resolutionspara 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. - 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.
- Sirve las demás pantallas con condiciones en lugar de copiarlo todo:
<include if="crt">. - Copia la carpeta a tu máquina y pruébalo — y lee
themes.logal 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/.
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és — views/, 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
| Atributo | Función | Ejemplo | Si falta |
|---|---|---|---|
name | Nombre mostrado en la lista de temas | name="Mi Tema" | el nombre de la carpeta |
version | Versión del tema | version="1.2" | no se muestra |
author | El autor | author="Benoît" | no se muestra |
recalbox | Versión mínima de Recalbox exigida | recalbox="10.0" | todas las versiones |
compatibility | Tipos de pantalla cubiertos: hdmi, crt, jamma, tate | compatibility="hdmi,crt" | hdmi |
resolutions | Resoluciones cubiertas: qvga, vga, hd, fhd | resolutions="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.xml — la 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.
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:
- los elementos que construye él mismo — el carrusel, la lista de juegos, la barra de ayuda, la carátula del juego… Tienen un nombre reservado, y el tema solo los ajusta;
- los componentes que tú añades — un texto, una imagen, un bloque de color, un vídeo. Son los componentes libres.
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
<extras>no es un componente: no se dibuja, no se posiciona.- No se mete dentro de sí mismo: un
<extras>dentro de un<extras>no tiene ningún efecto adicional. - Funciona en la vista Sistemas, la Lista de juegos y el Salvapantallas. ⚠️ No en el Menú: el motor no busca allí ningún componente libre. Un
<extras>escrito para la vista Menú se lee sin error… y nunca dibuja nada. - Los elementos de nombre reservado quedan fuera: ya existen, solo se ajustan.
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
nameyvalueson obligatorios los dos; sin uno de ellos, la línea se ignora y se señala en el registro;- un
namevacío se rechaza; - una variable puede contener otra, incluida una variable de Recalbox:
<variable name="CheminLogo" value="${root}/data/logos/${system.name}.svg" />
- el bloque
<variables>acepta una condición, y cada<variable>también:
<variables if="crt">
<variable name="TailleTitre" value="0.09" />
</variables>
- puede haber varios bloques
<variables>, en cualquier archivo; - una variable redefinida más adelante machaca la anterior — como los componentes.
⚠️ 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 archivo — variables.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.
| Escritura | Ejemplo | Qué significa |
|---|---|---|
| Ratio (por defecto) | 0.5 0.25 | una proporción de la pantalla, de 0 a 1 |
| Porcentaje | 50% 25% | lo mismo, escrito de otra forma |
| Píxeles | 960p 270p | pí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:
| Valor | Qué significa |
|---|---|
< 1 | una proporción del lado corto de la pantalla — 0.05 = 5 % de la altura en 16:9 |
>= 1 | un 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:
pos— dónde, en la PANTALLA, se coloca el componente.origin— qué 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.
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:
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 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
origin | El punto del componente posado sobre pos |
|---|---|
0 0 | esquina superior izquierda — el valor por defecto |
0.5 0 | centro del borde superior |
1 0 | esquina superior derecha |
0 0.5 | centro del borde izquierdo |
0.5 0.5 | el centro |
1 0.5 | centro del borde derecho |
0 1 | esquina inferior izquierda |
0.5 1 | centro del borde inferior |
1 1 | esquina 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 quiere | pos | origin |
|---|---|---|
| centrado en pantalla | 0.5 0.5 | 0.5 0.5 |
| pegado al borde derecho | 1 … | 1 … |
| pegado al borde inferior | … 1 | … 1 |
| centrado abajo | 0.5 1 | 0.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:
| Escritura | Lo que se garantiza |
|---|---|
size 0.3 0 | el ancho hace exactamente 30 %; la altura sigue, sea cual sea — puede desbordar |
maxSize 0.3 0.2 | la 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>
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: consize, 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.
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.
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 -->
- 6 caracteres:
RRGGBB, opaco; - 8 caracteres:
RRGGBBAA, los dos últimos dan la opacidad —00invisible,80a medias,FFopaco.
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:
| Opacidad | Escribir | Opacidad | Escribir |
|---|---|---|---|
| 0 % — invisible | 00 | 60 % | 99 |
| 10 % | 1A | 70 % | B3 |
| 20 % | 33 | 75 % | BF |
| 25 % | 40 | 80 % | CC |
| 30 % | 4D | 90 % | E6 |
| 40 % | 66 | 95 % | F2 |
| 50 % | 80 | 100 % — opaco | FF |
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.
| Propiedad | Efecto |
|---|---|
colorTop + colorBottom | degradado vertical |
colorLeft + colorRight | degradado horizontal |
colorTopLeft, colorTopRight, colorBottomLeft, colorBottomRight | degradado 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
| Sufijo | A qué apunta |
|---|---|
.fr .es .de | el idioma de la máquina, en minúsculas |
.fr_FR | el idioma y el país |
.US .EU .JP | la 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">
imagees el tipo de componente: decide lo que el componente sabe hacer y las propiedades que acepta. Debe elegirse de la lista de tipos existentes — ver Los componentes. Un tipo inventado se ignora;namees tu etiqueta. Es libre… salvo si retomas uno de los nombres reservados por Recalbox, en cuyo caso el componente queda conectado al motor — ver Las vistas y sus componentes.
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
| Tipo | Lo que hace |
|---|---|
text | un texto, en una o varias líneas |
scrolltext | un texto que se desplaza cuando es demasiado largo |
markdown | un texto con formato (negrita, títulos, listas) |
image | una imagen |
video | un vídeo |
box | un bloque de color, o un degradado |
datetime | una fecha |
rating | una puntuación, en estrellas |
sound | un sonido (no muestra nada) |
Listas y navegación
| Tipo | Lo que hace |
|---|---|
textlist | la lista de juegos |
carousel | el carrusel de sistemas |
helpsystem | la 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>
| Propiedad | Tipo | Función |
|---|---|---|
pos size origin rotation rotationOrigin | par | colocación — ver Posición, tamaño, origen |
text | texto | el contenido, variables incluidas |
path | ruta | lee el contenido desde un archivo, en lugar de text |
fontPath | ruta | la fuente |
fontSize | número | < 1 = proporción de la altura de pantalla, >= 1 = píxeles |
fontStyle | texto | normal, bold, italic, bolditalic |
color | color | el color del texto |
backgroundColor | color | un fondo detrás del texto |
alignment | texto | ver más abajo |
forceUppercase | sí/no | todo en mayúsculas |
lineSpacing | número | el interlineado, 1.2 por defecto |
multiline | sí/no | permitir los saltos de línea |
zIndex | número | la profundidad |
disabled | sí/no | apagar 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ón | Escribir | Sinónimo |
|---|---|---|
| arriba-izquierda | topleft | |
| arriba-centro | topcenter | top |
| arriba-derecha | topright | |
| centro-izquierda | centerleft | left |
| centro | center | |
| centro-derecha | centerright | right |
| abajo-izquierda | bottomleft | |
| abajo-centro | bottomcenter | bottom |
| abajo-derecha | bottomright |
⚠️ Un valor desconocido no conserva la alineación anterior: vuelve a centro-izquierda, el valor por defecto.
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 ».
⚠️
markdownno 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>
| Propiedad | Tipo | Función |
|---|---|---|
pos size origin rotation rotationOrigin | par | colocación |
maxSize | par | tamaño máximo sin deformación — ver Posición, tamaño |
keepratio | sí/no | conservar las proporciones (⚠️ todo en minúsculas) |
path | ruta | el archivo de imagen |
tile | sí/no | repetir la imagen en mosaico en lugar de estirarla |
color | color | tiñe la imagen (multiplicación) |
colorTop colorBottom colorLeft colorRight | color | tinte en degradado |
colorTopLeft colorTopRight colorBottomLeft colorBottomRight | color | tinte por las cuatro esquinas |
reflection | par | un reflejo bajo la imagen: opacidad inicial y final |
zIndex disabled | profundidad, 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:
| Propiedad | Tipo | Función |
|---|---|---|
delay | número | segundos antes de que arranque el vídeo |
loops | número | número de reproducciones; 0 = en bucle |
animations | texto | el efecto de aparición |
link | texto | vincular la reproducción a otro componente |
reflection | par | el reflejo, como en image |
video no acepta ni tile ni los colores de tinte.
Un
delayde 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>
| Propiedad | Función |
|---|---|
pos size origin rotation rotationOrigin | colocación |
color | color liso |
colorTop colorBottom | degradado vertical |
colorLeft colorRight | degradado horizontal |
colorTopLeft colorTopRight colorBottomLeft colorBottomRight | degradado por las cuatro esquinas |
zIndex disabled | profundidad, 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.
textlistsolo existe en la vista Juegos, bajo el nombre reservadogamelist. 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>
| Propiedad | Función |
|---|---|
pos size origin | colocación |
primaryColor | el color de los juegos |
secondaryColor | el color de las carpetas |
selectedColor | el color del texto de la línea elegida |
selectorColor | el color del resaltador |
selectorImagePath | una imagen de resaltador, en lugar del color |
selectorImageTile | repetir esa imagen en mosaico |
selectorHeight | la altura del resaltador |
selectorOffsetY | su desplazamiento vertical |
fontPath fontSize | la fuente |
alignment | la alineación de las líneas |
horizontalMargin | el margen izquierdo y derecho |
forceUppercase | todo en mayúsculas |
lineSpacing | el interlineado — es él quien espacia las líneas |
scrollSound | el sonido reproducido al desplazarse |
zIndex | la profundidad |
⚠️ 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.
La dirección de desplazamiento
type acepta horizontal (por defecto), vertical y vertical_wheel — la rueda. No existe rueda horizontal: cualquier otro valor vuelve silenciosamente a horizontal.
Las propiedades (28)
<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>
| Propiedad | Función |
|---|---|
type | horizontal, vertical, vertical_wheel |
pos size origin | colocación |
color | el fondo del carrusel |
logoSize | el tamaño de un logotipo (par) |
logoScale | el agrandamiento del logotipo elegido |
logoRotation logoRotationOrigin | la rotación de los logotipos (ruedas) |
logoAlignment | la alineación de los logotipos en su casilla |
maxLogoCount | cuántos logotipos visibles a la vez |
defaultTransition | fade o instant; cualquier otro valor da slide |
fontPath fontSize fontColor | la fuente del modo texto |
forceUppercase | los nombres de sistemas en mayúsculas |
textOnly | escribir los nombres en lugar de los logotipos |
primaryColor secondaryColor | el color de los nombres |
selectedColor | el color del nombre elegido |
selectorColor selectorHeight | el resaltador del modo texto |
selectorOffsetX selectorOffsetY | su desplazamiento |
textOffsetX | el desplazamiento del texto |
lineSpacing horizontalMargin | interlineado y márgenes del modo texto |
zIndex | la profundidad |
⚠️ 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.
Logotipos, o nombres
En la sección Lista de sistemas, « QUÉ DESFILA » elige entre:
- Logotipos — el comportamiento habitual;
- Nombres — el carrusel escribe el nombre de cada sistema.
⚠️ 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.
Las propiedades que lo acompañan
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:
- Desplazamiento horizontal del resaltador (
selectorOffsetX); - Desplazamiento horizontal del texto (
textOffsetX).
Lo que escribe
<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,
textOnlyse 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>
| Propiedad | Función |
|---|---|
pos size origin rotation rotationOrigin | colocación |
filledPath | la imagen de estrella llena |
unfilledPath | la imagen de estrella vacía |
zIndex disabled | profundidad, 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
| Escribir | Lo que se muestra |
|---|---|
date | 1991/06/23 |
dateTime | 1991/06/23 14:05:30 |
year | 1991 |
time | 14:05:30 |
realTime | la 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)
| Propiedad | Función |
|---|---|
pos size origin | colocación |
display | la forma de la fecha |
color backgroundColor | los colores |
fontPath fontSize | la fuente |
alignment forceUppercase | el formato |
zIndex disabled | profundidad, 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:
| Nombre | Lo que hace la máquina |
|---|---|
bgsound | reproduce esa pista |
directory | elige 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
| Propiedad | Función |
|---|---|
pos size | colocación |
textColor | el color de las etiquetas |
iconColor | el tinte de los iconos — proporciónalos en blanco |
fontPath fontSize | la fuente |
Los 32 iconos
Reemplazar un icono es opcional: Recalbox proporciona los suyos. Solo redefines los que quieres.
Direcciones — iconUpDown, iconLeftRight, iconUpDownLeftRight
Botones — iconA, iconB, iconX, iconY
Gatillos — iconL, iconR, iconL2, iconR2, iconL3, iconR3, iconLR, iconL2R2, iconL3R3
Sistema — iconStart, iconSelect, iconHotkey
Combinaciones hotkey — iconHkA, iconHkB, iconHkX, iconHkY, iconHkL, iconHkR, iconHkLeftRight
Joysticks — iconJ1UpDown, 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.
iconHotkeycuenta 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:
- el mismo juego de iconos en todas partes — declarar la barra en una vista que lo cubra todo:
<view name="system, detailed, menu">; - una barra distinta por pantalla — un
<helpsystem>en cada vista, con sus propias imágenes.
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>
iconsetes 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>
| Propiedad | Función |
|---|---|
color | el color del marco — tiñe la imagen si se da path |
path | la imagen del marco |
fadePath | la imagen de velo que oscurece la vista de detrás |
menuText (6) — las líneas del menú
| Propiedad | Función |
|---|---|
fontPath fontSize | la fuente |
color | el texto de las líneas |
selectedColor | el texto de la línea elegida |
selectorColor | el resaltador |
separatorColor | los 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
⚠️
iconListva 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.
| Propiedad | Lo que pinta |
|---|---|
keyColor | el fondo de cada tecla en reposo |
keySelectedColor | la tecla en la que estás |
keyTextColor | la letra escrita en la tecla |
keyDisabledColor | la letra de un carácter que la entrada rechaza |
keyModifierColor | Mayús / Ctrl / Alt pulsado para una sola tecla |
keyModifierLockedColor | Mayús / Ctrl / Alt bloqueado |
keyTitleColor | el título encima del teclado |
keyEditTextColor | el texto que se está escribiendo |
fontPath | la 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.
- Rueda arcade — solo cuatro: tecla apuntada, letra, título, texto escrito. Ni fondo de tecla ni fuente.
- Teclado clásico — los ocho, más la fuente.
- Teclado simplificado — los ocho salvo los dos colores Mayús / Ctrl / Alt (armado y bloqueado): este teclado no tiene esas teclas.
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:
- sus componentes reservados, que construye ella misma;
- los componentes marcados
extra="true".Un componente libre sin
extrano aparece nunca.
<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 · markdown | textlist · 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
- un solo
<video>por vista — el segundo se ignora sin mensaje; - un extra recibe un
zIndexde 10 por defecto; - los extras se ordenan por
zIndexantes de mostrarse.
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
| Nombre | Tipo | Función |
|---|---|---|
systemcarousel | carousel | el carrusel — uno solo, no renombrable |
logo | image | el logotipo del sistema en el carrusel |
systemInfo | text | la línea « 510 juegos disponibles, 13 favoritos » |
bgsound | sound | la música de fondo del tema |
directory | sound | la carpeta de músicas del tema |
bgsoundydirectoryson 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
| Propiedad | Por defecto | Precisión |
|---|---|---|
type | horizontal | horizontal, vertical, vertical_wheel; cualquier otro valor vuelve a horizontal |
logoSize | calculado | proporción de la pantalla, no del carrusel |
logoScale | 1.2 | agrandamiento del logotipo elegido |
maxLogoCount | 3 | redondeado al entero — un decimal no sirve de nada |
color | transparente | el 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
basicnunca es solicitada por el motor, y la vista de arcade reutilizadetailed.
La lista y los medios
| Nombre | Tipo | Función |
|---|---|---|
gamelist | textlist | la lista de juegos |
logo | image | el logotipo del sistema |
md_image | image | la carátula |
default_image_path | image | la imagen de reemplazo cuando el juego no tiene carátula |
md_video | video | el vídeo de vista previa |
md_region1 … md_region4 | image | las cuatro banderas de región del juego |
En
md_image, elpathescrito en el tema se ignora: la imagen viene del juego. En losmd_region*, solo se leenpos,size,zIndexypath.
La información del juego
| Nombre | Tipo |
|---|---|
md_description | text, markdown o scrolltext — a elegir |
md_folder_name | text |
md_rating | rating |
md_releasedate, md_lastplayed | datetime |
md_developer, md_publisher, md_genre, md_players, md_playcount, md_favorite | text |
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 salvotext: su contenido viene del juego.
Los colores de la lista
gamelist usa cinco colores, de los cuales tres no son tematizables:
| Línea | Color |
|---|---|
| un juego | primaryColor |
| una carpeta | secondaryColor |
| un juego atenuado | calculado: primaryColor con la opacidad dividida por dos |
| una carpeta atenuada | calculado igual |
| el fondo de un encabezado de ordenación | impuesto |
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
- añadir, quitar o renombrar una línea de menú;
- cambiar el orden de las secciones;
- colocar un componente libre en un menú: los extras no se leen en esta vista.
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
menuse 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:
| Familia | Vistas 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 juego | su nombre | su fecha de salida | el archivo de la rom |
| una carpeta | el nombre de la carpeta | DESCONOCIDO | el nombre de la carpeta |
| un encabezado de ordenación | nada | DESCONOCIDO | nada |
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:
| Antigua | Lo que da | Equivalente actual |
|---|---|---|
$system | el nombre corto — « snes » | ${system.name} |
$theme | la 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é escribir | Qué es | Qué devuelve | Dónde |
|---|---|---|---|
${system} | Nombre del sistema | El nombre completo — p. ej. « Sega Megadrive » | Sistemas, Juegos |
${system.input.keyboard} | ¿Teclado necesario? | mandatory · recommended · optional · no | Sistemas, Juegos |
${system.input.mouse} | ¿Ratón necesario? | mandatory · recommended · optional · no | Sistemas, Juegos |
${system.input.pad} | ¿Mando necesario? | mandatory · recommended · optional · no | Juegos, Sistemas |
${system.logo} | Logotipo del sistema | La ruta del logotipo proporcionado por Recalbox | Sistemas, Juegos |
${system.manufacturer} | Fabricante | P. ej. « Sega », « Nintendo ». Vacío si se desconoce | Sistemas, Juegos |
${system.name} | Nombre corto del sistema | — | Sistemas, Juegos |
${system.releasedate} | Año de salida | Añ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-arcade | Sistemas, Juegos |
${system.type.name} | Tipo de máquina | El mismo, en claro: « Home Console », « handheld Console », « Arcade »… | Sistemas, Juegos |
El juego
| Qué escribir | Qué es | Qué devuelve | Dónde |
|---|---|---|---|
${game.developer} | Desarrollador | P. ej. « Konami ». « UNKNOWN » si falta | Salvapantallas, Juegos |
${game.file.name} | Nombre del archivo | El nombre del archivo, extensión incluida | Salvapantallas, Juegos |
${game.file.path} | Ruta completa del archivo | La ruta completa del archivo | Salvapantallas, Juegos |
${game.file.stem} | Nombre del archivo (sin extensión) | El nombre del archivo, sin extensión | Salvapantallas, 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énero | El género tal como está escrito en la ficha del juego | Salvapantallas, Juegos |
${game.isadult} | ¿Reservado a adultos? | yes o no | Salvapantallas, Juegos |
${game.isfavorite} | ¿Es un favorito? | yes o no (nunca true/false) | Salvapantallas, Juegos |
${game.ishidden} | ¿Está oculto? | yes o no | Salvapantallas, Juegos |
${game.islastversion} | ¿Es la última versión? | yes o no | Salvapantallas, Juegos |
${game.isnotagame} | ¿No es un juego? | yes o no | Salvapantallas, Juegos |
${game.ispreinstalled} | ¿Está preinstalado? | yes o no | Salvapantallas, Juegos |
${game.license} | Licencia | La licencia, a menudo vacía | Salvapantallas, Juegos |
${game.name} | Nombre del juego | El nombre del juego | Salvapantallas, Juegos |
${game.players} | Número de jugadores | « 1 », « 2 », « 1-4 », « 4+ »… | Salvapantallas, Juegos |
${game.players.max} | Jugadores — máximo | Un número — p. ej. « 4 » | Juegos, Salvapantallas |
${game.players.min} | Jugadores — mínimo | Un número — p. ej. « 1 » | Salvapantallas, Juegos |
${game.publisher} | Editor | P. ej. « Sega ». « UNKNOWN » si falta | Salvapantallas, Juegos |
${game.releasedate} | Fecha de salida | Fecha ISO — p. ej. « 1991-06-23 ». « UNKNOWN » si falta | Salvapantallas, Juegos |
${game.synopsis} | Descripción | El texto de presentación, a menudo largo | Salvapantallas, Juegos |
Puntuación y estadísticas
| Qué escribir | Qué es | Qué devuelve | Dónde |
|---|---|---|---|
${game.lastplayed} | Última partida | Fecha ISO, o « NEVER » si nunca se ha jugado | Salvapantallas, Juegos |
${game.rating.10} | Puntuación (sobre 10) | Un entero de 0 a 10 | Salvapantallas, Juegos |
${game.rating.100} | Puntuación (sobre 100) | Un entero de 0 a 100 | Salvapantallas, Juegos |
${game.rating.5} | Puntuación (sobre 5) | Un entero de 0 a 5 — no estrellas | Salvapantallas, Juegos |
${game.timesplayed} | Número de partidas | Un número de partidas | Salvapantallas, Juegos |
${game.totalplayed} | Tiempo de juego total | Una duración — p. ej. « 3h 12m ». « NONE » si es cero | Salvapantallas, Juegos |
Imágenes y vídeo del juego
| Qué escribir | Qué es | Qué devuelve | Dónde |
|---|---|---|---|
${game.media.boxpath} | Caja (box art) | — | Juegos, Salvapantallas |
${game.media.imagepath} | Carátula / imagen | La ruta de la carátula. Vacía si el juego no tiene — ver ifexists | Salvapantallas, Juegos |
${game.media.thumbpath} | Miniatura | La ruta de la miniatura | Salvapantallas, Juegos |
${game.media.videopath} | Vídeo | La ruta del vídeo | Salvapantallas, Juegos |
Soporte del juego
| Qué escribir | Qué es | Qué devuelve | Dónde |
|---|---|---|---|
${game.support.index} | Índice del soporte | El número del disco — vacío si solo hay uno | Salvapantallas, Juegos |
${game.support.number} | Número del soporte | Todo junto — p. ej. « 2A/3 » | Salvapantallas, Juegos |
${game.support.side} | Cara del soporte | La cara del soporte — A, B… | Salvapantallas, Juegos |
${game.support.total} | Número de soportes | El número de soportes. « UNKNOWN » si se desconoce | Salvapantallas, Juegos |
${game.support.type} | Tipo de soporte | Cartridge · CD/DVD · Harddisk · Files · Tape · Quick Disc · 3" Floppy · 3".5 Floppy · 5".25 Floppy · PCB · Unknown | Salvapantallas, Juegos |
Sistema del juego
| Qué escribir | Qué es | Qué devuelve | Dónde |
|---|---|---|---|
${game.system} | Nombre del sistema del juego | El nombre completo del sistema del juego | Salvapantallas, Juegos |
${game.system.input.keyboard} | Teclado exigido por el sistema del juego | mandatory · recommended · optional · no | Salvapantallas, Juegos |
${game.system.input.mouse} | Ratón exigido por el sistema del juego | mandatory · recommended · optional · no | Salvapantallas, Juegos |
${game.system.input.pad} | Mando exigido por el sistema del juego | mandatory · recommended · optional · no | Salvapantallas, Juegos |
${game.system.logo} | Logotipo del sistema del juego | La ruta de su logotipo | Salvapantallas, Juegos |
${game.system.manufacturer} | Fabricante del sistema del juego | Su fabricante | Salvapantallas, Juegos |
${game.system.name} | Nombre corto del sistema del juego | Su nombre interno | Salvapantallas, Juegos |
${game.system.releasedate} | Año del sistema del juego | Su año de salida | Salvapantallas, 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 juego | El mismo, en claro | Salvapantallas, Juegos |
Emulador
| Qué escribir | Qué es | Qué devuelve | Dónde |
|---|---|---|---|
${game.emulator.compatibility} | Compatibilidad | unknown · low · average · good · high · perfect | Salvapantallas, Juegos |
${game.emulator.extensions} | Extensiones admitidas | Las extensiones admitidas — p. ej. « .bin .gen .md » | Salvapantallas, Juegos |
${game.emulator.hasnetplay} | ¿Compatible con juego en línea? | yes o no | Salvapantallas, Juegos |
${game.emulator.hassoftpatching} | ¿Acepta parches? | yes o no | Salvapantallas, Juegos |
${game.emulator.islibretro} | ¿Es un núcleo Libretro? | yes o no | Salvapantallas, Juegos |
${game.emulator.name} | Nombre del emulador | P. ej. « libretro picodrive » | Salvapantallas, Juegos |
${game.emulator.speed} | Velocidad | unknown · low · average · good · high · perfect | Salvapantallas, Juegos |
La máquina y sus ajustes
| Qué escribir | Qué es | Qué devuelve | Dónde |
|---|---|---|---|
${display.overscan} | ¿Overscan? | yes o no | Salvapantallas, Sistemas, Menú, Juegos |
${random.between(a,b,c)} | Un valor al azar entre… | uno de los valores dados | en todas partes |
${random.range(1,10)} | Un número al azar entre… | un entero entre los dos límites | en todas partes |
${display.resolution} | Resolución | fhd (1080p y más) · hd (720p) · vga · qvga | Sistemas, Menú, Juegos, Salvapantallas |
${display.tate} | ¿Pantalla vertical (TATE)? | yes o no | Salvapantallas, Sistemas, Menú, Juegos |
${display.tateleft} | ¿Vertical hacia la izquierda? | yes o no | Salvapantallas, Sistemas, Menú, Juegos |
${display.tateright} | ¿Vertical hacia la derecha? | yes o no | Menú, Juegos, Salvapantallas, Sistemas |
${hardware.board} | Modelo de máquina | El modelo — « RPi 5 », « PC x64 », « RG351P/M »… | Salvapantallas, Sistemas, Menú, Juegos |
${hardware.crt} | ¿Pantalla CRT? | yes o no | Salvapantallas, Sistemas, Menú, Juegos |
${hardware.isanbernic} | ¿Es una Anbernic? | yes o no | Salvapantallas, Sistemas, Menú, Juegos |
${hardware.isodroid} | ¿Es una Odroid? | yes o no | Salvapantallas, Sistemas, Menú, Juegos |
${hardware.ispc} | ¿Es un PC? | yes o no | Sistemas, Menú, Juegos, Salvapantallas |
${hardware.ispi} | ¿Es una Raspberry Pi? | yes o no | Salvapantallas, Sistemas, Menú, Juegos |
${hardware.jamma} | ¿Mueble Jamma? | yes o no | Salvapantallas, Sistemas, Menú, Juegos |
${recalbox.built} | Fecha de compilación | La fecha de compilación | Menú, Juegos, Salvapantallas, Sistemas |
${recalbox.version} | Versión de Recalbox | P. ej. « 10.0 » | Salvapantallas, Sistemas, Menú, Juegos |
${root} | Carpeta del tema | La raíz del tema seleccionado — hay que ponerla delante de todas tus rutas | Salvapantallas, Sistemas, Menú, Juegos |
${settings.language} | Idioma | El idioma solo — p. ej. « fr » | Salvapantallas, Sistemas, Menú, Juegos |
${settings.locale} | Idioma y país | Idioma y país — p. ej. « fr_FR » | Salvapantallas, Sistemas, Menú, Juegos |
${settings.region} | Región elegida | eu · us · jp | Sistemas, Menú, Juegos, Salvapantallas |
${settings.timezone} | Zona horaria | P. 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
- abre Variables en la barra de herramientas: el panel se abre a la derecha;
- + 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);
- 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ón | Verdadera cuando… |
|---|---|
hd fhd vga qvga | la pantalla tiene esa resolución |
crt | la pantalla es un tubo de rayos catódicos |
overscan | la imagen desborda (CRT sin Jamma) |
tate tateleft tateright | la pantalla es vertical |
jamma bartop | la máquina es una recreativa |
ispc ispi isodroid isanbernic | la máquina es de ese modelo |
nomenu | los 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ón | Verdadera cuando… |
|---|---|
console handheld computer arcade engine port fantasy | el sistema es de ese tipo |
virtual | es un sistema automático (Favoritos, Jugados recientemente, Todos los juegos…) |
favorite | es el sistema automático Favoritos |
lastplayed | es el sistema automático Jugados recientemente |
⚠️
favoriteno 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}) oifexists.
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:
- si — solo en ese caso;
- si no — en todas partes salvo en ese caso.
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 decir | Signo | Con 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:
- El sistema — su nombre habitual, del que se habla. No aparece en ningún archivo;
- las variables, rellenadas por el motor al mostrar.
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} |
|---|---|---|---|---|
| 240ptestsuite | 240ptestsuite | 240ptestsuite | virtual | virtual |
| Acorn BBC Micro | bbcmicro | Acorn BBC Micro | Acorn | computer |
| Amiga AGA | amiga1200 | Amiga AGA | Commodore | computer |
| Amiga CD32 | amigacd32 | Amiga CD32 | Commodore | console |
| Amiga CDTV | amigacdtv | Amiga CDTV | Commodore | console |
| Amiga ECS/OCS | amiga600 | Amiga ECS/OCS | Commodore | computer |
| Amstrad GX4000 | gx4000 | Amstrad GX4000 | Amstrad | console |
| AmstradCPC | amstradcpc | AmstradCPC | Amstrad | computer |
| Apple II | apple2 | Apple II | Apple | computer |
| Apple IIGS | apple2gs | Apple IIGS | Apple | computer |
| Apple Macintosh | macintosh | Apple Macintosh | Apple | computer |
| Arduboy | arduboy | Arduboy | fantasy | fantasy |
| Atari 2600 | atari2600 | Atari 2600 | Atari | console |
| Atari 5200 | atari5200 | Atari 5200 | Atari | console |
| Atari 7800 | atari7800 | Atari 7800 | Atari | console |
| Atari 8bits | atari800 | Atari 8bits | Atari | computer |
| Atari Jaguar | jaguar | Atari Jaguar | Atari | console |
| Atari ST | atarist | Atari ST | Atari | computer |
| Colecovision | colecovision | Colecovision | Coleco | console |
| Commodore 64 | c64 | Commodore 64 | Commodore | computer |
| Commodore VIC-20 | vic20 | Commodore VIC-20 | Commodore | computer |
| Daphne | daphne | Daphne | Daphne | arcade |
| DICE | dice | DICE | DICE | arcade |
| Dos (x86) | dos | Dos (x86) | IBM | computer |
| Dragon 32/64 | dragon | Dragon 32/64 | DragonData | computer |
| EasyRPG | easyrpg | EasyRPG | virtual | engine |
| Elektronika BK | bk | Elektronika BK | Elektronika | computer |
| Epoch Cassette Vision | cassettevision | Epoch Cassette Vision | Epoch | console |
| Exelvision EXL 100 | exl100 | Exelvision EXL 100 | Exelvision | computer |
| Fairchild Channel F | channelf | Fairchild Channel F | Fairchild | console |
| Family Computer Disk System | fds | Family Computer Disk System | Nintendo | console |
| FinalBurn Neo | fbneo | FinalBurn Neo | FBN | arcade |
| Game and Watch | gw | Game and Watch | Nintendo | handheld |
| Game Boy | gb | Game Boy | Nintendo | handheld |
| Game Boy Advance | gba | Game Boy Advance | Nintendo | handheld |
| Game Boy Color | gbc | Game Boy Color | Nintendo | handheld |
| GameCube | gamecube | GameCube | Nintendo | console |
| Infocom Z-Machine | zmachine | Infocom Z-Machine | Infocom | engine |
| LowRes NX | lowresnx | LowRes NX | virtual | fantasy |
| Lutro | lutro | Lutro | virtual | fantasy |
| Lynx | lynx | Lynx | Atari | handheld |
| Mame | mame | Mame | Mame | arcade |
| Mattel Intellivision | intellivision | Mattel Intellivision | Mattel | console |
| MegaDuck | megaduck | MegaDuck | Welback | handheld |
| MGT SAM Coupé | samcoupe | MGT SAM Coupé | MGT | computer |
| Moonlight | moonlight | Moonlight | NVidia | virtual |
| MSX1 | msx1 | MSX1 | Microsoft | computer |
| MSX2 | msx2 | MSX2 | Microsoft | computer |
| MSXturboR | msxturbor | MSXturboR | Microsoft | computer |
| NEC PC-88 | pc88 | NEC PC-88 | NEC | computer |
| NEC PC-98 | pc98 | NEC PC-98 | NEC | computer |
| NEC PC-FX | pcfx | NEC PC-FX | NEC | console |
| Neo-Geo AES | neogeo | Neo-Geo AES | SNK | console |
| Neo-Geo CD | neogeocd | Neo-Geo CD | SNK | console |
| Neo-Geo Pocket | ngp | Neo-Geo Pocket | SNK | handheld |
| Neo-Geo Pocket Color | ngpc | Neo-Geo Pocket Color | SNK | handheld |
| Nintendo 64 | n64 | Nintendo 64 | Nintendo | console |
| Nintendo 64DD | 64dd | Nintendo 64DD | Nintendo | console |
| Nintendo DS | nds | Nintendo DS | Nintendo | handheld |
| Nintendo Entertainment System | nes | Nintendo Entertainment System | Nintendo | console |
| Odyssey2 | o2em | Odyssey2 | Magnavox | console |
| OpenBOR | openbor | OpenBOR | Senile Team | engine |
| Oric/Atmos | oricatmos | Oric/Atmos | Tangerine | computer |
| Othello Multivision | multivision | Othello Multivision | Tsukuda | console |
| Palm | palm | Palm | Palm | handheld |
| Panasonic 3DO | 3do | Panasonic 3DO | Panasonic | console |
| PC Engine | pcengine | PC Engine | NEC | console |
| PC Engine CD | pcenginecd | PC Engine CD | NEC | console |
| Philips CD-I | cdi | Philips CD-I | Phillips | console |
| Philips P2000T | p2000t | Philips P2000T | Philips | computer |
| Philips VG 5000 | vg5000 | Philips VG 5000 | Philips | computer |
| PICO-8 | pico8 | PICO-8 | virtual | fantasy |
| Pocket Challenge v2 | pcv2 | Pocket Challenge v2 | Benesse | handheld |
| Pokémon Mini | pokemini | Pokémon Mini | Nintendo | handheld |
| Sammy Atomiswave | atomiswave | Sammy Atomiswave | Sammy | arcade |
| Satellaview | satellaview | Satellaview | Nintendo | console |
| Screenshots | imageviewer | Screenshots | virtual | virtual |
| ScummVM | scummvm | ScummVM | Ludvig Strigeus | engine |
| Sega 32X | sega32x | Sega 32X | Sega | console |
| Sega CD | segacd | Sega CD | Sega | console |
| Sega Dreamcast | dreamcast | Sega Dreamcast | Sega | console |
| Sega Game Gear | gamegear | Sega Game Gear | Sega | handheld |
| Sega Master System / Mark III | mastersystem | Sega Master System / Mark III | Sega | console |
| Sega Megadrive | megadrive | Sega Megadrive | Sega | console |
| Sega Model3 | model3 | Sega Model3 | Sega | arcade |
| Sega NAOMI | naomi | Sega NAOMI | Sega | arcade |
| Sega NAOMI 2 | naomi2 | Sega NAOMI 2 | Sega | arcade |
| Sega NAOMI GD-ROM System | naomigd | Sega NAOMI GD-ROM System | Sega | arcade |
| Sega Pico | pico | Sega Pico | Sega | console |
| Sega Saturn | saturn | Sega Saturn | Sega | console |
| Sega SG1000 | sg1000 | Sega SG1000 | Sega | console |
| Sharp X1 | x1 | Sharp X1 | Sharp | computer |
| Sharp X68000 | x68000 | Sharp X68000 | Sharp | computer |
| Solarus | solarus | Solarus | Solarus | engine |
| Sony Playstation 1 | psx | Sony Playstation 1 | Sony | console |
| Sony Playstation 2 | ps2 | Sony Playstation 2 | Sony | console |
| Sony Playstation Portable | psp | Sony Playstation Portable | Sony | handheld |
| Spectravideo | spectravideo | Spectravideo | Spectravideo | computer |
| ST-V | stv | ST-V | Sega | arcade |
| SuFami Turbo | sufami | SuFami Turbo | Bandai | console |
| Super Cassette Vision | scv | Super Cassette Vision | Epoch | console |
| Super Nintendo Entertainment System | snes | Super Nintendo Entertainment System | Nintendo | console |
| Supergrafx | supergrafx | Supergrafx | NEC | console |
| Texas Instrument TI-99/4A | ti994a | Texas Instrument TI-99/4A | Texas Instrument | computer |
| Thomson | thomson | Thomson | Thomson | computer |
| TIC-80 | tic80 | TIC-80 | port | fantasy |
| TRS-80 Color Computer | trs80coco | TRS-80 Color Computer | Tandy | computer |
| Uzebox | uzebox | Uzebox | port | console |
| Vectrex | vectrex | Vectrex | MB | console |
| Videopac+ G7400 | videopacplus | Videopac+ G7400 | Philips | console |
| Vircon32 | vircon32 | Vircon32 | virtual | console |
| Virtual Boy | virtualboy | Virtual Boy | Nintendo | console |
| Visual Pinball Standalone | vpinball | Visual Pinball Standalone | Randy Davis | engine |
| WASM-4 | wasm4 | WASM-4 | Bruno Garcia | fantasy |
| Watara Supervision | supervision | Watara Supervision | Watara | handheld |
| Wii | wii | Wii | Nintendo | console |
| WonderSwan | wswan | WonderSwan | Bandai | handheld |
| WonderSwan Color | wswanc | WonderSwan Color | Bandai | handheld |
| Xbox | xbox | Xbox | Microsoft | console |
| ZX81 | zx81 | ZX81 | Sinclair | computer |
| ZXSpectrum | zxspectrum | ZXSpectrum | Sinclair | computer |
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) | dos | pc |
| GameCube | gamecube | gc |
| Odyssey2 | o2em | odyssey2 |
| Oric/Atmos | oricatmos | oric |
| Thomson | thomson | to8 |
| WonderSwan | wswan | wonderswan |
| WonderSwan Color | wswanc | wonderswancolor |
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} |
|---|---|---|---|
| Ports | ports | Ports | virtual |
| Favorites | favorites | Favorites | virtual |
| Last played | lastplayed | Last played | virtual |
| All games | allgames | All games | virtual |
| Multiplayer | multiplayer | Multiplayer | virtual |
| Arcade | arcade | Arcade | virtual-arcade |
| Lightgun | lightgun | Lightgun | virtual |
| Tate | tate | Tate | virtual |
| Dial | dial | Dial | virtual |
| Trackball | trackball | Trackball | virtual |
| Challenges | challenges | Challenges | virtual |
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 played | lastplayed | auto-lastplayed |
| All games | allgames | auto-allgames |
| Multiplayer | multiplayer | auto-multiplayer |
| Lightgun | lightgun | auto-lightgun |
| Tate | tate | auto-tate |
| Dial | dial | auto-dial |
| Trackball | trackball | auto-trackball |
| Challenges | challenges | auto-challenges |
Arcade por fabricante (54) (${system.type} = virtual-arcade)
| Sistema | ${system.name} | ${system} |
|---|---|---|
| Acclaim | arcade-manufacturer-acclaim | Acclaim |
| Atari | arcade-manufacturer-atari | Atari |
| Atlus | arcade-manufacturer-atlus | Atlus |
| Banpresto | arcade-manufacturer-banpresto | Banpresto |
| Capcom Cps1 | arcade-manufacturer-capcom-cps1 | Capcom Cps1 |
| Capcom Cps2 | arcade-manufacturer-capcom-cps2 | Capcom Cps2 |
| Capcom Cps3 | arcade-manufacturer-capcom-cps3 | Capcom Cps3 |
| Capcom | arcade-manufacturer-capcom | Capcom |
| Cave | arcade-manufacturer-cave | Cave |
| Data east | arcade-manufacturer-data east | Data east |
| Exidy | arcade-manufacturer-exidy | Exidy |
| Hng64 | arcade-manufacturer-hng64 | Hng64 |
| Igs | arcade-manufacturer-igs | Igs |
| Irem M72 | arcade-manufacturer-irem-m72 | Irem M72 |
| Irem M92 | arcade-manufacturer-irem-m92 | Irem M92 |
| Irem | arcade-manufacturer-irem | Irem |
| Itech | arcade-manufacturer-itech | Itech |
| Jaleco | arcade-manufacturer-jaleco | Jaleco |
| Kaneko | arcade-manufacturer-kaneko | Kaneko |
| Konami Gx | arcade-manufacturer-konami-gx | Konami Gx |
| Konami | arcade-manufacturer-konami | Konami |
| Midway | arcade-manufacturer-midway | Midway |
| Mitchell | arcade-manufacturer-mitchell | Mitchell |
| Namco Na | arcade-manufacturer-namco-na | Namco Na |
| Namco Nb | arcade-manufacturer-namco-nb | Namco Nb |
| Namco System1 | arcade-manufacturer-namco-system1 | Namco System1 |
| Namco System10 | arcade-manufacturer-namco-system10 | Namco System10 |
| Namco System11 | arcade-manufacturer-namco-system11 | Namco System11 |
| Namco System12 | arcade-manufacturer-namco-system12 | Namco System12 |
| Namco System18 | arcade-manufacturer-namco-system18 | Namco System18 |
| Namco System2 | arcade-manufacturer-namco-system2 | Namco System2 |
| Namco | arcade-manufacturer-namco | Namco |
| Neogeo | arcade-manufacturer-neogeo | Neogeo |
| Nichibutsu | arcade-manufacturer-nichibutsu | Nichibutsu |
| Nintendo | arcade-manufacturer-nintendo | Nintendo |
| Nmk | arcade-manufacturer-nmk | Nmk |
| Psikyo | arcade-manufacturer-psikyo | Psikyo |
| Raizing | arcade-manufacturer-raizing | Raizing |
| Sammy | arcade-manufacturer-sammy | Sammy |
| Sega Stv | arcade-manufacturer-sega-stv | Sega Stv |
| Sega System16 | arcade-manufacturer-sega-system16 | Sega System16 |
| Sega System18 | arcade-manufacturer-sega-system18 | Sega System18 |
| Sega System32 | arcade-manufacturer-sega-system32 | Sega System32 |
| Sega | arcade-manufacturer-sega | Sega |
| Seibu | arcade-manufacturer-seibu | Seibu |
| Seta | arcade-manufacturer-seta | Seta |
| Snk | arcade-manufacturer-snk | Snk |
| Taito F3 | arcade-manufacturer-taito-f3 | Taito F3 |
| Taito Gnet | arcade-manufacturer-taito-gnet | Taito Gnet |
| Taito | arcade-manufacturer-taito | Taito |
| Technos | arcade-manufacturer-technos | Technos |
| Tecmo | arcade-manufacturer-tecmo | Tecmo |
| Toaplan | arcade-manufacturer-toaplan | Toaplan |
| Visco | arcade-manufacturer-visco | Visco |
Por género (56) (${system.type} = virtual)
| Sistema | ${system.name} | ${system} |
|---|---|---|
| Action | genre-action | Action |
| Platform | genre-actionplatformer | Platform |
| Platform Shooter | genre-actionplatformshooter | Platform Shooter |
| First Person Shooter | genre-actionfirstpersonshooter | First Person Shooter |
| Shoot'em Up | genre-actionshootemup | Shoot'em Up |
| Shoot with Gun | genre-actionshootwithgun | Shoot with Gun |
| Fighting | genre-actionfighting | Fighting |
| Beat'em All | genre-actionbeatemup | Beat'em All |
| Infiltration | genre-actionstealth | Infiltration |
| Battle Royale | genre-actionbattleroyale | Battle Royale |
| Rythm & Music | genre-actionrythm | Rythm & Music |
| Adventure | genre-adventure | Adventure |
| Textual Adventure | genre-adventuretext | Textual Adventure |
| Graphical Adventure | genre-adventuregraphics | Graphical Adventure |
| Visual Novel | genre-adventurevisualnovels | Visual Novel |
| Interactive Movie | genre-adventureinteractivemovie | Interactive Movie |
| Real Time 3D Adventure | genre-adventurerealtime3d | Real Time 3D Adventure |
| Survival | genre-adventuresurvivalhorror | Survival |
| RPG | genre-rpg | RPG |
| Action RPG | genre-rpgaction | Action RPG |
| MMORPG | genre-rpgmmo | MMORPG |
| Dungeon Crawler | genre-rpgdungeoncrawler | Dungeon Crawler |
| Tactical RPG | genre-rpgtactical | Tactical RPG |
| JRPG | genre-rpgjapanese | JRPG |
| Party based RPG | genre-rpgfirstpersonpartybased | Party based RPG |
| Simulation | genre-simulation | Simulation |
| Build & Management | genre-simulationbuildandmanagement | Build & Management |
| Life Simulation | genre-simulationlife | Life Simulation |
| Fishing & Hunting | genre-simulationfishandhunt | Fishing & Hunting |
| Vehicle Simulation | genre-simulationvehicle | Vehicle Simulation |
| Science Fiction Simulation | genre-simulationscifi | Science Fiction Simulation |
| Strategy | genre-strategy | Strategy |
| eXplore, eXpand, eXploit & eXterminate | genre-strategy4x | eXplore, eXpand, eXploit & eXterminate |
| Artillery | genre-strategyartillery | Artillery |
| Auto-battler | genre-strategyautobattler | Auto-battler |
| Multiplayer Online Battle Arena | genre-strategymoba | Multiplayer Online Battle Arena |
| Real Time Strategy | genre-strategyrts | Real Time Strategy |
| Turn Based Strategy | genre-strategytbs | Turn Based Strategy |
| Tower Defense | genre-strategytowerdefense | Tower Defense |
| Wargame | genre-strategywargame | Wargame |
| Sports | genre-sports | Sports |
| Racing | genre-sportracing | Racing |
| Sport Simulation | genre-sportsimulation | Sport Simulation |
| Competition Sport | genre-sportcompetitive | Competition Sport |
| Fighting/Violent Sport | genre-sportfight | Fighting/Violent Sport |
| Pinball | genre-pinball | Pinball |
| Board game | genre-board | Board game |
| Casual game | genre-casual | Casual game |
| Digital Cards | genre-digitalcard | Digital Cards |
| Puzzle & Logic | genre-puzzleandlogic | Puzzle & Logic |
| Multiplayer Party Game | genre-party | Multiplayer Party Game |
| Trivia | genre-trivia | Trivia |
| Casino | genre-casino | Casino |
| Multi Game Compilation | genre-compilation | Multi Game Compilation |
| Demo from Demo Screne | genre-demoscene | Demo from Demo Screne |
| Educative | genre-educative | Educative |
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.
| Fuente | Qué 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ón | Lo que cambia |
|---|---|
systemView | la disposición de la lista de sistemas |
gameList | la de la lista de juegos |
gameclipview | la del salvapantallas |
SysInfos | la información de los sistemas: completa, mínima, oculta |
gameInfos | la información de los juegos |
colorTheme | 12 paletas de colores |
shader | el filtro retro: CRT, scanlines, panal, ninguno |
shadow | el sombreado |
bands | las bandas de color: finas, gruesas, ninguna |
iconesetTheme | los 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.
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" />
| Atributo | Función |
|---|---|
subset | el identificador del grupo — es él quien enlaza las elecciones entre sí |
title | el rótulo que el usuario lee en el menú |
help | la 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>
| Atributo | Función |
|---|---|
subset | a qué grupo pertenece esta elección |
name | el 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:
- si TODAS las elecciones tienen un número al principio de su
name, ordena por ese número; - 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.
- Exportar el tema desde el studio;
- copiar la carpeta en
/recalbox/share/themes/; - 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:
- una propiedad desconocida — a menudo un error de mayúsculas (
keepRatioen lugar dekeepratio); - un componente cuyo tipo no existe;
- un
Extra type unknown: …— has puesto comoextraun tipo que no lo acepta; - una variable sin
nameo sinvalue; - un par mal escrito (
pos,size).
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:
- Tu tema está en el estudio — botón «Exportar o publicar», pestaña «Publicar»;
- Tu tema es una carpeta o un zip — «Importar un tema existente», y luego «proponerlo para su publicación».
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
- fotografía tu tema — cada vista, cada resolución que anuncias y una imagen por cada opción del tema — y se queda con las mejores;
- escribe la ficha del tema (nombre, versión, autor, descripción, pantallas compatibles);
- sube los archivos y avisa a todo el mundo.
⚠️ 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
- 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;
- un administrador decide. El voto orienta, no decide: nadie se publica por un recuento;
- 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
- un tema incompleto: una vista vacía, una pantalla anunciada pero sin trabajar;
- imágenes que no son tuyas;
- una compatibilidad anunciada sin haberla probado — anunciar CRT cuando nunca lo has visto en un tubo se nota enseguida.