- Movies: H.264 decoded with VideoToolbox (dm/host/hle_movie_avc.c). This SDK's MP4 demuxer passes the parameter sets as the "avcc" record; pictures leave in presentation order through a 4-deep queue (41 of Odyssey's 44 movies have B-frames), and an end of stream drains the queue. The hint videos in Odyssey's tutorial boxes now play (they were black). VP9 unchanged (Engage: 2,816 packets in, 2,816 frames out).
- Controller input: GetNpadStates fills every requested history entry with the current state under consecutive sampling numbers. Odyssey reads all 16 entries whatever count comes back and polls every slot each frame; with only the newest written, neither stick did anything in play while buttons and menus worked (its first hint, "Look Around", waited forever). DM_KEYS takes RLeft / RUp / RRight / RDown.
- Odyssey's HUD counters were solid white cards: the profile lists its 26 layout shaders (main's BNSH at 0x132c000) under alpha_from_red, as for Breath of the Wild.
- -fpreserve-invariance on every Metal compile (dmsh_build.py MAC_METAL, ios_metal.py): Odyssey draws a depth pre-pass with alRenderDepthOnly, then the G-buffer with other vertex shaders and depth test less-or-equal; Metal gave the identical position math slightly different depths and those pixels kept stale content (Cap Kingdom's ground in 32x32 blocks on every fourth frame). Checked by recompiling the frame's 78 vertex shaders with the flag: four consecutive frames identical, no blocks. All eight chain versions change; Mac libraries and c1_full.tsv are being rebuilt and follow.
- DM_NVN_TEXSNAP works again (its entries lacked the layer field the dump loop reads) and names its files <path>_s<pass index>_<serial>_<level>.png.
- Smoke runs of the seven playable games on the Mac after these changes: only their known red lines.
- dmsh_build.py vs_init: every float4 vertex output is set to (0, 0, 0, 1) before the translated body, as unwritten components read on the hardware. The translator's MSL started from all zeros; Link's Awakening's surface shaders divide a world position by its w, which the vertex shader never writes, so every sun-shadow compare value was infinite and the whole outdoor scene was lit as if in shadow (dim, no shadows from fences, house or trees). All seven chain versions change.
- Mac libraries and c1_full.tsv rebuilt for Link's Awakening, Engage, 13 Sentinels and Mario Wonder (Breath of the Wild, Super Mario 3D World and Metroid Dread follow).
- DM_NVN_TEXRAW dumps the depth plane of a Depth32Float_Stencil8 texture (shadow maps).
- The IPA's version (CFBundleShortVersionString / CFBundleVersion) is the packed game's display version: the update's when an update is packed, else the base game's (nacp.py --version, DM_APP_VERSION in build_ipa.sh, project.yml; the NSP script prints it).
- README: Link's Awakening screenshot outdoors in Mabe Village.
- NVN's depth mode is runtime state: Mario, Metroid Dread, Super Mario 3D
World and Breath of the Wild keep near = -w (GL); Link's Awakening,
13 Sentinels and Engage set near = 0. The translator rewrote z for GL
in every vertex shader, so near = 0 games had all depths in 0.5..1 and
depth-to-distance effects were wrong: Link's Awakening's depth of field
blurred the whole screen outdoors.
- The translator no longer rewrites z; dmsh_build.py (vs_depth) writes two
entry points into every vertex library, main0 with the GL rewrite (the
same arithmetic as before) and main0_z without; the host picks one from
the mode the game sets (mtl_set_depth_zero, shader_load). No per-game
setting; a red line if the mode changes after vertex shaders loaded.
Metal function constants were measured at about 2.4 ms of
specialization per vertex shader, so two entry points instead.
- New translator dll (Ryujinx dlls unchanged), lock and chain versions for
every profile; Mac libraries and c1_full.tsv rebuilt for Link's
Awakening, Engage, 13 Sentinels and Mario Wonder (Breath of the Wild,
Super Mario 3D World and Metroid Dread follow).
- Checked on the Mac: Link's Awakening outdoors (from a save in Mabe
Village) has a sharp middle band again; Mario Wonder's title renders
the same as before (differences only in animation).
- README gallery: Engage, 13 Sentinels and Link's Awakening recaptured
with this build.
- Link's Awakening 1.1.0 main: the per-world PhysX completion task destroys
itself in its release (vtable back to the base, mTm = 0). At 30 fps the
game steps physics twice per frame; a worker descheduled between the run's
unlock and the release let the main thread rebuild the task first, and
the late destructor wiped the new one, so the next completion crashed in
removeReference (main+0x10ccf28). A per-build cut makes that release a
ret. Unfixed, every Mac run with the CPU loaded crashed; fixed, runs with
138-257 switches to 30 fps and walks into and out of the house are clean.
- Crash reports print what each register points at ([dm] *xN), so an
object's vtable names its class.
- RED_ONCE's flag array was one slot short.
- README gallery: Super Mario Bros. Wonder, Super Mario 3D World, Breath of
the Wild and Metroid Dread recaptured with the current build; no "(Mac)"
captions.
- docs: the crash in the bring-up catalogue; debugging recipe for racy
crashes (CPU load, trace gates, a ring printed at the crash).
- README: a gallery with one picture per game (docs/images): iPhone shots
with the virtual gamepad for Mario Wonder, 3D World, BotW and Link's
Awakening; Mac shots (captioned) for Engage, Metroid Dread and 13
Sentinels. Link's Awakening is now listed as in testing on an iPhone.
- scripts/build_ipa_from_nsp.py: a game with no profile is surveyed, then
gets a provisional profile guessed from the survey in
<NSP folder>/<id>_build/profile/<id>/ (outside the repo, reused on the
next run) and a best-effort IPA; --survey-only keeps the old behaviour.
game.py searches DM_GAMES_DIR after dm/games; the host Makefile reaches
such a profile through a symlink; build_ipa.sh finds it through game.py.
zip_store also stores files whose headers say they are compressed.
- copy_t2t_draw: depth-stencil copies now carry the stencil ([[stencil]]
export from an X32_Stencil8 view). Link's Awakening's occlusion pass
tests stencil bit 1 of its quarter-size depth copy, whose stencil was
the new texture's undefined content.
- Link's Awakening: four outdoor shaders with the foliage shader's input
loop failed on the iPhone (Half2 / normalized formats); listed in
shader_facts_manual.tsv. Chain c4995bb3161c.
- Sound: SDK 8 numbers the DSP commands differently and its DeviceSink is
0x10, not 0x13, so every rendered frame played silence (only the movies
had sound). capture() now takes the one 0x148-byte command with 1-6
inputs as the sink when the expected ID is missing.
- Lighting: the light-culling compute shader reads its workgroup count
from NVN's driver segment c0 (+0x200). dmsh_build's drv_reads scan only
matches fragment-shader names, so compute and vertex shaders got an
all-zero c0: every tile row wrote row 0, and the doorway step flickered
with white 64-pixel tiles. A declared driver-segment binding now counts
as read, and compute c0 carries the dispatch size (0x200) and the
uniform buffer table (0x210 + 16 r). BotW and SM3DW render as before.
- Foliage: the shadow / depth pre-pass pipeline 147c829e79fb322f failed
(uint4 inputs fed 16-bit normalized formats), so with depth test EQUAL
the palm tree and flowers never drew. New profile file
shader_facts_manual.tsv (merged by shader_split.py) declares those
inputs float; Link's Awakening's chain is now ccb18ba743bf.
The prompt mask is a layout capture (panes tagged CaptureOn / A8): an R8
render target mapped (R, 0, 0, 1) holding the blurred alpha in red. Besides
the black shadow (e6a88e12), each prompt bar draws a cream glow (aa209f57)
whose alpha is min(cloud alpha, capture alpha); with only the shadow shader
listed, the glow filled each key's rectangle with the Kumo64 cloud.
alpha_from_red now lists every pixel-shader variant of the layout library
(main's BNSH at 0x1d83000) and tex_alpha_red only converts render targets.
Game work folders now live in <NSP folder>/<id>-work instead of the home
folder: AGENTS.md and the docs say so, and build_ipa.sh requires W and
writes the IPA next to the work folder by default.
BotW: the button-prompt shadow samples an R8 blur whose swizzle (R,0,0,1)
made alpha 1, so every prompt got a solid box. New profile key
alpha_from_red takes alpha from red for the named shader.
Link's Awakening:
- NVN lower-left window origin (negative viewport height, winding flip,
flipped present and raw screenshots)
- texture copies with format change, scaling, mirroring and depth
(copy_t2t_draw); SetCopyImageStride; nvnWindowGetPresentInterval
- oe::PopNotificationMessage, vi SetLayerCrop / DestroyLayer /
CloseDisplay / Finalize, audren P_SIZE 0x40 for SDK 8, hid style-set
update event signalled once on bind
- Vorbis movie audio through stb_vorbis (dm/third_party/stb_vorbis)
- patch_nso jump tables: other index registers, mov copies, masked copies