Пример #1
0
            public bool ReadDir(string root, uint dir_offset, uint base_offset)
            {
                m_index.Position = dir_offset;
                int dir_count = m_index.ReadInt32();

                dir_offset += 4;
                for (int i = 0; i < dir_count; ++i)
                {
                    var  name        = m_index.ReadCString(0x20);
                    uint offset      = m_index.ReadUInt32();
                    uint data_offset = m_index.ReadUInt32();
                    if (offset <= dir_offset || offset > m_index.Length || data_offset > m_max_offset)
                    {
                        return(false);
                    }
                    if (!ReadDir(Path.Combine(root, name), offset, data_offset))
                    {
                        return(false);
                    }
                    dir_offset      += 0x28;
                    m_index.Position = dir_offset;
                }
                int count = m_index.ReadInt32();

                if (0 == count)
                {
                    return(true);
                }
                if (!IsSaneCount(count))
                {
                    return(false);
                }
                for (int i = 0; i < count; ++i)
                {
                    var name = m_index.ReadCString(0x20);
                    name = Path.Combine(root, name);
                    var entry = FormatCatalog.Instance.Create <Entry> (name);
                    entry.Offset = m_index.ReadUInt32() + base_offset;
                    entry.Size   = m_index.ReadUInt32();
                    if (!entry.CheckPlacement(m_max_offset))
                    {
                        return(false);
                    }
                    if (name.HasExtension(".hse"))
                    {
                        entry.Type = "image";
                    }
                    m_dir.Add(entry);
                }
                return(true);
            }
Пример #2
0
        internal static object ReadField(this IBinaryStream input, FieldInfo field)
        {
            var field_type = field.FieldType;
            var type_code  = Type.GetTypeCode(field_type);

            switch (type_code)
            {
            case TypeCode.SByte:    return(input.ReadInt8());

            case TypeCode.Byte:     return(input.ReadUInt8());

            case TypeCode.Int16:    return(input.ReadInt16());

            case TypeCode.UInt16:   return(input.ReadUInt16());

            case TypeCode.Int32:    return(input.ReadInt32());

            case TypeCode.UInt32:   return(input.ReadUInt32());

            case TypeCode.Int64:    return(input.ReadInt64());

            case TypeCode.UInt64:   return(input.ReadUInt64());

            case TypeCode.Char:     return((char)input.ReadInt16());

            case TypeCode.String:
                var cstring_attr = field.GetCustomAttribute <CStringAttribute>();
                if (cstring_attr != null)
                {
                    var encoding = cstring_attr.Encoding ?? Encodings.cp932;
                    if (cstring_attr.IsLengthDefined)
                    {
                        return(input.ReadCString(cstring_attr.Length, encoding));
                    }
                    else
                    {
                        return(input.ReadCString(encoding));
                    }
                }
                throw new FormatException("Serialization method for string field is not defined.");

            case TypeCode.Object:
                object val = Activator.CreateInstance(field_type);
                ReadStruct(input, field_type, ref val);  // FIXME check object graph for cycles
                return(val);

            default:
                throw new NotSupportedException("Not supported serialization type.");
            }
        }
Пример #3
0
        List <Entry> ReadIndex(IBinaryStream index, long max_offset, int align)
        {
            var index_length = index.Length;
            int index_pos    = 0;
            var dir          = new List <Entry>();

            while (index_pos < index_length)
            {
                index.Position = index_pos;
                uint offset = index.ReadUInt32();
                if (0 == offset)
                {
                    break;
                }
                uint size        = index.ReadUInt32();
                byte name_length = index.ReadUInt8();
                var  name        = index.ReadCString(name_length);
                index_pos += ((align + 1 + name_length) & -align) + 8;
//                index_pos += ((9 + name_length) & ~7) + 8;
//                index_pos += ((5 + name_length) & ~3) + 8;

                var entry = FormatCatalog.Instance.Create <Entry> (name);
                entry.Offset = offset;
                entry.Size   = size;
                if (!entry.CheckPlacement(max_offset))
                {
                    return(null);
                }
                dir.Add(entry);
            }
            return(dir);
        }
Пример #4
0
        protected virtual string ReadName()
        {
            int name_length = m_input.ReadUInt8();

            Skip(2);
            return(m_input.ReadCString(name_length));
        }
Пример #5
0
 byte[] ReadBaseImage(IBinaryStream file, RctMetaData meta)
 {
     try
     {
         file.Position = meta.DataOffset;
         var    name     = file.ReadCString(meta.BaseNameLength);
         string dir_name = VFS.GetDirectoryName(meta.FileName);
         name = VFS.CombinePath(dir_name, name);
         if (VFS.FileExists(name))
         {
             using (var base_file = VFS.OpenBinaryStream(name))
             {
                 var base_info = ReadMetaData(base_file) as RctMetaData;
                 if (null != base_info &&
                     meta.Width == base_info.Width && meta.Height == base_info.Height)
                 {
                     base_info.BaseRecursionDepth = meta.BaseRecursionDepth + 1;
                     base_info.FileName           = name;
                     return(ReadPixelsData(base_file, base_info));
                 }
             }
         }
     }
     catch { /* ignore baseline image read errors */ }
     return(null);
 }
Пример #6
0
        public override ImageMetaData ReadMetaData(IBinaryStream file)
        {
            var  info           = new AkbMetaData();
            bool is_incremental = '+' == (file.ReadUInt32() >> 24);

            info.Width       = file.ReadUInt16();
            info.Height      = file.ReadUInt16();
            info.Flags       = file.ReadUInt32();
            info.BPP         = 0 == (info.Flags & 0x40000000) ? 32 : 24;
            info.Background  = file.ReadBytes(4);
            info.OffsetX     = file.ReadInt32();
            info.OffsetY     = file.ReadInt32();
            info.InnerWidth  = file.ReadInt32() - info.OffsetX;
            info.InnerHeight = file.ReadInt32() - info.OffsetY;
            if (info.InnerWidth > info.Width || info.InnerHeight > info.Height)
            {
                return(null);
            }
            if (is_incremental)
            {
                info.BaseFileName = file.ReadCString(0x20);
            }
            info.DataOffset = (uint)file.Position;
            return(info);
        }
Пример #7
0
 public List <Entry> Read(IBinaryStream input, int count)
 {
     m_dir.Clear();
     if (m_dir.Capacity < count)
     {
         m_dir.Capacity = count;
     }
     try
     {
         for (int i = 0; i < count; ++i)
         {
             uint offset = input.ReadUInt32();
             uint size   = input.ReadUInt32();
             var  name   = input.ReadCString(0x18);
             var  entry  = FormatCatalog.Instance.Create <Entry> (name);
             entry.Offset = offset;
             entry.Size   = size;
             if (!entry.CheckPlacement(m_arc_length))
             {
                 return(null);
             }
             m_dir.Add(entry);
         }
         return(m_dir);
     }
     catch
     {
         return(null);
     }
 }
Пример #8
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,
            });
        }
Пример #9
0
        public void Parse(IBinaryStream index)
        {
            index.Position = 16;
            int segment_count = Binary.BigEndian(index.ReadInt32());

            m_segments = new List <BundleSegment> (segment_count);
            long packed_offset   = m_data_offset;
            long unpacked_offset = 0;

            for (int i = 0; i < segment_count; ++i)
            {
                var segment = new BundleSegment();
                segment.Offset         = packed_offset;
                segment.UnpackedOffset = unpacked_offset;
                segment.UnpackedSize   = Binary.BigEndian(index.ReadUInt32());
                segment.PackedSize     = Binary.BigEndian(index.ReadUInt32());
                segment.Compression    = Binary.BigEndian(index.ReadUInt16());
                m_segments.Add(segment);
                packed_offset   += segment.PackedSize;
                unpacked_offset += segment.UnpackedSize;
            }
            int count = Binary.BigEndian(index.ReadInt32());

            m_bundles = new List <BundleEntry> (count);
            for (int i = 0; i < count; ++i)
            {
                var entry = new BundleEntry();
                entry.Offset = Binary.BigEndian(index.ReadInt64());
                entry.Size   = (uint)Binary.BigEndian(index.ReadInt64());
                entry.Flags  = Binary.BigEndian(index.ReadUInt32());
                entry.Name   = index.ReadCString(Encoding.UTF8);
                m_bundles.Add(entry);
            }
        }
Пример #10
0
        internal Dictionary <string, List <Entry> > ReadSysIni(IBinaryStream index)
        {
            int arc_count = index.ReadInt32();

            if (!IsSaneCount(arc_count))
            {
                return(null);
            }
            var file_table = new Dictionary <string, List <Entry> > (arc_count, StringComparer.OrdinalIgnoreCase);
            var arc_list   = new List <Entry> [arc_count];

            for (int i = 0; i < arc_count; ++i)
            {
                var name      = index.ReadCString(0x100);
                var file_list = new List <Entry>();
                file_table.Add(name, file_list);
                arc_list[i] = file_list;
            }
            int file_count = index.ReadInt32();

            if (!IsSaneCount(file_count))
            {
                return(null);
            }
            for (int i = 0; i < file_count; ++i)
            {
                var name   = index.ReadCString(0x40);
                int arc_id = index.ReadInt32();
                if (arc_id < 0 || arc_id >= arc_list.Length)
                {
                    return(null);
                }
                index.ReadInt32(); // file number
                uint offset = index.ReadUInt32();
                uint size   = index.ReadUInt32();
                if ("@" == name)
                {
                    continue;
                }
                var entry = Create <Entry> (name);
                entry.Offset = offset;
                entry.Size   = size;
                arc_list[arc_id].Add(entry);
            }
            return(file_table);
        }
Пример #11
0
        }                                                                 // 'Divided Picture'

        public override ImageMetaData ReadMetaData(IBinaryStream file)
        {
            var header = file.ReadHeader(0x30);

            if (!header.AsciiEqual("Divided Picture") || header.ToInt32(0x10) != 1)
            {
                return(null);
            }
            int version = header.ToInt32(0x14);

            if (version != 1 && version != 2)
            {
                return(null);
            }
            int info_pos = header.ToInt32(0x18);

            if (header.ToInt32(0x1C) < 4)
            {
                return(null);
            }
            int name_table_pos  = header.ToInt32(0x20);
            int name_table_size = header.ToInt32(0x24);
            int layout_pos      = header.ToInt32(0x28);

            file.Position = info_pos;
            ushort width  = file.ReadUInt16();
            ushort height = file.ReadUInt16();

            file.Position = name_table_pos;
            int name_count = file.ReadUInt16();

            if (name_count * 32 + 2 != name_table_size)
            {
                return(null);
            }
            var dir_name = VFS.GetDirectoryName(file.Name);
            var files    = new List <string> (name_count);

            for (int i = 0; i < name_count; ++i)
            {
                var name = file.ReadCString(0x20);
                if (name.StartsWith(@".\"))
                {
                    name = name.Substring(2);
                }
                name = VFS.CombinePath(dir_name, name);
                files.Add(name);
            }
            return(new DpoMetaData {
                Width = width,
                Height = height,
                BPP = 32,
                Version = version,
                LayoutOffset = layout_pos,
                Files = files,
            });
        }
Пример #12
0
 void ParseRegularIndex(int count)
 {
     for (int i = 0; i < count; ++i)
     {
         int name_length = m_index.ReadByte();
         var name        = m_index.ReadCString(name_length);
         var entry       = FormatCatalog.Instance.Create <EpkEntry> (name);
         ReadEntry(entry);
         m_dir.Add(entry);
     }
 }
Пример #13
0
        public List <Entry> Deserialize()
        {
            m_index.Position = 8;
            int count = Binary.BigEndian(m_index.ReadInt32());

            m_name_list = new string[count];
            for (int i = 0; i < count; ++i)
            {
                int length = m_index.ReadUInt8();
                m_name_list[i] = m_index.ReadCString(length, Encoding.UTF8);
            }

            count = Binary.BigEndian(m_index.ReadInt32());
            m_dir = new List <Entry> (count);
            for (int i = 0; i < count; ++i)
            {
                m_index.ReadUInt16();
                ushort flags  = Binary.BigEndian(m_index.ReadUInt16());
                uint   offset = Binary.BigEndian(m_index.ReadUInt32());
                uint   size   = Binary.BigEndian(m_index.ReadUInt32());
                var    entry  = new SxEntry {
                    Flags        = flags,
                    Offset       = (long)offset << 4,
                        Size     = size,
                        IsPacked = 0 != (flags & 0x03),
                };
                if (!entry.CheckPlacement(m_max_offset))
                {
                    return(null);
                }
                m_dir.Add(entry);
            }

            count = Binary.BigEndian(m_index.ReadUInt16());
            for (int i = 0; i < count; ++i)
            {
                m_index.ReadUInt32();
                m_index.ReadUInt32();
                m_index.ReadUInt32();
                Binary.BigEndian(m_index.ReadUInt32()); // archive body length
                m_index.ReadUInt64();
                m_index.Seek(16, SeekOrigin.Current);   // MD5 sum
            }

            count = Binary.BigEndian(m_index.ReadUInt16());
            if (count > 0)
            {
                m_index.Seek(count * 24, SeekOrigin.Current);
            }
            DeserializeTree();
            return(m_dir);
        }
Пример #14
0
        string ReadString()
        {
            var len_str = m_ini.ReadCString(4);
            int length  = Convert.ToInt32(len_str);
            var buf     = m_ini.ReadBytes(length);

            if (buf.Length != length)
            {
                throw new InvalidFormatException();
            }
            for (int i = 0; i < length; ++i)
            {
                buf[i] ^= 0xD1;
            }
            return(Encodings.cp932.GetString(buf));
        }
Пример #15
0
        string DeserializeString(IBinaryStream input)
        {
            int length = DeserializeLength(input);

            if (0 == length)
            {
                return("");
            }
            if (length != -1)
            {
                return(input.ReadCString(length));
            }
            length = DeserializeLength(input) * 2;
            var chars = input.ReadBytes(length);

            return(Encoding.Unicode.GetString(chars, 0, length));
        }
Пример #16
0
 bool ReadFromStream(IBinaryStream index, int name_length)
 {
     m_dir.Clear();
     for (int i = 0; i < m_count; ++i)
     {
         var name = index.ReadCString(name_length);
         if (string.IsNullOrWhiteSpace(name))
         {
             return(false);
         }
         var entry = FormatCatalog.Instance.Create <PackedEntry> (name);
         entry.Offset       = index.ReadUInt32();
         entry.UnpackedSize = index.ReadUInt32();
         entry.Size         = index.ReadUInt32();
         if (!entry.CheckPlacement(m_file.MaxOffset))
         {
             return(false);
         }
         entry.IsPacked = m_pack_type != 0 && (m_pack_type != 4 || entry.Size != entry.UnpackedSize);
         m_dir.Add(entry);
     }
     return(true);
 }
Пример #17
0
 /// <summary>
 /// Read null-terminated UTF8 string.
 /// </summary>
 public string ReadCString()
 {
     return(m_input.ReadCString(Encoding.UTF8));
 }
Пример #18
0
        public List <Entry> ReadIndex()
        {
            m_input.Position = 0x10;
            int n        = 0;
            var type_buf = new byte[0x10];

            while (0x10 == m_input.Read(type_buf, 0, 0x10))
            {
                if (Binary.AsciiEqual(type_buf, "abdata"))
                {
                    uint size  = m_input.ReadUInt32();
                    var  entry = new Entry {
                        Name   = string.Format("{0}#{1}.dat", m_base_name, n++),
                        Offset = m_input.Position,
                        Size   = size,
                    };
                    m_dir.Add(entry);
                    Skip(size);
                }
                else if (Binary.AsciiEqual(type_buf, "abimage10\0") ||
                         Binary.AsciiEqual(type_buf, "absound10\0"))
                {
                    int count = m_input.ReadByte();
                    for (int i = 0; i < count; ++i)
                    {
                        if (0x10 != m_input.Read(type_buf, 0, 0x10))
                        {
                            break;
                        }
                        var    tag  = Binary.GetCString(type_buf, 0, 0x10, Encoding.ASCII);
                        string name = null;
                        if ("abimgdat15" == tag)
                        {
                            Skip(4);
                            int name_length = m_input.ReadUInt16();
                            if (name_length > 0)
                            {
                                var name_bytes = m_input.ReadBytes(name_length * 2);
                                name = Encoding.Unicode.GetString(name_bytes);
                            }
                            name_length = m_input.ReadUInt16();
                            if (name_length > 0)
                            {
                                if (string.IsNullOrEmpty(name))
                                {
                                    name = m_input.ReadCString(name_length);
                                }
                                else
                                {
                                    Skip((uint)name_length);
                                }
                            }
                            byte type = m_input.ReadUInt8();

                            /*
                             * case 0:   ".bmp"
                             * case 1:   ".jpg"
                             * case 2:
                             * case 3:   ".png"
                             * case 4:   ".m"
                             * case 5:   ".argb"
                             * case 6:   ".b"
                             * case 7:   ".ogv"
                             * case 8:   ".mdl"
                             */
                            Skip(0x11);
                        }
                        else
                        {
                            int name_length = m_input.ReadUInt16();
                            name = m_input.ReadCString(name_length);

                            if (tag != "abimgdat10" && tag != "absnddat10")
                            {
                                Skip(m_input.ReadUInt16());
                                if ("abimgdat13" == tag)
                                {
                                    Skip(0x0C);
                                }
                                else if ("abimgdat14" == tag)
                                {
                                    Skip(0x4C);
                                }
                            }
                            m_input.ReadByte();
                        }
                        var size = m_input.ReadUInt32();
                        if (0 != size)
                        {
                            if (string.IsNullOrEmpty(name))
                            {
                                name = string.Format("{0}#{1}", m_base_name, n++);
                            }
                            else
                            {
                                name = s_InvalidChars.Replace(name, "_");
                            }
                            var entry = new Entry {
                                Name   = name,
                                Type   = tag.StartsWith("abimg") ? "image" : tag.StartsWith("absnd") ? "audio" : "",
                                Offset = m_input.Position,
                                Size   = size,
                            };
                            if (entry.CheckPlacement(m_file.MaxOffset))
                            {
                                DetectFileType(m_file, entry);
                                m_dir.Add(entry);
                            }
                        }
                        Skip(size);
                    }
                }
                else
                {
                    var entry = new Entry {
                        Name   = string.Format("{0}#{1}#{2}", m_base_name, n++, GetTypeName(type_buf)),
                        Offset = m_input.Position,
                        Size   = (uint)(m_file.MaxOffset - m_input.Position),
                    };
                    m_dir.Add(entry);
                    Skip(entry.Size);
                }
            }
            return(m_dir);
        }
Пример #19
0
        protected virtual string ReadString()
        {
            int length = m_input.ReadUInt8();

            return(m_input.ReadCString(length));
        }
Пример #20
0
 string ReadString(int length)
 {
     return(m_input.ReadCString(length, Encoding));
 }