Skip to content

Enhanced texture dictionaries

RAGETexturesApplies toGTA V

Enhanced YTD resources use version 5. Drawables can embed dictionaries with the same texture representation. A dictionary has a sorted array of name hashes and a parallel array of texture pointers; some embedded entries have null pointers. Proven

The structural census reads all 89,813 version-5 YTD copies and embedded dictionaries in every accepted Enhanced drawable resource, with no failures. Four YTDs with other layouts (one version 2 and three version 13) and fifteen other-version YDRs are excluded. Every decoded texture’s computed mip/slice byte length equals its stored block count times block size. The proven record and storage claims below have this scope; texture lookup examples are separate observations. Proven · version-filtered full-install census

Texture dictionary64 bytes38% known
ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x016bytesresource baseSourced
0x1016bytesunknownUnknown
0x208pointersorted name hashesProven
0x282u16hash countProven
0x2A2u16hash capacityProven
0x2C4bytesunknownUnknown
0x308pointertexture pointersProven
0x382u16texture countProven
0x3A2u16texture capacityProven
0x3C4bytesunknownUnknown
Enhanced texture128 bytes33% known

The first 80 bytes form the texture base also used by shader references.

ProvenObservedSourcedInferredUnknownNot described
OffsetSizeTypeFieldConfidenceNotes
0x08bytesunknownUnknown
0x84u32block countProven
0xC4u32block sizeProven
0x104u32flagsProven
0x144bytesunknownUnknown
0x182u16widthProven
0x1A2u16heightProven
0x1C2u16depthProven
0x1E1u8dimensionProven1 2D, 2 3D, 3 cube
0x1F1u8SGA buffer formatProven
0x201u8tile modeProven
0x211u8unknownUnknown
0x221u8mip countProven
0x235bytesunknownUnknown
0x288pointertexture nameProven
0x308bytesunknownUnknown
0x388pointertexture dataProven
0x404u32usage wordProven
0x4460bytesunknown tailUnknown

Texture data contains every mip of every slice, largest mip first. Each mip occupies whole compression blocks; computed sizes from dimensions, format and mip count match blockCount * blockSize in the inspected format census. Mip sides halve down to at least one texel. Proven

SGA format numbers partly resemble DXGI but use their own numbering. The table gives selected decoded codes, not an exhaustive list of all possible formats. Observed

Code Format Confidence
0x1C / 0x1D RGBA8 UNORM / sRGB Observed
0x38 R16 UNORM Observed
0x47 / 0x48 BC1 UNORM / sRGB Observed
0x4A / 0x4B BC2 UNORM / sRGB Observed
0x4D / 0x4E BC3 UNORM / sRGB Observed
0x50 / 0x51 BC4 UNORM / SNORM Observed
0x53 / 0x54 BC5 UNORM / SNORM Observed
0x57 / 0x5B BGRA8 UNORM / sRGB Observed
0x5F / 0x60 BC6H unsigned / signed float Observed
0x62 / 0x63 BC7 UNORM / sRGB Observed

CodeWalker’s Gen9-to-Legacy conversion can be lossy: R16 UNORM becomes A8, and unknown codes can fall back to A8R8G8B8. A converted texture’s format is therefore not evidence for its original Enhanced storage format. Sourced · CodeWalker

CodeWalker’s BC5 decoder (DDSIO.DecompressBC5Block, at commit 485d56b) decodes the second channel into red with the first channel’s endpoints and leaves green at 255. BC5 normal maps, about 2% of the city’s normal maps, then decode as a flat y = +1, z = 0 normal; an independent BC5 decoder gives the correct channels. Observed

Texture parenting comes from live gtxd.ymt RBF data, mph4_gtxd.ymt and enabled GTXD_PARENTING_DATA XML. CMapParentTxds/txdRelationships records name child/parent dictionary pairs; lookup can walk a parent chain. Observed

CodeWalker also searches resident dictionaries after local and parent dictionaries. Its resident initialization loads mapdetail, then vehshare, with later duplicate names replacing earlier resident entries. Sourced · CodeWalker

Sampled vehicle-mod fragments obtain shared vehicle_generic_detail2, detail2_normal, detail_spec and genericmud_car textures from vehshare; parent relationships alone do not supply them. Observed

Is dimension 2 a volume or a cube?

The layout above reads dimension 2 as 3D and 3 as cube. CodeWalker, ragekit and rage-formats all read 2 as cube and 3 as 3D, and ragekit writes its volume view kind (0xA3) only for dimension 3. Sourced[CodeWalker, ragekit, rage-formats] Those readers share CodeWalker’s tables, so they are one source, not three. The single volume texture of the install, cloudnoisevolume in graphics.ytd, would decide it from its depth and dimension bytes; whether a volume’s mips halve its depth and how its slices are ordered are open with it. Unknown

Which unresolved textures have additional ownership rules?

Sampled blank and Tulip mesh_3a/mesh3_normal references remain unresolved after the resident lookup described above. They do not establish permission to synthesize a replacement texture. Unknown