Textures *.tex Files
This section discusses the "\Textures\*.tex" files in the "Texture.mpq" file. MPQ Patches to this file are located in the "base" subdirectory of the Diablo 3 "MPQs" directory. Please see the MPQs section for general MPQ information and basic information about how files are encoded.
Textures File Structure
The Textures files contain images; and as the name implies, some, but not all, of these are used for textures. My interest in this file had nothing to do with 3D modeling, but rather with extracting the 2D images that are used to display items in the inventory and in the character screen. Each Textures file can contain multiple images, and these images can be encoded in a variety of ways.
The Textures file structure is made up of three header parts (not including the 0x10 byte MPQ header): the TexHeader, the TexEntries, and the TexAtlasEntries. These headers are followed by the image data which is of variable size. Here are the details of the TexHeader structure:
|struct TexHeader||// sizeof 0x368|
|0x000||DWord mpqId;||// MPQ Id|
|0x004||DWord unknown1;||// ???|
|0x010||DWord dwPixelFormat;||// format of the pixel data|
|0x01C||DWord nMipLevels;||// also used for 0-sized mips|
|0x020||DWord unknown2;||// ???|
|0x028||TexMipLevel pMipLevels;||// array of 31 TexMipLevels|
|0x120||DWord unknown3;||// ???|
|0x124||DWord dwLoadType;;||// frame header size: 1 -> 0x10, 0 ->0x14|
|0x128||DWord unknown4;||// ???|
|0x12C||DWord dwPixelDataStart;||// only used at runtime|
|0x130||DWord unknown5;||// ???|
|0x208||DWord dwAtlasEntries;||// number of TexAtlasEntries|
|0x20C||DWord dwAtlasOffset;||// offset to the start of the TexAtlasEntries|
|0x210||DWord unknown6;||// ???|
|0x244||void* pTexture;||// runtime store of the texture pointer|
|0x24C||DWord unknown7;||// ???|
|0x250||char szIFLName;||// IFL file name|
|0x350||DWord unknown8;||// ???|
The "TexMipLevel" structure referenced above is a simple 0x08 byte structure containing two DWords: one for the dwDataStart, and one for the dwDataSize.
This header is immediately followed by the TexEntries. The number of such entries is determined by the "dwAtlasEntries" value above. Here is the structure:
|struct TexEntry||// sizeof 0x204|
|0x000||char szInternalName;||// internal file name not used by D3|
|0x100||char szFileName;||// file name not used by D3|
|0x200||DWord nEntryNumber;||// the index number of this TexEntry|
The TexEntries are immediately followed by the TexAtlasEntries. This is where the image names used by Diablo 3 are stored (at least for the 2D images).
|struct TexAtlasEntry||// sizeof 0x50|
|0x000||char szName;||// image file name|
|0x040||float fXpos;||// x-position in float notation|
|0x044||float fYpos;||// y-position in float notation|
|0x048||float fXposEnd;||// x-end-position in float notation|
|0x04C||float fYposEnd;||// y-end-position in float notation|
Floats are encoded using the standard IEEE-754 floating-point encoding process.
Please note that the credit for all of this information goes to Necrolis and those who helped him. I had absolutely nothing to do with the decode of this file type other than understanding how the 2D item images fit into the broader scope.
Extracting the 2D Image Files
Necrolis from Phrozen Keep wrote the D3TexConv tool which can decompose a Textures file into a text file containing the TexAtlasEntries and a DirectDraw Surface (*.dds) file. Information and the download URL for the D3TexConv tool can be found in this thread. Necrolis has also made the C source for his tool available.
I then used infranView to extract all of the images from the DDS files. This required first extracting the position coordinates from the TexAtlasEntries. I used the command line parameters of InfranView to keep the transparency color (black=0x000000), and also to crop out (with /crop) the specific item image from the overall image using the positioning information from the TexAtlasEntries.
Items and Image Files
Not being a 3D modeling or animation expert, I came to learn about the Textures files because they happen to also contain the 2D images that are used to display items in the inventory and in the character screen.
There is no direct relationship between the Items*.gam files and the images. Instead, the Items*.gam files each reference an Actor (*.acr) file. These in turn contain the string hashes to the actual image file names. I encourage you to click on these links if you are curious about how the reverse-engineering process evolves.