} // 'METAL' public override ImageMetaData ReadMetaData(IBinaryStream file) { var header = file.ReadHeader(0x2C); if (!header.AsciiEqual("METAL") || header.ToInt32(0x10) != 0x28 || header[0x15] == 0) { return(null); } int name_length = header.ToInt32(0x28); if (name_length <= 0) { return(null); } var name = file.ReadCString(name_length); if (file.ReadInt32() != 0xC) { return(null); } int frame_count = file.ReadInt32(); if (!ArchiveFormat.IsSaneCount(frame_count)) { return(null); } var data_pos = file.Position + frame_count * 0x18; return(new MtlMetaData { Width = header.ToUInt32(0x20), Height = header.ToUInt32(0x24), BPP = 32, DataOffset = data_pos, }); }
public List <Entry> ReadIndexV1() { if (!ArchiveFormat.IsSaneCount((int)m_count)) { return(null); } uint index_size = m_count * 0x88; var index = m_file.View.ReadBytes(0x10, index_size); if (index.Length != index_size) { return(null); } Decrypt(index); int index_offset = 0; var dir = new List <Entry> ((int)m_count); for (uint i = 0; i < m_count; ++i) { var name = Binary.GetCString(index, index_offset, 0x80); var entry = FormatCatalog.Instance.Create <Entry> (name); entry.Offset = LittleEndian.ToUInt32(index, index_offset + 0x80); entry.Size = LittleEndian.ToUInt32(index, index_offset + 0x84); if (!entry.CheckPlacement(m_file.MaxOffset)) { return(null); } index_offset += 0x88; dir.Add(entry); } return(dir); }
public List <Entry> Read() { byte[] packed; using (var input = m_file.CreateStream(12, m_data_offset - 12)) using (var bits = new MsbBitStream(input)) { bits.GetNextBit(); m_dict = ReadBytes(bits); if (null == m_dict) { return(null); } int packed_size = ReadInt32(bits); int unpacked_size = ReadInt32(bits); packed = new byte[packed_size]; for (int i = 0; i < packed_size; ++i) { packed[i] = (byte)bits.GetBits(8); } } using (var bstr = new BinMemoryStream(packed)) using (var zstr = new ZLibStream(bstr, CompressionMode.Decompress)) using (var index = new MsbBitStream(zstr)) { index.GetNextBit(); int count = ReadInt32(index); if (!ArchiveFormat.IsSaneCount(count)) { return(null); } var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { if (index.GetBits(2) == -1) { break; } var name_buf = ReadEncryptedChars(index); if (null == name_buf) { return(null); } var name = DecryptString(name_buf, name_buf.Length); var entry = FormatCatalog.Instance.Create <Entry> (name); ReadInt32(index); ReadInt32(index); entry.Offset = (uint)ReadInt32(index) + m_data_offset; entry.Size = (uint)ReadInt32(index); if (!entry.CheckPlacement(m_file.MaxOffset)) { return(null); } dir.Add(entry); } return(dir); } }
public List <Entry> ReadIndex(uint entry_size) { int count = (int)(m_index.MaxOffset / entry_size); if (!ArchiveFormat.IsSaneCount(count)) { return(null); } if (null == m_dir) { m_dir = new List <Entry> (count); } else { m_dir.Clear(); } uint idx_offset = 0; for (int i = 0; i < count; ++i) { if (idx_offset + entry_size > m_index.MaxOffset) { return(null); } int name_offset = m_index.View.ReadInt32(idx_offset); if (name_offset < 0 || name_offset >= m_names.Length) { return(null); } var name = Binary.GetCString(m_names, name_offset, m_names.Length - name_offset); var entry = FormatCatalog.Instance.Create <PackedEntry> (name); entry.Offset = m_index.View.ReadUInt32(idx_offset + 4); entry.Size = m_index.View.ReadUInt32(idx_offset + 8); if (!entry.CheckPlacement(m_arc.MaxOffset)) { return(null); } entry.IsPacked = true; if (entry_size >= 0x14) { entry.UnpackedSize = m_index.View.ReadUInt32(idx_offset + 0x10); } if (name.EndsWith(".bmp.txt", StringComparison.OrdinalIgnoreCase)) { entry.Type = "image"; } m_dir.Add(entry); idx_offset += entry_size; } return(m_dir); }
public List <Entry> ReadIndexV2() { if (!ArchiveFormat.IsSaneCount((int)m_count)) { return(null); } uint names_size = m_file.View.ReadUInt32(0x10) ^ NextKey(); uint index_size = m_count * 12; var index = m_file.View.ReadBytes(0x14, index_size); if (index.Length != index_size) { return(null); } uint filenames_base = 0x14 + index_size; var names = m_file.View.ReadBytes(filenames_base, names_size); if (names.Length != names_size) { return(null); } Decrypt(index); int index_offset = 0; var dir = new List <Entry> ((int)m_count); for (uint i = 0; i < m_count; ++i) { int filename_offset = LittleEndian.ToInt32(index, index_offset); if (filename_offset < 0 || filename_offset >= names.Length) { return(null); } var name = Binary.GetCString(names, filename_offset, names.Length - filename_offset); if (0 == name.Length) { return(null); } var entry = FormatCatalog.Instance.Create <Entry> (name); entry.Offset = LittleEndian.ToUInt32(index, index_offset + 4); entry.Size = LittleEndian.ToUInt32(index, index_offset + 8); if (!entry.CheckPlacement(m_file.MaxOffset)) { return(null); } index_offset += 12; dir.Add(entry); } return(dir); }
bool ReadDir(string root, long base_offset) { m_input.BaseStream.Position = base_offset; if (0x5542494C != m_input.ReadUInt32()) // 'LIBU' { return(false); } m_input.ReadInt32(); int count = m_input.ReadInt32(); if (!ArchiveFormat.IsSaneCount(count)) { return(false); } if (m_dir.Capacity < m_dir.Count + count) { m_dir.Capacity = m_dir.Count + count; } long index_pos = base_offset + 0x10; for (int i = 0; i < count; ++i) { m_input.BaseStream.Position = index_pos; var name = ReadName(); uint entry_size = m_input.ReadUInt32(); long entry_offset = base_offset + m_input.ReadInt64(); index_pos = m_input.BaseStream.Position; bool has_extension = -1 != name.IndexOf('.'); name = Path.Combine(root, name); if (!has_extension && ReadDir(name, entry_offset)) { continue; } var entry = FormatCatalog.Instance.Create <Entry> (name); entry.Offset = entry_offset; entry.Size = entry_size; if (!entry.CheckPlacement(m_max_offset)) { return(false); } m_dir.Add(entry); } return(true); }
public PackIndexReader(PackOpener fmt, ArcView file, long index_offset) { m_fmt = fmt; m_file = file; m_pack_version = new Version(m_file.View.ReadByte(index_offset + 0xB) - '0', m_file.View.ReadByte(index_offset + 0xD) - '0'); m_count = m_file.View.ReadInt32(index_offset + 0x10); if (!ArchiveFormat.IsSaneCount(m_count)) { throw new InvalidFormatException(); } m_index_offset = m_file.View.ReadInt64(index_offset + 0x14); if (index_offset < 0 || index_offset >= m_file.MaxOffset) { throw new InvalidFormatException(); } m_index = m_file.CreateStream(m_index_offset); m_dir = new List <Entry> (m_count); }
public List <Entry> Read(byte[] index) { m_index = index; int count = LittleEndian.ToInt32(m_index, 0); if (!ArchiveFormat.IsSaneCount(count)) { return(null); } int index_offset = 4; int prefix_length = m_index[index_offset++]; if (0 != prefix_length) { m_info.Prefix = new byte[prefix_length]; Buffer.BlockCopy(m_index, index_offset, m_info.Prefix, 0, prefix_length); index_offset += prefix_length; } m_index_width = 0 != m_index[index_offset++] ? 4 : 2; int letter_table_length = LittleEndian.ToInt32(m_index, index_offset); index_offset += 4; m_entries_offset = index_offset + letter_table_length; if (m_entries_offset >= m_index.Length) { return(null); } if ((m_index.Length - m_entries_offset) / EntrySize < count) { EntrySize = (m_index.Length - m_entries_offset) / count; } if (EntrySize < 8 || m_info.PackedEntries && EntrySize < 12) { return(null); } m_dir = new List <Entry> (count); m_name = new byte[260]; TraverseIndex(index_offset, 0); return(m_dir.Count == count ? m_dir : null); }
public List <Entry> Read(byte[] index) { using (m_index = new BinMemoryStream(index)) { int count = m_index.ReadInt32(); if (!ArchiveFormat.IsSaneCount(count)) { return(null); } m_dir = new List <Entry> (count); if (m_info.IndexEncrypted) { ParseEncryptedIndex(count); } else { ParseRegularIndex(count); } return(m_dir.Count > 0 ? m_dir : null); } }
public bool Read() { int entry_size = m_index.ReadInt32(); if (entry_size < 0x11) { return(false); } int count = (int)m_index.Length / (entry_size + 4); if (!ArchiveFormat.IsSaneCount(count)) { return(false); } long next_pos = 0; m_dir = new List <Entry> (count); while (next_pos < m_index.Length) { m_index.Position = next_pos; entry_size = m_index.ReadInt32(); if (entry_size <= 0) { return(false); } next_pos += 4 + entry_size; var entry = ReadEntryInfo(); if (ReadEntryType(entry, entry_size)) { if (entry.CheckPlacement(MaxOffset)) { m_dir.Add(entry); } } } return(true); }
public static IndexReader Create(ArcView file) { int count, record_size; bool is_encrypted = false; if (!file.View.AsciiEqual(0, "PACK")) { var header = file.View.ReadBytes(0, 12); byte k1 = file.View.ReadByte(file.MaxOffset - 9); byte k2 = file.View.ReadByte(file.MaxOffset - 6); DecryptHeader(header, k1, k2); if (!header.AsciiEqual("PACK")) { return(null); } count = header.ToInt32(4); record_size = header.ToInt32(8); is_encrypted = true; } else { count = file.View.ReadInt32(4); record_size = file.View.ReadInt32(8); } if (!ArchiveFormat.IsSaneCount(count) || record_size <= 0x10 || record_size > 0x100) { return(null); } var reader = new IndexReader(file, count, record_size, is_encrypted); if (reader.m_data_offset >= file.MaxOffset) { return(null); } return(reader); }
public List <Entry> ReadIndex() { if (!ArchiveFormat.IsSaneCount(Count)) { return(null); } var sections = ReadSections(m_section_count); var list = new List <Entry> (Count); foreach (var section in sections) { m_input.Position = section.IndexOffset; var dir_names = m_input.ReadBytes(section.DirNamesSize); if (section.DirNamesSize != dir_names.Length) { return(null); } byte section_key = dir_names[section.DirNameLength - 1]; DecryptNames(dir_names, section_key); var dirs = new TcdDirEntry[section.DirCount]; for (int i = 0; i < dirs.Length; ++i) { dirs[i].FileCount = m_input.ReadInt32(); dirs[i].NamesOffset = m_input.ReadInt32(); dirs[i].FirstIndex = m_input.ReadInt32(); m_input.ReadInt32(); } var file_names = m_input.ReadBytes(section.FileNamesSize); if (file_names.Length != section.FileNamesSize) { return(null); } DecryptNames(file_names, section_key); var offsets = new uint[section.FileCount + 1]; for (int i = 0; i < offsets.Length; ++i) { offsets[i] = m_input.ReadUInt32(); } int dir_name_offset = 0; foreach (var dir in dirs) { string dir_name = GetName(dir_names, section.DirNameLength, ref dir_name_offset); int index = dir.FirstIndex; int name_offset = dir.NamesOffset; for (int i = 0; i < dir.FileCount; ++i) { string name = GetName(file_names, section.FileNameLength, ref name_offset); name = Path.Combine(dir_name, name); name = Path.ChangeExtension(name, section.Extension); var entry = FormatCatalog.Instance.Create <TcdEntry> (name); if (name.HasExtension(".SPD")) { entry.Type = "image"; } entry.Offset = offsets[index]; entry.Size = offsets[index + 1] - offsets[index]; entry.Index = index; ++index; list.Add(entry); } } } return(list); }
public override ImageMetaData ReadMetaData(IBinaryStream stream) { var header = stream.ReadHeader(0x20); int type = header.ToUInt16(0x10); if (0x0C == type) { int count = header.ToInt32(0); if (!ArchiveFormat.IsSaneCount(count)) { return(null); } int block_size = header.ToInt32(4); if (block_size <= 0) { return(null); } int bpp = header.ToUInt16(0x12); uint width = header.ToUInt16(0x14); uint height = header.ToUInt16(0x16); if (bpp != 32 || 0 == width || 0 == height) { return(null); } return(new PxMetaData { Width = width, Height = height, BPP = bpp, Type = type, FrameCount = count, BlockSize = block_size, BlocksWidth = header.ToUInt16(0x1C), BlocksHeight = header.ToUInt16(0x1E), }); } else if (0x90 == type) { if (!header.AsciiEqual(0x14, "Leaf")) { return(null); } int count = header.ToInt32(4); if (!ArchiveFormat.IsSaneCount(count)) { return(null); } var header_ex = stream.ReadBytes(0x20); if (0x20 != header_ex.Length) { return(null); } if (0x0A != LittleEndian.ToUInt16(header_ex, 0x10)) { return(null); } return(new PxMetaData { Width = LittleEndian.ToUInt32(header_ex, 0), Height = LittleEndian.ToUInt32(header_ex, 4), BPP = LittleEndian.ToUInt16(header_ex, 0x12), Type = type, FrameCount = count, }); } else if (0x40 == type || 0x44 == type) { int count = header.ToInt32(0); if (!ArchiveFormat.IsSaneCount(count)) { return(null); } return(new PxMetaData { Width = header.ToUInt32(0x14), Height = header.ToUInt32(0x18), Type = 0x40, BPP = 32, FrameCount = count, }); } else if (1 == type || 4 == type || 7 == type) { int bpp = header.ToUInt16(0x12); if (bpp != 32 && bpp != 8) { return(null); } return(new PxMetaData { Width = header.ToUInt32(0x14), Height = header.ToUInt32(0x18), Type = type, BPP = bpp, FrameCount = 1, }); } return(null); }