The base import keeps its MIT license and third-party code the licenses THIRD_PARTY_NOTICES.md lists. The README's license section and AGENTS.md point to it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening and closing the menu, moving the cursor, changing a value, pressing an item, cancelling a dialog and changing tabs play the game's system sounds (Plus menu open and close, cursor, decide, cancel, tab move), read from the user's RomFS at the first use and decoded from BWAV (DSP-ADPCM or PCM16, 48 kHz) in runtime/menu_sound.c. They are mixed over the game's output in the audio callback with up to eight voices started without locks. The Sound tab gets a Menu sounds volume (menu_sound_volume, 0 to 100, default 80, under the output volume). A RomFS without the files stays silent.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kokiri Forest drew black, in tiles and in shadowed and indoor areas, where shaders read light, probe and instance data through pointers they load from other buffers at an index (a phi of a pushed pointer and a loaded one, a pointer spilled to local memory): those reads returned 0. Translator patch 0030 keeps such accesses global, with a new first source naming the table, and the SPIR-V back end looks the address's 4 KiB page up in it and loads through the buffer device address it gives (PhysicalStorageBuffer64). runtime/vk_gpa.c keeps the table: two levels over the 40-bit GPU address space, page entries naming immutable records, records reused only after the GPU finished with them. Imported pools, their VRAM mirrors and the pages of virtual pools go in it; pools in it are destroyed after the submissions that may still read them. The last failing compute program needed MATCH.ALL (subgroupAllEqual) and the aggregated shared increment ATOMS.POPC.INC, now lowered in AmpereLowering.cs; Kokiri Forest translates without a failure.
NX2NAVI_GPA=0 turns the table off and NX2NAVI_GPA_EMPTY=1 keeps it empty. A first try synced every VRAM mirror at each table reader's draw, which overwrote what the GPU had written into them and made the black worse; mirrors sync only when bound.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ocarina's NVN2 compute programs reach more than 16 buffers through their pushed pointers and pointer tables; past the 16th the translator found no slot, dropped the store, and its loop then read the next node of a node it had just removed, so every later global access in the block stayed global and the whole program failed with "Invalid storage kind GlobalMemory". Ten compute programs of Kokiri Forest were skipped on every dispatch and retried on every one, which also cost 10-25 ms frames. Now one program still fails (an Ampere MATCH instruction the lowering does not handle). NX2NAVI_XLATE_KEEP=2 keeps every translated job with its code for running the translator by hand.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each file that contains copied code names its copyright holder and license and points at THIRD_PARTY_NOTICES.md; zlib code keeps its full notice and the mark that it was altered. Comments and probe text only.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments say what the code does and why, docs/maxwell.md keeps the Maxwell facts, and fetch_refs.sh clones only the checkout the build reads. Code is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The issue forms ask for the version from the settings menu title and the log from logs\nx2navi.log. The guides and the sample settings cover the features this port has. The README lists the frame rate limits and widescreen and gets a Screenshots section for images attached on GitHub.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Patch 0028: when GlobalToStorage finds no base for a global access whose address is a constant buffer load at a
non-constant offset, every table entry that offset can reach becomes a candidate of the multi-target helper ({u64
address, u32 size} entries 16 bytes apart: C to C + 240 for E + C, each constant for phi(constants) << 4), and the
helper uses the one whose range holds the address. Ocarina's NVN2 compute shaders pick c0 storage slots this way;
unresolved compute accesses fell from 445 in 21 shaders to 243 in 17 over a Kokiri boot.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The patch sets of recomp/patches-v111.txt read the game's 2560x1440 picture and 1920x1080 scene sizes from the patch page, give every 16:9 camera the picture's ratio, squeeze the UI's full-screen projection into the middle 16:9 (fades and the menu backgrounds that redraw a capture stay full width) and pillarbox movies. runtime/widescreen.c sets them up from the new Screen tab row Widescreen (NX2NAVI_GAME_ASPECT: 16:9, window, 21:9 or 32:9, at the next start).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Patch 0027: a float colour output turns NaN into 0 and clamps the rest to +-1e30 before it reaches its target, so one
bad texel cannot spread through bloom, blur and downsample passes as black or white blocks; integer targets keep their
bits. Task and mesh shaders start their mesh and primitive counts at 0 behind a barrier, and a task emits at most one
mesh group per thread, so a task that culls everything no longer launches what the shared memory last held. Without a
gamepad SDL can open, the first connected XInput controller (slots 0-3, empty slots asked once a second) is read
directly. Kokiri Forest: 60 fps, GPU 5.5 ms a frame, unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A diagnosis for native ultrawide: each nvnTextureBuilderSetSize2D of a 16:9 size of at least 320 wide logs its
caller and the caller's caller (up to 200 lines).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Colour group (profile, brightness, contrast, saturation, gamma) is gone from the Screen tab; values left in
nx2navi.ini are no longer applied, since the menu could not undo them.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ocarina steps its game by the clock (the same frame-numbered walk covers half the distance at 120 fps), so in a build
without the fps60 and realtime patch sets the pacer holds frames to the frame limit alone: any rate from 30 to 1000,
the monitor's rate, or unlimited (164 fps average in Kokiri Forest). The menu always shows the row, with 165, 240 and
Unlimited added. NX2NAVI_PACE_HZ sets the pacer's rate for tests.
A compute pipeline is compiled outside the pipeline lock, and one compile serves the replay and the boot prebuild
alike; the prebuild uses half the CPUs. The guest waits at most NX2NAVI_PREWARM_WAIT_MS (3000) for the boot prewarm,
which then goes on in the background (a cold start waited 9.8 s). NX2NAVI_TEST_PAD_AT attaches the test gamepad late
and presses it, to test a controller switched on in play.
README, docs/architecture.md, docs/controls.md and AGENTS.md describe the Ocarina build.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every connected gamepad is kept open and rescanned each second, and the game reads the one pressed last: taking only
the first one SDL listed left the game deaf when that was a virtual or idle device. SDL may deliver gamepad presses in
the background, since it cannot see the Win32 window's focus; the keyboard stays gated on it. The log notes each
gamepad's first press. The version line, the window title and the Discord status say the project's name.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
NVN2 compute banks get the dispatch's group counts in bytes 0-0xb, for direct and indirect dispatches; the fog pass
after the integration divided by them. Indirect mesh draws read NVN's {count, first} record as {x, y, z}, so y = 0
drew nothing: each now draws from a ring entry holding {count, 1, 1}, copied on the GPU before the draw. An empty set 1
no longer leaves set 0 pushed with 0 bytes. Compute stages with subgroup operations whose width is a whole number of
subgroups require full subgroups.
The texture pool refresh fell from 3.1-3.7 ms to 1.0 ms a frame in Kokiri Forest: slots with the same descriptor,
address generation and entry generation share one lookup (about 14,500 of 15,000 refills a frame), and registering a
texture and view identical to what the slot holds keeps its resolution. Under 20 GiB of VRAM, ASTC textures are
encoded to BC3 by default (Kokiri: 15.9 to 8.2 GiB, same GPU time). The pool log counts refills by cause and what
invalidates them; frame dumps write BC textures as raw blocks and print a storage buffer's backing span; a profile with
NX2NAVI_PROFILE_FRAMES is written when its window ends; the alpha test logs once that it is not applied.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Patch 0023 turns a global RED or ATOM .F32 add, which the translator dropped, into a compare-and-swap loop with a float
add once GlobalToStorage knows its buffer; the light and fog accumulators of Ocarina use them, and their loss lit
Kokiri Forest's fog as if nothing shaded it. Patch 0024 reads RED's 20-bit offset as signed, as ATOM already did.
Patch 0025 keeps the block after a CAL as its successor, so code after a call is no longer dropped. Patch 0026 keeps
ballot, shuffle and vote operations where they are, so they see every lane. build_xlate.py now expects 25 patches.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A CPU-written texture slot could resolve to a released entry and upload from storage the game was already freeing,
which crashed in tex_bl_copy during the pool refresh. Each released entry now records the registration serial at
release, and slot_resolve treats slots registered at or before it as stale.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The translator dropped 36113 global accesses per Kokiri boot (loads read 0, stores and atomics deleted); 837 remain.
AmpereLowering computes a predicated LEA's carry sum unconditionally, so a base like c[0][0x110] no longer reaches the
address as a phi; the edge AA's tile list is written and its blend weights follow the edges. Patch 0022 extends
GlobalToStorage: a constant-buffer base inside a sum of terms, and buffers reached through a pointer the program loads
from another storage buffer at a constant offset (the pointer tables Ocarina's vertex, pixel, mesh and compute shaders
read, also through register spills and phis). Such a buffer is listed with its outer buffer and offset, and the runtime
binds it at the address read from guest memory when the stage is bound (vk_exec_draw.c ptr_addr). The fog injection's
64x36x96 volumes now hold in-scattering.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The post pass stores the square root of each channel, so the stand-in for Ocarina's untranslatable upscaler now
filters those values and squares them in its compute pass (shaders/fallback_tonemap.spvasm, vk_tonemap.c) instead of
decoding them with the sRGB curve, which darkened mid-tones and lifted the darkest values; the pass is compiled in again,
its round-24 device loss having been the push descriptor call outside the recorder. NX2NAVI_FALLBACK_EXPOSURE is gone.
AmpereLowering emitted SURED as 0xeb48, which matches no Maxwell instruction, so the translator skipped every image
reduction; with 0xeb58 the edge AA's blend-weight pass writes its image. The translator's own warnings go to res.json
notes, and shader dumps are named by program serial so they match the frame dumps' program numbers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A texture slot whose content the CPU writes now follows another image at its address only when that image differs in
swizzle alone or holds GPU-written content; Ocarina reuses freed glyph atlas memory for captions of another width, and
following the older image drew the Basic Controls screen's "Target" with the wrong row length. Mesh-shader pipelines
are built on the workers and recorded in pipeline-keys.bin (version 4 with the task stage; version 3 files are
converted) instead of stopping the frame for 0.26-0.51 s. The ASTC decoder reuses one scratch buffer per upload command
buffer, and CPU-provided textures up to 32 MiB are sub-allocated unless the driver requires dedicated memory, which
takes the scene-load frame from about 1.25 s to 0.7 s. The feedback scan looks only at bound texture slots instead of
the bindless pool arrays, per-draw knob lookups are cached and the texture address buckets grow to 65536, so Kokiri
Forest's replay falls from about 16 to 7-9 ms a frame and the forest holds 60 fps. A float clear of zero on an integer
image now clears instead of being skipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Screen tab hides Game resolution when the build has no output and scene patch sets, and the resolution code no
longer grows the memory pool for it. FSR sharpness now also runs when the game image is shrunk to the window, which is
always the case for Ocarina's 2560x1440 picture at 1920x1080, and the overlay drops NX2navi's fixed 3D scene size. A colour
profile set in nx2navi.ini now applies without the menu. The Game tab hides the frame limit in builds without frame-rate
patch sets and lists the game languages the RomFS ships, adding Polish and Brazilian Portuguese. 5.1 sound is reported to
the game's virtual output device. The remap page describes each button as Ocarina's controls screen does, gives each
D-pad direction its own description and drops NX2navi's shake row; the keyboard defaults follow Ocarina (Shift dashes on A,
Ctrl puts away on B, O and N for the ocarina and Navi, middle mouse resets the camera). docs/controls.md is updated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The texture pool descriptors are now a ring of sets, one per submission, brought up to date from a change log, and the first submission of each frame waits for its GPU work before the game goes on: the GPU ran late and part of a frame read data of the next one, and distant characters drew NaN that bloom spread over the frame. The window acquire also waits for the image's previous frame. Function locals start at zero unless DLAA is on, which removes the per-warp light tiles on the Great Fairy Fountain floor and Link's dark, speckled look. Texture slots follow only live entries of their own target, so the volumetric fog gets its 3D volume. The pool refresh walks only the slots that changed.
The translator implements PRMT (patch 0021), which it only logged before; the button prompts render again. HFMA2.RELU no longer depends on it, HMMA.F16 rounds once and HMMA.F32 is lowered, checked against GPU vectors with a new Maxwell warp emulator.
The frame dump gains a re-arming white-frame trigger, a trigger on a depth target's first pass, NaN pixels in magenta, image handles and view targets, and depth copies of sampled depth textures.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The names are NX2NAVI, NX2navi or nx2navi: the settings prefix (NX2NAVI_*), the ini file
(nx2navi.ini), the shader translator (nx2navi_xlate), the Windows resources, the installer and the docs. The 8-byte
file magics keep their size (NX2NSANS, NX2NSPRG, NX2NSPRP, NX2NPKEY, NX2NRFS1), so caches and the RomFS index from
older builds are not read. cfg.c and the settings pages took the prefix length as 5; it now follows the prefix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The NVN2 front end and the SM86 to Maxwell shader lowering (tools/xlate/AmpereLowering.cs, mesh and task stages,
bindless texture pools, BRX jump tables, the NVN2 compute c0 layout) with four translator patches (0017-0020) bring the
opening of the game to 58-60 fps on the Vulkan renderer.
This round fixes the haze: SM86 IPA is lowered as a plain Maxwell IPA.PASS (texture coordinates were corrected for
perspective twice); LDSM, TXD, both F2IP byte forms, HMMA, MOVM and HFMA2.RELU are lowered and spill mode has eight
uniform register groups; conditional rendering keeps the newest counter report per address and treats a report as
pending until its value is in guest memory, so occlusion tests and the depth clears around the depth copy behave; and
the upscaler stand-in decodes the post pass's sRGB picture before writing the linear target. Tensor-core programs keep
the stand-in unless NX2NAVI_NATIVE_TENSOR=1, because their lowering does not match the hardware yet.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>