private Stream OpenV3Entry(ArcFile arc, PakEntry entry) { uint enc_size = Math.Min(entry.Size, 0x10u); if (0 == enc_size) { return(Stream.Null); } var buf = arc.File.View.ReadBytes(entry.Offset, enc_size); uint key = entry.Key; for (int i = 0; i < buf.Length; ++i) { buf[i] ^= (byte)key; key = Binary.RotR(key, 8); } if (enc_size == entry.Size) { return(new BinMemoryStream(buf, entry.Name)); } return(new PrefixStream(buf, arc.File.CreateStream(entry.Offset + enc_size, entry.Size - enc_size))); }
private List <Entry> OpenPakV3(ArcView file) { if (0x110 > file.View.Reserve(4, 0x110)) { return(null); } uint size_xor = file.View.ReadUInt32(0x104); if (0x64 != size_xor) { return(null); } byte[] name_buf = file.View.ReadBytes(4, 0x100); int name_len = 0; for (int i = 0; i < name_buf.Length; ++i) { if (0 == name_buf[i]) { break; } if (name_buf[i] >= 0x80 || name_buf[i] < 0x20) { return(null); } ++name_len; } if (0 == name_len || name_len > 0x10) { return(null); } uint header_key = GetKey(name_buf, name_len); uint unpacked = file.View.ReadUInt32(0x108) ^ header_key; int count = (int)(file.View.ReadUInt32(0x10c) ^ header_key); if (!IsSaneCount(count)) { return(null); } var dir = new List <Entry> (count); uint header_size = file.View.ReadUInt32(0x110) ^ size_xor; long base_offset = 0x114 + header_size; var input = file.CreateStream(0x114, header_size); using (var header_stream = new ZLibStream(input, CompressionMode.Decompress)) using (var header = new BinaryReader(header_stream, Encoding.ASCII, true)) { for (int i = 0; i < count; ++i) { name_len = header.ReadInt32(); if (name_len <= 0 || name_len > name_buf.Length) { return(null); } if (name_len != header.Read(name_buf, 0, name_len)) { return(null); } uint key = GetKey(name_buf, name_len); uint offset = header.ReadUInt32() ^ key; uint size = header.ReadUInt32() ^ key; uint val1 = header.ReadUInt32() ^ key; uint val2 = header.ReadUInt32() ^ key; uint val3 = header.ReadUInt32() ^ key; var entry = new PakEntry { Name = Encodings.cp932.GetString(name_buf, 0, name_len), Offset = base_offset + offset, Size = size, Key = key, }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } entry.Type = FormatCatalog.Instance.GetTypeFromName(entry.Name); dir.Add(entry); } return(dir); } }