示例#1
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);
                    }
                }
            }
        }
示例#2
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());
        }
示例#3
0
        public static void UOPLoad(string path)
        {
            var stream       = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
            var streamReader = new BinaryReader(stream);

            // Head Information Start
            if (streamReader.ReadInt32() != 0x0050594D) // Not a UOP Files
            {
                return;
            }

            if (streamReader.ReadInt32() > 5) // Bad Version
            {
                return;
            }

            // Multi ID List Array Start
            var chunkIds  = new Dictionary <ulong, int>();
            var chunkIds2 = new Dictionary <ulong, int>();

            UOPHash.BuildChunkIDs(ref chunkIds, ref chunkIds2);
            // Multi ID List Array End

            streamReader.ReadUInt32();                      // format timestamp? 0xFD23EC43
            var startAddress = streamReader.ReadInt64();

            var blockSize = streamReader.ReadInt32();       // files in each block
            var totalSize = streamReader.ReadInt32();       // Total File Count

            stream.Seek(startAddress, SeekOrigin.Begin);    // Head Information End

            long nextBlock;

            do
            {
                var blockFileCount = streamReader.ReadInt32();
                nextBlock = streamReader.ReadInt64();

                var index = 0;

                do
                {
                    var offset = streamReader.ReadInt64();

                    var headerSize       = streamReader.ReadInt32();  // header length
                    var compressedSize   = streamReader.ReadInt32();  // compressed size
                    var decompressedSize = streamReader.ReadInt32();  // decompressed size

                    var filehash      = streamReader.ReadUInt64();    // filename hash (HashLittle2)
                    var datablockhash = streamReader.ReadUInt32();    // data hash (Adler32)
                    var flag          = streamReader.ReadInt16();     // compression method (0 = none, 1 = zlib)

                    index++;

                    if (offset == 0 || decompressedSize == 0 || filehash == 0x126D1E99DDEDEE0A) // Exclude housing.bin
                    {
                        continue;
                    }

                    // Multi ID Search Start
                    var chunkID = -1;

                    if (!chunkIds.TryGetValue(filehash, out chunkID))
                    {
                        if (chunkIds2.TryGetValue(filehash, out var tmpChunkID))
                        {
                            chunkID = tmpChunkID;
                        }
                    }
                    // Multi ID Search End

                    var positionpoint = stream.Position;  // save current position

                    // Decompress Data Start
                    stream.Seek(offset + headerSize, SeekOrigin.Begin);

                    var sourceData = new byte[compressedSize];

                    if (stream.Read(sourceData, 0, compressedSize) != compressedSize)
                    {
                        continue;
                    }

                    byte[] data;

                    if (flag == 1)
                    {
                        var destData = new byte[decompressedSize];
                        /*ZLibError error = */
                        Compression.Compressor.Decompress(destData, ref decompressedSize, sourceData, compressedSize);

                        data = destData;
                    }
                    else
                    {
                        data = sourceData;
                    }
                    // End Decompress Data

                    var tileList = new List <MultiTileEntry>();

                    using (var fs = new MemoryStream(data))
                    {
                        using (var reader = new BinaryReader(fs))
                        {
                            var a     = reader.ReadUInt32();
                            var count = reader.ReadUInt32();

                            for (uint i = 0; i < count; i++)
                            {
                                var ItemId = reader.ReadUInt16();
                                var x      = reader.ReadInt16();
                                var y      = reader.ReadInt16();
                                var z      = reader.ReadInt16();

                                var flagint = reader.ReadUInt16();

                                TileFlag flagg;

                                switch (flagint)
                                {
                                default:
                                case 0:
                                    flagg = TileFlag.Background;
                                    break;

                                case 1:
                                    flagg = TileFlag.None;
                                    break;

                                case 257:
                                    flagg = TileFlag.Generic;
                                    break;
                                }

                                var clilocsCount = reader.ReadUInt32();

                                if (clilocsCount != 0)
                                {
                                    fs.Seek(fs.Position + (clilocsCount * 4), SeekOrigin.Begin); // binary block bypass
                                }

                                tileList.Add(new MultiTileEntry(ItemId, x, y, z, flagg));
                            }

                            reader.Close();
                        }
                    }

                    Components[chunkID] = new MultiComponentList(tileList);

                    stream.Seek(positionpoint, SeekOrigin.Begin); // back to position
                }while (index < blockFileCount);
            }while (stream.Seek(nextBlock, SeekOrigin.Begin) != 0);

            chunkIds.Clear();
            chunkIds2.Clear();
        }
示例#4
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);
                    }
                }
            }
        }