public bool Fix() { // already converted if (!adt.Valid || !obj.Valid || !tex.Valid || adt.ReadUInt(0x18) > 0) { return(false); } CreateMCIN(); RetrieveMTEX(); RetrieveMMDX(); RetrieveMMID(); RetrieveMWMO(); RetrieveMWID(); RetrieveMDDF(); RetrieveMODF(); CheckMH2O(); for (int i = 0; i < 256; ++i) { RetrieveMCNK(i); } CheckMFBO(); RetrieveMTXF(); return(true); }
private void RetrieveMCNK(int id = 0) { adt.RemoveUnwantedChunksUntil(currentPos, (int)chunks.MCNK); tex.RemoveUnwantedChunksUntil(0, (int)chunks.MCNK); obj.RemoveUnwantedChunksUntil(0, (int)chunks.MCNK); int size_root_mcnk = adt.ReadInt(currentPos + 0x4); int size_tex_mcnk = tex.ReadInt(0x4); int size_obj_mcnk = obj.ReadInt(0x4); ChunkedWowFile root_mcnk = new ChunkedWowFile(adt.Data, currentPos, size_root_mcnk + 0x8); ChunkedWowFile tex_mcnk = new ChunkedWowFile(tex.Data, 8, size_tex_mcnk); ChunkedWowFile obj_mcnk = new ChunkedWowFile(obj.Data, 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(currentPos, root_mcnk.Size() - size_root_mcnk - 8); root_mcnk.BlockCopy(0, adt.Data, currentPos, root_mcnk.Size()); FillMCIN(id, currentPos, root_mcnk.Size()); adt.WriteInt(currentPos, ChunkedWowFile.MagicToInt("MCNK")); // should not be necessary adt.WriteInt(currentPos + 0x4, root_mcnk.Size() - 0x8); int ofsPos = currentPos + 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); currentPos += root_mcnk.Size(); }