Пример #1
0
        }                                                                 // '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,
            });
        }
Пример #2
0
        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);
        }
Пример #3
0
 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);
             }
 }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
 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);
 }
Пример #8
0
        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);
        }
Пример #9
0
 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);
     }
 }
Пример #10
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        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);
        }