public BlorbFile(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } this.memory = stream.ReadFully(); var reader = new MemoryReader(this.memory, 0); var dwords = reader.NextDWords(3); // First, ensure that this is a valid format if (dwords[0] != id_FORM) { throw new InvalidOperationException(); } if (dwords[2] != id_IFRS) { throw new InvalidOperationException(); } int totalLength = (int)dwords[1] + 8; // Collect all chunks this.chunks = new List <ChunkDescriptor>(); while (reader.Address < totalLength) { var chunk = new ChunkDescriptor(); chunk.Address = (uint)reader.Address; var type = reader.NextDWord(); var len = reader.NextDWord(); chunk.Type = type; if (type == id_FORM) { chunk.DataAddress = chunk.Address; chunk.Length = len + 8; } else { chunk.DataAddress = (uint)reader.Address; chunk.Length = len; } chunks.Add(chunk); reader.Skip((int)len); if ((reader.Address & 1) != 0) { reader.Skip(1); } if (reader.Address > totalLength) { throw new InvalidOperationException(); } } // Loop through chunks and collect resources this.resources = new List <ResourceDecriptor>(); foreach (var chunk in chunks) { if (chunk.Type == id_RIdx) { reader.Address = (int)chunk.DataAddress; var numResources = (int)reader.NextDWord(); if (chunk.Length < (numResources * 12) + 4) { throw new InvalidOperationException(); } for (int i = 0; i < numResources; i++) { var resource = new ResourceDecriptor(); resource.Usage = reader.NextDWord(); resource.Number = reader.NextDWord(); var resourcePos = reader.NextDWord(); var chunkIndex = chunks.FindIndex(c => c.Address == resourcePos); if (chunkIndex < 0) { throw new InvalidOperationException(); } resource.ChunkNumber = chunkIndex; resources.Add(resource); } } else if (chunk.Type == id_RelN) { reader.Address = (int)chunk.DataAddress; if (chunk.Length < 2) { throw new InvalidOperationException(); } releaseNumber = reader.NextWord(); } else if (chunk.Type == id_IFhd) { reader.Address = (int)chunk.DataAddress; if (chunk.Length < 3) { throw new InvalidOperationException(); } var header = new ZHeader(); header.ReleaseNumber = reader.NextWord(); header.SerialNumber = new char[6]; for (int i = 0; i < 6; i++) { header.SerialNumber[i] = (char)reader.NextByte(); } header.Checksum = reader.NextWord(); } else if (chunk.Type == id_Reso) { } else if (chunk.Type == id_Loop) { } else if (chunk.Type == id_Plte) { } } }