Las referencias a ficheros de código y a offsets del binario que verás aquí son la procedencia de cada afirmación: dicen de dónde sale. El motor está publicado bajo GPL-3.0-or-later en github.com/kokoima/openu5, así que se pueden ir a mirar una a una.
2 · Disposiciones (layouts)
Qué disposiciones ofrece el port, para qué sirve cada una y qué cuesta.
Las capturas son del port, tomadas el 24-08-2026 con el mismo escenario en todas: cabaña de Iolo, partida fresca, español, sin intro.
El resumen, antes del detalle
El original tenía una disposición: 320×200, marco EGA fijo, mapa 11×11 arriba a la izquierda, roster y consola a la derecha. El port ofrece cinco cosas que se combinan:
| Opción | Dónde se cambia | Por defecto |
|---|---|---|
| Píxel cuadrado ↔ 4:3 de época | ⚙ → Vídeo | Píxel cuadrado |
| Layout clásico ↔ layout partido | botón ▤ / ⚙ → Vídeo | Partido en táctil, clásico en escritorio |
| Piel 1988 ↔ piel smooth | F9 / ◧ / ⚙ → Vídeo | Smooth |
| Pantalla completa | ⚙ → Vídeo | Apagado |
| Lado de los cursores (izq/dcha) | deck táctil | Derecha |
Y hay una decisión de arquitectura que las gobierna a todas: ninguna disposición fabrica un solo píxel. Cada panel del layout partido es un drawImage de un rectángulo del canvas de la piel fiel. Es la razón de que se pueda añadir una disposición sin tocar el calco.
1 · La disposición clásica (escritorio)
✨ El punto de partida: el marco de 1988 escalado por entero y centrado con letterbox. · Por defecto en escritorio

Se ve el marco completo: visor 11×11 a la izquierda, roster con el oro de cada personaje, la caja de KPIs (C:63 O:150 y la fecha 4-5-139), la consola debajo, y las bandas de cielo y vientos arriba y abajo. En la esquina inferior derecha, los tres botones del shell: ES (idioma), ◧ (piel) y ⚙ (menú SISTEMA).
El botón de piel es ◧, no ▤ (ui/shell/skinSwitcher.ts:79). El ▤ es el del LAYOUT y en escritorio no está en este clúster: sólo lo instala el envoltorio del layout partido (
deck-ancho.ts:1535), o sea en táctil o con la bandera puesta — por eso en esta captura sólo hay tres botones. Desde el escritorio la vía al layout partido es ⚙ → Vídeo.
Para qué sirve: es la disposición fiel. Si lo que se quiere es ver el juego como era, esta es.
2 · Aspecto 4:3 de época
✨ AÑADIDO · ⚙ → Vídeo → «Aspecto 4:3 época (piel 1988)» · Código: game/src/skin/fiel/skin.ts (aspectStretchEnabled, clave u5clone:faithful:aspect43)
Estira los 320×200 a la geometría de un CRT de época: todo se ve un 20 % más alto, a cambio de superficie.
| Píxel cuadrado (por defecto) | 4:3 de época |
|---|---|
![]() | ![]() |
Un monitor CRT de 1988 no tenía píxeles cuadrados: estiraba los 320×200 a 4:3, o sea un píxel de 1:1,2. Con la casilla activada el port hace lo mismo, y todo se ve un 20% más alto.
La contrapartida, medida
Estirar cuesta superficie. En el viewport de prueba (1280×800 CSS) el canvas pasa de llenar el ancho a quedar en 960×720: la escala entera que cabe con el ratio bloqueado es menor. Se gana la geometría de época y se pierde tamaño.
Por eso el defecto es el píxel cuadrado (decisión F-0): la mayoría de la gente que abre esto hoy espera píxeles cuadrados, y quien busque la geometría del CRT sabe lo que está buscando.
Y una interacción que conviene conocer
El layout partido (§4) ignora aspectY a propósito. En el móvil el píxel es cuadrado en todos los paneles, y no por descuido: mezclar dos retículas —una estirada en el mapa y otra cuadrada en la banda— en la misma pantalla se ve mal. La invariante está atada por un test (tests/portrait-cuadrado.test.ts) que exige ratio 1 en los seis paneles, en las dos orientaciones y en los siete dispositivos del censo.
3 · La piel smooth, que también es una disposición
✨ AÑADIDO · F9 · ◧ · ⚙ → Vídeo
La misma piel filtrada por xBR: no mueve ninguna caja, pero cambia lo que se ve dentro del visor.
Cambiar de piel no mueve las cajas, pero cambia bastante lo que se ve:
| 1988 | smooth (xBR) |
|---|---|
![]() | ![]() |
El detalle que importa mirando las dos: el texto es idéntico. Sólo el rectángulo del visor pasa por el filtro. El porqué está en 1 · Imagen §1-2.
4 · El layout partido (móvil vertical)
✨ AÑADIDO · Código: game/src/skin/portrait/layout-cuadrado.ts, deck-ancho.ts, deck-nativo.ts · Se enciende con el botón ▤ o desde ⚙ → Vídeo → «Layout partido (vertical)»
En vertical el marco se parte: mapa cuadrado a ancho completo, banda de roster y log debajo, botonera al fondo.
El objetivo de esta disposición es doble: botonera a ancho completo real, y el mapa siempre cuadrado como en el original.
Antes / después, iPhone 15 (393×852)
Clásico (?reflow=off) | Partido (por defecto en táctil) |
|---|---|
![]() | ![]() |
En el clásico, el marco 320×200 entero se encoge para caber en el ancho del teléfono: el mapa queda minúsculo en el tercio superior y el resto de la pantalla es botonera. En el partido, el mapa es un cuadrado que llena el ancho, la banda de jugadores y log va debajo, y los botones al fondo.
Cómo se consigue el cuadrado
Con escala isótropa (sx == sy) en el bloque de mapa. La caja fuente ya es 178×178, así que basta con no estirar. Cero fabricación de píxel: cada panel es un rectángulo del canvas de la piel fiel, y no hay una sola línea nueva en skin/fiel/.
Lo que se ve y no está en el enunciado: la botonera también cambia
Comparando las dos capturas, no cambia sólo la geometría. El deck es otro:
| Clásico | Partido | |
|---|---|---|
| Aspecto | Botones pergamino, con relieve | Monocromo, contorno del marco |
| Selector de hojas | Fila «Mover / A-Z / 123 / Sí-No / Pantalla» | Desaparece: entra el teclado del sistema por el botón ⌨ |
Lo que ya no cambia es el disparo: los comandos deciden al levantar el dedo en los dos decks (ver 3 · Experiencia §2).
Los dos van juntos por construcción y está declarado así en el código: el layout partido está construido alrededor del deck, y el deck sólo existe donde el puntero es grueso.
Con la piel smooth encima
| Partido, piel 1988 | Partido, piel smooth |
|---|---|
![]() | ![]() |
Las dos pieles funcionan también partidas: el filtro sólo toca el rectángulo del visor, así que la banda, el log y la botonera son idénticos entre las dos capturas.
Contrapartidas del partido
- El hueco entre bloques se paga del deck, no del mapa. La separación mapa↔banda pasó de 2 a 6 píxeles de juego el 02-08 a petición del usuario. Está medido: los 2 originales daban 4,1 px CSS en un iPhone 15, de los que las dos líneas separadoras se comían 3 — quedaba 1,1 px de negro, o sea que a la vista era un solo bloque pegado. Con 6 son 12,3 px y ~9 de negro. Y el coste sale del presupuesto del deck: la escala del visor en vertical es
W/FRAME_Wy no depende del alto. - La unidad es de juego, no de CSS. Los 6 píxeles escalan con el mapa, así que el hueco se ve igual de grueso en un SE que en un Pro Max. Y 6 < 8 = la altura de una fila de texto: el hueco no llega a valer un renglón.
- Sin el ▤ no habría vuelta. El botón que apaga el layout partido vive en la botonera del layout partido, así que al apagarlo desaparece con él. Por eso la casilla del menú ⚙ no es un duplicado por comodidad: es la única vía que puede devolver el partido, y el menú ⚙ existe en las dos disposiciones (ui/shell/sections.ts).
5 · Apaisado
✨ AÑADIDO · Automático al girar el dispositivo
Con el dispositivo tumbado el juego queda centrado y el deck se reparte a los dos lados de la pantalla.
| Clásico | Partido |
|---|---|
![]() | ![]() |
En apaisado el juego queda centrado y el deck se reparte: en el clásico, todo el mando a la izquierda; en el partido, dos raíles —modos y cruceta a la izquierda, comandos a la derecha— con el juego en medio.
Por qué en estas dos capturas no se ve la rama de apaisado
layout-cuadrado.ts documenta una rama de apaisado propia: «mapa cuadrado a la izquierda llenando el ALTO, banda roster+log en UNA columna a la derecha». En estas capturas eso no se ve: lo que aparece es el marco 320×200 clásico en el centro.
No es un fallo, es el algoritmo funcionando. El tipo de composición (reflow vs clasico) se decide por área: si re-componer perdiese superficie útil frente al marco entero, se queda en clásico. A 852×393 gana el clásico. La rama de apaisado existe y se dispara en pantallas donde sale a cuenta (una tablet apaisada, por ejemplo); en un iPhone 15 tumbado, no.
Lo que sí cambia entre las dos capturas es el reparto del deck y su piel — que es suficiente diferencia como para que la elección importe en apaisado.
6 · Tablet vertical
✨ AÑADIDO · El mismo layout partido: botón ▤ o ⚙ → Vídeo
El layout partido con sitio de sobra: el mapa cuadrado llena la superficie y la banda cabe entera debajo.

820×1180. El mismo layout partido, y aquí se aprecia lo que gana: el mapa cuadrado ocupa casi toda la superficie útil y la banda cabe entera debajo sin apretar. Es el tamaño en el que la disposición está más cómoda.
7 · Pantalla completa
✨ AÑADIDO · ⚙ → Vídeo → «Pantalla completa»
Alterna el fullscreen del navegador, y nunca lanza: sin soporte es un no-op silencioso.
⚙ → Vídeo → «Pantalla completa». Alterna el fullscreen del documento y nunca lanza: sin soporte del navegador, es un no-op silencioso (try/catch explícito en ui/shell/sections.ts).
No se ilustra aquí porque una captura a pantalla completa en un navegador headless es indistinguible de la de arriba: lo que cambia es el cromo del navegador, no el juego.
8 · Dónde se cambia todo: el menú SISTEMA

El menú se abre con F10 o con el botón ⚙ (y en táctil, con el ☰ del deck). Secciones (medidas en vivo el 24-08-2026): Partidas y paneles · Vídeo · Idioma · Audio · Más (partidas, récords y momentos) · Teclas · Comandos (original) · Ayuda · Privacidad · Debug (QA).
Tres detalles de diseño que se ven en la captura:
- Está dibujado con el chrome EGA y la fuente 8×8 del juego, no con widgets modernos. Desde el 20-07-2026 la «ventana 1988» es el default bajo las dos pieles. El look vectorial redondeado sobrevive sólo como fallback de QA tras
?shellVector=1. - La sección Vídeo lista las pieles como botones, una por piel, con la activa mostrada arriba en «Piel activa». No hay desplegable: un clic salta a esa piel por el mismo camino de persistencia que F9.
- La casilla «Layout partido» no aparece en esta captura, y es correcto: sólo se pinta si el layout partido existe en la sesión (
layoutPartidoDisponible). En escritorio no existe, así que la fila no se ofrece en vez de ofrecerse desactivada.
El ⚙ y por qué se desvanece
El botón se desvanece tras 4 segundos sin movimiento del puntero, para no ensuciar la contemplación de la piel de 1988. Pero en pantallas táctiles (pointer: coarse) queda siempre visible: sin teclado, es la única puerta al menú. Dos comportamientos, y el motivo de cada uno está escrito en la cabecera de ui/shell/gear.ts.
Contrapartida: en escritorio, la única afordancia visible del shell desaparece sola. Quien deje de mover el ratón mirando la pantalla se queda sin ninguna pista de que hay menú, y F10 no se descubre solo — que es, literalmente, la razón por la que existe el botón. Se compra limpieza visual con descubribilidad, y el pago es en la moneda que más escasea: el primer minuto de un usuario nuevo.
Contrapartida del propio menú: se eligió coherencia sobre legibilidad
Que el menú esté dibujado con chrome EGA y fuente 8×8 cuesta algo real: una fuente de mapa de bits de 8 píxeles es menos legible que la tipográfica vectorial que había antes, sobre todo en las líneas de ayuda pequeñas. La captura de arriba lo enseña — compara los títulos de sección con las filas de «Teclas».
Se decidió a favor de la coherencia («la ventana 1988» bajo las dos pieles), y el look vectorial no se borró: sobrevive tras ?shellVector=1 como fallback de QA. Que se conservara un camino de vuelta es la señal de que la contrapartida se reconoció al tomar la decisión, no después.
Lo que este documento no cubre
- El lado de los cursores (izquierda/derecha, por defecto derecha «para los diestros»,
deck-nativo.ts:ladoGuardado) — es una preferencia del deck, no una disposición. - El companion / atlas, que se abre en otra pestaña y por eso no tiene disposición propia dentro del juego. Lo que es y lo que hace está en 3 · Experiencia §7.
- La cinemática de intro, que corre antes de montar ninguna piel y no tiene layout alternativo.






