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); } }
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(); } } }
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; } } } }