示例#1
0
        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;
            }
        }
示例#2
0
        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();
        }