Пример #1
0
        IarImage CombineImage(IarImage overlay, IarArchive iarc)
        {
            using (var input = new BinMemoryStream(overlay.Data))
            {
                var dir        = (List <Entry>)iarc.Dir;
                int base_index = input.ReadInt32();
                if (base_index >= dir.Count)
                {
                    throw new InvalidFormatException("Invalid base image index");
                }
                int diff_y     = input.ReadInt32();
                int diff_count = input.ReadInt32();

                var    overlay_info = overlay.Info;
                int    pixel_size   = overlay_info.BPP / 8;
                var    base_image   = new IarImage(iarc, dir[base_index]);
                byte[] output       = base_image.Data;
                if (overlay_info.Height != base_image.Info.Height || overlay_info.Stride != base_image.Info.Stride)
                {
                    int    src_height = (int)Math.Min(overlay_info.Height, base_image.Info.Height);
                    int    src_stride = Math.Min(overlay_info.Stride, base_image.Info.Stride);
                    byte[] src        = base_image.Data;
                    output = new byte[overlay_info.Height * overlay_info.Stride];
                    int dst_pos = 0;
                    if (base_image.Info.OffsetY < overlay_info.OffsetY)
                    {
                        dst_pos += (-base_image.Info.OffsetY + overlay_info.OffsetY) * overlay_info.Stride;
                    }
                    if (base_image.Info.OffsetX < overlay_info.OffsetX)
                    {
                        dst_pos += (-base_image.Info.OffsetX + overlay_info.OffsetX) * pixel_size;
                    }
                    for (int y = 0; y < src_height; ++y)
                    {
                        Buffer.BlockCopy(src, y * base_image.Info.Stride, output, dst_pos, src_stride);
                        dst_pos += overlay_info.Stride;
                    }
                }
                int dst = diff_y * overlay_info.Stride;
                for (int i = 0; i < diff_count; ++i)
                {
                    int chunk_count = input.ReadUInt16();
                    int x           = 0;
                    for (int j = 0; j < chunk_count; ++j)
                    {
                        int skip_count = pixel_size * input.ReadUInt16();
                        int copy_count = pixel_size * input.ReadUInt16();

                        x += skip_count;
                        input.Read(output, dst + x, copy_count);
                        x += copy_count;
                    }
                    dst += overlay_info.Stride;
                }
                return(new IarImage(overlay_info, output, overlay.Palette));
            }
        }
Пример #2
0
 /// <summary>
 // Try to parse file containing game meta-information.
 /// </summary>
 internal string TryParseMeta(string meta_arc_name)
 {
     if (!VFS.FileExists(meta_arc_name))
     {
         return(null);
     }
     using (var unpacker = new TocUnpacker(meta_arc_name))
     {
         if (unpacker.Length > 0x1000)
         {
             return(null);
         }
         var data = unpacker.Unpack(8);
         if (null == data)
         {
             return(null);
         }
         using (var content = new BinMemoryStream(data))
         {
             int title_length = content.ReadInt32();
             if (title_length <= 0 || title_length > content.Length)
             {
                 return(null);
             }
             var title = content.ReadBytes(title_length);
             if (title.Length != title_length)
             {
                 return(null);
             }
             return(Encodings.cp932.GetString(title));
         }
     }
 }
Пример #3
0
        public void UnpackAlpha(int offset)
        {
            using (var input = new BinMemoryStream(this.Input, offset, Input.Length - offset))
            {
                if (1 != input.ReadInt32())
                {
                    return;
                }
                int dst = 3;
                int ctl = 1 << 1;
                while (dst < Output.Length)
                {
                    ctl >>= 1;
                    if (1 == ctl)
                    {
                        ctl = input.ReadUInt8() | 0x100;
                    }

                    if (0 != (ctl & 1))
                    {
                        int v = input.ReadUInt16();
                        int x = v & 0x3F;
                        if (x > 0x1F)
                        {
                            x |= -0x40;
                        }
                        int y = (v >> 6) & 7;
                        if (y != 0)
                        {
                            y |= -8;
                        }
                        int count = ((v >> 9) & 0x7F) + 3;

                        int src = dst + (x + y * Width) * 4;
                        if (src < 0 || src >= dst)
                        {
                            return;
                        }

                        for (int i = 0; i < count; ++i)
                        {
                            Output[dst] = Output[src];
                            src        += 4;
                            dst        += 4;
                        }
                    }
                    else
                    {
                        Output[dst] = input.ReadUInt8();
                        dst        += 4;
                    }
                }
                HasAlpha = true;
            }
        }
Пример #4
0
        public override ArcFile TryOpen(ArcView file)
        {
            if ((file.View.ReadInt32(0) | file.View.ReadInt32(4) | file.View.ReadInt32(8)) != 0)
            {
                return(null);
            }
            int key   = file.View.ReadInt32(0x10);
            int count = file.View.ReadInt32(0x14);

            if (!IsSaneCount(count))
            {
                return(null);
            }
            uint index_offset = 0x18;
            var  index        = new Dictionary <int, Entry> (count);

            for (int i = 0; i < count; ++i)
            {
                int id    = file.View.ReadInt32(index_offset);
                var entry = new Entry {
                    Offset = file.View.ReadUInt32(index_offset + 4),
                    Size   = file.View.ReadUInt32(index_offset + 8),
                };
                if (!entry.CheckPlacement(file.MaxOffset))
                {
                    return(null);
                }
                index[id]     = entry;
                index_offset += 12;
            }
            var names_entry = index[0];
            var names       = file.View.ReadBytes(names_entry.Offset, names_entry.Size);

            if (key != 0)
            {
                DecryptData(names, key);
            }
            using (var input = new BinMemoryStream(names))
            {
                while (input.PeekByte() != -1)
                {
                    int id   = input.ReadInt32();
                    var name = input.ReadCString();
                    if (!string.IsNullOrEmpty(name))
                    {
                        var entry = index[id];
                        entry.Name = name;
                        entry.Type = FormatCatalog.Instance.GetTypeFromName(name);
                    }
                }
            }
            var dir = index.Values.Where(e => !string.IsNullOrEmpty(e.Name)).ToList();

            return(new YkArchive(file, this, dir, key));
        }
Пример #5
0
        void LoadBlob(AssetReader reader)
        {
            int count        = reader.ReadInt32();
            int buffer_bytes = reader.ReadInt32();
            var node_data    = reader.ReadBytes(24 * count);

            m_data = reader.ReadBytes(buffer_bytes);

            var parents = new Stack <TypeTree>();

            parents.Push(this);
            using (var buf = new BinMemoryStream(node_data))
            {
                for (int i = 0; i < count; ++i)
                {
                    int      version = buf.ReadInt16();
                    int      depth   = buf.ReadUInt8();
                    TypeTree current;
                    if (0 == depth)
                    {
                        current = this;
                    }
                    else
                    {
                        while (parents.Count > depth)
                        {
                            parents.Pop();
                        }
                        current = new TypeTree(m_format);
                        parents.Peek().Children.Add(current);
                        parents.Push(current);
                    }
                    current.Version = version;
                    current.IsArray = buf.ReadUInt8() != 0;
                    current.Type    = GetString(buf.ReadInt32());
                    current.Name    = GetString(buf.ReadInt32());
                    current.Size    = buf.ReadInt32();
                    current.Index   = buf.ReadUInt32();
                    current.Flags   = buf.ReadInt32();
                }
            }
        }
Пример #6
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.View.AsciiEqual(4, "ARC\0"))
            {
                return(null);
            }
            uint data_offset   = file.View.ReadUInt32(8);
            uint unpacked_size = file.View.ReadUInt32(0xC);
            uint packed_size   = file.View.ReadUInt32(0x10);

            byte[] unpacked = new byte[unpacked_size];
            using (var packed = file.CreateStream(0x14, packed_size))
                using (var input = new XoredStream(packed, 0xFF))
                {
                    LzssUnpack(input, unpacked);
                }
            using (var index = new BinMemoryStream(unpacked))
            {
                var key   = index.ReadBytes(256);
                int count = index.ReadInt32();
                if (!IsSaneCount(count))
                {
                    return(null);
                }
                var dir = new List <Entry> (count);
                for (int i = 0; i < count; ++i)
                {
                    int name_length = index.ReadInt32();
                    var name        = index.ReadCString(name_length);
                    var entry       = FormatCatalog.Instance.Create <GmlEntry> (name);
                    entry.Offset = index.ReadUInt32() + data_offset;
                    entry.Size   = index.ReadUInt32();
                    if (!entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                    dir.Add(entry);
                    entry.Header = index.ReadBytes(4);
                }
                return(new GmlArchive(file, this, dir, key));
            }
        }
Пример #7
0
        IarImage CombineLayers(IarImage layers, IarArchive iarc)
        {
            layers.Info.Stride = (int)layers.Info.Width * 4;
            layers.Info.BPP    = 32;
            var pixels = new byte[layers.Info.Stride * (int)layers.Info.Height];
            var output = new IarImage(layers.Info, pixels);

            using (var input = new BinMemoryStream(layers.Data))
            {
                int offset_x = 0, offset_y = 0;
                var dir = (List <Entry>)iarc.Dir;
                while (input.Position < input.Length)
                {
                    int cmd = input.ReadUInt8();
                    switch (cmd)
                    {
                    case 0x21:
                        offset_x += input.ReadInt16();
                        offset_y += input.ReadInt16();
                        break;

                    case 0x00:
                    case 0x20:
                    {
                        int index = input.ReadInt32();
                        if (index < 0 || index >= dir.Count)
                        {
                            throw new InvalidFormatException("Invalid image layer index");
                        }
                        var layer = new IarImage(iarc, dir[index]);
                        layer.Info.OffsetX -= offset_x;
                        layer.Info.OffsetY -= offset_y;
                        if (0x20 == cmd)
                        {
                            output.ApplyMask(layer);
                        }
                        else
                        {
                            output.Blend(layer);
                        }
                    }
                    break;

                    default:
                        Trace.WriteLine(string.Format("Unknown layer type 0x{0:X2}", cmd), "IAR");
                        break;
                    }
                }
                return(output);
            }
        }
Пример #8
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (file.MaxOffset <= 12 || file.MaxOffset > uint.MaxValue)
            {
                return(null);
            }
            uint       packed_size       = file.View.ReadUInt32(file.MaxOffset - 12) ^ 0xF0F0F0F0;
            uint       unpacked_size     = file.View.ReadUInt32(file.MaxOffset - 8) ^ 0xF0F0F0F0;
            const uint entry_record_size = 0x50;
            int        count             = (int)(unpacked_size / entry_record_size);

            if (unpacked_size % entry_record_size != 0 || packed_size >= file.MaxOffset || !IsSaneCount(count))
            {
                return(null);
            }

            var unpacked = new byte[unpacked_size];

            using (var packed = file.CreateStream(file.MaxOffset - 12 - packed_size, packed_size))
                LzUnpack(packed, unpacked);
            using (var index = new BinMemoryStream(unpacked))
            {
                var dir = new List <Entry> (count);
                for (int i = 0; i < count; ++i)
                {
                    int flags = index.ReadInt32();
                    var name  = index.ReadCString(0x40);
                    var entry = FormatCatalog.Instance.Create <PmDatEntry> (name);
                    entry.Offset       = index.ReadUInt32();
                    entry.Size         = index.ReadUInt32();
                    entry.UnpackedSize = index.ReadUInt32();
                    if (!entry.CheckPlacement(file.MaxOffset))
                    {
                        return(null);
                    }
                    if (entry.Name.HasAnyOfExtensions("CRGB", "CHAR", "rol", "edg"))
                    {
                        entry.Type = "image";
                    }
                    entry.IsPacked   = (flags & 0xFF0000) != 0;
                    entry.StoredSize = (flags & 0x2000000) != 0;
                    dir.Add(entry);
                }
                return(new ArcFile(file, this, dir));
            }
        }
Пример #9
0
        void UnpackV2()
        {
            Format = PixelFormats.Bgra32;
            int tile_count = m_input.ReadInt32();
            var tiles      = new List <Tile> (tile_count);

            for (int i = 0; i < tile_count; ++i)
            {
                var tile = new Tile();
                tile.X = m_input.ReadInt32();
                tile.Y = m_input.ReadInt32();
                tiles.Add(tile);
                m_input.Seek(0x10, SeekOrigin.Current);
            }
            using (var input = new BinMemoryStream(LzDecompress(m_input, 2, 1)))
            {
                if (input.ReadInt32() != tile_count)
                {
                    throw new InvalidFormatException();
                }
                int dst_stride = m_width * 4;
                m_output = new byte[m_height * dst_stride];
                for (int i = 0; i < tile_count; ++i)
                {
                    tiles[i].Offset = input.ReadUInt32();
                    tiles[i].Length = input.ReadInt32();
                }
                var tile = tiles.First(t => t.Length != 0);

                input.Position = tile.Offset;
                int tile_type = input.ReadUInt16();
                int count     = input.ReadUInt16();
                if (tile_type != 1)
                {
                    throw new InvalidFormatException();
                }
                input.Seek(0x70, SeekOrigin.Current);
                for (int i = 0; i < count; ++i)
                {
                    int tile_x = input.ReadUInt16();
                    int tile_y = input.ReadUInt16();
                    input.ReadInt16();
                    int tile_width  = input.ReadUInt16();
                    int tile_height = input.ReadUInt16();
                    input.Seek(0x52, SeekOrigin.Current);

                    tile_x += tile.X;
                    tile_y += tile.Y;
                    if (tile_x + tile_width > m_width || tile_y + tile_height > m_height)
                    {
                        throw new InvalidFormatException();
                    }
                    int dst         = tile_y * dst_stride + tile_x * 4;
                    int tile_stride = tile_width * 4;
                    for (int row = 0; row < tile_height; ++row)
                    {
                        input.Read(m_output, dst, tile_stride);
                        dst += dst_stride;
                    }
                }
            }
        }
Пример #10
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!VFS.IsPathEqualsToFileName(file.Name, "AVGDatas.pck"))
            {
                return(null);
            }
            int seed   = Binary.BigEndian(file.View.ReadInt32(file.MaxOffset - 104));
            var header = file.View.ReadBytes(file.MaxOffset - 100, 100);
            var rnd    = new RandomGenerator();

            rnd.Init(seed);
            rnd.Decrypt(header, 0, header.Length);

            uint checksum = (uint)(header[1] | header[2] << 8 | header[0] << 16 | header[3] << 24) ^ 0xDEFD32D3;
            uint length   = BigEndian.ToUInt32(header, 24);

            if (checksum != length)
            {
                return(null);
            }

            uint idx_pos  = BigEndian.ToUInt32(header, 28);
            uint idx_size = Binary.BigEndian(file.View.ReadUInt32(idx_pos));

            uint index_size;
            var  index = ReadChunk(file, 8, idx_pos + 4, out index_size);

            if (index_size >= 0x80000000)
            {
                index_size &= 0x7FFFFFFF;
                var unpacked = new byte[idx_size];
                LzssUnpack(index, index.Length, unpacked);
                index = unpacked;
            }
            using (var input = new BinMemoryStream(index))
            {
                var dir       = new List <Entry>();
                int dir_count = 0;
                while (input.PeekByte() != -1)
                {
                    input.ReadInt32();
                    input.ReadInt32();
                    input.ReadInt32();
                    int count    = Binary.BigEndian(input.ReadInt32());
                    var dir_name = dir_count.ToString("X4");
                    for (int i = 0; i < count; ++i)
                    {
                        var name = input.ReadCString(0x28);
                        name = Path.Combine(dir_name, name);
                        var entry = Create <PckEntry> (name);
                        entry.Offset       = Binary.BigEndian(input.ReadUInt32());
                        entry.Size         = Binary.BigEndian(input.ReadUInt32());
                        entry.IsEncrypted  = input.ReadInt32() != 0;
                        entry.UnpackedSize = input.ReadUInt32();
                        entry.IsPacked     = entry.Size != entry.UnpackedSize;
                        if (!entry.CheckPlacement(file.MaxOffset))
                        {
                            return(null);
                        }
                        dir.Add(entry);
                    }
                    ++dir_count;
                }
                return(new ArcFile(file, this, dir));
            }
        }
Пример #11
0
        public override ArcFile TryOpen(ArcView file)
        {
            if (!file.Name.HasExtension(".g00"))
            {
                return(null);
            }
            if (file.View.ReadByte(0) != 2)
            {
                return(null);
            }
            uint width  = file.View.ReadUInt16(1);
            uint height = file.View.ReadUInt16(3);

            if (0 == width || width > 0x8000 || 0 == height || height > 0x8000)
            {
                return(null);
            }
            int count = file.View.ReadInt16(5);

            if (count <= 1 || count > 0x1000)
            {
                return(null);
            }
            var base_name = Path.GetFileNameWithoutExtension(file.Name);

            uint index_offset = 9;
            var  dir          = new List <Entry> (count);

            for (int i = 0; i < count; ++i)
            {
                var entry = new G00Entry {
                    Name = string.Format("{0}#{1:D3}", base_name, i),
                    X    = file.View.ReadInt32(index_offset),
                    Y    = file.View.ReadInt32(index_offset + 4),
                };
                dir.Add(entry);
                index_offset += 0x18;
            }
            byte[] bitmap;
            using (var input = file.CreateStream(index_offset))
                bitmap = G00Reader.LzDecompress(input, 2, 1);

            using (var input = new BinMemoryStream(bitmap))
            {
                if (input.ReadInt32() != count)
                {
                    return(null);
                }
                for (int i = 0; i < count; ++i)
                {
                    dir[i].Offset = input.ReadUInt32();
                    dir[i].Size   = input.ReadUInt32();
                }
            }
            dir = dir.Where(e => e.Size != 0).ToList();
            if (0 == dir.Count)
            {
                return(null);
            }
            var info = new ImageMetaData {
                Width = width, Height = height, BPP = 32
            };

            return(new G00Archive(file, this, dir, info, bitmap));
        }