Skip to content

Breath of the Wild: a picture of a taller screen's own shape (DM_SCREEN_ASPECT) - #969

Open
zxcheergo wants to merge 2 commits into
seedds:mainfrom
zxcheergo:botw-screen-shape
Open

zxcheergo wants to merge 2 commits into
seedds:mainfrom
zxcheergo:botw-screen-shape

Conversation

@zxcheergo

Copy link
Copy Markdown
Contributor

What and why

On a screen taller than 16:9, such as the iPhone Duo's (about 1.43:1), Breath of the Wild is shown as a 16:9 picture: stretched, or with bars. This adds an opt-in picture of the screen's own shape for this game.

  • Host (dm/host/loader.c): DM_SCREEN_ASPECT=<width/height> (1.3 to 1.77) gives a game whose profile has screen_aspect on an output 1920 wide and as tall as the ratio asks (1.43 → 1920x1344, a 1280x896 layout space), written to the frame-step state page with the constants the stubs read. Launcher setting Picture shape; 0/unset is 16:9 and changes nothing.
  • Profile (dm/games/01007EF00011E000/patches.py, duo_anchor.c):
    • the output and layout sizes, and the game's own 1280x720 conversions, follow the host's;
    • sead::PerspectiveProjection takes the vertical angle that keeps 16:9's sides in view and stores it, so shadow cascades and culling see the view as drawn (widening only sin/cos/tan left the ground black in patches); the camera's fovy getters and the HUD camera follow;
    • in Pane::Calculate, widgets at the 720 space's edges, and edge-anchored widgets listed by name and place from the layout files (dialog box, subtitles, location and boss names, logos), move out with the taller edges; full-screen backgrounds stretch, page frames grow once, side masks scale about the centre (the scope's circle stays round), the title art scales without stretching, and the map's scrolling cut-outs are left alone;
    • the title menu's two 480x720 backing halves are stretched together (scaled about the centre, the right half's inner edge had moved out 39 units and left a bright band);
    • full-screen captures and their copied rect follow the layout height in both capture classes (the second, main+0xf66118 / main+0xf66334, is an NPC dialog box's blurred backing: with the file's 720 it copied a rect 88 units below the moved box, and the box's part below the 720 edge showed black from beyond the screen), projected background textures map the whole height, the map's footprint trail keeps its 720-pane projection, and the camera rune's photo takes the screen's middle 16:9 band instead of the whole screen squeezed into its 854x480 picture.

The details, offsets and what each stub fixed are in the game note's new section (README) and in the comments next to each stub. duo_anchor.c is compiled into ANCHOR_WORDS with the command in the comment above them (rebuilding it from this source gives the same 2,357 words).

Related: #117 (Hades edge to edge, a general output size, parked) and #631 (bars filled with a blurred copy). This one keeps the game's 16:9 composition and adds picture above and below instead of filling or stretching.

Checked

  • Tests: make -C dm/host/tests GAME=01007EF00011E000 run and make -C dm/gfx/tests GAME=01007EF00011E000 run on an M1 (all pass); dm/tools/tests test_docs, test_env_switches, test_launcher_settings, test_game_profile, test_settings, test_player_env; dm/tools/lint_python.py with .github/requirements/lint.txt (0 new). The C lint was not run here (no LLVM clang-tidy on this Mac): left to CI.
  • Games run, with title ID and version: The Legend of Zelda: Breath of the Wild 01007EF00011E000 1.9.0 with both DLC, headless on the Mac.
    • On an earlier base, each route at DM_SCREEN_ASPECT=1.43 against the same route at 16:9 (screenshots compared row by row): the map and footprint mode at four zoom levels (every region of the trail at 0 offset), the inventory, system and options pages, the album and compendium, the three weapon wheels, the scope (zoomed), the camera rune with its shutter and save prompt, a memory cutscene with subtitles, the Adventure Log, the map's sensor settings, fast travel and its loading screen, a shrine and its elevator. A photo taken at 1.43 matches the 16:9 photo at scale 1.0 (before: only after a 1.24 vertical stretch).
    • On this base (e5620b1a), the game built with the NSP script (--platform mac --allow-other-metal: this Mac's Metal compiler is Xcode 27.1's 32023.921, the lock's 32023.922), with a save standing by an NPC in Kakariko Village: the title, the field, the NPC's dialog (the backing's copy centred on the box, v 0.8605 against 0.9587 before the second commit; the box as dark below the 720 edge as above it), the inventory and the map at 1.43, and the same route with DM_SCREEN_ASPECT unset, unchanged. No [RED] line from the change.
  • Devices and OS: Apple M1, macOS 27.0.1; iPhone Duo (A20 Pro), iOS 27.1, where the title band and the dialog band were reported, on an older base.
  • scripts/regress.py impact origin/main..HEAD: Breath of the Wild (its profile), Tears of the Kingdom and Pokémon Scarlet (through loader.c's module loading). regress.py check was not run: this Mac has no harness root or the routes' saves, and building Tears of the Kingdom on this base would have taken another hour. With DM_SCREEN_ASPECT unset, or a profile without screen_aspect on, the loader writes nothing new and every stub keeps the original path (they test the ratio at state +0x58 first).
  • Not checked: shops in game (their layouts were checked against the rules only), a compendium registration photo, and this exact version on an iPhone. The taller picture renders about a quarter more pixels.

Docs

  • The finding is in its game note (dm/games/01007EF00011E000/README.md); docs/env_switches.tsv lists the four switches; dm/tools/docs_patches.py classifies screen_aspect and docs/agents/game-patches.md was regenerated
  • A chain tool changed (none)
  • No game files, keys or data extracted from a game in the change or the attachments

🤖 Generated with Claude Code

zxcheergo and others added 2 commits November 2, 2026 22:01
…EN_ASPECT)

On a screen taller than 16:9, such as the iPhone Duo's 1.43:1, the game
is shown as a 16:9 picture: stretched, or with bars. With
DM_SCREEN_ASPECT=1.43 (launcher setting "Picture shape", offered for
profiles with screen_aspect on) the host gives the game a 1920x1344
output and a 1280x896 layout space, and stubs in this profile make the
game follow it:

- sead::PerspectiveProjection takes the vertical angle that keeps 16:9's
  sides in view and stores it, so shadow cascades and culling see the
  view as drawn (widening only sin/cos/tan left the ground black in
  patches); the camera's fovy getters follow, the HUD camera takes the
  screen's ratio.
- In Pane::Calculate (duo_anchor.c, compiled into the profile) widgets
  at the 720 space's edges, and a list of edge-anchored widgets
  generated from the layout files (dialog box, subtitles, names, logos),
  move out with the taller edges; full-screen backgrounds stretch, page
  frames grow once, side masks scale about the centre so the scope's
  circle stays round, the title art scales without stretching, and the
  map's scrolling cut-outs are left alone.
- Full-screen captures and their copied rect follow the layout height,
  projected background textures map the whole height, the map's
  footprint trail keeps its 720-pane projection, and the camera rune's
  photo takes the screen's middle 16:9 band instead of the whole screen
  squeezed into its 854x480 picture.

Checked on an M1 Mac (macOS 27.0.1) against the same routes at 16:9:
the map and footprint mode at four zooms (trail offsets 0), inventory,
system, options, album, compendium, weapon wheels, scope, camera rune
and its shutter, a memory cutscene, the Adventure Log, sensor settings,
fast travel, loading screens and a shrine. A photo taken at 1.43 now
matches the 16:9 photo at scale 1.0 (it needed a 1.24 stretch). NPC
dialogs and shops were checked against the layout rules only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…dialog's backing

Two things seen on an iPhone Duo at DM_SCREEN_ASPECT=1.43:

- The title screen showed a bright band left of the menu. The menu's
  backing is two 480x720 halves side by side (FBLayout_00/01 from -320
  to 160, FBLayout_02/03 from 160 to the right edge); the half against
  the side was taken for a side mask and scaled about the centre, which
  moved its inner edge out to 199. duo_anchor.c now stretches those
  panes like a middle panel, so the halves still meet.
- An NPC's dialog box was dark across its bottom from the 720 space's
  edge down. Its blurred backing is a copy of the screen behind the box
  made by the second capture class (main+0xf66xxx, the same code as the
  first one at main+0xf5a0dc / main+0xf5a4b8), which still read the
  layout file's 720: its copied rect stood 88 units below the moved box,
  and its lower quarter read past the screen's bottom edge, black through
  the clamp-to-border sampler. The texture size (main+0xf66118) and the
  copied rect (main+0xf66334) now take the screen's layout height, as the
  first class does.

Checked on this base on an M1 Mac, the game built with the NSP script
(--allow-other-metal: this Mac's Xcode 27.1 Metal compiler), headless,
with a save by an NPC in Kakariko Village: the title, the field, the
dialog (the backing's copy centred on the box, v 0.8605 against 0.9587
before; the box as dark below the 720 edge as above it), the inventory
and the map at 1.43, and the same route at 16:9 unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant