private void RetrieveMTXF() { adt.WriteInt(0x40, adtPos - 0x14); int posMTXF = 0, posMTXP = 0; int i = 0; for (i = 0; i < tex.Size() - 8; i += tex.ReadInt(i + 4)) { if (tex.IsChunk(i, "MTXF")) { posMTXF = i; break; } else if (tex.IsChunk(i, "MTXP")) { posMTXP = i; break; } } if (posMTXF > 0) { int size = tex.ReadInt(i + 0x4); adt.AddEmptyBytes(adtPos, 0x8 + size); adt.WriteInt(adtPos, ChunkedWowFile.MagicToInt("MTXF")); adt.WriteInt(adtPos + 0x4, size); adtPos += 0x8; for (int k = posMTXF + 0x8; k < posMTXF + 0x8 + size; k += 0x4) { // only flag used in wotlk adt.WriteInt(adtPos, tex.Data[k] & 0x1); adtPos += 0x4; } } else if (posMTXP > 0) { int size = tex.ReadInt(i + 0x4); int mtxf_size = size / 4; adt.AddEmptyBytes(adtPos, 0x8 + mtxf_size); adt.WriteInt(adtPos, ChunkedWowFile.MagicToInt("MTXF")); adt.WriteInt(adtPos + 0x4, mtxf_size); adtPos += 0x8; for (int k = posMTXP + 0x8; k < posMTXP + 0x8 + size; k += 0x10) { // only flag used in wotlk adt.WriteInt(adtPos, tex.Data[k] & 0x1); adtPos += 0x4; } } else { adt.AddEmptyBytes(adtPos, 0x8 + textureCount * 4); adt.WriteInt(adtPos, ChunkedWowFile.MagicToInt("MTXF")); adt.WriteInt(adtPos + 0x4, textureCount * 4); adtPos += 0x8 + textureCount * 4; } }
private void RetrieveMCNK(int id = 0) { // adt.RemoveUnwantedChunksUntil(0, (int)chunks.MCNK); // tex.RemoveUnwantedChunksUntil(0, (int)chunks.MCNK); // obj.RemoveUnwantedChunksUntil(0, (int)chunks.MCNK); var root_mcnk_int = ChunkedWowFile.MagicToInt("MCNK"); var mcnk_ofs_root = adt.ChunksOfs(0, root_mcnk_int); var mcnk_ofs_tex = tex.ChunksOfs(0, root_mcnk_int); var mcnk_ofs_obj = obj.ChunksOfs(0, root_mcnk_int); int size_root_mcnk = adt.ReadInt(mcnk_ofs_root[root_mcnk_int] + 4); int size_tex_mcnk = tex.ReadInt(mcnk_ofs_tex[root_mcnk_int] + 4); int size_obj_mcnk = obj.ReadInt(mcnk_ofs_obj[root_mcnk_int] + 4); mcnk_ofs_root.Remove(root_mcnk_int); mcnk_ofs_tex.Remove(root_mcnk_int); mcnk_ofs_obj.Remove(root_mcnk_int); ChunkedWowFile root_mcnk = new ChunkedWowFile(adt.Data, mcnk_ofs_root[root_mcnk_int] + 8, size_root_mcnk); ChunkedWowFile tex_mcnk = new ChunkedWowFile(tex.Data, mcnk_ofs_tex[root_mcnk_int] + 8, size_tex_mcnk); ChunkedWowFile obj_mcnk = new ChunkedWowFile(obj.Data, mcnk_ofs_obj[root_mcnk_int] + 8, size_obj_mcnk); // remove MCNK in split files tex.RemoveBytes(0, size_tex_mcnk + 8); obj.RemoveBytes(0, size_obj_mcnk + 8); Dictionary <int, int> adt_chunks = root_mcnk.ChunksOfs(0x88, (int)chunks.MCNK); Dictionary <int, int> tex_chunks = tex_mcnk.ChunksOfs(0, (int)chunks.MCNK); Dictionary <int, int> obj_chunks = obj_mcnk.ChunksOfs(0, (int)chunks.MCNK); int pos = 0; int ofsMCVT = 0x88; int sizeMCVT = (9 * 9 + 8 * 8) * 4; root_mcnk.WriteInt(pos + 0x3C, 0); uint flags = root_mcnk.ReadUInt(pos + 0x8); // fix high res hole if ((flags & 0x10000) != 0) { root_mcnk.WriteUShort(pos + 0x3C + 0x8, HighToLowResHole(root_mcnk.ReadULong(pos + 0x14 + 0x8))); } root_mcnk.WriteUInt(pos + 0x8, flags & 0xFFFF); pos += ofsMCVT + 0x8 + sizeMCVT; int ofsMCCV = 0; int sizeMCCV = 0; if (adt_chunks.ContainsKey((int)chunks.MCCV)) { ofsMCCV = pos; sizeMCCV = root_mcnk.ReadInt(ofsMCCV + 0x4) + 0x8; pos += sizeMCCV; } // remove MCLV if (adt_chunks.ContainsKey((int)chunks.MCLV)) { root_mcnk.RemoveUnwantedChunksUntil(pos, (int)chunks.MCNR); } int ofsMCNR = pos; pos += 448 + 0x8; root_mcnk.WriteInt(ofsMCNR + 0x4, 435); int ofsMCLY = 0; int sizeMCLY = 0; int nLayer = 0; List <int> mcal_offsets = new List <int>(); if (tex_chunks.ContainsKey((int)chunks.MCLY)) { tex_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCLY); ofsMCLY = pos; int size = tex_mcnk.ReadInt(0x4); sizeMCLY = size + 0x8; root_mcnk.AddEmptyBytes(pos, sizeMCLY); tex_mcnk.BlockCopy(0, root_mcnk, pos, sizeMCLY); tex_mcnk.RemoveBytes(0, sizeMCLY); nLayer = size / 0x10; int layer_pos = pos + 0x8; for (int i = 0; i < nLayer; ++i) { uint groundEffect = root_mcnk.ReadUInt(layer_pos + 0xC); if (groundEffect > 73186) // max wotlk id in GroundEffectTexture { root_mcnk.WriteInt(layer_pos + 0xC, 0); } root_mcnk.WriteUInt(layer_pos + 0x4, root_mcnk.ReadUInt(layer_pos + 0x4) & 0x7FF); mcal_offsets.Add(root_mcnk.ReadInt(layer_pos + 0x8)); layer_pos += 0x10; } if (nLayer > 4) { root_mcnk.RemoveBytes(pos + 0x8 + 64, 16 * (nLayer - 4)); sizeMCLY = 64 + 0x8; root_mcnk.WriteInt(pos + 0x4, 64); nLayer = 4; } pos += sizeMCLY; } int ofsMCRF = pos; int sizeMCRF = 0x8; int nDoodads = 0, nMapObjRefs = 0; root_mcnk.AddEmptyBytes(pos, 8); root_mcnk.WriteInt(pos, ChunkedWowFile.MagicToInt("MCRF")); pos += 0x8; if (models) { if (obj_chunks.ContainsKey((int)chunks.MCRD)) { obj_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCRD); int sizeMCRD = obj_mcnk.ReadInt(0x4); root_mcnk.AddEmptyBytes(pos, sizeMCRD); obj_mcnk.BlockCopy(0x8, root_mcnk, pos, sizeMCRD); pos += sizeMCRD; nDoodads = sizeMCRD / 4; sizeMCRF += sizeMCRD; obj_mcnk.RemoveBytes(0, 0x8 + sizeMCRD); } if (obj_chunks.ContainsKey((int)chunks.MCRW)) { obj_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCRW); int sizeMCRW = obj_mcnk.ReadInt(0x4); root_mcnk.AddEmptyBytes(pos, sizeMCRW); obj_mcnk.BlockCopy(0x8, root_mcnk, pos, sizeMCRW); pos += sizeMCRW; nMapObjRefs = sizeMCRW / 4; sizeMCRF += sizeMCRW; obj_mcnk.RemoveBytes(0, 0x8 + sizeMCRW); } } // update MCRF size root_mcnk.WriteInt(ofsMCRF + 0x4, sizeMCRF - 0x8); // MCSH int ofsMCSH = 0; int sizeMCSH = 0; if (tex_chunks.ContainsKey((int)chunks.MCSH)) { ofsMCSH = pos; tex_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCSH); sizeMCSH = tex_mcnk.ReadInt(0x4) + 0x8; root_mcnk.AddEmptyBytes(pos, sizeMCSH); tex_mcnk.BlockCopy(0, root_mcnk, pos, sizeMCSH); pos += sizeMCSH; tex_mcnk.RemoveBytes(0, sizeMCSH); } // MCAL int ofsMCAL = 0; int sizeMCAL = 0; ofsMCAL = pos; if (tex_chunks.ContainsKey((int)chunks.MCAL)) { tex_mcnk.RemoveUnwantedChunksUntil(0, (int)chunks.MCAL); sizeMCAL = tex_mcnk.ReadInt(0x4) + 0x8; root_mcnk.AddEmptyBytes(pos, sizeMCAL); tex_mcnk.BlockCopy(0, root_mcnk, pos, sizeMCAL); tex_mcnk.RemoveBytes(0, sizeMCAL); if (mcal_offsets.Count() > 4) { int size = sizeMCAL - 0x8; int target = mcal_offsets[4]; root_mcnk.RemoveBytes(pos + 0x8 + target, size - target); sizeMCAL = target + 0x8; root_mcnk.WriteInt(pos + 0x4, target); } pos += sizeMCAL; } if (sizeMCAL == 0) { root_mcnk.AddEmptyBytes(pos, 8); root_mcnk.WriteInt(pos, (int)chunks.MCAL); sizeMCAL = 0x8; pos += 8; } // MCSE int ofsMCSE = pos; int sizeMCSE = 0; int nSoundEmitter = 0; if (adt_chunks.ContainsKey((int)chunks.MCSE)) { root_mcnk.RemoveUnwantedChunksUntil(pos, (int)chunks.MCSE); sizeMCSE = root_mcnk.ReadInt(pos + 0x4) + 0x8; nSoundEmitter = (sizeMCSE - 8) / 0x1C; pos += sizeMCSE; } else { ofsMCSE = 0; } adt.AddEmptyBytes(adtPos, root_mcnk.Size() - size_root_mcnk - 8); root_mcnk.BlockCopy(0, adt.Data, adtPos, root_mcnk.Size()); FillMCIN(id, adtPos, root_mcnk.Size()); adt.WriteInt(adtPos, ChunkedWowFile.MagicToInt("MCNK")); // should not be necessary adt.WriteInt(adtPos + 0x4, root_mcnk.Size() - 0x8); int ofsPos = adtPos + 0x8; // MCNK header for offsets // Update headers adt.WriteInt(ofsPos + 0x4, (id % 16)); adt.WriteInt(ofsPos + 0x8, (id / 16)); // nLayer adt.WriteInt(ofsPos + 0xC, nLayer); // nDoodads adt.WriteInt(ofsPos + 0x10, nDoodads); adt.WriteInt(ofsPos + 0x14, ofsMCVT); adt.WriteInt(ofsPos + 0x18, ofsMCNR); adt.WriteInt(ofsPos + 0x1C, ofsMCLY); adt.WriteInt(ofsPos + 0x20, ofsMCRF); adt.WriteInt(ofsPos + 0x24, ofsMCAL); // sizeAlpha adt.WriteInt(ofsPos + 0x28, sizeMCAL); adt.WriteInt(ofsPos + 0x2C, ofsMCSH); // size shadow adt.WriteInt(ofsPos + 0x30, sizeMCSH); // area id adt.WriteInt(ofsPos + 0x34, 0); // nMapObjRefs adt.WriteInt(ofsPos + 0x38, nMapObjRefs); adt.WriteInt(ofsPos + 0x50, 0); adt.WriteInt(ofsPos + 0x58, ofsMCSE); // nSoundEmitter adt.WriteInt(ofsPos + 0x5C, nSoundEmitter); adt.WriteInt(ofsPos + 0x60, 0); // MCLQ adt.WriteInt(ofsPos + 0x64, 0); // size Liquid adt.WriteInt(ofsPos + 0x74, ofsMCCV); adt.WriteInt(ofsPos + 0x78, 0); adt.WriteInt(ofsPos + 0x7C, 0); adtPos += root_mcnk.Size(); }