Esempio n. 1
0
        /// <summary>
        /// Parse the root file into <see cref="RootFile"/>
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        public static RootFile ParseRoot(MemoryStream contentStream)
        {
            var rootfile = new RootFile
            {
                Lookup      = new MultiDictionary <ulong, RootEntry>(),
                FileDataIds = new MultiDictionary <uint, RootEntry>()
            };

            var namedCount   = 0;
            var unnamedCount = 0;
            var newRoot      = false;

            using (var stream = new MemoryStream(BLTE.Parse(contentStream.ToArray())))
                using (var reader = new BinaryReader(stream))
                {
                    var header = reader.ReadUInt32();
                    if (header == HeaderFmt)
                    {
                        var totalFiles = reader.ReadUInt32();
                        var namedFiles = reader.ReadUInt32();
                        newRoot = true;
                    }
                    else
                    {
                        reader.BaseStream.Position = 0;
                    }

                    while (reader.BaseStream.Position < reader.BaseStream.Length)
                    {
                        var count        = reader.ReadUInt32();
                        var contentFlags = (ContentFlags)reader.ReadUInt32();
                        var localeFlags  = (LocaleFlags)reader.ReadUInt32();

                        var rootEntries = new RootEntry[count];
                        var fileDataIds = new int[count];

                        var idx = 0;
                        for (var i = 0; i < count; ++i)
                        {
                            rootEntries[i].LocaleFlags  = localeFlags;
                            rootEntries[i].ContentFlags = contentFlags;

                            fileDataIds[i]            = idx + reader.ReadInt32();
                            rootEntries[i].FileDataId = (uint)fileDataIds[i];
                            idx = fileDataIds[i] + 1;
                        }

                        if (!newRoot)
                        {
                            for (var i = 0; i < count; ++i)
                            {
                                rootEntries[i].MD5    = reader.Read <MD5Hash>();
                                rootEntries[i].Lookup = reader.ReadUInt64();

                                rootfile.Lookup.Add(rootEntries[i].Lookup, rootEntries[i]);
                                rootfile.FileDataIds.Add(rootEntries[i].FileDataId, rootEntries[i]);
                            }
                        }
                        else
                        {
                            for (var i = 0; i < count; ++i)
                            {
                                rootEntries[i].MD5 = reader.Read <MD5Hash>();
                            }

                            for (var i = 0; i < count; ++i)
                            {
                                if (contentFlags.HasFlag(ContentFlags.NoNameHash))
                                {
                                    rootEntries[i].Lookup = 0;
                                    unnamedCount++;
                                }
                                else
                                {
                                    rootEntries[i].Lookup = reader.ReadUInt64();
                                    namedCount++;

                                    rootfile.Lookup.Add(rootEntries[i].Lookup, rootEntries[i]);
                                }

                                rootfile.FileDataIds.Add(rootEntries[i].FileDataId, rootEntries[i]);
                            }
                        }
                    }
                }

            return(rootfile);
        }
Esempio n. 2
0
        /// <summary>
        /// Read the Encoding file and return a parsed <see cref="EncodingFile"/>
        /// </summary>
        /// <param name="contentStream"></param>
        /// <returns></returns>
        public static EncodingFile ParseEncoding(MemoryStream contentStream)
        {
            var encodingFile = new EncodingFile();

            using (var stream = new MemoryStream(BLTE.Parse(contentStream.ToArray())))
                using (var reader = new BinaryReader(stream))
                {
                    if (System.Text.Encoding.UTF8.GetString(reader.ReadBytes(2)) != "EN")
                    {
                        throw new Exception("Encoding file might be corrupted!");
                    }

                    encodingFile.version         = reader.ReadByte();
                    encodingFile.cKeyLength      = reader.ReadByte();
                    encodingFile.eKeyLength      = reader.ReadByte();
                    encodingFile.cKeyPageSize    = reader.ReadUInt16(true);
                    encodingFile.eKeyPageSize    = reader.ReadUInt16(true);
                    encodingFile.cKeyPageCount   = reader.ReadUInt32(true);
                    encodingFile.eKeyPageCount   = reader.ReadUInt32(true);
                    encodingFile.stringBlockSize = reader.ReadUInt40(true);

                    reader.BaseStream.Position += (long)encodingFile.stringBlockSize;
                    reader.BaseStream.Position += encodingFile.cKeyPageCount * 32;

                    var tableAStart = reader.BaseStream.Position;
                    var entries     = new Dictionary <MD5Hash, EncodingFileEntry>(new MD5HashComparer());

                    for (var i = 0; i < encodingFile.cKeyPageCount; ++i)
                    {
                        byte keysCount;

                        while ((keysCount = reader.ReadByte()) != 0)
                        {
                            var entry = new EncodingFileEntry {
                                size = reader.ReadInt40BE()
                            };
                            var cKey = reader.Read <MD5Hash>();

                            // @TODO add support for multiple encoding keys
                            for (int key = 0; key < keysCount; key++)
                            {
                                if (key == 0)
                                {
                                    entry.eKey = reader.Read <MD5Hash>();
                                }
                                else
                                {
                                    reader.ReadBytes(16);
                                }
                            }

                            entries.Add(cKey, entry);

                            if (!EncodingDictionary.ContainsKey(cKey))
                            {
                                EncodingDictionary.Add(cKey, entry.eKey);
                            }
                        }

                        var remaining = 4096 - ((reader.BaseStream.Position - tableAStart) % 4096);
                        if (remaining > 0)
                        {
                            reader.BaseStream.Position += remaining;
                        }
                    }

                    encodingFile.aEntries = entries;
                }

            return(encodingFile);
        }