/// <summary> /// Estimates the file size of the output file. /// Note: Not accurate, but will return equal or slightly more than actual file. /// </summary> public int EstimateFileSize(TextureArchiveWriterSettings options) { var estimateFileSize = 0; estimateFileSize += sizeof(int); // Header estimateFileSize += (sizeof(int) + 1 * Files.Count); // Offsets + Flags estimateFileSize += Files.Sum(x => x.Data.Length + x.Name.Length + 1); // Names and Data estimateFileSize += (options.Alignment * Files.Count); // Alignment return(estimateFileSize); }
/// <summary> /// Writes the contents of the archive to be generated to the stream. /// </summary> public void Write(Stream writeStream, TextureArchiveWriterSettings options) { if (options.BigEndian) { Write(options, new BigEndianStreamWriter(writeStream)); } else { Write(options, new LittleEndianStreamWriter(writeStream)); } }
/// <summary> /// Writes the contents of the archive to be generated to a byte array. /// </summary> public byte[] Write(TextureArchiveWriterSettings options) { using var stream = new MemoryStream(EstimateFileSize(options)); if (options.BigEndian) { Write(options, new BigEndianStreamWriter(stream)); } else { Write(options, new LittleEndianStreamWriter(stream)); } return(stream.ToArray()); }
private void PrecomputeFileOffsets(Span <int> offsets, int stringDataSize, TextureArchiveWriterSettings options) { const int headerSize = sizeof(int); int fileOffsetArraySize = Files.Count * sizeof(int); int unknownFlagArraySize = options.WriteFlagsSection ? Files.Count * sizeof(byte) : 0; // Get offset for first file, aligned. int currentFileDataOffset = Utilities.RoundUp(headerSize + fileOffsetArraySize + unknownFlagArraySize + stringDataSize, options.Alignment); // Populate offsets for every file. for (int x = 0; x < Files.Count; x++) { offsets[x] = currentFileDataOffset; currentFileDataOffset += Utilities.RoundUp(Files[x].Data.Length, options.Alignment); } }
/// <summary> /// Writes the contents of the archive to be generated to a byte array. /// </summary> public void Write <T>(TextureArchiveWriterSettings options, T target) where T : IEndianStreamWriter { // Precompute Offsets var fileNameSize = Files.Sum(x => x.Name.Length) + (Files.Count); Span <int> offsets = stackalloc int[Files.Count]; PrecomputeFileOffsets(offsets, fileNameSize, options); // Texture Count target.Write <short>((short)Files.Count); target.Write((byte)0); target.Write(options.WriteFlagsSection ? (byte)1 : (byte)0); // Texture Offsets for (int x = 0; x < offsets.Length; x++) { target.Write(offsets[x]); } // Texture Flags if (options.WriteFlagsSection) { for (int x = 0; x < Files.Count; x++) { target.Write((byte)0x11); } } // Texture Names Span <byte> currentString = stackalloc byte[1024]; foreach (var file in Files) { int numEncoded = Encoding.ASCII.GetBytes(file.Name, currentString); currentString[numEncoded] = 0x00; target.Write(currentString.Slice(0, numEncoded + 1)); } // Texture Data target.Stream.AddPadding(options.Alignment); for (int x = 0; x < Files.Count; x++) { target.Write(Files[x].Data.AsSpan()); target.Stream.AddPadding(options.Alignment); } }