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.
42 KiB
42 KiB
| 1 | name | class | meaning |
|---|---|---|---|
| 2 | DM_AB | diagnostic | `=<frames>` splits the run into phases of that many frames and alternates every switch set to `ab` (on in the odd phases); logs an `[ab]` line per phase with GPU and frame time and attachment traffic |
| 3 | DM_ALIAS_WINDOWS | diagnostic | `=<MB>` logs every 30 s how much of each window of that size in the alias region is mapped (windows aligned to their size in absolute addresses) |
| 4 | DM_AOC_DIR | path | Folder of add-on content: one numbered subfolder per DLC index holding that DLC's RomFS, reported by `aoc` and mounted read-only; the app, the Mac launcher and the NSP script set it when the build has DLC |
| 5 | DM_AOC_OWNED | switch | `0` reports no add-on content even when `DM_AOC_DIR` has some, for runs without the DLC |
| 6 | DM_APP_VERSION | switch | Overrides the IPA's version in `build_ipa.sh`; by default it is the packed game's display version from its control data (the update's when one is packed) |
| 7 | DM_AUDIO | switch | `1` plays audio through Core Audio, `0` uses the silent sink; real output is the default on iOS, the silent sink on the Mac (the Mac launcher sets `1`) |
| 8 | DM_AUDIO_DUMP | diagnostic | `=<file>` writes every PCM block the game appends as is (16-bit, 48 kHz, channel count as in the OpenAudioOut log), to judge whether a sound played |
| 9 | DM_AUDIO_MUTE | switch | `=1` runs the real Core Audio output path (callback pacing, background take-over) with the output silenced, for lifecycle tests on the Mac without noise |
| 10 | DM_AUDREN_TRACE | diagnostic | When set, the CPU audio renderer logs every update with the number of frames rendered since the previous one |
| 11 | DM_BOOTPROF | diagnostic | When set, logs boot timing: the loader's breakdown (mapping, relocation, probes), Metal library loading, pipeline creation, texture uploads and the first present |
| 12 | DM_BUNDLE_ID | switch | Overrides the iOS app's bundle ID in `build_ipa.sh` (default `org.nxnative.<title ID in lowercase>`) |
| 13 | DM_COPY_GAME_RESOURCES | switch | `NO` skips the Xcode build phase that copies the game's resources into the app (`stage_resources.sh`, on by default); `build_ipa.sh` sets it for its unsigned build, which packs them itself |
| 14 | DM_CTL | diagnostic | `=<file>` (Mac): the host polls the file every 100 ms and runs each appended line: button presses, `shot`, `passdump`, `texdump`, `env KEY=VALUE`, `peek`, `memdump`, `drag` and more |
| 15 | DM_DBG | diagnostic | When set, prints the guest's `svcOutputDebugString` text to stderr as `[guest]` lines |
| 16 | DM_DBG_AU_FRAMES | diagnostic | `=<frames>` asks the Mac's Core Audio output for that many frames per callback instead of about 5 ms (1024 reproduces the iOS default that caused crackling) |
| 17 | DM_DETCLOCK | switch | `=<step ns>`: from the first present on, the guest clock advances a fixed step per present instead of following the wall clock, and the random source becomes a fixed-seed stream (replay and test runs) |
| 18 | DM_DETCLOCK_PACE | switch | `=1` with `DM_DETCLOCK`: each frame takes at least one clock step of wall time, so background loading keeps up with the fixed clock (used by the screenshot gate) |
| 19 | DM_DISPLAY_NAME | switch | Overrides the iOS app's name in `build_ipa.sh` (default the game name in the base NSP's control data) |
| 20 | DM_ENTITLEMENTS | path | `=<plist>` gives a prepared Xcode project another entitlements file instead of the Increased Memory Limit one; empty means no entitlements |
| 21 | DM_ENV_FILE | path | `=<file>` makes `build_ipa.sh` bake its `KEY=VALUE` lines into the app as `dm/env.txt`, applied at boot; `Documents/env.txt` overrides them |
| 22 | DM_ENV_FILE_KEYS | switch | Set by the iOS app at launch to the space-separated names an env file set; the launcher keeps those values and shows them greyed out |
| 23 | DM_FD_LOG | diagnostic | `=<seconds>` logs, every that many seconds, the number and kinds of file descriptors the process has open |
| 24 | DM_FIXED_TIME | switch | `=<seconds>`: the user clock always returns that time and the host time zone is pinned to UTC, for deterministic comparison |
| 25 | DM_FONT_DIR | path | Folder of the shared-font stand-ins (`standard.ttf`, `nintendo_ext.ttf` with the button icons); the app, the Mac launcher and the NSP script set it |
| 26 | DM_FORCE_STRICT | diagnostic | `=1` makes the loader fail on forced-hook entries no module references, instead of only noting them (for checking a mistyped list) |
| 27 | DM_FPS | switch | `30` or `60` pins the frame rate the display link and frame pacing aim for; otherwise it follows the game's present interval (60, or 30 when the game asks for 30) |
| 28 | DM_FPS_HOLD | player | `on` / `off` overrides the profile's `fps_hold`: whether late frames may raise the hold above the frame cap's vsyncs (on by default) |
| 29 | DM_FPS_TARGET | player | Frame-rate cap: `30` or `60`, or `0` for the game's own limit; overrides the profile's `fps_target` |
| 30 | DM_FS | diagnostic | When set, logs file opens, paths not found or not mounted, and a read summary every 64 MiB or 1000 reads |
| 31 | DM_FSLOG | diagnostic | `=<file>` writes one TSV line per ReadFile: seconds since boot, guest path, offset, length and guest buffer address |
| 32 | DM_FSLOG_HASH | diagnostic | With `DM_FSLOG`, adds a column with the FNV-1a 64 hash of the bytes read |
| 33 | DM_FULLSCREEN | switch | When set, the Mac window starts in fullscreen |
| 34 | DM_GAME | switch | Selects the game profile (a title ID under `dm/games` or `DM_GAMES_DIR`) for the Python tools and the rewriter; there is no default |
| 35 | DM_GAMES_DIR | path | Profile folders outside the repository, separated by `:`, searched after `dm/games`; the NSP script points it at a provisional or derived profile |
| 36 | DM_GAMES_FIRST | switch | `=1` searches `DM_GAMES_DIR` before `dm/games`, so a provisional or derived profile wins over the game's own (the NSP script's `--provisional`) |
| 37 | DM_GAME_ENV | switch | `KEY=VALUE` pairs, separated by spaces, that the game's own `getenv` returns, in place of the profile's `game_env` (`hle_os.c`); any other name goes to the SDK's empty environment |
| 38 | DM_GFX_FIXTURE_OUT | test | `=<dir>`: graphics tests write their raw result textures and buffers there |
| 39 | DM_GLSLC_CAPTURE | path | `=<dir>` saves every GLSLC output the game compiles at run time; `shader_split.py` reads it (default `<version dir>/glslc_capture`) |
| 40 | DM_GL_CAPTURE | path | `=<dir>`: the GL layer writes every shader source the game compiles (`<key>.vert` / `<key>.frag`) for `gl_shaders.py`; the NSP script uses it to capture run-time shaders |
| 41 | DM_GL_LOG | diagnostic | `=1` makes the GL layer log object creation |
| 42 | DM_GL_STUBS | diagnostic | `=1` gives every GL function the layer lacks a stub that reports its first call and returns 0, instead of a null pointer (bring-up) |
| 43 | DM_GPU_CAPTURE | diagnostic | `=<frame>[:<frames>]` or `gpu:<ms>[:<after frame>]` writes a Metal GPU trace of those frames for Xcode's Metal debugger; can be set while running through `DM_CTL` |
| 44 | DM_GPU_CAPTURE_DIR | path | Folder for `DM_GPU_CAPTURE`'s traces (default `gpu_captures/` in the working directory) |
| 45 | DM_GPU_CAPTURE_KEEP | diagnostic | Before each GPU capture, prunes the capture folder's `dm_*.gputrace` entries so that the newest `KEEP - 1` stay (default 2) |
| 46 | DM_GUEST_SPAWN_TEST | diagnostic | `=1` runs a self-test before `nnMain`: a host-started guest thread does SDK malloc / free and locks an `nn::os` mutex, and the result is logged; `=2` also keeps a resident thread |
| 47 | DM_HITCH_DUMP | diagnostic | `=<ms>[:<s>]`: when no frame has been presented for that long (from s seconds on), logs every guest thread once per stall: wait, last SVC, pc, lr, frames and registers |
| 48 | DM_HLECOUNT | diagnostic | `=<file>` (`%d` = process ID) writes at exit a TSV of how many times the guest called each HLE function, zero counts included |
| 49 | DM_ICON | path | `=<image>` gives `build_ipa.sh` another app icon (default the `icon.jpg` beside the RomFS) |
| 50 | DM_IMPORTS | diagnostic | When set, logs each import the loader binds to a host function and each forced takeover |
| 51 | DM_KBD | switch | `=<text>`: the system keyboard returns that text as OK without showing an input box; unset with no window, it returns cancel |
| 52 | DM_KBD_PLAYER | switch | `own` makes the Mac keyboard player 1 on its own, with controllers from player 2 on (by default the first controller shares player 1 with the keyboard) |
| 53 | DM_KEYS | switch | Scripted input: `<seconds or f<frame>>:<key>[+key][~hold][*count/interval],…` presses buttons, sticks and `Shake` at those times |
| 54 | DM_LANG | player | Game language as a language code (default `en-US`; the iOS app sets the one the IPA was packed with) |
| 55 | DM_LAUNCHER | switch | `0` skips the iOS settings screen and starts the game at once |
| 56 | DM_LINK_VTICK | switch | `0` keeps the system's display-link rate on 144 or 165 Hz Mac screens; by default the link counts only the refreshes nearest a steady 1/60 s clock |
| 57 | DM_LOADHASH | diagnostic | `=1` logs an address-independent SHA-256 per module after loading |
| 58 | DM_LONGFRAME | diagnostic | `0` turns off the long-frame log (on by default), a line for a frame over 20 ms or with GPU time over 16.7 ms that is clearly above recent frames |
| 59 | DM_MEASURE_LOCK | path | `=<file>`: `scripts/regress.py`'s default `--lock`, the measuring lock `scripts/bench.py --lock` shares: held only while a game runs, and the harness's shader builds pause while another process holds it |
| 60 | DM_MEMSTAT | diagnostic | `=<tsv>` writes one line per second of memory accounting: footprint, Metal allocation and resident and charged memory by region class (guest, code, malloc, gpu, …) |
| 61 | DM_MEMSTAT_DUMP | diagnostic | `=<seconds>`: with `DM_MEMSTAT`, at that second writes every VM region of 1 MiB or more to `<tsv>.regions` |
| 62 | DM_MEM_CAP_GB | switch | `=<GB>`: the memory watchdog exits when resident memory exceeds that many GB (default 24 on the Mac, none on iOS; `0` turns it off) |
| 63 | DM_METAL_CAPTURE | diagnostic | `=1` makes `build_ipa.sh` produce a build that can write GPU frame captures (`MetalCaptureEnabled` in `Info.plist`), for `DM_GPU_CAPTURE` |
| 64 | DM_METAL_HUD | player | `1` shows Apple's Metal performance HUD over the game (frame rate, frame and GPU time, memory) |
| 65 | DM_MOVIE_TRACE | diagnostic | When set, the movie decoder logs every call with its thread and decoder (by default the first 12 calls, then every 2^k-th) |
| 66 | DM_MSL_DIR | path | Parent folder of the shader libraries: NVN loads from `b-<chain version>/` beneath it, Vulkan from `vk/`, GL from `gl/`; the app and the Mac launcher set it |
| 67 | DM_NICK | switch | The account nickname the game sees (default `Player`) |
| 68 | DM_NRO | switch | `0` turns off loading of the NRO modules the game's NRR files register (on by default): every `nn::ro::LoadModule` then fails |
| 69 | DM_NVN_ALLOCPROF | diagnostic | `=1` charges Metal allocation growth to each replayed op type and function, and logs command allocator sizes and each new texture (serial, size, format, storage) |
| 70 | DM_NVN_API | switch | `=<major>.<minor>` overrides the NVN API version `nvnDeviceGetInteger` reports (by default decided by the SDK version or the profile's `device_api`: 55.15 for SDK 11 and later, 53.313 before) |
| 71 | DM_NVN_BARRIER | switch | How draw passes are ordered: `full` (default) waits for all earlier GPU work, `game` only for the previous pass's fragment stage unless the game set a barrier, `ab` alternates with the `DM_AB` phases |
| 72 | DM_NVN_BF_WANT | path | `=<file>`: appends the key of each fragment shader whose passes could not be merged for lack of a readable-tile version to that file, once per key |
| 73 | DM_NVN_BLIT_ORDER | diagnostic | `0` drops the barriers between dependent operations in the copy encoder, which reproduces the fountain's vertical stripes in Mario Wonder |
| 74 | DM_NVN_CBDUMP | diagnostic | `=<dir>`: saves each draw's whole uniform blocks as `F<frame>_p<pass>_st<stage>_cb<slot>_<address>.bin`, and the source bytes of buffer-to-3D-texture copies, with `DM_NVN_PASSDUMP` |
| 75 | DM_NVN_CBDUMP_KEY | diagnostic | `=<shader key>`: limits `DM_NVN_CBDUMP` to draws using that shader; for a vertex shader key also saves the draw's vertex streams and index buffer |
| 76 | DM_NVN_CBLOG | diagnostic | `=1` logs the command memory the game adds to command buffers (`AddCommandMemory`: the first 60, then every 500th) and the out-of-memory callbacks |
| 77 | DM_NVN_CLEARLOG | diagnostic | `=1` logs the first 40 colour clears drawn as a triangle (inside a pass, with a partial channel mask or a partial scissor) |
| 78 | DM_NVN_CMDSTAT | diagnostic | `=1` logs every 300 frames the command recording usage: bytes and records per frame, command memory segment sizes, out-of-memory callbacks, host segments, count and bytes per command type |
| 79 | DM_NVN_CS_HOIST | switch | `0` makes a compute dispatch between the draws of a pass end it (on by default: the dispatch runs ahead of the pass when that changes nothing the draws before it read) |
| 80 | DM_NVN_CUT | switch | `=<draws>`: the replay commits its command buffer every that many draws, between passes (default 64; `0` one command buffer per submission, except the cut after a buffer-to-texture copy) |
| 81 | DM_NVN_DEFER | switch | `0` turns off the deferred pass merging of the TBDR optimizations (which run only with `DM_NVN_TBDR=1`) |
| 82 | DM_NVN_DEFER_AB | diagnostic | `=1` keeps the deferred pass merging (with `DM_NVN_TBDR=1`) off until the second screenshot has been written, then turns it on, to compare the pictures with and without it |
| 83 | DM_NVN_DIRTYCHECK | diagnostic | `=1` fully hashes pool content on every use to find changes the dirty-page tracking missed |
| 84 | DM_NVN_DISPATCH_OWN | switch | `=1` gives every compute dispatch a compute encoder of its own with full barriers, as before (by default dispatches share the copy encoder); `DM_NVN_PASSGPU` does the same |
| 85 | DM_NVN_ENC_LABEL | diagnostic | `=1` labels every render encoder `p<pass in frame> <width>x<height> <first 8 digits of the first draw's fragment key> d<draws>` for Instruments traces |
| 86 | DM_NVN_ENC_THREAD | player | `1` runs the replay's Metal encoding on a thread of its own while the submit thread goes on translating; on by default on iOS (`0` turns it off), off on macOS |
| 87 | DM_NVN_FAST_WAKE | switch | `0` makes the game's `SyncWait`s wake on the commit feedback handler instead of the GPU's own signal of the fence (on by default) |
| 88 | DM_NVN_FB_SNAP | switch | Which fragment shaders sampling a colour attachment of their own pass read a snapshot of it: `0` none, `all` every shader (slow), `<keys,…>` that list instead of the profile's `feedback_snap` |
| 89 | DM_NVN_FLUSH_FILL | switch | `0` starts a new GPU texture in a CPU-writable pool as zeros; by default one whose storage the game flushed before its first use is filled from that storage once |
| 90 | DM_NVN_FRAMES | diagnostic | `=<N>` prints the NVN call table frame by frame for the first N frames (default 3) |
| 91 | DM_NVN_FUSE_CHECK | diagnostic | `=1` checks pass merging in the same frame: renders the merged passes again apart and logs the comparison of the attachments every time |
| 92 | DM_NVN_GPUPROF | diagnostic | `=<f>`, `<f1>-<f2>` or `every:<n>`: logs the GPU start and duration of every encoder of those frames (`[gpuprof]` lines from Metal 4 counter heap timestamps) |
| 93 | DM_NVN_GPU_TS | switch | `segment` or `submission`: what timestamp reports record (GPU start / end of the segment holding each report, or one time for the whole submission), instead of the profile's `gpu_timestamps` |
| 94 | DM_NVN_HILITE | diagnostic | `=<fragment shader key>,…`: those draws use a solid colour instead (magenta, green, cyan, yellow, blue, white in order), to tell wrong geometry from wrong shading |
| 95 | DM_NVN_IXCLOG | diagnostic | `=<n>` logs the first n indirect draw and dispatch conversions (record to arguments) once the GPU has run them |
| 96 | DM_NVN_KEYDUMP | diagnostic | `=<fs key>[:n[:every]]`: for up to n draws of that fragment shader (default 6), logs the pass dump binding lines plus vertex formats, vertex streams and uniform values; meant for devices |
| 97 | DM_NVN_LAZY_CLEAR | switch | `0` makes clears with no draw after them open a pass of their own, as before; by default they wait to become the load action of the next pass on that target |
| 98 | DM_NVN_LOADPROBE | diagnostic | `=1`, `2` or `3`: attachments whose load is skipped are cleared to a sentinel colour (`3` NaN; `1` NaN for float formats) and the sentinel pixels left at pass end are counted (should be 0) |
| 99 | DM_NVN_LOG | diagnostic | `=1` logs the creation of NVN objects |
| 100 | DM_NVN_MAGSCAN | diagnostic | `=<fs key>[:every[:phase]]`: device self-check that reads each pass's colour attachments every `every` frames (default 30) and logs `[mag]` lines for solid magenta 16×16 blocks or non-finite pixels |
| 101 | DM_NVN_PASSDUMP | diagnostic | `=<f>`, `<f1>-<f2>` or `every:<n>`: logs every render pass of those frames (attachments, clears, shader keys, bindings, draw state, presents) for the `tbdr_*.py` tools |
| 102 | DM_NVN_PASSDUMP_ALL | diagnostic | `=1` makes `DM_NVN_PASSDUMP` record every draw and binding change, not only the first per pass and stage, including copies and inline uniform updates |
| 103 | DM_NVN_PASSGPU | diagnostic | `=<file>` writes the GPU time of each render and compute pass from stage-boundary timestamp counters (off under Metal 4); also gives each dispatch its own encoder |
| 104 | DM_NVN_PASSGPU_SERIAL | diagnostic | `=1` makes each encoder on the main command buffer wait until all earlier work has finished, so `DM_NVN_PASSGPU` times read each pass's exclusive time (totals read high) |
| 105 | DM_NVN_PREDICT | switch | `0` turns off the parallel precompile look-ahead: a pipeline miss compiles only the pipeline it needs |
| 106 | DM_NVN_PROF | diagnostic | `=1` wraps the implemented NVN functions in a timing wrapper and collects the time each takes during recording |
| 107 | DM_NVN_PROGTRACE | diagnostic | `=<vertex keys,...>` logs matching ProgramSetShaders calls and their guest backtraces |
| 108 | DM_NVN_REGLUM | diagnostic | `=x0,y0,x1,y1:<file>` (normalized coordinates): on every present records the present number, time, mean luminance and a grayscale thumbnail of that region, to check animation speed against frame rate |
| 109 | DM_NVN_RT_RANGE | switch | `=1` (experimental, off by default; with `DM_NVN_TBDR=1`) keeps the pass open when the game sets the same colour and depth target again with a view that differs only in its level count |
| 110 | DM_NVN_RT_RANGE_CHECK | diagnostic | With `DM_NVN_RT_RANGE=1` and `DM_NVN_PASSDUMP`, renders a candidate pass both ways in the same frame and logs and writes the comparison (`CHECK_RESULTS.tsv`, `[RED]` on a difference) |
| 111 | DM_NVN_SHDUMP | diagnostic | `=<dir>` saves programs missing from the shader map as `<key>.ctl` (control section) and `<key>.code`, to find the files that hold them |
| 112 | DM_NVN_SHMAP | path | The shader map (`shader_map.tsv`); `c1_full.tsv` and `pso_manifest.tsv` are taken from the same folder. Default: the game profile's folder on the Mac; the iOS app sets it |
| 113 | DM_NVN_SHOT | diagnostic | `=<frame>[,<frame>…]:<path>` saves the swapchain texture as an image at those frames (`%d` in the path = frame number) |
| 114 | DM_NVN_SHOT_OUT | diagnostic | `=<W>x<H>` makes `DM_NVN_SHOT` capture the picture as the present pass upscales it to that size, the crop included, instead of the raw swapchain texture |
| 115 | DM_NVN_SKIP_FS | diagnostic | `=<fragment key>[,…]` (up to 16) drops all draws of those fragment shaders, to measure their GPU cost or bisect a wrong draw; the picture is wrong |
| 116 | DM_NVN_SKIP_SMALL | diagnostic | `=<width>` drops all draws whose target width is at most that, to measure the cost of tiny render passes; the picture is wrong |
| 117 | DM_NVN_SLICE_MERGE | switch | `0` keeps passes into other layers of one array or cube texture level apart (on by default: they run as one layered pass) |
| 118 | DM_NVN_SNAPRAW | diagnostic | `=1` makes `DM_NVN_TEXDUMP` also save each target's raw bytes, with a text header line, since converting an HDR target to an 8-bit image truncates |
| 119 | DM_NVN_T2T_FROM | diagnostic | `=<frame>`: `DM_NVN_T2T_TRACE` records copies only from that frame on (default 0) |
| 120 | DM_NVN_T2T_TRACE | diagnostic | `=<W>x<H>:<file>`: after each copy into an RGBA16F texture of that size, copies the result into a trace buffer on the GPU timeline; 240 entries are written to the file |
| 121 | DM_NVN_TBDR | switch | `=1` turns on the replay's TBDR pass optimizations (store / load elision, pass merging, same-target continuation); off by default since bindless textures defeat their read inference |
| 122 | DM_NVN_TEXCPU | diagnostic | `=1` logs non-packaged (non-swizzled) textures in CPU-visible pools |
| 123 | DM_NVN_TEXDUMP | diagnostic | `=<frame>:<path>`, `size=<W>x<H>:<path>` or `layers=<n>:<path>`: saves every colour render target of that frame as PNG (`%d` = serial × 100 + layer × 10 + level) |
| 124 | DM_NVN_TEXINFO | diagnostic | `=<W>x<H>` logs storage and description of every texture of that size on first use, registration and initialization (pool, flags, packaged, non-zero bytes, swizzles) |
| 125 | DM_NVN_TEXRAW | diagnostic | `=<serial>,…` or `info` (the textures `DM_NVN_TEXINFO` picked out): saves those textures' raw bytes at the `DM_NVN_TEXDUMP` frame, with a text header line |
| 126 | DM_NVN_TEXSNAP | diagnostic | `=<in-frame pass index>,…`: with `DM_NVN_TEXDUMP`, copies those passes' colour attachments as they end and saves them with the end-of-frame dump |
| 127 | DM_NVN_TREG_ID | diagnostic | `=<n>` logs every registration of texture ID n: what it holds from then on, and the frame being recorded |
| 128 | DM_NVN_TSV | diagnostic | `=<path>` writes the per-frame NVN call table and timing rows (frame, metric, value) to a TSV, read by `scripts/bench.py` |
| 129 | DM_NVN_TSV_CALLS | diagnostic | `0` makes `DM_NVN_TSV` write only the timing rows, without the call counts (about two thirds of the file) |
| 130 | DM_NVN_UBP_CHECK | diagnostic | `=1` checks every uniform shadow made from memory: the pass ends, the updates land, the replay waits for the GPU and compares (a difference is a red line; slow) |
| 131 | DM_NVN_UB_COPY_THREAD | switch | `0` copies uniform shadows of 512 bytes or more on the submit thread, as before (by default a worker copies them) |
| 132 | DM_NVN_UB_DEFER | switch | `0` ends the render pass at every inline uniform update, as before; by default an update inside an open pass is deferred to the pass end and later draws read a shadow (off in TBDR mode) |
| 133 | DM_NVN_UB_LAZY | switch | `=<n>`: the most deferred inline uniform updates kept across a render pass end (default 160); they land before the next copy, a conflicting draw or dispatch, or the submission end; `0` lands them at every pass end |
| 134 | DM_NVN_UB_N | diagnostic | `=<frames>`: the length of each phase of the same-process alternating measurement `DM_NVN_UB` (default 180, minimum 60) |
| 135 | DM_NVN_UB_PARTIAL | switch | `0`: a uniform block the deferred updates cover only in part ends the pass, as before; by default its shadow starts from memory and takes the submission's queued updates (on by default) |
| 136 | DM_NVN_UDC_AB | diagnostic | `=1` starts with the DontCare store for unwritten attachments off and turns it on after the second screenshot, for an on/off picture comparison in one run |
| 137 | DM_NVN_UNWRITTEN_DC | switch | `0` turns off storing attachments a render pass did not write as DontCare (on by default; part of the TBDR store lookahead), for equivalence comparisons |
| 138 | DM_NVN_VBUF_CACHE | switch | `0` turns off the cache of resolved vertex stream addresses and vertex argument table writes across draws (on by default), for A/B runs |
| 139 | DM_NVN_VCONV_CHECK | diagnostic | `=1` scans the indices again at every reuse of a cached vertex conversion range (`vconv_range`) and reports differences |
| 140 | DM_NVN_VCONV_CPU | switch | `=1` converts integer vertex inputs fed formats of another class on the CPU, as before, instead of through the shader's shadow inputs (`<key>_bv`) |
| 141 | DM_NVN_VCONV_RANGE | switch | `0` / `1` overrides the profile's `vconv_range`: CPU vertex conversion only over the vertices each draw reads instead of the whole bound range |
| 142 | DM_NVN_VLOG | diagnostic | Set: logs each NVN memory pool as it is created (address, memory, size, flags) with a backtrace |
| 143 | DM_NVN_VSDUMP | path | Output file for post-vertex captures; used with DM_NVN_VSDUMP_KEY and the frame/count bounds |
| 144 | DM_NVN_VSDUMP_FROM | diagnostic | First presented frame eligible for a post-vertex capture (default 0) |
| 145 | DM_NVN_VSDUMP_KEY | diagnostic | Vertex key to capture, or `*` for all eligible vertex shaders; storage-writing shaders are excluded |
| 146 | DM_NVN_VSDUMP_MAX | diagnostic | Maximum post-vertex captures (default 1, or 256 for the wildcard key) |
| 147 | DM_NVN_WAITS | diagnostic | `=1` turns on the wait ledger: every place a host or game thread waits on the CPU for the GPU or the encode thread, counted per frame |
| 148 | DM_NVN_XV | switch | `0` turns off the cross-submission attachment validity ledger, which skips write-backs of colour attachments cleared before their next use (on by default, only with `DM_NVN_TBDR` on) |
| 149 | DM_NVN_ZBLOCK | diagnostic | `=1` logs (`[zb]`) the all-zero blocks per level of each ASTC texture uploaded on the CPU (magenta when drawn); `=<folder>` also writes the raw storage of the first one per format and size |
| 150 | DM_NVN_ZSKIP | switch | `0` turns off the zero-source skip, which drops a draw whose fragment shader is proven to write 0 over targets already 0 (on by default, only with `DM_NVN_TBDR` on) |
| 151 | DM_OE_SCRIPT | diagnostic | Scripted applet state changes at given seconds, `key=value@seconds,…` with keys `focus`, `opmode` and `bg` (`bg=1` / `bg=0` run the whole background round trip), e.g. `bg=1@20,bg=0@25` |
| 152 | DM_OODLE_HOST | path | The Mac host binary that `shader_split.py` runs in its Oodle tool mode to decode Trinity packs (`ONEPACK` files); set by the NSP script |
| 153 | DM_OODLE_JOB | path | `=<job file>`: the host runs the game's own Oodle decoder on every record of the job file right before `nnMain`, writes `<job file>.out` and exits (Unreal shader archives) |
| 154 | DM_OODLE_MODULES | path | The rewritten modules the Mac host's Oodle tool mode loads when `shader_split.py` decodes Trinity packs; set by the NSP script |
| 155 | DM_OODLE_SERVE | switch | `=1`: the host answers decode requests on stdin / stdout with the game's own Oodle (or LZ5) decoder from the guest main thread before the SDK starts, until stdin ends |
| 156 | DM_OPMODE | player | The operation mode the game sees: `0` handheld, `1` console (default: the profile's `op_mode`, console unless set); read once at startup |
| 157 | DM_PAD_MERGE | switch | `=1` on the Mac merges every controller into player 1, as before, instead of giving each controller a player of its own |
| 158 | DM_PATCH_FRONT | switch | `=<bytes>`: the size of the patch area right before the module base for a long text (`BIG_TEXT`); set only by the rewriter's own rerun with the size it needs |
| 159 | DM_PREEMPT | switch | `0` / `1` overrides the profile's `core_preempt`: also check already-runnable higher-priority peers on the caller's core after every thread SVC |
| 160 | DM_PRELOAD | diagnostic | Set: on the Mac, runs the host's early background loading (`dm_host_preload_start`) as the iOS app does, to exercise that path |
| 161 | DM_PRESENT_FIFO | switch | `0` makes the display link take the newest queued frame each tick, as before; by default it shows frames in order, at most one tick behind |
| 162 | DM_PRESENT_HZ | switch | `=<N>`: the frequency of presentation pacing (default 60); `0` means no frame limit and is for performance profiling only |
| 163 | DM_PRESENT_INTERVAL | switch | `display` presents one frame per display-link tick whatever interval the game sets; `game` follows the game's present interval (default: the profile's `present_interval`) |
| 164 | DM_PRESENT_LATENCY | switch | `=<n>` (above 0): the display link's preferred frame latency (default 1) |
| 165 | DM_PRESENT_LINK | switch | Present pacing: `0` acquires the drawable itself, `1` (the default) presents on a 60 Hz display link, `2` uses a 120 Hz display link with a frame every other tick |
| 166 | DM_PRESENT_SNAP | player | `=<n>`: present snapshots, a ring of n host textures (2 to 4; `1` = 2) the presents are copied to so the game's swapchain texture is free at once; `0` off (default: the profile's `present_snap`) |
| 167 | DM_PRESENT_UPSCALE | player | `metalfx` scales a picture smaller than its rectangle on the screen through MetalFX's spatial scaler; `off` (the default) scales it bilinearly |
| 168 | DM_PROBE | diagnostic | `=module:offset,…` (Mac only): puts a `brk` at each guest address and on every hit prints the thread, registers, strings they point to and a backtrace, then runs the original instruction |
| 169 | DM_PROBE_ALL | diagnostic | Set: probe hits (`DM_PROBE`) also print x9–x18 |
| 170 | DM_PROBE_DUMP | diagnostic | `=module:offset:length[:file]`: on the first hit of any probe, writes that range of guest memory to a file (default `run/<platform>/probe_dump.bin`) |
| 171 | DM_PROBE_FRAMES | diagnostic | Presented frame or inclusive `start-end` range in which guest probes print observations |
| 172 | DM_PROBE_HEAP | diagnostic | `=<name>,<start>,<size>,<free list>,<used list>`: hex offsets of the sead heap layout the probes' `!xN` heap walk uses (default Mario's `0,28,30,b0,c8`) |
| 173 | DM_PROBE_HEAPFRAME | diagnostic | `=<vtable offset in main>` (hex): the probes' heap walk treats heaps of that class as frame heaps (head +0xe0, tail +0xe8) |
| 174 | DM_PROBE_HEAPNAME | diagnostic | `=<text>`: the probes' `!xN` heap walk reports only hits on heaps whose name contains the text |
| 175 | DM_PROBE_HEAPRAW | diagnostic | Set: the probes' heap walk also prints the heap object's first 0x130 bytes |
| 176 | DM_PROBE_HEAPWORDS | diagnostic | Set: the probes' heap walk also prints each used block's first two words |
| 177 | DM_PROBE_LIMIT | diagnostic | Maximum printed hits per guest probe; 0 or absent leaves the count unlimited |
| 178 | DM_PROBE_POLL | diagnostic | `=<address>[+<length>]` (hex, 4 bytes by default, up to 8): a host thread spins on the bytes and on each change snapshots every thread's pc, lr and frames, for writes the watch misses |
| 179 | DM_PROBE_WATCH | diagnostic | `=<address>[+<length>]` (hex, 8 bytes by default): write-protects that host page and reports who writes these bytes, without a debugger |
| 180 | DM_PROBE_X2 | diagnostic | `=<bytes>` (hex): probe hits also dump that many bytes of the memory x2 points to |
| 181 | DM_PROGRAM_ID | switch | `=<hex>`: the program ID the host reports from `svcGetInfo(ProgramId)` (default: the profile's `program_id`) |
| 182 | DM_PSO_ARCHIVE | path | The folder of the per-game Metal 4 pipeline archive of pipeline bases (default `pso_archive/` beside `pso_user.tsv`); `off` keeps no archive |
| 183 | DM_PSO_BUNDLE | path | The pipeline archive made offline (`<GPU architecture>.mtl4a`, `prebuilt.tsv`), read only; the iOS app and Mac launcher set it to their `pso/` folder; `off` ignores it |
| 184 | DM_PSO_GPUS | switch | `build_ipa.sh`: the GPU architectures, comma-separated, to build the offline pipeline archive for (`none` builds none); unset, `g18p` for a profile with `pso_mtl4 on`, else none |
| 185 | DM_PSO_HYBRID | switch | `0`: a draw whose pipeline is not built yet waits for it instead of drawing with its shader pair's pulling pipeline meanwhile (on by default with the Metal 4 path) |
| 186 | DM_PSO_IOS_MIN | switch | `build_ipa.sh`: the minimum iOS version of the offline pipeline archives (default the SDK's major version); an older system cannot open them and builds the bases itself |
| 187 | DM_PSO_MANIFEST | path | The prewarm manifest to use instead of the profile's `pso_manifest.tsv`; `off` turns the prewarm off |
| 188 | DM_PSO_MTL4 | player | `0` builds render pipelines through the `MTLDevice` with no bases and no archive; `1` uses MTL4Compiler with the archive, hybrid pipelines and prebuild (default on on the Mac, the profile's `pso_mtl4` on iOS) |
| 189 | DM_PSO_PAIRS | path | The prebuild's second shader pair table (default: `pso_pairs.tsv` beside the shader map) |
| 190 | DM_PSO_PREBUILD | player | `0` turns off the prebuild of every known shader pair's pulling base into the pipeline archive (on by default); `tool` runs the prebuild alone on the Mac and exits |
| 191 | DM_PSO_PREBUILD_DEPTH | switch | `zero`: the prebuild tool (`DM_PSO_PREBUILD=tool`) builds bases for the near = 0 depth mode; the NSP script sets it from the profile's `depth_mode` |
| 192 | DM_PSO_PREBUILD_THREADS | switch | `=<n>`: the workers of the prebuild tool (`DM_PSO_PREBUILD=tool`; default: the performance cores less one) |
| 193 | DM_PSO_PREPARE | switch | `0` runs the prewarm in the background while the game starts, as without a window; `1` makes the first submission wait for the prewarm lists also without a window |
| 194 | DM_PSO_PREPARE_THREADS | switch | `=<n>`: the workers of the prepare step that builds the prewarm lists before the first frame (default: the device's active cores) |
| 195 | DM_PSO_PULL_ALL | diagnostic | `=1`: every draw that has a pulling pipeline draws with it, never with the pipeline for its vertex layout |
| 196 | DM_PSO_RECORD | path | `=<file>`: appends the shaders and pipelines used in the run to that file, for re-recording the prewarm manifest |
| 197 | DM_PSO_USER | path | The per-device list of shaders and pipelines built on the spot (default: `pso_user.tsv` in the parent of `DM_SAVE`) |
| 198 | DM_PSO_WAITLOG | diagnostic | `=1` logs each draw that waited more than 20 ms for its pipeline, with its shader pair and why no stand-in served it |
| 199 | DM_QOS_EDGES | switch | `=e1,e2`: the Switch priority edges of `DM_QOS_MAP` (default `44,59`) |
| 200 | DM_QOS_MAP | switch | `=1` maps guest thread priority to QoS class: ≤ 44 user-interactive, 45–59 user-initiated, the rest utility (off by default: every guest thread runs user-interactive) |
| 201 | DM_RENDER_SCALE | player | `0.5` to `1.0`: fixes the game's 3D views at that fraction of their size and turns its dynamic resolution off, for builds with a render scale stub; `1.0` (the default) keeps it |
| 202 | DM_RESOURCE_AOC | path | The add-on content folder the iOS build copies into the app's `aoc/` (empty for none); written by `gen_resources.py`, read by `stage_resources.sh` |
| 203 | DM_RESOURCE_CHAIN_H | path | Path of `dm/gfx/nvn/dmsh_chain.h`, written to `Gen/resources.env` by `build_ipa.sh`; the Xcode copy phase (`stage_resources.sh`) stops when the prepared shaders are not of its chain version |
| 204 | DM_RESOURCE_MARKER | path | A file under the RomFS, written to `Gen/resources.env` by `build_ipa.sh`, that the Xcode copy phase (`stage_resources.sh`) checks for before copying the game files |
| 205 | DM_RESOURCE_MSLDIR | path | Name of the shader library folder (`b-<chain>`), written to `Gen/resources.env` by `build_ipa.sh`; the Xcode copy phase copies the shaders to `msl/<name>` in the app |
| 206 | DM_RESOURCE_PSO | path | Folder of the offline Metal pipeline archive (empty for none), written to `Gen/resources.env` by `build_ipa.sh`; the Xcode copy phase copies it to `<App>/pso` |
| 207 | DM_RESOURCE_ROMFS | path | RomFS folder, written to `Gen/resources.env` by `build_ipa.sh`; the Xcode copy phase (`stage_resources.sh`) copies it into the app's `romfs` |
| 208 | DM_RESOURCE_SHADERS | path | iOS shader library folder, written to `Gen/resources.env` by `build_ipa.sh`; the Xcode copy phase (`stage_resources.sh`) copies it into the app's `msl/b-<chain>` |
| 209 | DM_RES_CHECK | diagnostic | `=1` prints the first 40 textures or buffers a shader reaches through its argument block that are not in the residency set (textures attributed to their parent allocation) |
| 210 | DM_ROMFS | path | The game's RomFS folder, mounted read-only as `rom` (default `$DM_ROOT/romfs`); the Mac launcher, the iOS app and the NSP script set it |
| 211 | DM_ROMFS_OVERLAY | path | `=<dir>[:<dir>…]`: RomFS reads look in these folders first, in order, and fall back to `DM_ROMFS` (for a modified copy of some files) |
| 212 | DM_ROOT | path | Workspace root (default `~/dm-work`): the host's and tools' default paths (RomFS, temporary storage, shader libraries under `build/cache/metal_shader_cache`, probe dumps) are under it |
| 213 | DM_RT | diagnostic | `0` leaves the thread that acquires the window on its QoS only, with no Mach time-constraint policy declaring the frame deadline (on by default; for power A/B) |
| 214 | DM_RT_COMP | switch | `=<ms>` fixes the computation the present thread's time-constraint policy declares; default `auto` re-declares it every 120 frames from that thread's per-frame CPU time (p90 and peak) |
| 215 | DM_RUMBLE | player | `0` turns game rumble off (on by default); launcher setting |
| 216 | DM_RUMBLE_GAIN | player | `=0..3` scales the rumble strength (default 1, `0` is silent); launcher setting |
| 217 | DM_RUMBLE_LOG | diagnostic | `=1` logs the game's vibration handle requests and, once a second, the values it sent, how many had no routed output and the peak amplitude |
| 218 | DM_SAVE | path | This run's save folder (must be set); the device save is `<DM_SAVE>_device`, and `pso_user.tsv` goes in its parent folder; the Mac launcher, the iOS app and the NSP script set it |
| 219 | DM_SCHEME_NAME | switch | Set by `build_ipa.sh` itself for xcodegen's `project.yml`: the Xcode scheme name, `DmIOS`, or `<display name> (<title ID>)` for a project prepared with `--prepare-xcode` |
| 220 | DM_SCREEN_MATCH | switch | `0` keeps the screen's refresh rate in fullscreen; by default a Mac screen whose rate is not a multiple of the game's frame rate switches to one that is (144 → 120 Hz) |
| 221 | DM_SF_TRACE | diagnostic | `=1` logs every request on the game's own HIPC client sessions that the host answers (`hle_sf.c`) |
| 222 | DM_SHAKE_G | switch | `=<G>`: on iOS, the acceleration beyond gravity above which a flick of the phone shakes the controller's six-axis sensor (default 1.5) |
| 223 | DM_SHARED_FONT | path | Font file served for every shared-font type except the Nintendo extension (default `$DM_FONT_DIR/standard.ttf`, then macOS's Arial Unicode) |
| 224 | DM_SHARED_FONT_EXT | path | Font file served for shared-font type 5, the Nintendo extension with the button icons (default `$DM_FONT_DIR/nintendo_ext.ttf`, made by `make_ext_font.py`) |
| 225 | DM_SHOW_FPS | player | `1` shows the frame-rate counter on the iPhone (frames put on screen per second, top left); at IPA build it sets `DMShowFPS` in `Info.plist`, which `Documents/env.txt` overrides |
| 226 | DM_SLOWFRAME | diagnostic | `=1` writes the per-frame timing breakdown to the log only for dropped frames (kept in a ring of the last 16 frames, judged 8 frames late) |
| 227 | DM_SPIN | switch | `0` makes the rewriter's spin gate return at once, so guest poll loops spin with no sleep; the gate stays (on by default) |
| 228 | DM_SPIN_LIST | diagnostic | `=1` makes `patch_nso.py` print every guest poll loop it found and sends through a spin gate |
| 229 | DM_SPIN_POLL | switch | `=<µs>`: how long a spin-gate wait polls before it sleeps with the yield back-off (default 2000; `0` yields on every pass) |
| 230 | DM_SVC | diagnostic | `=1` logs memory SVCs (`SetHeapSize`, `MapMemory`, `Map`/`UnmapPhysicalMemory`) with their addresses and sizes |
| 231 | DM_SYMCHECK | diagnostic | `=1` checks every hashed module symbol lookup against a linear search and logs a red line for each mismatch |
| 232 | DM_TEAM_ID | switch | Apple team ID for the per-game Xcode project, used when `--team-id` / `TEAM_ID` is not given; `build_ipa.sh` uses the placeholder `0000000000` (unsigned) when unset |
| 233 | DM_TEMP | path | Temporary storage folder (default `$DM_ROOT/run/platform/temp`); stand-in system data goes in `<DM_TEMP>_sysdata`; the Mac launcher, the iOS app and the NSP script set it |
| 234 | DM_TEST_FS_FAIL | diagnostic | `=write:<n>[:<errno>]` makes the nth save write fail with that errno (default ENOSPC), which refuses the save transaction's commit |
| 235 | DM_TEST_FS_FAILAT | diagnostic | `=<point>[:<count>][,…]` makes steps of the save transaction (`mountclone`, `reclone`, `guestname`, `renameback`) fail with ENOSPC |
| 236 | DM_TEST_GEOMETRY | test | Path of the native `t_geometry` executable; `test_dmsh_geometry.py` runs its native geometry emitter checks only when it is set |
| 237 | DM_TEST_KEYRACE | diagnostic | `=<n>` creates up to n (at most 512) pthread keys on a thread of its own while the host starts up |
| 238 | DM_TEST_KILL_AT | diagnostic | `=write:<n>` exits the process (`_exit(9)`) at the nth save write, imitating a kill mid-write |
| 239 | DM_TEST_LEAK_GPU | diagnostic | `=1` allocates and keeps a 1 MB shared Metal buffer every 100 ticks: a GPU memory leak on demand |
| 240 | DM_TEST_LINK_STALL | diagnostic | `=<start s>,<duration s>`: counting from the first present, pauses the display link at that point for that long, to check the present fallback |
| 241 | DM_TEST_NO_METAL4 | diagnostic | `=1` treats the GPU as one without Metal 4, as on a virtual Mac: the NVN layer starts only its classic part and drops every present |
| 242 | DM_TEST_PRESENT_LAG | diagnostic | `=<every n>,<ms>[,<in a row>][;…]` sleeps that long before every nth present (and the ones after it in the run): a slow frame on demand |
| 243 | DM_TEST_SWKBD_HOLD_MS | diagnostic | `=<ms>` (with `DM_KBD`) keeps the system keyboard up that long before `DM_KBD`'s text is returned, as a player typing would |
| 244 | DM_TEST_SWKBD_LAG_MS | diagnostic | `=<ms>` sleeps that long between the keyboard handing back its text and the game's thread getting the result, to check that auto-accept does not act early |
| 245 | DM_TEST_TRANSFORM_FEEDBACK | test | Path to the native t_transform_feedback executable used by the Python feedback tests |
| 246 | DM_TEST_UP_LEAK | diagnostic | `=1` keeps the old upload staging block instead of retiring it, as before the fix, to measure the leak |
| 247 | DM_TEST_UP_LOST | diagnostic | `=<batch index>` treats that batch of uploads as dropped, to exercise the re-upload path |
| 248 | DM_THERMAL_CAP | switch | `0` turns off the thermal cap, which holds the frame step at 30 fps while iOS reports a serious or critical thermal state (on by default) |
| 249 | DM_THR | diagnostic | `=1` logs each SVC (except `SleepThread`) with its first four arguments, and each `CreateThread` with entry, stack, priority and core |
| 250 | DM_THRCPU | diagnostic | `=<tsv path>[,<seconds>]` writes each thread's CPU time (100% = one core) and the total every interval (default 10 s); on iOS a relative path is under `Documents` |
| 251 | DM_TOUCH_HAPTICS | player | `0` turns off the light haptic tap when a touch control is pressed (on by default); launcher setting |
| 252 | DM_TOUCH_LOG | diagnostic | `=1` logs each touch-screen read with touch points (sample, finger, position, attributes) and each gesture entry, up to 500 lines |
| 253 | DM_UDC_SELFTEST | diagnostic | `=1` runs a start-up check of DontCare load and store on private depth-stencil and RGBA8 textures (clear, Load + DontCare, read back) and logs one result line |
| 254 | DM_UE_SHADERS | path | Folder of the Unreal shader code archives decoded by `uepak.py`, for `shader_split.py` (default `ue_shaders` beside the RomFS); needed when the RomFS has Unreal paks |
| 255 | DM_VK_CAPTURE | path | `=<dir>` (Mac) writes every SPIR-V module the game creates to `<dir>/<key>.spv`; the NSP script's Vulkan shader capture stage sets it |
| 256 | DM_VK_LOG | diagnostic | `=1` logs Vulkan object creation in the Vulkan-on-Metal layer |
| 257 | DM_VSYNC_HZ | switch | `=<Hz>`: rate at which a host thread fires the vi vsync event when the display link does not drive it (default 60) |
| 258 | DM_WATCH | diagnostic | `=<s>` dumps all threads after that many seconds (SIGALRM) and turns on the stall watchdog; off unless set |
| 259 | DM_WATCH_SAMPLE | diagnostic | `=<path>` (Mac): when the stall watchdog fires, samples the process for 1 s with `/usr/bin/sample` and writes the thread stacks to that path |
| 260 | DM_WATCH_STALL | diagnostic | `=<s>`: when the frame loop makes no progress for that long (default 15 with `DM_WATCH`), logs a red line, dumps the threads and exits |
| 261 | DM_WINDOW | switch | When set (to any value, `0` included) opens a Mac window with keyboard and controller input; unset runs headless with the guest on the current thread; the Mac launcher sets it |
| 262 | DM_XCODE_DERIVED_DATA | path | Xcode derived data folder for `build_ipa.sh` (default `$W/build/ios/xcode-dd`); the NSP script points it into the game's build folder |
| 263 | DM_XCODE_PROJECT_DIR | path | Folder of the per-game Xcode project that `build_ipa.sh --prepare-xcode` makes (default `$W/xcode`); the NSP script sets it |
| 264 | DM_XV_FILE | path | File where the attachment validity ledger keeps the keys it disabled after a violation, read at the next launch |
| 265 | DM_YIELD_BACKOFF | switch | `0` turns off the yield back-off; `=<cap µs>[:<start µs>]` sets its sleep cap and the run of yields after which it starts (default 250:2000) |