public override Stream OpenEntry(ArcFile arc, Entry entry) { if (0 == entry.Size) { return(Stream.Null); } var input = arc.File.CreateStream(entry.Offset, entry.Size); var pentry = entry as PackedEntry; if (null == pentry || !pentry.IsPacked) { return(input); } if (!arc.File.View.AsciiEqual(entry.Offset, "GCE")) { Trace.WriteLine("Packed entry is not GCE", entry.Name); return(input); } using (input) using (var reader = new GceReader(input, (int)pentry.UnpackedSize)) { return(new MemoryStream(reader.Data)); } }
public override ArcFile TryOpen(ArcView file) { if (0 != file.View.ReadInt32(4)) { return(null); } long index_offset = file.View.ReadInt64(8); if (index_offset >= file.MaxOffset) { return(null); } if (!file.View.AsciiEqual(index_offset, "GCE3")) { return(null); } int count = file.View.ReadInt32(index_offset + 0x18); if (!IsSaneCount(count)) { return(null); } bool index_packed = 0x11 == file.View.ReadInt32(index_offset + 4); uint index_size = file.View.ReadUInt32(index_offset + 8); byte[] index = null; if (index_packed) { index_size -= 0x28; int unpacked_size = file.View.ReadInt32(index_offset + 0x20); using (var input = file.CreateStream(index_offset + 0x28, index_size)) using (var reader = new GceReader(input, unpacked_size)) index = reader.Data; } else { index_size -= 0x20; index = new byte[index_size]; if (index.Length != file.View.Read(index_offset + 0x20, index, 0, index_size)) { return(null); } } int current_index = 0; int current_filename = 0x20 * count; long current_offset = 0x10; var dir = new List <Entry> (count); for (int i = 0; i < count; ++i) { int name_length = LittleEndian.ToUInt16(index, current_filename); if (current_filename + 2 + name_length > index.Length) { return(null); } uint size = LittleEndian.ToUInt32(index, current_index + 0x18); if (size != 0) { string name = Encodings.cp932.GetString(index, current_filename + 2, name_length); var entry = new PackedEntry { Name = name, Type = FormatCatalog.Instance.GetTypeFromName(name), Offset = current_offset, Size = size, UnpackedSize = LittleEndian.ToUInt32(index, current_index + 0x10), }; if (!entry.CheckPlacement(file.MaxOffset)) { return(null); } entry.IsPacked = entry.Size != entry.UnpackedSize; current_offset += entry.Size; dir.Add(entry); } current_index += 0x20; current_filename += 2 + name_length; } return(new ArcFile(file, this, dir)); }