2026-11-01 claude/gfx-nvn-api-2026-11-01-r2: the 14 missing NVN entry points, refused MSAA branches, ACNH program hash¶
Batch 2026-11-01-r2, orchestration gfx-nvn-api. Mac (Apple M5), local only.
NVN entry points (gfx/src/nvnapi/, api_cmd.c, api_device.c, api_program.c, api_texture.c)¶
names.txt gains the 14 names titles look up (Animal Crossing 13, Mario Kart 8 Deluxe nvnDeviceWaitForError), in the same commit as their prototypes
(nvn_protos_ext.h) and implementations: NVN 537 of 537 entry points implemented.
| entry point | behaviour |
|---|---|
nvnCommandBufferBind{UniformBuffers,StorageBuffers,Textures,Images,SeparateTextures,SeparateSamplers}Deferred |
bind like the plain variants (arrays copied into the recording) |
nvnCommandBufferOverrideSubtileSize, nvnCommandBufferSetZCullZF32CompressionEnable |
hints, no-ops (Metal's tile renderer chooses tile size and depth compression) |
nvnProgramGetSubtileSize |
0 x 0 (the driver's choice) |
nvnCommandBufferSetControlMemoryCallbackEnabled |
no-op (control memory is host-allocated) |
nvnCommandBufferSetProvokingVertexMode |
mode kept, a non-zero mode reported once; flat outputs keep Metal's provoking vertex |
nvnDeviceSetAutomaticCheckpointsMask |
no-op like the other checkpoint setters |
nvnDeviceWaitForError |
returns "no error" at once; calls counted, first one logged |
nvnTextureBuilderGetViewOffset |
same computation as nvnTextureGetViewOffset, from the builder's description |
The parameter lists are inferred from the neighbouring entry points of each family (no public header has them; nxnative lists them as names only). An xref scan of Animal Crossing's main module (string -> loader -> GOT slot -> function-pointer global -> readers) shows the loader stores the 13 pointers and nothing reads them back, so no call site depends on the exact lists.
tools/gen_a32_nvn.py now reads nvn_protos_ext.h as well: runtime/src/a32/a32_nvn_sigs.inc has a row for all 537 entry points (was 477), so 32-bit titles
get marshalled stubs for every newer entry point (MK8D's "no host implementation or signature for nvnDeviceWaitForError" is gone).
Refused copy / Downsample branches (mtl_replay.m)¶
xcopy_draw, a generic copy pass, replaces the three refusals: copy_t2t_draw (depth/multisampled/3D copy with another size or format), resolve_int (integer
Downsample across formats / of an array layer) and resolve_generic (depth <-> float, integer <-> float Downsample). It reads the source with read() (2D,
array, 3D, multisampled, multisampled array or their depth counterparts; cube faces as layers) at the scaled pixel and writes colour or [[depth(any)]]:
multisampled destinations per sample, a float colour Downsample averages samples, anything else takes sample 0 (as the 2D engine); integer <-> float by value,
depth <-> integer by bits. Draw copies cover every layer / depth slice of the region (one draw each), and copies between different sample counts no longer
reach Metal's blit (which aborts).
Animal Crossing "program hash 0x3 is not a shader hash"¶
A host layout bug, not the guest double-job race: diagnosed on the title, the value 0x3 sat in prog_t.hash[4] (object offset 0x88) where SetShaders had
stored 0. The title's NVNprogram is followed by another object at +0x88 at the latest; prog_t assumed 152 bytes, so Initialize / Finalize zeroed and
SetShaders wrote the neighbour's memory, and the neighbour's writes became stage hashes. Stage hashes now live in a host table keyed by program address
(gfx_program_hashes), used by BindProgram and the transform feedback / tessellation setters; the object mirrors stages 0..3 only (below +0x88, static
assert) for programs copied by value; a scribbled object is reported once. Possible earlier symptom: with a compute program (stage 5, +0x90) SetShaders would
have overwritten that neighbour.
Tests¶
t_nvn_ext.c (every name resolves, BindTexturesDeferred draws, view offsets, getters), t_nvn_ext_prog.c (no write past +0x88, scribbled and by-value
programs bind), t_msaa_copy.c (7 readback cases).
Status¶
See integrators/claude-gfx-nvn-api-2026-11-01-r2.md.