public void Disassemble(Action <ChunkItem> callback = null) { void HandleChunk(ChunkItem chunk) { callback?.Invoke(chunk); Chunks.Add(chunk); } if (Metadata.Codec == CodecKind.FGDM || Metadata.Codec == CodecKind.FGDC) { if (ChunkItem.Read(_input) is FileVersionChunk version && ChunkItem.Read(_input) is FileCompressionTypesChunk compressionTypes && ChunkItem.Read(_input) is AfterburnerMapChunk afterburnerMap && ChunkItem.Read(_input) is FGEIChunk fgei) { var ilsChunk = fgei.ReadInitialLoadSegment(afterburnerMap.Entries[0]); fgei.ReadChunks(afterburnerMap.Entries, HandleChunk); ilsChunk.ReadChunks(afterburnerMap.Entries, HandleChunk); } } else if (Metadata.Codec == CodecKind.MV93) { var imapChunk = ChunkItem.Read(_input) as InitialMapChunk; Version = imapChunk.Version; foreach (int offset in imapChunk.MemoryMapOffsets) { _input.Position = offset; if (ChunkItem.Read(_input) is MemoryMapChunk mmapChunk) { foreach (ChunkEntry entry in mmapChunk.Entries) { if (entry.Flags.HasFlag(ChunkEntryFlags.Ignore)) { HandleChunk(new UnknownChunk(_input, entry.Header)); //TODO: continue; } _input.Position = entry.Offset; ChunkItem chunk = ChunkItem.Read(_input); chunk.Header.Id = entry.Header.Id; HandleChunk(chunk); } } } } }
public void Disassemble() { var input = new ShockwaveReader(_input.Span, Metadata.IsBigEndian); input.Advance(Metadata.Header.GetBodySize() + Metadata.GetBodySize()); if (Metadata.Codec == CodecKind.FGDM || Metadata.Codec == CodecKind.FGDC) { if (ChunkItem.Read(ref input) is FileVersionChunk version && ChunkItem.Read(ref input) is FileCompressionTypesChunk compressionTypes && ChunkItem.Read(ref input) is AfterburnerMapChunk afterburnerMap && ChunkItem.Read(ref input) is FileGzipEmbeddedImageChunk fgei) { Chunks = fgei.ReadChunks(ref input, afterburnerMap.Entries); } } else if (Metadata.Codec == CodecKind.MV93) { var imapChunk = ChunkItem.Read(ref input) as InitialMapChunk; Version = imapChunk.Version; foreach (int offset in imapChunk.MemoryMapOffsets) { input.Position = offset; if (ChunkItem.Read(ref input) is MemoryMapChunk mmapChunk) { foreach (ChunkEntry entry in mmapChunk.Entries) { if (entry.Header.Kind == ChunkKind.RIFX) { continue; //TODO: HACK } if (entry.Flags.HasFlag(ChunkEntryFlags.Ignore)) { Chunks.Add(entry.Id, new UnknownChunk(ref input, entry.Header)); continue; } input.Position = entry.Offset; Chunks.Add(entry.Id, ChunkItem.Read(ref input)); } } } } //TODO: _input = null; }
public unsafe ChunkItem ReadCompressedChunk(AfterBurnerMapEntry entry) { Span <byte> decompressedData = entry.DecompressedLength <= 1024 ? stackalloc byte[entry.DecompressedLength] : new byte[entry.DecompressedLength]; fixed(byte *pBuffer = &_data.Slice(Position + 2)[0]) //Skip ZLib header { using var stream = new UnmanagedMemoryStream(pBuffer, entry.Length - 2); using var deflateStream = new DeflateStream(stream, CompressionMode.Decompress); deflateStream.Read(decompressedData); } Advance(entry.Length); ShockwaveReader input = new ShockwaveReader(decompressedData, IsBigEndian); return(ChunkItem.Read(ref input, entry.Header)); }