Example #1
0
        public FileIndex(string uopFile, int entryCount, string entryExt, bool extended)
            : this(entryCount)
        {
            do
            {
                _IdxPath = _BinPath = Core.FindDataFile(uopFile);

                try
                {
                    if (_BinPath != null)
                    {
                        try
                        { File = new FileInfo(_BinPath); }
                        catch { File = null; }

                        _BinLoaded = File?.Exists ?? false;
                    }
                }
                catch { }

                try
                {
                    if (File != null)
                    {
                        using (var stream = new FileStream(File.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                            using (var reader = new BinaryReader(stream))
                            {
                                if (reader.ReadInt32() == 0x50594D)
                                {
                                    reader.ReadInt64();                             // version + signature

                                    var nextBlock = reader.ReadInt64();

                                    reader.ReadInt32();                             // block capacity
                                    reader.ReadInt32();                             // block count

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

                                    var root = $"build/{Path.GetFileNameWithoutExtension(_IdxPath).ToLowerInvariant()}";

                                    for (var i = 0; i < entryCount; i++)
                                    {
                                        hashes[UOPHash.HashLittle2($"{root}/{i:D8}{entryExt}")] = i;
                                    }

                                    stream.Seek(nextBlock, SeekOrigin.Begin);

                                    do
                                    {
                                        var filesCount = reader.ReadInt32();

                                        nextBlock = reader.ReadInt64();

                                        for (var i = 0; i < filesCount; i++)
                                        {
                                            var offset             = reader.ReadInt64();
                                            var headerLength       = reader.ReadInt32();
                                            var compressedLength   = reader.ReadInt32();
                                            var decompressedLength = reader.ReadInt32();
                                            var hash = reader.ReadUInt64();

                                            reader.ReadUInt32();                                     // Adler32

                                            var flag = reader.ReadInt16();

                                            var entryLength = flag == 1 ? compressedLength : decompressedLength;

                                            if (offset == 0 || !hashes.TryGetValue(hash, out var idx))
                                            {
                                                continue;
                                            }

                                            if (idx < 0 || idx > Index.Length)
                                            {
                                                continue;
                                            }

                                            Index[idx].Offset = (int)(offset + headerLength);
                                            Index[idx].Size   = entryLength;

                                            if (!extended)
                                            {
                                                continue;
                                            }

                                            var curPos = stream.Position;

                                            stream.Seek(offset + headerLength, SeekOrigin.Begin);

                                            var extra  = reader.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]);

                                            Index[idx].Offset += 8;
                                            Index[idx].Data    = extra1 << 16 | extra2;

                                            stream.Seek(curPos, SeekOrigin.Begin);
                                        }
                                    }while (stream.Seek(nextBlock, SeekOrigin.Begin) != 0);

                                    _IdxLoaded = true;
                                }
                            }
                    }
                }
                catch { }
            }while (CheckRetry());
        }
Example #2
0
        public FileIndex(
            string uopFile,
            int length,
            string uopEntryExtension,
            int idxLength,
            bool hasExtra)
        {
            Index = new Entry3D[length];

            MulPath = Core.FindDataFile(uopFile);

            /* UOP files support code, written by Wyatt (c) www.ruosi.org
             * idxLength variable was added for compatibility with legacy code for art (see art.cs)
             * At the moment the only UOP file having entries with extra field is gumpartlegacy.uop,
             * and it's two dwords in the beginning of the entry.
             * It's possible that UOP can include some entries with unknown hash: not really unknown for me, but
             * not useful for reading legacy entries. That's why i removed unknown hash exception throwing from this code
             */
            if (MulPath != null && MulPath.EndsWith(".uop"))
            {
                using (FileStream index = new FileStream(MulPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
                {
                    Stream = new FileStream(MulPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);

                    FileInfo fi         = new FileInfo(MulPath);
                    string   uopPattern = fi.Name.Replace(fi.Extension, "").ToLowerInvariant();

                    using (BinaryReader br = new BinaryReader(Stream))
                    {
                        br.BaseStream.Seek(0, SeekOrigin.Begin);

                        if (br.ReadInt32() != 0x50594D)
                        {
                            return;
                        }

                        br.ReadInt64(); // version + signature
                        long nextBlock = br.ReadInt64();
                        br.ReadInt32(); // block capacity
                        int count = br.ReadInt32();

                        if (idxLength > 0)
                        {
                            IdxLength = idxLength * 12;
                        }

                        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, uopEntryExtension);
                            ulong  hash      = UOPHash.HashLittle2(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;
                                }

                                if (hashes.TryGetValue(hash, out int idx))
                                {
                                    if (idx < 0 || idx > Index.Length)
                                    {
                                        return;
                                    }

                                    Index[idx].lookup = (int)(offset + headerLength);
                                    Index[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]);

                                        Index[idx].lookup += 8;
                                        Index[idx].extra   = extra1 << 16 | extra2;

                                        br.BaseStream.Seek(curPos, SeekOrigin.Begin);
                                    }
                                }
                            }
                        }while (br.BaseStream.Seek(nextBlock, SeekOrigin.Begin) != 0);
                    }
                }
            }
        }
Example #3
0
        public FileIndex(string uopFile, int length, string uopEntryExtension, int idxLength, bool hasExtra)
        {
            Index = new Entry3D[length];

            _Path = Core.FindDataFile(uopFile);

            if (_Path != null && _Path.EndsWith(".uop"))
            {
                using (var index = new FileStream(_Path, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    Stream = new FileStream(_Path, FileMode.Open, FileAccess.Read, FileShare.Read);

                    var fi = new FileInfo(_Path);

                    var uopPattern = fi.Name.Replace(fi.Extension, "").ToLowerInvariant();

                    using (var br = new BinaryReader(Stream))
                    {
                        br.BaseStream.Seek(0, SeekOrigin.Begin);

                        if (br.ReadInt32() != 0x50594D)
                        {
                            return;
                        }

                        br.ReadInt64();                         // version + signature

                        var nextBlock = br.ReadInt64();

                        br.ReadInt32();                         // block capacity

                        var count = br.ReadInt32();

                        if (idxLength > 0)
                        {
                            IdxLength = idxLength * 12;
                        }

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

                        for (var i = 0; i < length; i++)
                        {
                            var entryName = System.String.Format("build/{0}/{1:D8}{2}", uopPattern, i, uopEntryExtension);

                            var hash = UOPHash.HashLittle2(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();                                 // Adler32

                                var flag = br.ReadInt16();

                                var entryLength = flag == 1 ? compressedLength : decompressedLength;

                                if (offset == 0)
                                {
                                    continue;
                                }

                                if (hashes.TryGetValue(hash, out var idx))
                                {
                                    if (idx < 0 || idx > Index.Length)
                                    {
                                        return;
                                    }

                                    Index[idx].lookup = (int)(offset + headerLength);

                                    Index[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]);

                                        Index[idx].lookup += 8;
                                        Index[idx].extra   = extra1 << 16 | extra2;

                                        br.BaseStream.Seek(curPos, SeekOrigin.Begin);
                                    }
                                }
                            }
                        }while (br.BaseStream.Seek(nextBlock, SeekOrigin.Begin) != 0);
                    }
                }
            }
        }