public override void Flush() { // Determine the length of each entry in the header // and the flags that indicate what is stored in the header int entryLength = 2; ushort flags = 0; if (HasFilenames) { entryLength += 28; flags |= 0x8; } if (HasFormats) { entryLength += 2; flags |= 0x4; } if (HasDimensions) { entryLength += 2; flags |= 0x2; } if (HasGlobalIndexes) { entryLength += 4; flags |= 0x1; } // Write the start of the header destination.WriteByte((byte)'G'); destination.WriteByte((byte)'V'); destination.WriteByte((byte)'M'); destination.WriteByte((byte)'H'); // Offset of the first texture in the archive long entryOffset = PTMethods.RoundUp(28 + (entries.Count * entryLength), 16); PTStream.WriteInt32(destination, (int)entryOffset - 8); // Write out the flags PTStream.WriteUInt16BE(destination, flags); // Write out the number of entries PTStream.WriteUInt16BE(destination, (ushort)entries.Count); // We're going to be using this a few times. Might as well do this here long oldPosition; // Now, let's add the entries for (int i = 0; i < entries.Count; i++) { Stream entryData = entries[i].Open(); // We need to get some information about the texture. // We already checked to make sure this texture is a GVR. // No need to check it again. oldPosition = entryData.Position; VrSharp.GvrTexture.GvrTexture texture = new VrSharp.GvrTexture.GvrTexture(entryData); entryData.Position = oldPosition; // Write out the entry number PTStream.WriteUInt16BE(destination, (ushort)i); // Write the information for this entry in the header if (HasFilenames) { PTStream.WriteCString(destination, Path.GetFileNameWithoutExtension(entries[i].Name), 28); } if (HasFormats) { destination.WriteByte((byte)(((byte)texture.PixelFormat << 4) | ((byte)texture.DataFlags & 0xF))); destination.WriteByte((byte)texture.DataFormat); } if (HasDimensions) { ushort dimensions = 0; dimensions |= (ushort)(((byte)Math.Log(texture.TextureWidth, 2) - 2) & 0xF); dimensions |= (ushort)((((byte)Math.Log(texture.TextureHeight, 2) - 2) & 0xF) << 4); PTStream.WriteUInt16BE(destination, dimensions); } if (HasGlobalIndexes) { PTStream.WriteUInt32BE(destination, texture.GlobalIndex); } // Now write out the entry information oldPosition = destination.Position; destination.Position = entryOffset; entryData.Position += texture.PvrtOffset; PTStream.CopyToPadded(entryData, destination, 16, 0); entryOffset = destination.Position; destination.Position = oldPosition; // Call the file added event OnFileAdded(EventArgs.Empty); } }