/// <summary> /// Reads a tag's data from the file. /// </summary> /// <param name="stream">The stream to read from.</param> /// <param name="tag">The tag to read.</param> /// <returns>The data that was read.</returns> public CachedTagData ExtractTag(Stream stream, CachedTagInstance tag) { if (tag == null) { throw new ArgumentNullException(nameof(tag)); } else if (tag.HeaderOffset < 0) { throw new ArgumentException("The tag is not in the cache file"); } // Build the description info and get the data offset var data = BuildTagData(stream, tag, out uint dataOffset); // Read the tag data stream.Position = tag.HeaderOffset + dataOffset; data.Data = new byte[tag.TotalSize - dataOffset]; stream.Read(data.Data, 0, data.Data.Length); // Correct pointers using (var dataWriter = new BinaryWriter(new MemoryStream(data.Data))) { foreach (var fixup in data.PointerFixups) { dataWriter.BaseStream.Position = fixup.WriteOffset; dataWriter.Write(tag.OffsetToPointer(fixup.TargetOffset)); } } return(data); }
/// <summary> /// Overwrites a tag's data. /// </summary> /// <param name="stream">The stream to write to.</param> /// <param name="tag">The tag to overwrite.</param> /// <param name="data">The data to store.</param> public void SetTagData(Stream stream, CachedTagInstance tag, CachedTagData data) { if (tag == null) { throw new ArgumentNullException(nameof(tag)); } else if (data == null) { throw new ArgumentNullException(nameof(data)); } else if (data.Group == TagGroup.None) { throw new ArgumentException("Cannot assign a tag to a null tag group"); } else if (data.Data == null) { throw new ArgumentException("The tag data buffer is null"); } // Ensure the data fits var headerSize = CachedTagInstance.CalculateHeaderSize(data); var alignedHeaderSize = (uint)((headerSize + 0xF) & ~0xF); if (tag.HeaderOffset < 0) { tag.HeaderOffset = GetNewTagOffset(tag.Index); } var alignedLength = (data.Data.Length + 0xF) & ~0xF; ResizeBlock(stream, tag, tag.HeaderOffset, tag.TotalSize, alignedHeaderSize + alignedLength); tag.TotalSize = alignedHeaderSize + alignedLength; tag.Update(data, alignedHeaderSize); // Write in the new header and data stream.Position = tag.HeaderOffset; var writer = new BinaryWriter(stream); tag.WriteHeader(writer); StreamUtil.Fill(stream, 0, (int)(alignedHeaderSize - headerSize)); stream.Write(data.Data, 0, data.Data.Length); StreamUtil.Fill(stream, 0, alignedLength - data.Data.Length); // Correct pointers foreach (var fixup in data.PointerFixups) { writer.BaseStream.Position = tag.HeaderOffset + alignedHeaderSize + fixup.WriteOffset; writer.Write(tag.OffsetToPointer(alignedHeaderSize + fixup.TargetOffset)); } UpdateTagOffsets(writer); }