public override ImageData Read(IBinaryStream stream, ImageMetaData info) { var meta = (FcbMetaData)info; byte[] input; if (1 == meta.Method) { stream.Position = 0x14; int unpacked_size = Binary.BigEndian(stream.ReadInt32()); stream.ReadInt32(); // packed_size input = new byte[unpacked_size]; using (var z = new ZLibStream(stream.AsStream, CompressionMode.Decompress, true)) if (unpacked_size != z.Read(input, 0, unpacked_size)) { throw new EndOfStreamException(); } } else if (0 == meta.Method) { stream.Position = 0x10; using (var tz = new TzCompression(stream.AsStream)) input = tz.Unpack(); } else { throw new InvalidFormatException(); } var pixels = Unpack(input, info); return(ImageData.Create(info, PixelFormats.Bgra32, null, pixels)); }
public override Stream OpenEntry(ArcFile arc, Entry entry) { var xent = (Arc4Entry)entry; Stream input; if (1 == xent.Segments.Count) { input = arc.File.CreateStream(entry.Offset, entry.Size); } else { input = new Arc4Stream(arc.File, xent); } if (!xent.IsPacked) { return(input); } using (input) using (var tz = new TzCompression(input)) return(new BinMemoryStream(tz.Unpack(), entry.Name)); }
public override ArcFile TryOpen(ArcView file) { if (0x010000 != file.View.ReadUInt32(4)) { return(null); } int count = file.View.ReadInt32(0x10); if (!IsSaneCount(count)) { return(null); } uint index_length = file.View.ReadUInt32(8); uint alignment = file.View.ReadUInt32(0xC); int index_offset = file.View.ReadInt32(0x14); int names_offset = file.View.ReadInt32(0x1C) - index_offset; int segment_table = file.View.ReadInt32(0x24) - index_offset; uint base_offset = file.View.ReadUInt32(0x2C); if (0 == alignment || index_offset <= 0 || names_offset <= 0 || segment_table <= 0) { return(null); } if (!file.View.AsciiEqual(index_offset, "tZ")) { return(null); } byte[] index; using (var packed = file.CreateStream(index_offset, index_length)) using (var tz = new TzCompression(packed)) index = tz.Unpack(); int current_offset = 0; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { int name_pos = ReadInt24(index, current_offset) * 2; int name_length = index[current_offset + 3]; int chunk_count = index[current_offset + 4]; int offset = ReadInt24(index, current_offset + 5); var name = Binary.GetCString(index, names_offset + name_pos, name_length); var entry = FormatCatalog.Instance.Create <Arc4Entry> (name); entry.Segments = new List <long> (chunk_count); if (chunk_count > 1) { int segment_pos = segment_table + 3 * offset; for (int j = 0; j < chunk_count; ++j) { entry.Segments.Add(ReadInt24(index, segment_pos) + base_offset); segment_pos += 3; } } else { entry.Segments.Add(offset + base_offset); } for (int j = 0; j < chunk_count; ++j) { entry.Segments[j] *= alignment; } dir.Add(entry); current_offset += 8; } foreach (Arc4Entry entry in dir) { uint size = 0; foreach (var segment in entry.Segments) { size += Binary.BigEndian(file.View.ReadUInt32(segment + 4)); } entry.Offset = entry.Segments[0] + 0x10; entry.Size = size; entry.IsPacked = file.View.AsciiEqual(entry.Offset, "tZ"); if (entry.IsPacked) { entry.UnpackedSize = file.View.ReadUInt32(entry.Offset + 2); } else { entry.UnpackedSize = size; } } return(new ArcFile(file, this, dir)); }