protected override FileIndexEntry3D[] ReadEntries() { int length = Length; string dataPath = DataPath; FileIndexEntry3D[] 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 (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, m_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(); 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 (m_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); }
protected override FileIndexEntry3D[] ReadEntries() { int length = Length; string dataPath = DataPath; FileIndexEntry3D[] 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 (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, m_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(); 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 (m_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; }