From af313cf6b4a063f3f3871b564d534a9e8d4888c8 Mon Sep 17 00:00:00 2001 From: ArchLeaders Date: Fri, 15 Mar 2024 10:29:12 -0700 Subject: [PATCH] Optimize Sarc.Write --- src/SarcLibrary/Sarc.cs | 32 ++++++++++++++------------- src/SarcLibrary/SarcLibrary.csproj | 3 ++- src/SarcLibrary/Writers/SfatWriter.cs | 4 ++-- src/SarcLibrary/Writers/SfntWriter.cs | 2 +- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/SarcLibrary/Sarc.cs b/src/SarcLibrary/Sarc.cs index b85c993..476ae61 100644 --- a/src/SarcLibrary/Sarc.cs +++ b/src/SarcLibrary/Sarc.cs @@ -1,5 +1,5 @@ global using SarcNodeData = (string Name, (uint FileNameHash, System.ArraySegment Data, int Alignment) Value); - +using CommunityToolkit.HighPerformance.Buffers; using Revrs; using SarcLibrary.Structures; using SarcLibrary.Writers; @@ -69,29 +69,31 @@ public unsafe void Write(Stream stream, Endianness? endianness = null, bool lega writer.Move(sizeof(SarcHeader)); - SarcNodeData[] sorted = this - .Select(x => (x.Key, Value: ( - Hash: SfatWriter.GetFileNameHash(x.Key), x.Value, - Alignment: SarcAlignment.Estimate(x, endianness.Value, legacy) - ))) - .OrderBy(x => x.Value.Hash) - .ToArray(); + int sarcAlignment = 1; + using SpanOwner sorted = SpanOwner.Allocate(Count); + + int i = -1; + foreach (KeyValuePair> entry in this) { + uint hash = SfatWriter.GetFileNameHash(entry.Key); - SfatWriter.Write(writer, sorted, IsHashOnly); + int alignment = SarcAlignment.Estimate(entry, endianness.Value, legacy); + sarcAlignment = SarcAlignment.LCM(sarcAlignment, alignment); - if (!IsHashOnly) { - SfntWriter.Write(writer, sorted); + sorted.Span[++i] = (entry.Key, Value: (hash, entry.Value, alignment)); } - int sarcAlignment = 1; - foreach ((var _, var value) in sorted) { - sarcAlignment = SarcAlignment.LCM(sarcAlignment, value.Alignment); + sorted.Span.Sort((SarcNodeData x, SarcNodeData y) => x.Value.FileNameHash.CompareTo(y.Value.FileNameHash)); + + SfatWriter.Write(ref writer, sorted.Span, IsHashOnly); + + if (!IsHashOnly) { + SfntWriter.Write(ref writer, sorted.Span); } writer.Align(sarcAlignment); int dataOffset = (int)writer.Position; - foreach ((var _, var value) in sorted) { + foreach ((var _, var value) in sorted.Span) { writer.Align(value.Alignment); writer.Write(value.Data); } diff --git a/src/SarcLibrary/SarcLibrary.csproj b/src/SarcLibrary/SarcLibrary.csproj index cfde6d5..708d61c 100644 --- a/src/SarcLibrary/SarcLibrary.csproj +++ b/src/SarcLibrary/SarcLibrary.csproj @@ -22,7 +22,8 @@ - + + diff --git a/src/SarcLibrary/Writers/SfatWriter.cs b/src/SarcLibrary/Writers/SfatWriter.cs index dfa5f90..f162652 100644 --- a/src/SarcLibrary/Writers/SfatWriter.cs +++ b/src/SarcLibrary/Writers/SfatWriter.cs @@ -8,7 +8,7 @@ internal class SfatWriter private const uint HASH_KEY = 0x65; private const ushort HEADER_SIZE = 0xC; - public static void Write(RevrsWriter writer, SarcNodeData[] entries, bool isHashOnly) + public static void Write(ref RevrsWriter writer, Span entries, bool isHashOnly) { SfatHeader header = new() { Magic = Sarc.SFAT_MAGIC, @@ -29,7 +29,7 @@ public static void Write(RevrsWriter writer, SarcNodeData[] entries, bool isHash FileNameHash = entry.Value.FileNameHash, FileAttributes = isHashOnly ? 0x0 : 0x01000000 | (nameOffset / 4), DataStartOffset = dataOffset += dataOffset.AlignUp(entry.Value.Alignment), - DataEndOffset = dataOffset += entry.Value.Data.Length + DataEndOffset = dataOffset += entry.Value.Data.Count }; nameOffset += entry.Name.Length + 1; diff --git a/src/SarcLibrary/Writers/SfntWriter.cs b/src/SarcLibrary/Writers/SfntWriter.cs index 40e8be9..1768637 100644 --- a/src/SarcLibrary/Writers/SfntWriter.cs +++ b/src/SarcLibrary/Writers/SfntWriter.cs @@ -6,7 +6,7 @@ namespace SarcLibrary.Writers; public class SfntWriter { - public unsafe static void Write(RevrsWriter writer, SarcNodeData[] entries) + public unsafe static void Write(ref RevrsWriter writer, Span entries) { SfntHeader header = new() { Magic = Sarc.SFNT_MAGIC,