A converted game fails at launch on the first system function that no
built library exports, one function per run. tools/import_audit.py reads
the registry written by relinker --registry and classifies every imported
NID in one pass:
- implemented: a built library exports it
- stub: exported, but the whole function calls NotImplemented_nid_no_patch
- absent: no built library exports it, so the loader fails
- module: the import names a file the title ships itself
Exports are read from the built .prx files (ELF dynsym and PE export
table), the same view the loader has. Stubs come from the source tree
through tools/progress.py, and NIDs through tools/nid_names.py. The report
also lists needed libraries without a file and imports found only in a
different library than the one they name. --names adds names from an
aerolib.csv file and never downloads one; --json writes the full result
stamped with the repository commit.
The test builds ELF and PE libraries byte by byte, checks that every
reference lands in exactly one class, and pins the NID of
sceMsgDialogProgressBarSetValue (wTpfglkmv34) as an external anchor.
Registered in CTest as import_audit.
The segment filter dropped every header in the PT_LOOS..PT_HIOS range,
which includes PT_GNU_EH_FRAME. The unwinders find the executable's
unwind tables through that header, so no C++ exception thrown in the
main executable could be caught on Linux.
The header is kept only when the output program header table still fits
in the input's table; otherwise it is dropped as before, with a warning.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HeC9bA3n74TzJRYv9AgBE8
The retry that waits for a target to leave NtContinue, NtContinueEx or
libwinpthread-1.dll had no bound, so a target that stayed there made
sceKernelRaiseException spin forever. It now throws after 1 s. A new
guest_raise_exception phase keeps a thread inside NtContinue by
continuing a context that calls NtContinue again, and checks that the
raise throws and that the handler did not run.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The console's DCC of a single-level 4-byte SW_64KB_R_X surface is
ceil(W/512) * ceil(H/512) * 4096 bytes, 49152 for 1920x1080, but the
driver stored and read one key per 256 surface bytes (34560).
PPSA26344 retiles its render DCC into the displayable copy it
registers (cs_dcc_retile_32bpp); a retile of the stale tail gives the
mixed keys PPSA12544 stops on.
DccKeyCount gives that extent. Color target and storage image key
stores cover it when the DCC is pipe-aligned (CB_COLOR_ATTRIB3 bit 30,
T# word 6 bit 19), whose CB keys reach its last meta block, and throw
where it is not writable; unaligned DCC keeps one key per 256 bytes,
as do texture and color target key reads. DisplayBufferKeys reads the
display DCC over the extent, presents only when every key agrees,
names the first differing key's pixels and checks a pending image
against those keys.
Mode 0 of CB_COLOR_CONTROL turns color writes off, but a draw with a
written color target and this mode was skipped as unsupported. Count no
export as written when the mode is disable, so the draw renders without
a color attachment like the existing attachment-free path, and accept
the mode with any ROP3, which does not apply while writes are off.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The vertex entry set only the vertex and instance index VGPRs, leaving
the NGG merged wave info SGPR s3 at 0. NGG shaders build EXEC from it
(s_bfe_u64 exec, -1, <count in bits 16..22>), so Mesa's NGG vertex
shaders ran with an empty EXEC and rasterized nothing.
Each host invocation on the vertex path is one vertex of a full wave:
when the user data starts at s8 or later, set s3 to the wave size as
both vertex and primitive count, with wave index 0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Store: negative, -0, NaN (quiet and low-payload), +-Inf, overflow to the
largest finite value, truncation and small-float denormals. Load: Inf,
denormal and largest finite codes. Values measured on gfx1035.
Co-Authored-By: Claude <[email protected]>
Format 43 packs R as a 10-bit and G and B as 11-bit unsigned floats, which
Vulkan has no format for. Keep it in an R32_UINT image like the other
packed formats without a host equivalent, and convert texels in the shader
on image loads and stores; sampling it still throws.
When one guest sampler is paired both with an image that needs point
filtering (sint, depth-bits or converted format) and with an ordinary
image, ResourceMaterializer::Apply appends a point-filtered copy of the
sampler after the original samplers. The resource snapshot only holds
the original samplers, so DescriptorBindingBuilder::Populate threw
"guest sampler index is out of range" for the copy, both in the sampler
binding and in the unnormalized-coordinate check.
SamplerResource::copyOf records the sampler a copy was made from, and
the guest sampler descriptor of a copy is read from that sampler; the
point-filter rewrite of word 2 still applies to the copy. The field is
part of the disk cache encoding: cache format version 8.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The integer emulation of the round-to-nearest-even float-to-half
conversion is exact but costly: a compute shader with about 3600
conversions never finished compiling on NVIDIA. When the device enables
shaderFloat16 and guarantees shaderRoundingModeRTEFloat16,
shaderDenormPreserveFloat16 and shaderSignedZeroInfNanPreserveFloat16,
it advertises Float16, RoundingModeRTE and DenormPreserve, and the
recompiler emits OpFConvert under the 16-bit RoundingModeRTE,
DenormPreserve and SignedZeroInfNanPreserve execution modes instead.
NaNs keep the emulated quiet NaN with the high payload bits. Devices
without these guarantees keep the emulation.
Graphics validation accepts the RoundingModeRTE, DenormPreserve and
SignedZeroInfNanPreserve execution modes for 16-, 32- and 64-bit floats,
so vertex and pixel shaders with a native conversion still draw.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
On GFX10.3 to GFX11.7, ACO lowers a subgroup-scope OpReadClockKHR to
s_getreg_b32 of SHADER_CYCLES, 20 bits zero-extended to 64, so s_memtime
wrapped every 2^20 cycles and went backwards. Detect those families from
the RADV device name and read the device clock there instead.
Fixes#985
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Resolve ASCII case differences in guest paths and mount aliases while preferring exact names and rejecting ambiguous fallback matches. Preserve new filenames and host roots. Five filesystem tests pass; Skyrim now loads its INI and shader archives, initializes Vulkan and uploads intro textures instead of dereferencing null shader metadata. Written with AI assistance.