private void ReadContentTreeSection(ContentTree.Node node, BinaryReader r, long dataOffset, string fullPath = null) { ResourceFlags flags = (ResourceFlags)r.ReadByte(); string name = r.ReadAsciiString(); if (!string.IsNullOrEmpty(fullPath)) { fullPath += PathOp.DirectorySeparatorChar; } fullPath += name; ushort childrenCount; if ((flags & ResourceFlags.HasChildren) != 0) { childrenCount = r.ReadUInt16(); } else { childrenCount = 0; } FileResourceSource source = null; if ((flags & ResourceFlags.HasResource) != 0) { string path; long offset, size; if ((flags & ResourceFlags.External) == 0) { path = this.path; offset = r.ReadUInt32(); size = r.ReadUInt32(); offset += dataOffset; } else { path = r.ReadAsciiString(); offset = r.ReadUInt32(); size = r.ReadUInt32(); } source = new FileResourceSource(path, offset, size, (flags & ResourceFlags.Compressed) != 0); } if (!string.IsNullOrEmpty(name)) { node = node.TryAdd(name); node.Source = source; } for (uint i = 0; i < childrenCount; i++) { ReadContentTreeSection(node, r, dataOffset, fullPath); } }
public SourceStream(FileResourceSource source) { this.offset = source.offset; this.size = source.size; if (DualityApp.ExecContext == DualityApp.ExecutionContext.Game) { this.stream = DualityApp.SystemBackend.FileSystem.OpenFile(source.path, FileAccessMode.Read); } else { this.stream = File.Open(source.path, FileMode.Open, FileAccess.Read, FileShare.Read); } if (this.stream.Length < this.offset + this.size) { this.stream.Dispose(); throw new FileLoadException("File is not large enough to contain specified section"); } this.stream.Position = this.offset; }
private static void WriteContentTreeSection(ContentTree.Node node, Stream tableStream, Stream dataStream, Func <string, ResourceFlags, ResourceFlags> resourceFlagsModifier) { using (BinaryWriter w = new BinaryWriter(tableStream, Encoding.UTF8, true)) { ResourceFlags flags = 0; if (node.Children.Count > 0) { flags |= ResourceFlags.HasChildren; } if (node.Source != null) { flags |= ResourceFlags.HasResource; flags &= ~ResourceFlags.External; } if (resourceFlagsModifier != null) { flags = resourceFlagsModifier(node.Name, flags); } w.Write((byte)flags); w.WriteAsciiString(node.Name); if ((flags & ResourceFlags.HasChildren) != 0) { w.Write((ushort)node.Children.Count); } if ((flags & ResourceFlags.HasResource) != 0) { if ((flags & ResourceFlags.External) != 0) { FileResourceSource source = node.Source as FileResourceSource; w.WriteAsciiString(source.Path); w.Write((uint)source.Offset); w.Write((uint)source.Size); } else { long offset = dataStream.Position; w.Write((uint)offset); using (Stream stream = (flags & ResourceFlags.Compressed) != 0 ? node.Source.GetCompressedStream() : node.Source.GetUncompressedStream()) { stream.CopyTo(dataStream); } long size = (dataStream.Position - offset); w.Write((uint)size); } } } foreach (ContentTree.Node children in node.Children) { WriteContentTreeSection(children, tableStream, dataStream, resourceFlagsModifier); } }
private static void WriteContentTreeSection(ContentTree.Node node, Stream tableStream, Stream dataStream, PostprocessFileCallback postprocessFileCallback) { using (BinaryWriter w = new BinaryWriter(tableStream, Encoding.UTF8, true)) { ResourceFlags flags = 0; if (node.Children.Count > 0) { flags |= ResourceFlags.HasChildren; } if (node.Source != null) { flags |= ResourceFlags.HasResource; flags &= ~ResourceFlags.External; } Stream overrideStream = null; if (postprocessFileCallback != null) { postprocessFileCallback(node, ref flags, ref overrideStream); } try { w.Write((byte)flags); w.WriteAsciiString(node.Name); if ((flags & ResourceFlags.HasChildren) != 0) { w.Write((ushort)node.Children.Count); } if ((flags & ResourceFlags.HasResource) != 0) { if ((flags & ResourceFlags.External) != 0) { if (overrideStream != null) { throw new InvalidOperationException("Cannot use overrideStream with ResourceFlags.External"); } FileResourceSource source = node.Source as FileResourceSource; if (source == null) { throw new InvalidOperationException("Specified resource must be saved as file"); } w.WriteAsciiString(source.Path); w.Write((uint)source.Offset); w.Write((uint)source.Size); } else { long offset = dataStream.Position; if (overrideStream != null) { if ((flags & ResourceFlags.Compressed) != 0) { using (DeflateStream ds = new DeflateStream(dataStream, CompressionLevel.Optimal, true)) { overrideStream.CopyTo(ds); } } else { overrideStream.CopyTo(dataStream); } } else { using (Stream stream = (flags & ResourceFlags.Compressed) != 0 ? node.Source.GetCompressedStream() : node.Source.GetUncompressedStream()) { stream.CopyTo(dataStream); } } long size = (dataStream.Position - offset); w.Write((uint)offset); w.Write((uint)size); } } } finally { if (overrideStream != null) { overrideStream.Dispose(); } } } foreach (ContentTree.Node children in node.Children) { WriteContentTreeSection(children, tableStream, dataStream, postprocessFileCallback); } }