示例#1
0
        private void AddLayoutEntry(CASResult blte)
        {
            if (EKeys.ContainsKey(blte.EKey))
            {
                EKeys.Remove(blte.EKey);
            }

            // generate ESpecString
            string ESpecString;
            uint   size = blte.CompressedSize - 30;

            // the below suffices and is technically correct
            // however this could be more compliant https://wowdev.wiki/CASC#Encoding_Specification_.28ESpec.29
            if (blte.CEKey == CASContainer.BuildConfig.GetKey("root"))             // root is always z
            {
                ESpecString = "z";
            }
            else if (size >= 1024 * 256)             // 256K* seems to be the max
            {
                ESpecString = "b:{256K*=z}";
            }
            else if (size > 1024)
            {
                ESpecString = "b:{" + (int)Math.Floor(size / 1024d) + "K*=z}";                 // closest floored KB
            }
            else
            {
                ESpecString = "b:{" + size + "*=z}";                 // actual B size
            }
            // string index
            int stridx = ESpecStringTable.IndexOf(ESpecString);

            if (stridx == -1)
            {
                stridx = ESpecStringTable.Count - 2;                 // ignore the 0 byte
                ESpecStringTable.Insert(stridx, ESpecString);
            }

            // create the entry
            var entry = new EncodingEKeyPageTable()
            {
                FileSize         = size,
                EKey             = blte.EKey,
                ESpecStringIndex = (uint)stridx
            };

            EKeys.Add(entry.EKey, entry);
        }
示例#2
0
        public EncodingHandler(BLTEStream blte)
        {
            if (blte.Length != long.Parse(CASContainer.BuildConfig["encoding-size"][0]))
            {
                CASContainer.Settings?.Logger.LogAndThrow(Logging.LogType.Critical, "Encoding File is corrupt.");
            }

            BinaryReader stream = new BinaryReader(blte);

            Header = new EncodingHeader()
            {
                Magic          = stream.ReadBytes(2),
                Version        = stream.ReadByte(),
                ChecksumSizeC  = stream.ReadByte(),
                ChecksumSizeE  = stream.ReadByte(),
                PageSizeCEKey  = stream.ReadUInt16(),
                PageSizeEKey   = stream.ReadUInt16(),
                PageCountCEKey = stream.ReadUInt32BE(),
                PageCountEKey  = stream.ReadUInt32BE(),
                Unknown_x11    = stream.ReadByte(),
                ESpecBlockSize = stream.ReadUInt32BE()
            };

            // ESpec string table
            ESpecStringTable.AddRange(Encoding.ASCII.GetString(stream.ReadBytes((int)Header.ESpecBlockSize)).Split('\0'));

            // skip CE page table lookup
            stream.ReadBytes((int)Header.PageCountCEKey * 32);

            // read CE page table data
            for (int i = 0; i < Header.PageCountCEKey; i++)
            {
                long start = stream.BaseStream.Position;

                ushort keysCount;
                while ((keysCount = stream.ReadUInt16()) != 0)
                {
                    var entry = new EncodingCEKeyPageTable()
                    {
                        DecompressedSize = stream.ReadUInt32BE(),
                        CKey             = new MD5Hash(stream)
                    };

                    for (int ki = 0; ki < keysCount; ki++)
                    {
                        entry.EKeys.Add(new MD5Hash(stream));
                    }

                    CEKeys.Add(entry.CKey, entry);
                }

                if (stream.BaseStream.Position % CHUNK_SIZE != 0)
                {
                    stream.BaseStream.Position += CHUNK_SIZE - ((stream.BaseStream.Position - start) % CHUNK_SIZE);
                }
            }

            // skip EKey page table lookup
            stream.ReadBytes((int)Header.PageCountEKey * 32);

            // read EKey page table data
            for (int i = 0; i < Header.PageCountEKey; i++)
            {
                long start = stream.BaseStream.Position;

                MD5Hash hash;
                while (!(hash = new MD5Hash(stream)).IsEmpty)
                {
                    var entry = new EncodingEKeyPageTable()
                    {
                        EKey             = hash,
                        ESpecStringIndex = stream.ReadUInt32BE(),
                        FileSize         = stream.ReadUInt40BE()
                    };

                    EKeys.Add(entry.EKey, entry);
                }

                if (stream.BaseStream.Position % CHUNK_SIZE != 0)
                {
                    stream.BaseStream.Position += CHUNK_SIZE - ((stream.BaseStream.Position - start) % CHUNK_SIZE);
                }
            }

            // Encoding file ESpecStringTable
            stream.ReadBytes((int)(stream.BaseStream.Length - stream.BaseStream.Position));

            EncodingMap = blte.EncodingMap.ToArray();

            blte?.Dispose();
            stream?.Dispose();
        }