219 Commits
Author SHA1 Message Date
seedds 8334fdfb50 Compile translated shaders with the Metal front end at -O1
At -O2, CorrelatedValuePropagation and SimplifyCFG fold a translated
shader's repeated tests of one value into switches whose cases jump past
their own join. Apple's GPU backend then runs out of control-flow IDs
("Max Unstruct ID 758 ... exceeds supported limit", a note: metal-tt
still exits 0) and lowers the function a far slower way. Odyssey's
alRenderMaterialUber took 24.6 minutes and 17.3 MB of applegpu_g13s code;
at -O1 it takes 31 s and 1.3 MB.

Sampled archive bases from seven games compile to code within a few
percent of -O2. Odyssey's full g13s archive builds in 15.6 minutes
(exit 0), its Cap Kingdom frames match -O2 within 3/255 on scattered
pixels, and GPU time per frame is within run-to-run noise.

Document the mechanism, and correct the Odyssey note: the 758 line never
failed the build; the reporter's exit 1 came from the BAHS link errors
fixed in ff44c59.

Refs #276
2026-10-27 10:16:49 +08:00
seeddsandaldomrodriguez 15805ef525 Defer audio layout detection until a valid command list (#331)
An incomplete startup command list consumed both layout detection and the
one-time DeviceSink scan, leaving valid SDK 4 audio frames permanently
silent. Keep both decisions pending until a supported layout walks the
whole list, as proposed in PR #331.

Extend the reproducer with valid-first and incomplete-startup stereo PCM
checks for SDK 4, 6, 16 and 21, and document the finding.

Co-authored-by: aldomrodriguez <rodriguez.aldo.91@hotmail.com>
2026-10-27 08:56:25 +08:00
seeddsandv0lumehi b3f97efe22 regress.py usage / impact: which games a change can reach (#329)
From PR #329 (stacked on #328): a game's usage manifest, dm/games/<id>/usage.tsv,
written by its owner with regress.py usage (shader features of its chain build,
and the NVN / HLE functions, SVCs and present path of one smoke-route run;
names and counts only), and regress.py impact <base>..<head>, which maps the
functions around the changed lines through the host's callers and the rules of
dm/tools/impact_map.tsv to manifest rows. Manifests for Breath of the Wild,
Tears of the Kingdom and Hades.

Fixed on top of the PR:
- impact checked the head out as a git worktree under the harness root, so it
  stopped (PermissionError on /Volumes/NX) for exactly the contributors it is
  for, who have no games and no harness root. The call graph is now read from
  the git object store at the head revision, and the report is printed and
  written only to --out or an existing harness root.
- A hunk mapped only to the function at its first line: a hunk spanning two
  functions named one. Every added line is mapped now, and a pure deletion maps
  to the function around it (it was moved one line up).
- Functions defined in headers were not in the call graph: the frame step
  (nvn_fstep.h, static inline, called from nvnQueuePresentTexture) reached no
  entry point, so 4acde72 named no game. Headers are scanned, and their
  functions are visible to every file. 4acde72 now names both Zeldas through
  nvnQueuePresentTexture.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-27 08:50:52 +08:00
seedds 9bdef355ab Port Xenoblade Chronicles 3 2.2.1
Add Monolith archive and shader extraction, a build-gated compact memory layout, vertex storage writes under rasterizer discard, primitive ordering and interleaved geometry feedback. Correct native decoder/audio wait accounting and the oe calls used after movies.

Validated opening combat and movement on Mac with real audio, the full Mac/iOS shader build, GPU regressions, and the unsigned IPA archive. iOS runtime, later areas and DLC gameplay remain untested.
2026-10-27 07:58:05 +08:00
seeddsandv0lumehi 6f58a7d4f6 Add cross-game regression harness and prevent false passes (#328)
Compare revision shader builds and pipeline interfaces across local games,
and run available smoke routes with crash, hang, timing and image checks.
Add the developer loop and share the measuring lock with bench.py.

Keep all local games in static checks and honor --no-smoke. Include shader
bytes and fallback pairs in cache keys, recheck interfaces on reuse, and
reuse smoke baselines only for matching inputs and run settings. Detect
failed prebuilds, missing or intermittently bad screenshots, and Vulkan
build failures even when no MSL was emitted. Keep game-derived files and
writable profile copies inside each game's NSP work folder.

Validation: tool tests and the lint ratchet pass. Full shader rebuilds and
gameplay comparisons remain unverified; the 26 discovered Mac builds have
no smoke routes in this checkout.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-27 07:18:30 +08:00
seedds 5708054153 Port Mario + Rabbids Sparks of Hope 2026-10-27 07:13:46 +08:00
seedds c484b13cdb Share physical storage for live NVN resolution variants
Back compatible GPU-only image families at one NVN pool offset with exact-sized placement heaps. Keep descriptor dimensions, initialize fresh storage, register parent-heap residency and retire backing with its textures. Preserve ordinary allocations for single-description storage and exclude unsupported storage classes.

Add synthetic allocation, pixel, indirect-read, depth/stencil and lifetime regressions. Record the LM3 live-allocation census, measured Mac memory reduction and remaining validation limits. Refs #257 and #100.
2026-10-27 03:42:10 +08:00
seedds f8642c480f Run image atomics as native Metal texture atomics, 3D images and CAS included
Below MSL 3.1, SPIRV-Cross emulates an image atomic with a raw device pointer
beside the texture, laid out like a linear image. A block-linear image's Metal
texture is a deswizzled copy, so its atomics went to a scratch buffer nothing
read (Pokemon Legends: Z-A's atomic max into texture 302), and a 3D image's
pointer was indexed with the int3 coordinate itself, which does not compile
(16 shaders of Octopath Traveler 0, 5 of Ghost Trick, 8 of FINAL FANTASY
RESONANCE).

- dmsh_atomic.py: shaders with image atomics (OpImageTexelPointer) are written
  at MSL 3.1, so the atomics run on the image's own texture; every other
  shader keeps its MSL 2.3 source byte for byte. MSL that still holds the
  pointer form fails the build.
- Translator (TranslationFlags.MetalImageAtomics, renamed from
  Msl23ImageAtomics): admits 3D images and SUATOM.CAS (Metal's texture
  compare-exchange); the IGN coordinate guard is unchanged.
- Host: the IMGA pointer binding, the scratch buffer and the layout admission
  are gone. NVN images of R32Uint / R32Sint take MTLTextureUsageShaderAtomic
  (img_usage, kept by tex_upgrade: Metal leaves that bit out of the usage
  property); any other texture in an atomic slot is replaced by an
  atomic-capable write sink with a red line.
- Chain a4e2088c2e69 (with main's vertex-output padding). Tested on
  chain 0ce4b5e8aefb, this change before that rebase: Octopath Traveler 0
  builds all 10,324 shaders, Z-A all
  28,603, Ghost Trick's five 3D-atomic shaders build. Mac runs of both games
  under the Metal API validation layer showed no validation error (Octopath
  Traveler 0 to frame 14,400, its particle atomics on buffer texture 2049;
  Z-A to frame 12,000 through the atomic max on texture 302). Synthetic
  atomics and CAS run on buffer, 2D, 2D-array and 3D textures of a Mac GPU
  (test_image_atomic_bounds.py, t_atomic_return.m).

GitHub issue #290: at 40b643b Octopath Traveler 0 already built 10,308 of
10,324 shaders (2e655b7 fixed the returning atomics); the 16 left were the 3D
ones, which build now. Not checked: an iPhone, FINAL FANTASY RESONANCE's
library, the picture of Z-A's atomic scene.
2026-10-27 03:01:45 +08:00
seedds ed3007f1ef Port Kirby and the Forgotten Land 1.1.0
HAL Laboratory's engine on NintendoWare, SDK 11.4.0, NVN. Plays on the Mac at 30 fps, as on
the Switch: online and difficulty prompts, the 1080p opening movie, Point of Arrival with its
guide movies, the city reveal, the Sword ability and fights, title and Continue; a 15-minute
soak with no crash. No game code is cut; the profile is the memory layout and the shader groups.
All 27,297 shaders build for Mac and iOS; the IPA (6.4 GB) is untested on a device.

- Threads (general): a guest thread waiting for a host lock that HLE code holds while it runs
  guest code is blocked, not runnable (dm_host_lock, a native HLE wait). The movie decoder held
  its decode lock across SignalEvent; the signal's same-core handoff waited for the movie input
  thread, which waited for that lock, and the game froze at its first guide movie. t_preempt
  has the case.

Docs: the game note, games table, README gallery, threads.md, shaders.md, symptom index;
AGENTS count 73 -> 74. Checked: host tests, preempt, tool tests (253, 15 skips), docs tests;
a Mac run on chain 5cddc47253ab through the first guide movie.
2026-10-27 02:51:05 +08:00
seeddsandmarco ff44c59e12 Pad vertex outputs for every pipeline prebuild pair
Read both shader pair tables, including the generated BAHS fallback, for
padding, build order and shader cache dependencies. Include the optional
profile table in the input stamp and the generated table in step reuse;
regenerate a missing fallback before reusing the shader split.

Add native Metal and cache/order regressions, update the shared chain,
and document full validation on TotK and Odyssey. All 301 affected pairs
compile for g13s and g16s, both full Mac shader/host builds pass, all
57,039 pair interfaces match, and TotK's 24,153-base archive succeeds.
The separate Odyssey Max Unstruct ID compiler limit remains open.

Fixes #283
Refs #276, #298

Co-authored-by: marco <6410852+marcolaux@users.noreply.github.com>
2026-10-27 02:33:44 +08:00
seeddsandv0lumehi de13572121 Correct docs that still name removed environment switches (#312)
DM_FRAME_STEP was removed in 79d82f7b, but frame-rate.md and Breath of the
Wild's note still said DM_FRAME_STEP=legacy ran the old interval-controller
method. Both now say it was removed and that the controller cuts stay, for
the interval the framework keeps while the game's VFR override holds.
rendering.md names c76f6798, which removed DM_NVN_ALPHA_RED.

Every doc mention of a name no code reads now says it was removed.

Validation: test_docs and test_env_switches pass.

Co-authored-by: v0lumehi <34629096+v0lumehi@users.noreply.github.com>
2026-10-27 02:12:30 +08:00
seeddsandparsifal295 40b643bbe6 Keep Mac audio buffers near 5 ms across output changes
Apply PR #262's device-buffer fix for clicks caused by audio underruns.
Reconfigure on both output-device and hardware sample-rate changes, respect
the device's frame range, and read back the actual buffer size. Avoid
rewriting unchanged sizes when buffer changes notify the format listener.
Remove listeners before teardown, including failed initialization, so they
cannot configure a device that the AudioUnit has already released.

Add hardware-independent regression coverage for switching, rate changes,
scope filtering, limits, synchronous notifications, diagnostic overrides,
absent devices, and listener cleanup. Record the original gameplay evidence
and the additional silent Core Audio validation in the audio reference.

Validation: full host tests, Mac host build, docs checks, and the iOS source
compile check (178 files) passed. Silent USB/speaker switching and speaker
rates of 44.1/96/48 kHz verified 221/480/240 frames. HDMI switching and
gameplay listening after these listener changes remain unvalidated.

Co-authored-by: parsifal295 <130349765+parsifal295@users.noreply.github.com>
2026-10-27 00:41:13 +08:00
seedds 53843cc7d5 Port Donkey Kong Country Returns HD 1.1.0 2026-10-27 00:13:42 +08:00
seeddsandJose Rosendo 89744da753 Discover Homebrew .NET runtimes for standalone build tools
Derive DOTNET_ROOT from dotnet's Microsoft.NETCore.App runtime listing and
export it to both explicit and inherited build environments. Preserve caller
overrides, use the build environment for discovery, and leave discovery
unchanged on probe failures instead of treating Homebrew's wrapper directory
as a runtime root.

Add regression coverage and document the packing failure and its resolution.
Based on PR #284.

Co-authored-by: Jose Rosendo <josemrb99@gmail.com>
2026-10-26 23:54:32 +08:00
seedds b117c91317 Check translation chain changes on games their author does not own (#272)
One translation chain serves every game, so a translator or host change was checked
only on its author's games; on another game the first sign was a crash at run time
(c3a0880 broke the image atomics of SHIN MEGAMI TENSEI V, Yoshi's Crafted World and
FINAL FANTASY RESONANCE).

- CI: the tool-tests job installs .NET 10, spirv-cross and spirv-tools and points
  DMSH_TEST_XLATE at the committed translator, so the translator's synthetic-shader
  tests (test_image_atomic_bounds, test_dmsh_geometry) run on every change.
  test_dmsh_geometry imports its sibling module when run from the repository root.
- dm/gfx/tools/shader_regressions.py: lists the shaders that translated in the
  game's previous b-*/ and fail in the current chain's, from dmsh_build.py's build
  reports (not part of the chain). The NSP script runs it after its shader step and
  stops on a regression unless ALLOW_SHADER_REGRESSIONS / --allow-shader-regressions;
  docs/development.md describes it.
- FINAL FANTASY RESONANCE: the c3a0880 regression is resolved since 2e655b7 (image
  atomics with a used result): chain 39e4d9585b1d builds 73,488 of 73,496 shaders
  (the 8 3D image atomics as before), shader_regressions.py finds 0 against the
  earlier build, and a new game from an empty save plays the opening cutscene on
  the Mac with no red line; the two shaders that failed and aborted run their
  atomics on their buffer textures.

Checked: every CI test file as the job runs it (DMSH_TEST_XLATE set), the docs tests.
2026-10-26 23:43:09 +08:00
seeddsandb1tdr3amer24 99d0aae38f Keep bindless reads through mixed handle phis; read misaligned buffer textures through an aligned copy (#168)
Two general causes of FINAL FANTASY RESONANCE's missing fires, smoke and muzzle
flashes, found and first fixed by b1tdr3amer24 (GitHub issue #168).

- Translator (vendored BindlessElimination.cs, TryTableHandle): a texture read
  whose handle phi mixes c2 handle words with values that are not handles
  (undefined, or float values the compiler kept in the register on paths where
  the predicated read does not run) was removed and its result set to 0:
  58,122 reads in FINAL FANTASY RESONANCE, mostly Niagara particle vertex
  factories, whose meshes collapsed to a point. The read now takes the c2
  handle among the inputs, or reads each candidate and picks by the phi's run-
  time value; candidates read elsewhere as another texture shape are left out
  (a second sweep, ResourceManager.GetTextureTypes). Only phis that
  GenerateBindlessAccess refuses come here, so tex_dyn_slots arrays keep their
  path: the other 69,449 shaders' SPIR-V is unchanged. Several candidates are
  never used for an image store or atomic. dmsh_xlate's Log now reaches the
  notes as "translator: ..." and the build summary counts those apart.
- Host (nvn_mtl.m, tbuf_shadow): a texture buffer view at an offset that is
  not 16-byte aligned reads from the boundary below on an M4 Pro (t_tbuf_align:
  56 of 56 views wrong; the M6 measurement in the old comment does not hold).
  Such views are read through a per-submission aligned copy; aligned views are
  untouched. A workaround for the Metal limit, its gaps (GPU writes in the same
  submission, CPU_NO_ACCESS pools, image writes) recorded as open.

Translator rebuilt; lock and chain header updated. Checked: all FFR shaders
translated before and after; FFR on the Mac (fires and smoke column render,
steady; with the copy off they flicker); gfx, chain and docs tests.

Co-authored-by: b1tdr3amer24 <240231594+b1tdr3amer24@users.noreply.github.com>
2026-10-26 23:43:09 +08:00
seeddsandNishikori-Yui a0841d6b3c Isolate save failures by backing transaction
Keep save failure state and write timing with the canonical backing save, and
retain that identity on open files and mount aliases. Coordinate commits with
in-flight writes and file-size changes, preserve taint when recovery fails,
and mark the affected saves after a failed rename rollback.

Initialize shared write-injection settings with pthread_once so simultaneous
first writes do not race. Expand regressions for independent saves, aliases,
overlapping I/O and commits, failed recovery, and concurrent first writes.

Validation: 98 save regression checks, filesystem ThreadSanitizer, the full
host unit suite, and documentation checks pass.

Refs: https://github.com/seedds/nxnative/pull/288

Co-authored-by: Nishikori-Yui <165007678+Nishikori-Yui@users.noreply.github.com>
2026-10-26 23:25:17 +08:00
seeddsandhuajiaoshu520 0963959f2f Fix startup deadlock in blocking notification waits
Publish native HLE condition waits to the guest scheduler and end inherited
same-core handoffs at the blocking boundary. Restore runnable state on wake.

Exercise real thread creation, startup and exit in the notification regression,
including spurious wakes and both scheduling modes. Record the real-game Mac
startup comparison and the remaining visual gameplay and iPhone validation.

Co-authored-by: huajiaoshu520 <huajiaoshu@jasonml.eu.org>
2026-10-26 22:41:52 +08:00
seedds 4db4c69f0b Port Donkey Kong Country: Tropical Freeze 1.0.2
Profile 0100C1F0051B6000 (SDK 4.4.0, Retro Studios' engine, NVN): plays on the Mac from boot
through the menus and the intro cinematic into the first level at 60 fps. General changes:

- svc SetHeapSize: a request beyond the heap region returns ResultOutOfMemory, as Horizon
  (the game binary-searches its heap size between 3 and 6 GB)
- shader_split.py: SNVN program records in Retro's RFRM forms (MaterialArchive.arc, the packs'
  MTRL resources) and the LZSS-compressed startup material archive in main
- nvn_mtl.m: a texture in a CPU_UNCACHED pool starts with its storage at first use (title logo,
  menu panels); transform feedback captures draws that rasterize too
- dmsh_build.py: transform feedback buffers holding several outputs (DK's fur simulation);
  chain header regenerated
- hle_audren.c: the renderer event is the kernel event the audio service gives, not the SDK's
  local one (the main thread was starved at the first level's load)
- hle_oe.c: oe::GetUserInactivityDetectionTimeExtensionMode
2026-10-26 22:38:18 +08:00
seedds 1402ded2d9 BotW 1.9.0: held-button counts step by the VFR ratio (menu repeat in game time at 60 fps); archive build folders never taken at a recapture; unsupported sample counts not made
- sead::ControllerBase::updateDerivativeParams_ added a constant 1.0 per frame to held counts, so menus
  repeated twice as fast at 60 (0.3 s went 5 entries, 2 at 30). A FRAME_STEP stub at main+0xeb0f88
  takes the VFR's ratio (+0x3c); checked in game: 0.2 / 0.3 / 0.4 s move 1 / 2 / 3 entries at 60
  (MacNativeGames 866beb9).
- ga_capture: a recapture through lookup archives makes no folder at its compile, so it no longer
  lists the folder (it could take another program's folder made meanwhile).
- tex_desc: a multisample texture of a sample count the GPU lacks is not made instead of being made
  with fewer samples (shaders could read sample indices past it).
2026-10-26 21:49:19 +08:00
seedds 933b67590c Port OCTOPATH TRAVELER 1.0.5 (Unreal Engine 4.18, SDK 3.5.1)
Profile 010057D006492000 (no virtual address memory: the 4 GB heap layout; tex_flush_upload and tex_dirty_upload for the textures Unreal writes from the CPU into uncached pools after creating them) and its note. Brought up on the Mac through the boot, the language notice, the title, the traveler selection and Ophilia's and H'aanit's openings (free play in the cathedral and in S'warkii) at 30 fps; battles, sound and the iPhone not yet tested.

General changes found on it:
- patch_nso.py: a jump table whose index is bounds-checked with a 64-bit cmp (main+0x1676f58), accepted only in the last pass so earlier rewrites are byte-identical.
- profile_guess.py: Unreal's 64 GB alias layout only with virtual address memory (this game sets a 3.08 GB heap instead).
- NVN: nvnTextureBuilderGetSparseTileLayout / nvnTextureGetSparseTileLayout (Unreal sizes a sparse texture's mip tail with it; unimplemented, it asked for 1.75 GB twice); sparse 2D textures without a packaged layout take the block height of their 64 KB tile (the world map's tiles were shuffled); every virtual pool gets an address range of its own until its first mapping decides between the alias (a whole-pool mapping, Mario's pool) and the sparse page table (Unreal's one-texture pools, mapped piece by piece: streamed textures were black and later mappings refused).
- Audio renderer: SdkMutexType is looked up only when the SDK uses it (SDK 3.5.1 takes LockMutex at +0x1f8).

README: the gallery entry (Mac screenshot of S'warkii, IPA ~3.6 GB, all 5,434 shaders built for iOS); AGENTS.md: seventy-one games.

Checked on the rebased tree: the tool tests (15 skipped), the docs tests, a Mac boot into the traveler selection; before the rebase the graphics tests (make run, exit 0).
2026-10-26 21:25:17 +08:00
seedds ce9b30b010 Port Sea of Stars 2.0.59001 at 60 fps
Unity 2021.3.25f1 on SDK 16.2.0 (the sdk build of Super Mario Bros. Wonder 1.0.0).
The sdk build takes the node-area cut and SDK 20's 2 MB region alignment: Unity's
N MB + 252 KB regions each took the next size class's slot, which exhausted the
4.375 GB alias region after about six minutes. Profile with a 1.5 GB pool, note,
games table row, README gallery entry and reference entry.
2026-10-26 19:40:09 +08:00
seedds 2e655b79bf Port SHIN MEGAMI TENSEI V: Vengeance 1.0.3 at 60 fps
Profile 010069C01AB82000 (Atlus, Unreal Engine 4.27, SDK 15.3.2, NVN). Opening gameplay
tested on the Mac: new game, classroom, saves and reload in a fresh process, Tokyo map,
Shinagawa Station and its event. iOS and combat untested.

- Memory: the FMallocBinned3 constructor cut (main+0x1f2f63c, gate +0x1f2f644) with the
  measured UE4 vtable in hle_uemalloc.c; -SwitchVirtualAddressSpaceSize=2048 and a 3.75 GB
  block. profile_guess.py now leaves 128 MB for the initial heap in provisional Unreal
  layouts (test_profile_guess.py).
- Shaders (general, chain 86c8282f6fb4): returning IGN image atomics keep the old value with
  bounded access (Ryujinx translator, t_atomic_return.m); buffer-image reflection keeps its
  Metal texture type (nvn_refl.m, t_refl.m). All 19,746 shaders build for Mac and iOS.
- 60 fps: hle_fpslock.c writes the game's own Project.FrameRateLimit (main+0x6d6d5d0, which
  GameUserSettings applies to t.MaxFPS) and rhi.SyncInterval, gated on main 0a4f14a5...
  Mac (M4 Pro): 59.2-60.1 fps at the station, frame p95 17.5-20.3 ms; a 1 s walk ends at
  the same place at 30 and 60 fps. DM_FPS_TARGET=30 keeps 30.

Docs: the game note, games table, README gallery, memory.md, shaders.md, symptom index;
AGENTS count 68 -> 69. Checked: tool tests (186, 6 skips), docs tests.
2026-10-26 19:35:03 +08:00
4639c5114c Pack shader pairs and the offline pipeline archive into Mac apps (#241, #260)
The Mac app packer left out shader_pairs.tsv and pso_pairs.tsv, which the
host's pipeline prebuild reads beside the shader map and build_ipa.sh already
copies into the IPA. Every NVN game's Mac app therefore built no pulling
bases, had no hybrid stand-ins, and compiled first-seen pipelines on the
submit thread. Copy both tables, and the shader split's pso_pairs.tsv for a
profile without one.

An NVN game's Mac app also carries its pipeline archive made offline for this
Mac's GPU (pso_offline.py --platform macos), handed to the host as
DM_PSO_BUNDLE as on iOS; --gpu none leaves it out. Integrated with three
fixes: the archive is validated and counted in the free-space check before
anything is copied; a plan whose pairs all need function constants packs the
app without an archive instead of aborting; and a PSO_GPUS value that does
not name this Mac's GPU is reported.

Validation: test_nsp_mac_app 22 (pair tables, split copy, bad archive, free
space, GPU note, no-archive plan; the table and space tests fail without the
fixes), the tool suite, iOS packaging tests and test_docs. A Breath of the
Wild Mac app on an M4 Pro (applegpu_g16s, 629.4 MB archive): 16 of 16 probed
bases found, no pair base built, no red line; the run stayed in the title.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
Co-authored-by: blindlight86 <25404088+blindlight86@users.noreply.github.com>
2026-10-26 16:46:44 +08:00
seedds ecbeae164c Port Pokemon Brilliant Diamond 1.3.0 at 60 fps
Add the registered profile, Unity 2019 compute shaders, VP8 decoding, depth initialization and AudioOut stop fixes. Include build-gated frame limiting, regression coverage and Mac validation notes.
2026-10-26 15:40:36 +08:00
seedds ceb5046b3f Apply Pokémon Legends: Z-A's allocator cut to other builds by function match (#266)
The base game 1.0.0 (main 7222e13e…) aborted in nninitStartup: the 12 GB → 4 GB
StandardAllocator cut was registered for 2.0.2's main only. The same function
(an exact fingerprint match, main+0x19f8480 in v0) now gets it through MATCH_CUTS.
2026-10-26 15:34:21 +08:00
58f74014f4 Seed TotK prewarm from the recorded M2 iPad route (#261)
Add 1,537 shader, 2,512 render-pipeline and 43 compute-pipeline rows from
the update 1.4.3 capture, preserving first-use order. Document the
author-reported route and results, and limit the coverage claim to
that route.

This profile-only capture is separate from the shared CPU and loader
optimizations. Validation checks the row counts, uniqueness and exact
data/order preservation; no new cold-start or gameplay run here.

Co-authored-by: draco-cong <71372970+draco-cong@users.noreply.github.com>
Co-authored-by: laobeibei <laobeibei@users.noreply.github.com>
2026-10-26 15:28:59 +08:00
5632203274 Optimize CPU deswizzle copies and host symbol lookup (#261)
Hoist block-linear row and slice addressing out of segment copies, and
index HLE, forced-takeover and missing-import names while retaining
existing duplicate precedence and stub identity.

Add byte-address differential tests and direct collision, duplicate,
growth and reuse checks. Correct the ASTC-tail and loader-serialization
comments and document independent CPU microbenchmarks. Keep TotK
prewarm data in a separate change.

Validation: 5,334 texture checks; symbol-index and NRO lifecycle tests;
AddressSanitizer/UBSan; documentation checks; Mac host build and changed
iOS source compilation. No new gameplay validation.

Co-authored-by: draco-cong <71372970+draco-cong@users.noreply.github.com>
Co-authored-by: laobeibei <laobeibei@users.noreply.github.com>
2026-10-26 15:28:52 +08:00
f7345d9a00 Same-core handoffs wait only for the threads their wake made runnable (#247, #259 section 6)
A wake's handoff waited until every runnable higher-priority thread pinned to the caller's core was blocked, not only the ones the wake made runnable. The host runs a lower-priority thread beside such threads at all other times, and a core's busy loaders, workers and pollers are seldom all blocked at once, so the wait had no bound. Tears of the Kingdom 1.4.3 (issue #247) stayed on an empty scene after the boot logos: on 82ab25b, 84 functions / 771 NVN calls a frame, no packaged texture uploaded, 250,008 ms of handoff waits in a 180 s run; a temporary log showed BootupBackgroundWorkThread (priority 58) waiting 200-290 ms at a time for ARes Loading 1, Presentation Thread and BaseProcExecutor. Donkey Kong Country: Tropical Freeze's priority-58 job thread waited the same way for pollers (issue #259, section 6).

A wake now records the woken thread in the waker's current handoff and in those the waker belongs to (note_runnable, at most four), so Metroid Dread's main thread still waits for its movie dispatcher and for the worker the dispatcher wakes. Blocking, a sleep, YieldToAnyThread (SleepThread -2, which on Horizon takes the thread off its core so that lower-priority threads run there), exit, suspension and host GPU work end a thread's hold; a handoff ends when its caller's thread SVC returns (hand_epoch). There is still no timeout, and core_preempt keeps checking every runnable peer.

Checked on the Mac, without shader libraries for chain 8393d85a4eae (draws skipped): TotK on the issue #70 route for 180 s, 1,221 ms of handoff waits and the same per-frame NVN call counts and texture first uploads as 9feac2f (before the unbounded handoff). Dread, fresh saves, DM_KEYS=4:A*20/0.7, 60 s: a control host with the handoff off crashed in 1 of 3 runs at sdk+0x347eb4 from main+0x225338; the limited handoff passed 12 of 12 runs, each through three decoders and two teardowns with about 12,400 handoffs. t_preempt adds three handoff-scope cases: a busy peer nobody woke (main's code never returns), a worker woken by the woken dispatcher (fails without the recorded chain), a woken thread yielding to any thread (never returns without that rule). Host tests, docs tests and an iOS syntax check of hle_thread.c pass. Gameplay with shaders, iOS and DKC itself are not checked here.

Co-authored-by: HougeLangley <1161594+HougeLangley@users.noreply.github.com>
Co-authored-by: aurlight <120410928+aurlight@users.noreply.github.com>
2026-10-26 15:00:32 +08:00
seeddsandRAHUL REX 4acde72a6e Recover the frame step after movie and thermal caps (#253)
Keep the proven frame cost and GPU reference for each cap, and probe the
shorter hold when a movie or thermal cap ends. Otherwise a GPU-bound game
can fall straight back to 30 fps without a usable recovery reference.

Save an uninterrupted sustained run when a cap begins, even if no earlier
hitch populated cref. Keep the earlier reference through short runs and
update it after another sustained run. Count cap-release probes and give
them all 30 grace frames: the completed frame at the old cap consumes none.

Add movie and thermal recovery regressions, including first movies,
repeated caps, full grace and failed-probe backoff. Document the mechanism
and link it from both Zelda game notes.

Validated: 64/64 frame-step checks, including ASan/UBSan; six checks fail
against the original PR. Production thermal tests and ThreadSanitizer,
docs tests and diff checks pass; the BotW Mac host builds. Device clock
recovery remains modelled, without a new gameplay observation.

Co-authored-by: RAHUL REX <75500427+RahulRex0@users.noreply.github.com>
2026-10-26 14:22:03 +08:00
seeddsandv0lumehi 60625182c4 Harden GPU fence wake and pass scheduling (#158, #213)
Integrate fast shared-event wakeups, per-segment publication, array-slice
pass merging, and independent compute dispatch hoisting from the PRs.
Serialize CPU completion effects before publishing completed fences and
validate recycled post records. Preserve submission order for early waits.

Guard scheduling against attachment aliases, first-draw and bindless
reads, indirect ranges, stencil writes, and explicit barriers. Add direct
Metal regression coverage and a gated CPU completion race test with TSAN.

Record final BotW and Metroid Dread gameplay validation with optimizations
on and off. BotW retains fewer render passes, but the measured 60 Hz M4
Pro runs do not establish a timing speedup. Keep the original higher-load
and iOS performance claims explicitly unverified.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-26 13:33:02 +08:00
seedds f171088e2e Fire Emblem: Three Houses: record why its two pacing cuts stay per-build. Checked on the Mac (host at 7753b7b, headless boot to the title, 100 s per run, each cut undone in the rewritten main): without the frame-limiter cut the general yield back-off holds 59.7-59.8 fps (frame p50 16.73 ms against 16.68) at 0.9-1.2 W of CPU energy against 0.14-0.42 W (about 9,700 plain yields a frame before the back-off starts at 2 ms); without the render-thread timeout cut, 53,000-55,000 wakeups a second against 1,450 and 0.7-1.0 W. The 16 us timeout is the game's own: the render thread passes (1/fps) x 1000 = 16 to main+0xaa90e0, which multiplies it by 1000 into the TimeSpan (nanoseconds) of nn::os::TimedWaitEvent. Of the 206 modules on hand, the limiter (main+0x5be4b4) is the only loop whose only calls are YieldThread and GetSystemTick, so a rewriter pass for such loops would match this one site. Docs: the game note; docs tests pass 2026-10-26 13:29:13 +08:00
seedds dac7ba6338 Function-matched cuts: same-name rules are one patch's implementations; Taiko Risshiden V DX's frame-limiter cut reaches the base game and later builds. nso_match.resolve groups rules by name: exactly one implementation must match (the log names it), a red line only when none or more than one does. Before, each implementation of a changed function logged a red line on every build it did not fit. Taiko's MATCH_CUTS has two implementations of the frame end under one name: 1.1.1's (main+0x443e8c, 364 bytes, cut at +288) and the base game's (v0 main 47d7baf6..., main+0x43e140, 172 bytes: 1.1.1 added the frame-skip branch; the same 20 bytes at +104 = main+0x43e1a8). In v0 N is likewise a global (GOT 0xa1be28, data 0x9ec55c, 1) set to 2 only by CPrivateBattleWindow / CPrivateBattleTutorialWindow, and the start tick is read after the update; nso_fnmap.py finds no exact match for 1.1.1's function in v0, found by disassembly. Checked through patch_nso.py: v0 main takes the cut at 0x43e1a8 (implementation 2, no red line); a 1.1.1 main copy with another build ID takes implementation 1, output byte-identical to the registered cut; 1.1.1 keeps its exact CUTS. A scan of the 42 distinct mains on the drives found this limiter only in Taiko. The base game has not been run. Docs: rewriter.md (same-name implementations, procedure step 2, Found on), the game note. Checked: test_nso_match.py (new test fails on the old matcher), all 19 tool test files, docs tests 2026-10-26 13:24:01 +08:00
seedds 7753b7b685 Taiko Risshiden V DX: keep the frame limiter for N = 2, cut it only at N = 1, and record its cause. KTGL's frame end (main+0x443e8c) presents, acquires, then waits until N / 60 s since the frame's start tick in 2 ms SleepThread rounds; the tick is read after the scene's update (main+0x443d44), so every frame lasts N / 60 s plus the time to the next start, rounded up: never one vsync, on any hardware. That is the game's code, not the host (SleepThread and the tick are exact; a model of the loop gives 54 fps with the host's acquire and with the Switch's double-buffered one). N (GOT 0xa1c088, data 0x9ec764) is the game's vsyncs per frame: 2 in CPrivateBattleWindow / CPrivateBattleTutorialWindow (main+0xf02d0, main+0xec4cc), whose code counts 60 / N frames a second, and the game presents at interval 1 everywhere. The earlier cut (b.hs -> b at main+0x443fd4) skipped the wait for every N: with N forced to 2 it presented 60 frames a second against the game's 28.8. The new cut at main+0x443fac computes the threshold with udiv by 60 and sets it to 0 only when N = 1, where the host's present pacing holds one vsync. Checked on the Mac (host at d50ecc1, Mac libraries for chain 8393d85a4eae): title N = 1 54.6 -> 60.0 fps (frame p50 16.67 ms, wakeups 2,050 -> 300/s), N forced to 2 28.9 fps (no cut 28.8, old cut 60.0); town on the rewriter's own output 60.0 fps, p50 16.66 / p95 17.08 ms, no red line; patch_nso.py applies the cut with its byte checks. The CPrivateBattle scenes (small unit battles, PBBATTLE) were not reached: open in the game note. Docs: the game note and the frame-rate reference entry give the corrected cause; tool tests (17 files) and docs tests pass 2026-10-26 13:04:04 +08:00
seeddsandv0lumehi fb20bce70e Add GPU diagnostics and close periodic profiles per frame (#225)
Add periodic encoder profiles with attachment traffic and formats, alternating A/B measurement phases, bounded Metal trace capture, and gpuprof.py log summaries. Preserve main's offline pipeline-archive integration while adding the capture build setting.

Close periodic samples at frame boundaries through the last committed shared-event fence, so every:1 reports without mixing frames or reusing an unresolved heap. Add 28 CPU checks of production profiling code and include them in CI; document the mechanism and update the symptom index.

Validated with all 31 CI-style Python test files, the profiling regression, a Mac host build, and all 133 iOS source compiles. Profiling completion and heap ownership were checked with synthetic counter/event objects; no new real-GPU or gameplay validation.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-26 12:09:07 +08:00
seeddsandv0lumehi 3f22526e87 Add repeatable Mac benchmarks and harden report generation (#191)
Run profile-defined routes from independent copies of one save and report frame-time, presentation and GPU percentiles across repeated variants. Preserve the display-link behavior for targets at or below 60 fps.

Resolve relative paths before launching in the run folder, preserve the archive-disable sentinel, aggregate optional metrics from the runs that supplied them, and release the measurement lock when launch fails. Regression tests exercise an actual synthetic child host and leave the source save intact.

Validated with benchmark regressions, the CI-style Python test suite, and documentation checks. The three new benchmark regression cases reject the original PR code.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-26 12:09:07 +08:00
seeddsandAmost d50ecc1f84 Support masked-predecessor jump tables and external patches (#237)
Recognize offset-table dispatches whose predecessor masks the index while
the dispatch checks a masked copy of the same source. Reject calls and
resolved table paths that bypass masking, undecodable instruction gaps or
targets, and writes that invalidate the table base. Keep the existing
recognizers ahead of this fallback.

Load build-gated patches from DM_GAMES_DIR and include them in rewrite reuse
keys. Preserve repository matching rules for derived profiles, select the
first external profile for provisional matching rules, and deduplicate
patch paths while retaining conflicts between distinct build claims.

Validation on current main: Python tool tests (156, 14 skipped), iOS tests
(6), graphics tests (44, 2 skipped), documentation index and diff checks.
Regression cases fail on the original implementation and pass with these
guards; both supported base-loading forms remain accepted. Real game
modules and gameplay were not revalidated.

Co-authored-by: Amost <6445689+Amost-@users.noreply.github.com>
2026-10-26 11:03:47 +08:00
seeddsandv0lumehi 92fc2f2711 Build and ship offline Metal pipeline archives (#226)
Compile eligible shader-pair bases on the Mac with metal-tt, package one
archive per selected iPhone GPU, and use a matching bundle before falling
back to on-device preparation. Carry the profile depth mode through packing
and include the pulling libraries required by the bundled bases.

Integrate PR #226 with four confirmed fixes: validate archive container
bounds before invoking Metal; require at least one actual successful bundle
probe; hash consumed library bytes into offline cache keys; and emit device
remainder lists for constant-only plans instead of aborting packaging.
Keep game measurements in the game note and document the general findings.

Validation on current main: 52 real Metal bundle checks, 57 archive checks,
79 prewarm checks on each pipeline path, 73 Python regressions covering
offline tools, packaging, documentation and chain checks, and compilation
of all 133 iOS source files. No new iPhone gameplay validation. The archive guard validates
container structure, not private Metal payloads.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-26 10:52:50 +08:00
seeddsandFernando Messias 62a640b037 Fix custom key loading for compressed game inputs (#204)
nsz 4.6.1 rejects --keys and loads keys.txt beside argv[0] during import.
Run the converter in its temporary output folder with the selected key
file linked there before import, using absolute input and output paths.
Remove the temporary link on both successful and failed conversions.

Integrate PR #204 with XCZ and relative-path regressions, rename the test
flag that shadowed unittest.TestCase.fail, and qualify the documentation
for the verified nsz release. Record the packing finding and provenance.

Validation: reproduced the exact parser failure using real nsz 4.6.1;
a synthetic NSZ conversion verifies selected-key lookup and link cleanup;
52 NSP tests, four documentation tests and git diff --check pass.
The synthetic payload is unencrypted and uses dummy keys. Real-game
decryption, actual XCZ conversion and a full IPA build remain unverified.

Co-authored-by: Fernando Messias <fernandomessias95@gmail.com>
2026-10-26 10:36:23 +08:00
seedds 435a231051 Preserve Horizon audio renderer work-buffer requirements
DSP callers were charged the local SDK CPU server budget, whose command representation is larger than the Horizon service representation. For Age of Calamity the service requires 0x61d000 while the local SDK requires 0x760000, exhausting the fixed sound heap.

Calculate the service requirement through renderer revision 15 and supply larger local backend storage separately, with cleanup on failed open and after renderer close. Remove the two game heap cuts and add sizing, nested-open, failure and lifetime regression coverage.

Validation: 360 seeded cases match isolated Horizon machine-code execution across REV1-REV15; the original game heaps initialize all five players and produce audio; the host suite, documentation and patch checks, SDK 8/20 smoke checks and iOS C compilation pass. iOS runtime and long battles remain untested.
2026-10-26 10:18:29 +08:00
seeddsandv0lumehi c4b74a62f9 Add thermal frame-rate cap with synchronized recovery (#220)
Hold the host frame step at 30 fps while iOS reports serious or critical
thermal pressure, and restore its configured cap after 30 calm seconds.
Keep the existing movie cap and DM_THERMAL_CAP=0 override.

Sample thermal state independently of movies and configured 30 fps targets
so heating resets recovery and cooling counts during playback. Serialize
the sample, cached cap and recovery timer across acquire/present readers.
The original PR failed five timing checks and ThreadSanitizer detected a
race through concurrent production cap getters.

Add controlled-clock production-path regressions and CI coverage, including
disabled/inactive caps and ThreadSanitizer. Record the shared mechanism
and validation limits in the frame-rate reference and BotW note.

Validated on latest main with the BotW profile: 24 thermal checks normally
and under ThreadSanitizer, 51 frame-step checks, 154 NVN checks, the
present-snapshot suite, 21 tool/docs checks, Mac host build, and iOS compile
check (133 sources). No new device gameplay or thermal recovery run.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-26 10:13:42 +08:00
seedds c76f679834 Remove alpha_from_red: Super Mario Odyssey's layout captures need only the nvnTextureCompare fix. The game creates each capture with its per-format default mapping (an R8 one reads (R, 0, 0, 1)), rebuilds it on the same storage with the capture's own, (1, 1, 1, R), and replaces the registered descriptor only on a difference (main+0x982320); while the host's comparison ignored the mapping the captures kept alpha 1 (white coin cards, a dark box behind hints), which the 26-shader alpha_from_red list papered over. Checked on the Mac from the "Look Around" hint with a probe host on the comparison (a c3a0880^ host for the profile's chain dec5ee141a9f libraries): 40 mapping-only rebuilds in 11,700 frames (R8 captures 640x80 down to 48x57 to (1, 1, 1, R), a 320x180 RGBA one to (R, G, B, A)); ignoring the mapping again brings back the box (about 12,800 pixels from frame 4,200), the old list hid it by converting the 378x80 capture, and with the fix the list converted nothing and changed no pixel of frames 4,200-6,600. The comparison and the views have no platform branch, so the iPhone gets the same rebuilt mapping (not run on a device). With no profile left using it, the key, its host code (tex_alpha_red, afr_want, DM_NVN_ALPHA_RED) and its docs go; treg_drop_ar becomes treg_drop_im (the image-slot view it also drops stays). Odyssey's note has the A/B runs. Checked: the host builds for Odyssey, the iOS compile check (133 files), the tool tests (111, 14 skipped) 2026-10-26 10:01:20 +08:00
seeddsandparsifal295 2db12f7efd Fix vibration handles before controller haptics routing (#246)
GetVibrationDeviceHandles used routed haptics availability to decide whether
handles existed. Games that cache this answer at startup could retain an empty
answer after a controller connected. Return handles for a connected npad style
when rumble is enabled and an output sink is installed; check routed outputs
when values are sent, keeping the existing permission and lifecycle behavior.

Include the PR's rumble diagnostics, count unroutable values individually in
mixed batches, and protect aggregate counters across game threads. Correct the
code comment to describe Unicorn Overlord's observed empty handles and zero
values without claiming restored physical rumble.

Add regressions for cached startup handles delivering a nonzero value after
routing, diagnostic totals and concurrent sends. Include HID in the existing
ThreadSanitizer target and record the mechanism in the service reference.

Checked with GAME=010069401ADB8000: full host suite, 73 HID checks, audio and HID
ThreadSanitizer checks, docs checks, Mac host build, and iOS compilation
(133 files). Physical rumble and iOS runtime remain untested. Broader tool
validation is incomplete because Capstone is missing and iconutil failed.

Co-authored-by: parsifal295 <130349765+parsifal295@users.noreply.github.com>
2026-10-26 09:54:43 +08:00
seeddsandv0lumehi c13ddcf531 Add opt-in MetalFX spatial upscaling and a single-screen launcher (#215)
Scale the valid presented image with MetalFX's spatial scaler on the shared
Metal 4 path, preserving crop, letterboxing, origin and gamma-encoded colours.
Keep Standard as the default and fall back when scaling is unsupported.

Use the same path for asynchronous whole-window captures and diagnostic
screenshots, retaining resources until GPU completion. Bound scaler recreation
during resizing and report presentation GPU time separately by scaling mode.

Put all launcher settings on one screen with Game, Controls and Performance
sections, inline menus and sliders, and a reset to tested defaults. Extract the
settings model for native persistence tests, validate saved ranges, share HUD
setup, and document the measured costs without claiming an iPhone baseline.

Validated with Metal presentation, NVN and snapshot regressions; tool and iOS
tests; the Mac host; and an unsigned iOS smoke build. No new device gameplay run.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-26 09:38:05 +08:00
seedds 3aa706a3fd Pokémon Shield (01008DB008C2C000, update 1.3.2 = v458752, Game Freak's engine on SDK 7.3.2): game profile, no host change. Sword's twin: the same sdk, subsdk0 (movie) and subsdk1 (GLSLC) builds, only main is its own (a1680262…), and the shader split gives Sword's 41,516 shaders with the same data rows in all three tables; the profile is Sword's with Shield's title, name, IPA name, build row and tables (prewarm list copied). The game note (dm/games/01008DB008C2C000/README.md) has what differs, the Mac route (a fresh save needs DM_KBD for the name; Sword's route out of the house works unchanged) and the shader build with DMSH_PREFILL from Sword's libraries (21,974 Mac / 21,684 iOS filled, 176 / 175 compiled). Plays on the iPhone (IPA 12.4 GB, user) and on the Mac at 30 fps with no red line from the first boot through the opening and Postwick to Hop. README gallery entry with a Mac screenshot, a row in the games table, a pointer from Sword's note, AGENTS.md's count to sixty-seven. Checked: the tool tests pass (111, 14 skipped) 2026-10-26 09:20:23 +08:00
seedds 3dd5d25a51 Add Echoes of Wisdom 1.1.0 port and correct cube fallback diagnostic 2026-10-26 09:14:43 +08:00
seeddsandv0lumehi 577df01c39 Fix iOS pulling shader packaging for profile defaults (#211)
Include pulling vertex libraries when the compiled game profile enables the
Metal 4 path, preserving explicit IOS_PULL overrides. Keep the pack options
array nonempty so inclusion also works with macOS Bash 3.2 and set -u.

Exercise the actual archive step with tiny shader fixtures for Breath of
the Wild and Wonder, checking both defaults and explicit overrides. Record
the packaging failures and fixes in the rendering reference and game note.

Co-authored-by: v0lumehi <aljic.zijad@gmail.com>
2026-10-26 08:56:50 +08:00
v0lumehi 037ff69562 Profile keys present_snap and pso_mtl4: a game ships the presentation and pipeline settings it was tested with. present_snap on: present snapshots by default (a ring of 2 host textures; the iOS launcher's Frame buffering defaults to it; DM_PRESENT_SNAP and Documents/env.txt override); pso_mtl4 on: render pipelines through MTL4Compiler on iOS by default, with the pipeline archive, the prepare step and the hybrid pipelines (on by default on the Mac; DM_PSO_MTL4 overrides). Breath of the Wild sets both: they held a steady 60 fps on an iPhone 17 Pro Max (issues #142 / #159; without the snapshots the GPU idled between frames and iOS lowered its clock, 30 fps). README, docs/development.md and docs/reference/frame-rate.md say the new defaults. Checked: the host builds for Breath of the Wild (DM_GAME_PRESENT_SNAP 1, DM_GAME_PSO_MTL4 1) and Mario Wonder (0, 0), dm/tools/tests pass, t_present_snap and t_nvn pass with Breath of the Wild's profile, the iOS compile check passes 2026-10-26 01:43:25 +01:00
v0lumehi 1eeb109b35 docs: the prepare step (docs/development.md "The prepare step", Breath of the Wild's measurements in its note dm/games/01007EF00011E000/README.md; dm/gfx/README.md DM_PSO_PREPARE; README). Mac, M2 Max, runs started at a 1-minute load below 4, Metal cache empty, the prebuilt archive, the Zora's Domain save: with no list, 4 frames over 25 ms with new pipelines and 5 with shader library loads (75 libraries, 168 ms of that work, worst 128 ms) in the 60 s after the last menu press; with the new pso_manifest.tsv none, whether it was built in the background (14.6 and 16.0 s on one worker, done during boot) or by the prepare step (5.2 and 2.2 s on 12 workers, 3.3 s on 8, 872 bases compiled); a second start prepares it in 0.08 s and a player's 5,783-line list in 0.23 s, both with no screen. Hades (Vulkan) is unchanged: it builds its 1,856 pipelines itself while it loads 2026-10-26 01:43:20 +01:00
v0lumehi d9aa864d0d Breath of the Wild: a prewarm seed list (pso_manifest.tsv, 1,789 lines: 960 render pipelines, 819 shaders, 10 compute shaders), so a first start has something to prepare. Recorded on the Mac with prewarm off (DM_PSO_MANIFEST=off DM_PSO_RECORD) over update 1.9.0: boot, title, New Game and the Shrine of Resurrection until Link can move (1,298 lines); then boot, title, a save load into Zora's Domain and a minute of play, whose new lines are appended (491). The lines name shaders by their Switch content key and pipelines by NVN state (pso_skey), which no translation chain version changes: the save-load part was recorded on chain b7b9aa970b37 and every line resolves on 97e2f301eb73 2026-10-26 01:43:20 +01:00