Пример #1
0
        protected override FileIndexEntry3D[] ReadEntries()
        {
            if (!File.Exists(IndexPath) || !File.Exists(DataPath))
            {
                return(new FileIndexEntry3D[0]);
            }
            var entries = new List <FileIndexEntry3D>();
            var length  = (int)((new FileInfo(IndexPath).Length / 3) / 4);

            using (var index = new FileStream(IndexPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                var bin   = new BinaryReader(index);
                var count = (int)(index.Length / 12);
                for (var i = 0; i < count && i < length; ++i)
                {
                    var entry = new FileIndexEntry3D(bin.ReadInt32(), bin.ReadInt32(), bin.ReadInt32());
                    entries.Add(entry);
                }
                for (var i = count; i < length; ++i)
                {
                    var entry = new FileIndexEntry3D(-1, -1, -1);
                    entries.Add(entry);
                }
            }
            var patches = VerData.Patches;

            for (var i = 0; i < patches.Length; ++i)
            {
                var patch = patches[i];
                if (patch.file == patchFile && patch.index >= 0 && patch.index < entries.Count)
                {
                    var entry = entries.ElementAt(patch.index);
                    entry.Lookup = patch.lookup;
                    entry.Length = patch.length | (1 << 31);
                    entry.Extra  = patch.extra;
                }
            }
            return(entries.ToArray());
        }
Пример #2
0
        protected override FileIndexEntry3D[] ReadEntries()
        {
            var length   = Length;
            var dataPath = DataPath;
            var entries  = new FileIndexEntry3D[length];

            // In the mul file index, we read everything sequentially, and -1 is applied to invalid lookups.
            // UOP does not do this, so we need to do it ourselves.
            for (var i = 0; i < entries.Length; i++)
            {
                entries[i].Lookup = -1;
            }
            using (var index = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                var fi         = new FileInfo(dataPath);
                var uopPattern = Path.GetFileNameWithoutExtension(fi.Name).ToLowerInvariant();
                using (var br = new BinaryReader(index))
                {
                    br.BaseStream.Seek(0, SeekOrigin.Begin);
                    if (br.ReadInt32() != UOP_MAGIC_NUMBER)
                    {
                        throw new ArgumentException("Bad UOP file.");
                    }
                    br.ReadInt64(); // version + signature
                    var nextBlock = br.ReadInt64();
                    br.ReadInt32(); // block capacity
                    var count  = br.ReadInt32();
                    var hashes = new Dictionary <ulong, int>();
                    for (var i = 0; i < length; i++)
                    {
                        var entryName = string.Format("build/{0}/{1:D8}{2}", uopPattern, i, _extension);
                        var hash      = CreateHash(entryName);
                        if (!hashes.ContainsKey(hash))
                        {
                            hashes.Add(hash, i);
                        }
                    }
                    br.BaseStream.Seek(nextBlock, SeekOrigin.Begin);
                    do
                    {
                        var filesCount = br.ReadInt32();
                        nextBlock = br.ReadInt64();
                        for (var i = 0; i < filesCount; i++)
                        {
                            var offset             = br.ReadInt64();
                            var headerLength       = br.ReadInt32();
                            var compressedLength   = br.ReadInt32();
                            var decompressedLength = br.ReadInt32();
                            var hash = br.ReadUInt64();
                            br.ReadUInt32();
                            var flag        = br.ReadInt16();
                            var entryLength = flag == 1 ? compressedLength : decompressedLength;
                            if (offset == 0)
                            {
                                continue;
                            }
                            int idx;
                            if (hashes.TryGetValue(hash, out idx))
                            {
                                if (idx < 0 || idx > entries.Length)
                                {
                                    throw new IndexOutOfRangeException("hashes dictionary and files collection have different count of entries!");
                                }
                                entries[idx].Lookup = (int)(offset + headerLength);
                                entries[idx].Length = entryLength;
                                if (_hasExtra)
                                {
                                    var curPos = br.BaseStream.Position;
                                    br.BaseStream.Seek(offset + headerLength, SeekOrigin.Begin);
                                    var extra  = br.ReadBytes(8);
                                    var extra1 = (ushort)((extra[3] << 24) | (extra[2] << 16) | (extra[1] << 8) | extra[0]);
                                    var extra2 = (ushort)((extra[7] << 24) | (extra[6] << 16) | (extra[5] << 8) | extra[4]);
                                    entries[idx].Lookup += 8;
                                    entries[idx].Extra   = extra1 << 16 | extra2;
                                    br.BaseStream.Seek(curPos, SeekOrigin.Begin);
                                }
                            }
                        }
                    } while (br.BaseStream.Seek(nextBlock, SeekOrigin.Begin) != 0);
                }
            }
            return(entries);
        }