public override ArcFile TryOpen(ArcView file) { if (!file.View.AsciiEqual(4, "PACK")) { return(null); } int length = file.View.ReadInt32(0x14); if (length < 0x10 || length >= file.MaxOffset) { return(null); } uint seed = file.View.ReadUInt32(8); var dec = new NekoEncryption32bit(seed); byte[] index = ReadBlock(file.View, dec, 0x10, out length); using (var reader = new IndexReader(file, dec, index, length)) { var dir = reader.Parse(0x18 + length); if (null == dir) { return(null); } byte[] buffer = new byte[0x10]; reader.DetectTypes(dir, entry => { file.View.Read(entry.Offset, buffer, 0, 0x10); uint hash = LittleEndian.ToUInt32(buffer, 0); if (0 != hash) { dec.Decrypt(hash, buffer, 8, 8); } return(LittleEndian.ToUInt32(buffer, 8)); }); return(new NekoArchive(file, this, dir, dec)); } }
public override ArcFile TryOpen(ArcView file) { if (!file.View.AsciiEqual(4, "PACK")) { return(null); } int length = file.View.ReadInt32(0x14); if (length <= 0 || length >= file.MaxOffset) { return(null); } uint id = file.View.ReadUInt32(8); var dec = new NekoEncryption32bit(id); byte[] index = ReadBlock(file.View, dec, 0x10, out length); long offset = 0x18 + length; var dir = new List <Entry>(); int index_pos = 0; for (int remaining = length; remaining > 0;) { int count = LittleEndian.ToInt32(index, index_pos + 4); if (count <= 0 || count > remaining / 8 - 1) { return(null); } uint hash = LittleEndian.ToUInt32(index, index_pos); dir.Capacity = dir.Count + count; index_pos += 8; for (int j = 0; j < count; ++j) { var entry = new Entry { Offset = offset, Size = LittleEndian.ToUInt32(index, index_pos + 4) }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } index_pos += 8; offset += entry.Size + 8; dir.Add(entry); } remaining -= 8 + count * 8; } int i = 0; byte[] buffer = new byte[0x10]; foreach (var entry in dir) { file.View.Read(entry.Offset, buffer, 0, 0x10); uint hash = LittleEndian.ToUInt32(buffer, 0); if (0 != hash) { dec.Decrypt(hash, buffer, 8, 8); } uint signature = LittleEndian.ToUInt32(buffer, 8); var res = AutoEntry.DetectFileType(signature); string ext = ""; if (null != res) { ext = res.Extensions.FirstOrDefault(); entry.Type = res.Type; } else if (0x474e4d8a == signature) { ext = "mng"; } if (!string.IsNullOrEmpty(ext)) { entry.Name = string.Format("{0:D4}.{1}", i, ext); } else { entry.Name = i.ToString("D4"); } ++i; } return(new NekoArchive(file, this, dir, dec)); }
public override ArcFile TryOpen(ArcView file) { if (!file.View.AsciiEqual (4, "PACK")) return null; int length = file.View.ReadInt32 (0x14); if (length <= 0 || length >= file.MaxOffset) return null; uint id = file.View.ReadUInt32 (8); var dec = new NekoEncryption32bit (id); byte[] index = ReadBlock (file.View, dec, 0x10, out length); long offset = 0x18 + length; var dir = new List<Entry>(); int index_pos = 0; for (int remaining = length; remaining > 0;) { int count = LittleEndian.ToInt32 (index, index_pos+4); if (count <= 0 || count > remaining/8-1) return null; uint hash = LittleEndian.ToUInt32 (index, index_pos); dir.Capacity = dir.Count + count; index_pos += 8; for (int j = 0; j < count; ++j) { var entry = new Entry { Offset = offset, Size = LittleEndian.ToUInt32 (index, index_pos+4) }; if (!entry.CheckPlacement (file.MaxOffset)) return null; index_pos += 8; offset += entry.Size + 8; dir.Add (entry); } remaining -= 8 + count * 8; } int i = 0; byte[] buffer = new byte[0x10]; foreach (var entry in dir) { file.View.Read (entry.Offset, buffer, 0, 0x10); uint hash = LittleEndian.ToUInt32 (buffer, 0); if (0 != hash) { dec.Decrypt (hash, buffer, 8, 8); } uint signature = LittleEndian.ToUInt32 (buffer, 8); var res = AutoEntry.DetectFileType (signature); string ext = ""; if (null != res) { ext = res.Extensions.FirstOrDefault(); entry.Type = res.Type; } else if (0x474e4d8a == signature) ext = "mng"; if (!string.IsNullOrEmpty (ext)) entry.Name = string.Format ("{0:D4}.{1}", i, ext); else entry.Name = i.ToString ("D4"); ++i; } return new NekoArchive (file, this, dir, dec); }