示例#1
0
        public Stream Seek(int index, out int length, out int extra)
        {
            if (!FilesExist || index < 0 || index >= _length)
            {
                length = extra = 0;
                return(null);
            }

            FileIndexEntry e = _entries[index];

            if (e.Lookup < 0 || e.Length <= 0)
            {
                length = extra = 0;
                return(null);
            }

            length = e.Length & 0x7FFFFFFF;
            extra  = e.Extra;

            if (_stream != null && (!_stream.CanRead || !_stream.CanSeek))
            {
                _stream.Dispose();
                _stream = null;
            }

            if (_stream == null)
            {
                _stream = new FileStream(_dataPath, FileMode.Open, FileAccess.Read, FileShare.Read);
            }

            _stream.Seek(e.Lookup, SeekOrigin.Begin);

            return(_stream);
        }
示例#2
0
        private FileIndexEntry[] ReadLegacyEntries()
        {
            List <FileIndexEntry> entries = new List <FileIndexEntry>();

            int length = (int)((new FileInfo(_indexPath).Length / 3) / 4);

            using (FileStream index = new FileStream(_indexPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                BinaryReader bin = new BinaryReader(index);
                _stream = new FileStream(_mulPath, FileMode.Open, FileAccess.Read, FileShare.Read);

                int count = (int)(index.Length / 12);

                for (int i = 0; i < count && i < length; ++i)
                {
                    FileIndexEntry entry = new FileIndexEntry()
                    {
                        Lookup = bin.ReadInt32(),
                        Length = bin.ReadInt32(),
                        Extra  = bin.ReadInt32(),
                    };

                    entries.Add(entry);
                }

                for (int i = count; i < length; ++i)
                {
                    FileIndexEntry entry = new FileIndexEntry()
                    {
                        Lookup = -1,
                        Length = -1,
                        Extra  = -1,
                    };

                    entries.Add(entry);
                }
            }

            return(entries.ToArray());
        }
示例#3
0
        protected override FileIndexEntry[] ReadEntries()
        {
            var entries = new List<FileIndexEntry>();

            var length = (int)((new FileInfo(_indexPath).Length / 3) / 4);

            using(var index = new FileStream(_indexPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                var bin = new BinaryReader(index);

                var count = (int)(index.Length / 12);

                for(var i = 0; i < count && i < length; ++i)
                {
                    var entry = new FileIndexEntry
                                {
                                    Lookup = bin.ReadInt32(),
                                    Length = bin.ReadInt32(),
                                    Extra = bin.ReadInt32()
                                };

                    entries.Add(entry);
                }

                for(var i = count; i < length; ++i)
                {
                    var entry = new FileIndexEntry
                                {
                                    Lookup = -1,
                                    Length = -1,
                                    Extra = -1
                                };

                    entries.Add(entry);
                }
            }

            return entries.ToArray();
        }
示例#4
0
        protected override FileIndexEntry[] ReadEntries()
        {
            var entries = new List <FileIndexEntry>();

            var length = (int)((new FileInfo(_indexPath).Length / 3) / 4);

            using (var index = new FileStream(_indexPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                var bin = new BinaryReader(index);

                var count = (int)(index.Length / 12);

                for (var i = 0; i < count && i < length; ++i)
                {
                    var entry = new FileIndexEntry
                    {
                        Lookup = bin.ReadInt32(),
                        Length = bin.ReadInt32(),
                        Extra  = bin.ReadInt32()
                    };

                    entries.Add(entry);
                }

                for (var i = count; i < length; ++i)
                {
                    var entry = new FileIndexEntry
                    {
                        Lookup = -1,
                        Length = -1,
                        Extra  = -1
                    };

                    entries.Add(entry);
                }
            }

            return(entries.ToArray());
        }
示例#5
0
        protected override FileIndexEntry[] ReadEntries()
        {
            int length = Length;
            string dataPath = DataPath;
            FileIndexEntry[] entries = new FileIndexEntry[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 (int i = 0; i < entries.Length; i++)
                entries[i].Lookup = -1;

            using (FileStream index = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                FileInfo fi = new FileInfo(dataPath);
                string uopPattern = Path.GetFileNameWithoutExtension(fi.Name).ToLowerInvariant();

                using (BinaryReader 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
                    long nextBlock = br.ReadInt64();
                    br.ReadInt32(); // block capacity
                    int count = br.ReadInt32();

                    Dictionary<ulong, int> hashes = new Dictionary<ulong, int>();

                    for (int i = 0; i < length; i++)
                    {
                        string entryName = string.Format("build/{0}/{1:D8}{2}", uopPattern, i, _extension);
                        ulong hash = CreateHash(entryName);

                        if (!hashes.ContainsKey(hash))
                            hashes.Add(hash, i);
                    }

                    br.BaseStream.Seek(nextBlock, SeekOrigin.Begin);

                    do
                    {
                        int filesCount = br.ReadInt32();
                        nextBlock = br.ReadInt64();

                        for (int i = 0; i < filesCount; i++)
                        {
                            long offset = br.ReadInt64();
                            int headerLength = br.ReadInt32();
                            int compressedLength = br.ReadInt32();
                            int decompressedLength = br.ReadInt32();
                            ulong hash = br.ReadUInt64();
                            br.ReadUInt32(); // Adler32
                            short flag = br.ReadInt16();

                            int 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)
                                {
                                    long curPos = br.BaseStream.Position;

                                    br.BaseStream.Seek(offset + headerLength, SeekOrigin.Begin);

                                    byte[] extra = br.ReadBytes(8);

                                    ushort extra1 = (ushort)((extra[3] << 24) | (extra[2] << 16) | (extra[1] << 8) | extra[0]);
                                    ushort 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;
        }
示例#6
0
        protected override FileIndexEntry[] ReadEntries()
        {
            int    length   = Length;
            string dataPath = DataPath;

            FileIndexEntry[] entries = new FileIndexEntry[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 (int i = 0; i < entries.Length; i++)
            {
                entries[i].Lookup = -1;
            }

            using (FileStream index = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                FileInfo fi         = new FileInfo(dataPath);
                string   uopPattern = Path.GetFileNameWithoutExtension(fi.Name).ToLowerInvariant();

                using (BinaryReader 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
                    long nextBlock = br.ReadInt64();
                    br.ReadInt32(); // block capacity
                    int count = br.ReadInt32();

                    Dictionary <ulong, int> hashes = new Dictionary <ulong, int>();

                    for (int i = 0; i < length; i++)
                    {
                        string entryName = string.Format("build/{0}/{1:D8}{2}", uopPattern, i, _extension);
                        ulong  hash      = CreateHash(entryName);

                        if (!hashes.ContainsKey(hash))
                        {
                            hashes.Add(hash, i);
                        }
                    }

                    br.BaseStream.Seek(nextBlock, SeekOrigin.Begin);

                    do
                    {
                        int filesCount = br.ReadInt32();
                        nextBlock = br.ReadInt64();

                        for (int i = 0; i < filesCount; i++)
                        {
                            long  offset             = br.ReadInt64();
                            int   headerLength       = br.ReadInt32();
                            int   compressedLength   = br.ReadInt32();
                            int   decompressedLength = br.ReadInt32();
                            ulong hash = br.ReadUInt64();
                            br.ReadUInt32(); // Adler32
                            short flag = br.ReadInt16();

                            int 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)
                                {
                                    long curPos = br.BaseStream.Position;

                                    br.BaseStream.Seek(offset + headerLength, SeekOrigin.Begin);

                                    byte[] extra = br.ReadBytes(8);

                                    ushort extra1 = (ushort)((extra[3] << 24) | (extra[2] << 16) | (extra[1] << 8) | extra[0]);
                                    ushort 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);
        }
示例#7
0
        private FileIndexEntry[] ReadLegacyEntries()
        {
            List<FileIndexEntry> entries = new List<FileIndexEntry>();

            int length = (int)((new FileInfo(_indexPath).Length / 3) / 4);

            using (FileStream index = new FileStream(_indexPath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                BinaryReader bin = new BinaryReader(index);
                _stream = new FileStream(_mulPath, FileMode.Open, FileAccess.Read, FileShare.Read);

                int count = (int)(index.Length / 12);

                for (int i = 0; i < count && i < length; ++i)
                {
                    FileIndexEntry entry = new FileIndexEntry()
                    {
                        Lookup = bin.ReadInt32(),
                        Length = bin.ReadInt32(),
                        Extra = bin.ReadInt32(),
                    };

                    entries.Add(entry);
                }

                for (int i = count; i < length; ++i)
                {
                    FileIndexEntry entry = new FileIndexEntry()
                    {
                        Lookup = -1,
                        Length = -1,
                        Extra = -1,
                    };

                    entries.Add(entry);
                }
            }

            return entries.ToArray();
        }
示例#8
0
        private FileIndexEntry[] ReadUOPEntries()
        {
            List<FileIndexEntry> entries = new List<FileIndexEntry>();

            _stream = new FileStream(_indexPath, FileMode.Open);

            using (BinaryReader reader = new BinaryReader(_stream))
            {
                UopHeader header = new UopHeader()
                {
                    MagicNumber = reader.ReadInt32(),
                    Version = reader.ReadInt32(),
                    Misc = reader.ReadInt32(),
                    StartAddress = reader.ReadInt64(),
                    BlockSize = reader.ReadInt32(),
                    FileCount = reader.ReadInt32(),
                };

                if (header.MagicNumber != UOPMagicNumber)
                {
                    Tracer.Error("{0} is not a UOP file, magic number not found!", _indexPath);
                    return new FileIndexEntry[0];
                }

                long nextBlockAddress = header.StartAddress;

                List<UopIndexEntry> uopEntries = new List<UopIndexEntry>();

                while (nextBlockAddress != 0L)
                {
                    _stream.Seek(nextBlockAddress, SeekOrigin.Begin);

                    UopBlock block = new UopBlock()
                    {
                        FileCount = reader.ReadInt32(),
                        NextBlockAddress = reader.ReadInt64()
                    };

                    for (int i = 0; i < block.FileCount; i++)
                    {
                        UopIndexEntry uopEntry = new UopIndexEntry()
                        {
                            Lookup = reader.ReadInt64(),
                            Length = reader.ReadInt32(),
                            CompressedSize = reader.ReadInt32(),
                            DecompressedSize = reader.ReadInt32(),
                            EntryHash = reader.ReadInt64(),
                            BlockHash = reader.ReadInt32(),
                            IsCompressed = reader.ReadInt16() == 1,
                        };

                        uopEntries.Add(uopEntry);
                    }

                    nextBlockAddress = block.NextBlockAddress;
                }

                foreach (var uopEntry in uopEntries)
                {
                    FileIndexEntry entry = new FileIndexEntry()
                    {
                        Lookup = (int)uopEntry.Lookup,
                        Length = uopEntry.DecompressedSize
                    };

                    entries.Add(entry);
                }
            }

            return entries.ToArray();
        }
示例#9
0
        private FileIndexEntry[] ReadUOPEntries()
        {
            List <FileIndexEntry> entries = new List <FileIndexEntry>();

            _stream = new FileStream(_indexPath, FileMode.Open);

            using (BinaryReader reader = new BinaryReader(_stream))
            {
                UopHeader header = new UopHeader()
                {
                    MagicNumber  = reader.ReadInt32(),
                    Version      = reader.ReadInt32(),
                    Misc         = reader.ReadInt32(),
                    StartAddress = reader.ReadInt64(),
                    BlockSize    = reader.ReadInt32(),
                    FileCount    = reader.ReadInt32(),
                };

                if (header.MagicNumber != UOPMagicNumber)
                {
                    Tracer.Error("{0} is not a UOP file, magic number not found!", _indexPath);
                    return(new FileIndexEntry[0]);
                }

                long nextBlockAddress = header.StartAddress;

                List <UopIndexEntry> uopEntries = new List <UopIndexEntry>();

                while (nextBlockAddress != 0L)
                {
                    _stream.Seek(nextBlockAddress, SeekOrigin.Begin);

                    UopBlock block = new UopBlock()
                    {
                        FileCount        = reader.ReadInt32(),
                        NextBlockAddress = reader.ReadInt64()
                    };

                    for (int i = 0; i < block.FileCount; i++)
                    {
                        UopIndexEntry uopEntry = new UopIndexEntry()
                        {
                            Lookup           = reader.ReadInt64(),
                            Length           = reader.ReadInt32(),
                            CompressedSize   = reader.ReadInt32(),
                            DecompressedSize = reader.ReadInt32(),
                            EntryHash        = reader.ReadInt64(),
                            BlockHash        = reader.ReadInt32(),
                            IsCompressed     = reader.ReadInt16() == 1,
                        };

                        uopEntries.Add(uopEntry);
                    }

                    nextBlockAddress = block.NextBlockAddress;
                }

                foreach (var uopEntry in uopEntries)
                {
                    FileIndexEntry entry = new FileIndexEntry()
                    {
                        Lookup = (int)uopEntry.Lookup,
                        Length = uopEntry.DecompressedSize
                    };

                    entries.Add(entry);
                }
            }

            return(entries.ToArray());
        }