Texture resources and mip chunks
A Texture resource (0x6bde20ba) supplies dimensions, format and mip sizes; its pixels live in the chunk named
by its header. The stock install holds 61,618 distinct texture headers (78,566 resources), every one of them 180 bytes;
the 16-byte resource metadata is 0x0c, the header’s flags as a u32, and two zero words in all of them.
Proven · all stock texture resources ReSkate reads an extended 180-byte header for resource-metadata versions 12 and 13.
Sourced · ReSkate
Little-endian.
| Offset | Size | Type | Field | Confidence | Notes |
|---|---|---|---|---|---|
| 0x0 | 4 | u32 | compressed offset of the mip 1 block | Observed | Byte offset in the chunk CAS range of the 64 KiB block that holds the first byte of mip 1; zero in 21,978 of 61,618 stock textures |
| 0x4 | 4 | u32 | compressed offset of the mip 2 block | Observed | As the word at 0, for mip 2 |
| 0x8 | 4 | u32 | texture kind | Observed | 0 2D; 1 cube; 2 volume; 3 array |
| 0xC | 4 | u32 | format ordinal | Sourced | |
| 0x10 | 4 | u32 | unknown | Unknown | Zero in all 61,618 stock textures |
| 0x14 | 2 | u16 | flags | Sourced | Only the values 0x0000, 0x0001, 0x0009 and 0x0020 occur; the resource metadata repeats them |
| 0x16 | 2 | u16 | width | Observed | |
| 0x18 | 2 | u16 | height | Observed | |
| 0x1A | 2 | u16 | depth | Observed | |
| 0x1C | 2 | u16 | slices | Observed | |
| 0x1E | 1 | u8 | mip count | Observed | |
| 0x1F | 1 | u8 | first mip | Sourced | |
| 0x20 | 1 | u8 | streaming mip floor | Inferred | Never below the first mip (byte 31): equal in 60,033 stock textures and 1 to 5 larger in 1,585 |
| 0x21 | 1 | u8 | repeated mip count | Proven | Equals the mip count in all 61,618 stock textures |
| 0x22 | 6 | bytes | unknown | Unknown | |
| 0x28 | 16 | GUID | pixel chunk GUID | Observed | |
| 0x38 | 60 | u32[15] | mip byte sizes | Observed | |
| 0x74 | 4 | u32 | chunk size | Observed | |
| 0x78 | 4 | u32 | resource name hash | Proven | djb2-XOR of the lowercase resource name in all 61,618 stock textures |
| 0x7C | 4 | u32 | h64 high half | Unknown | 19,803 distinct values over 25,719 distinct names; not a hash of any part of the name |
| 0x80 | 52 | bytes | texture group region | Observed | Includes the group name; not all trailing bytes have an established meaning. |
| Ordinals | Pixel storage | Confidence |
|---|---|---|
18, 20 |
RGBA8, four bytes per texel | Sourced · ReSkate |
23, 24 |
BGRA8, four bytes per texel | Sourced · ReSkate |
54–57 |
BC1, eight bytes per 4×4 block | Sourced · ReSkate |
58, 59 |
BC2, sixteen bytes per block | Sourced · ReSkate |
60, 61 |
BC3, sixteen bytes per block | Sourced · ReSkate |
66, 67 |
BC7, sixteen bytes per block | Sourced · ReSkate |
Block-compressed levels occupy ceil(width/4) * ceil(height/4) * block_bytes, with at least one block on each
axis. Levels halve each dimension down to one. Sourced · ReSkate
Arrays and cubes store all images of one mip together, followed by all images of the next mip. A downsample
comparison validates this arrangement on 559 decodable layered textures. Their chunk size is
sum(mip_sizes) * layer_count. The nine measured volume textures have one mip; its size describes the whole
volume, including a 128³ BC7 texture occupying 2,097,152 bytes. Observed
The kind word holds only 0 (59,220 textures), 1 (21), 2 (145) and 3 (2,232). The two words at offset 0 are the byte
offsets, inside the chunk’s CAS range, of the 64 KiB blocks that start the data of mips 1 and 2 (the block that
contains the first byte of the mip, where the mip does not begin on a block boundary): in all 39,632 textures where the
words are not both zero, each names such a block; they are zero in 21,978 textures, among them 16,198 whose chunk is
a single block. Proven · all stock texture resources Why they are zero in 5,213 textures whose chunk has several
blocks is not established. Unknown
The low 32 bits of the h64 at offset 120 are the djb2-XOR hash of the texture’s lowercase resource name in all
61,618 headers (25,719 distinct names), the same hash resource names
use elsewhere. Proven · all stock texture resources
When first_mip > 0, the bundle manifest can describe only the lower-resolution tail of a chunk, at a logical
offset corresponding to earlier mip bytes. The TOC chunk table locates the whole mip chain, including all images.
Treating the manifest tail as a complete texture gives a size mismatch rather than evidence of corrupt pixels.
Observed
Across 987 texture references from fifteen bundles, the depot reference’s second GUID resolves an EBX TextureAsset or TextureArrayAsset and its Resource field resolves a Texture resource. Only 353 of those assets/resources are in the material’s own bundle; 634 are found in other install bundles. The streamable texture-set bytes contain neither the resource id nor the referenced GUID in that sample. Observed
All 5,112 normal textures in a measured stock material census use BC7; masks use BC1 or BC3. This is a content measurement, not a requirement that a normal map use BC7. Observed
The texture streamer uses h64, not merely the resource name or GUID, as identity. See
resource identity and
texture-handle limits.
The mip-major arrangement is measured; cube face orientation and ordering are not established by that check. Unknown