OPENU5 Home ES

These pages are generated from the project's internal documentation. References to source files and binary offsets are kept as provenance — so you can see where each claim comes from — but they are not followable yet: the engine is not published. Once it is, they will become links.

2 · Layouts

Which layouts the port offers, what each is for, and what it costs.

New screenshots. The images in this document were produced for it on 2026-08-04 against a dedicated dev server. Same scene in all of them: Iolo's hut, fresh game, Spanish, no intro. They live in docs/verdicts/layouts/.


The summary, before the detail

The original had one layout: 320×200, fixed EGA frame, 11×11 map top left, roster and console on the right. The port offers five things that combine:

OptionWhere you change itDefault
Square pixelsperiod 4:3⚙ → VideoSquare pixels
Classic layoutsplit layout▤ button / ⚙ → VideoSplit on touch, classic on desktop
1988 skinsmooth skinF9 / ◧ / ⚙ → Video1988
Fullscreen⚙ → VideoOff
Cursor side (left/right)touch deckRight

And there is one architectural decision governing all of them: no layout fabricates a single pixel. Every panel of the split layout is a drawImage of a rectangle from the faithful skin's canvas. That is why a layout can be added without touching the replica.


1 · The classic layout (desktop)

✨ The starting point: the 1988 frame scaled by an integer factor and centred with letterboxing.

Desktop, classic layout, square pixels

The whole frame is visible: 11×11 viewport on the left, roster with each character's gold, the KPI box (C:63 O:150 and the date 4-5-139), the console below, and the sky and wind bands top and bottom. Bottom right, the three shell buttons: ES (language), (skin) and (SYSTEM menu).

The skin button is , not ▤ (ui/shell/skinSwitcher.ts:79). The is the LAYOUT one and on desktop it is not in this cluster: it is only installed by the split layout wrapper (deck-ancho.ts:1535), that is, on touch or with the flag set — which is why there are only three buttons in this screenshot. From desktop the route to the split layout is ⚙ → Video.

What it is for: it is the faithful layout. If what you want is to see the game as it was, this is the one.


2 · Period 4:3 aspect

ADDED · ⚙ → Video → "Period 4:3 aspect (1988 skin)" · Code: game/src/skin/fiel/skin.ts (aspectStretchEnabled, key u5clone:faithful:aspect43)

Square pixels (default)Period 4:3
square pixels4:3

A 1988 CRT monitor did not have square pixels: it stretched 320×200 to 4:3, that is, a 1:1.2 pixel. With the box ticked the port does the same, and everything looks 20% taller.

The trade-off, measured

Stretching costs area. In the test viewport (1280×800 CSS) the canvas goes from filling the width to 960×720: the integer scale that fits with the ratio locked is smaller. You gain the period geometry and lose size.

That is why the default is square pixels (decision F-0): most people opening this today expect square pixels, and whoever is after CRT geometry knows what they are looking for.

And one interaction worth knowing

The split layout (§4) ignores aspectY on purpose. On mobile the pixel is square in every panel, and not by oversight: mixing two grids — one stretched in the map and one square in the band — on the same screen looks wrong. The invariant is pinned by a test (tests/portrait-cuadrado.test.ts) demanding a ratio of 1 across the six panels, in both orientations and on the seven devices of the census.


3 · The smooth skin, which is also a layout

Changing skin does not move the boxes, but it changes quite a lot of what you see:

1988smooth (xBR)
1988 skinsmooth skin

The detail that matters when comparing the two: the text is identical. Only the viewport rectangle goes through the filter. The why is in 1 · Image.


4 · The split layout (portrait mobile)

ADDED · Code: game/src/skin/portrait/layout-cuadrado.ts, deck-ancho.ts, deck-nativo.ts · Turned on with the button or from ⚙ → Video → "Split layout (portrait)"

The user's request, verbatim (2026-07-25)

"I want to see a prototype of the re-flow + a real full-width button deck. In general I want the map view to always be square like the original."

Before / after, iPhone 15 (393×852)

Classic (?reflow=off)Split (default on touch)
mobile, classic layoutmobile, split layout

In the classic one, the whole 320×200 frame shrinks to fit the phone's width: the map ends up tiny in the top third and the rest of the screen is buttons. In the split one the map is a square filling the width, the player and log band sits below it, and the buttons go at the bottom.

How the square is achieved

With isotropic scaling (sx == sy) on the map block. The source box is already 178×178, so it is enough not to stretch. Zero pixel fabrication: every panel is a rectangle of the faithful skin's canvas, and there is not a single new line in skin/fiel/.

What you can see that is not in the brief: the deck changes too

Comparing the two screenshots, it is not only the geometry. The deck is a different one:

ClassicSplit
LookBrown buttons, embossedMonochrome, thin outline
Sheet selectorRow "Move / A-Z / 123 / Yes-No / Screen"Gone: the system keyboard comes in via the ⌨ button
TriggerOn pointerdown (as the finger lands)On pointerup, and only if the finger is still inside the button

The two go together by construction and it is declared that way in the code: the split layout is built around the deck, and the deck only exists where the pointer is coarse. The docstring of layoutPartidoInicial tells it from the report that caused it — the user added the port to the iPhone home screen and saw it "with the old version of brown buttons, no split layout".

That change of trigger is detailed in 3 · Experience.

With the smooth skin on top

Split, 1988 skinSplit, smooth skin
split 1988split smooth

That these two screenshots exist is itself the result of a work lane. For a while smooth and split were incompatible, and the incompatibility was written down in two places as if it were a product decision. The diagnosis found they were two construction blockers with a declaration on top, and the work lane removed them:

  1. PortraitSkin consumes five members of the hosted skin that ShaderSkin did not re-export. Solved with a new contract (skin/hostable.ts) and zero lines edited in skin/fiel/.
  2. Hosted in a hidden 0×0 host, the shader collapsed its backbuffer to ×1 and xBR stopped smoothing without raising any error.

🔴 The trap that point 2 teaches

One of the five members, sourceFrameGen, could not be delegated to the faithful skin. It returns the composited-frame counter of the shader, which changes far more often than the faithful one (scroll tweens, actors, overlays). Delegating it would have made the wrapper's dirty-check skip exactly the frames of smooth movement — that is, the only reason anyone picks this skin. Four out of five were passthrough; the fifth was not, and it was the one that mattered.

Trade-offs of the split layout


5 · Landscape

ClassicSplit
landscape classiclandscape split

In landscape the game is centred and the deck splits up: in the classic one, all the controls on the left; in the split one, two rails — modes and D-pad on the left, commands on the right — with the game in between.

⚠️ An honest caveat about these two screenshots

layout-cuadrado.ts documents a landscape branch of its own: "square map on the left filling the HEIGHT, roster+log band in ONE column on the right". That is not what you see in these screenshots: what appears is the classic 320×200 frame in the centre.

It is not a fault, it is the algorithm working. The composition type (reflow vs clasico) is decided by area: if re-composing would lose usable surface against the whole frame, it stays classic. At 852×393 the classic wins. The landscape branch exists and fires on screens where it pays off (a tablet in landscape, for instance); on an iPhone 15 lying down, it does not.

What does change between the two screenshots is how the deck is distributed and its look — which is difference enough for the choice to matter in landscape.


6 · Tablet, portrait

tablet portrait, split layout

820×1180. The same split layout, and here you can see what it gains: the square map takes up nearly all the usable surface and the band fits underneath without cramping. It is the size at which this layout is most comfortable.


7 · Fullscreen

⚙ → Video → "Fullscreen". Toggles document fullscreen and never throws: without browser support it is a silent no-op (explicit try/catch in ui/shell/sections.ts).

It is not illustrated here because a fullscreen screenshot in a headless browser is indistinguishable from the one above: what changes is the browser chrome, not the game.


8 · Where all of it is changed: the SYSTEM menu

SYSTEM menu

The menu opens with F10 or the button. Sections (measured live on 2026-08-04): Saves & panels · Video · Audio · Keys · Commands (original) · Help · Debug (QA).

Three design details visible in the screenshot:

  1. It is drawn with the game's EGA chrome and 8×8 font, not with modern widgets. That is decision #23 (2026-07-20): the "1988 window" became the default under both skins. The rounded vector look survives only as a QA fallback behind ?shellVector=1.
  2. The Video section lists the skins as buttons, one per skin, with the active one shown above under "Active skin". There is no dropdown: one click jumps to that skin through the same persistence path as F9.
  3. The "Split layout" checkbox does not appear in this screenshot, and that is correct: it is only drawn if the split layout exists in the session (layoutPartidoDisponible). On desktop it does not exist, so the row is not offered rather than offered greyed out.

The ⚙ and why it fades

The button fades after 4 seconds without pointer movement, so as not to clutter the view of the 1988 skin. But on touch screens (pointer: coarse) it stays always visible: without a keyboard, it is the only door to the menu. Two behaviours, and the reason for each is written in the header of ui/shell/gear.ts.

Trade-off: on desktop, the shell's only visible affordance disappears by itself. Anyone who stops moving the mouse while looking at the screen is left with no hint that there is a menu at all, and F10 is not self-discoverable — which is, literally, the reason the button exists. Visual cleanliness is bought with discoverability, and the payment is in the scarcest currency there is: a new user's first minute.

The menu's own trade-off: coherence was chosen over legibility

Drawing the menu with EGA chrome and an 8×8 font (decision #23) costs something real: an 8-pixel bitmap font is less legible than the vector typeface that was there before, especially in the small help lines. The screenshot above shows it — compare the section titles with the "Keys" rows.

It was decided in favour of coherence ("the 1988 window" under both skins), and the vector look was not deleted: it survives behind ?shellVector=1 as a QA fallback. That a way back was kept is the sign that the trade-off was acknowledged when the decision was taken, not afterwards.


What this document does not cover