CoD2 Material


CoD2 Material File Format

Each file has a header, an array of MapInfoBlocks, and strings for the image file names and file types.
Some also have StringInfoBlocks, function unknown.

typedef struct tagMapInfoBlock
{
    DWORD    dwMapTypeOffset;
    // The start of a string for the type of image map.
    BYTE         Unk0[4];                     
// Unk[1] looks like a type enumeration where "colorMap" = 2.
    DWORD    dwMapNameOffset; 
// The start of a string for the image file name.
}MapInfoBlock;

typedef struct tagStringInfoBlock
{
    DWORD dwMapTypeOffset;
 // The start of an info string.
    float Unk1[4];                            // Four floats, function unknown.
}StringInfoBlock;
 

Note1: All offsets are from the beginning of the file.
Note2: All strings are C style, zero terminated.

typedef struct tagHeader
{
    DWORD    dwMaterialNameOffset;            
// Not very useful since it always seems to be same as material filename.
    DWORD    dwColorMapFilenameOffset;     // A shortcut to the most important map, the mesh's skin.
    BYTE         Unk2[0x2c];                           
    WORD       nNumMapInfoBlocks;               
// See above.
    WORD       nNumMapInfoStrings;               
// Not sure of their function.
    DWORD    dwMaterialTypeOffset;
    DWORD    dwMapInfoBlockOffset;            
// Always 0x44; Offset to the first MapInfoBlock
    DWORD    Unk3;
    DWORD    dwStringInfoBlockOffset;         
// Offset to the first StringInfoBlock;
}MaterialHeader;

CString CXmodelCoD2::MaterialToMap(CString &sMaterialFileName, CString sMapType)
{
    // Valid MapTypes are:
    //     "colorMap",
    //     "detailMap",'
    //     "normalMap",
    //     "specularMap"
    // These are the names in the material file.
    //
    // Returns the requested filename or "" if not found.    
    CString  sRet("");
    CFile      file;
    char        buffer[255];
   
   
    if
(file.Open(sMaterialFileName, CFile::modeRead))
    {
        MaterialHeader    header;
        file.Read(&header, sizeof(MaterialHeader));
       
        MapInfoBlock* pBlocks = new MapInfoBlock[header.wNumMapInfoBlocks];
        // Move to first MapInfoBlock and read them all in.
        file.Seek(header.dwInfoBlockOffset, CFile::begin);
        file.Read(pBlocks, sizeof(MapInfoBlock)):
       
        // If interested in them, the file pointer is now pointing to the InfoStringBlocks

        for(WORD i = 0; i < header.wNumMapInfoBlocks; i++)
        {
            file.Seek(pBlocks[i].dwMapTypeOffset,  CFile::begin);
            file.Read(buffer, 255);    // Just grab a bunch;
            CString sTemp(buffer);
            if(sTemp == sMapType)
            {
                file.Seek(pBlocks[i].dwMapNameOffset, CFile::begin);
                file.Read(buffer, 255);
                sRet = buffer;
                sRet += ".iwi";
                break;
            }
        }        

        delete[] pBlocks;
    }

    file.Close();
    return sRet;
}

Note 3: This code was typed from memory.  If it compiles, I wrote it. If not, then Anonymous wrote it.

CoD4 Material File Format