Skip to content

Commit

Permalink
Changed: Deduplicated some code
Browse files Browse the repository at this point in the history
  • Loading branch information
Sewer56 committed Aug 10, 2023
1 parent 0e0917f commit 21b18e5
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Persona.Merger.Patching.Tbl.FieldResolvers.P3P.AICalc;
using Persona.Merger.Patching.Tbl.FieldResolvers.P3P.Item;
using Persona.Merger.Patching.Tbl.FieldResolvers.P3P.Message;
using static Persona.Merger.Patching.Tbl.FieldResolvers.TblPatcherCommon;

namespace Persona.Merger.Patching.Tbl.FieldResolvers.P3P;

Expand Down Expand Up @@ -161,13 +162,7 @@ public unsafe byte[] Apply(List<TblPatch> patches, TblType type, byte[]?[]? over
P3PTblSegmentFinder.Populate(tblData, segmentCount, originalSegments);

// Convert original segments into Memory<T>.
var segments = new Memory<byte>[segmentCount];
for (int x = 0; x < segmentCount; x++)
{
ref var originalSegment = ref originalSegments[x];
var offset = originalSegment.Pointer - tblData;
segments[x] = new Memory<byte>(TblData, (int)offset, originalSegment.Length);
}
var segments = ConvertSegmentsToMemory(segmentCount, originalSegments, tblData, TblData);

// Apply Patch(es).
for (int x = 0; x < segmentCount; x++)
Expand All @@ -180,17 +175,10 @@ public unsafe byte[] Apply(List<TblPatch> patches, TblType type, byte[]?[]? over

foreach (var patch in CollectionsMarshal.AsSpan(patches))
{
if (patch.SegmentDiffs.Count <= x) continue;
var destination = GC.AllocateUninitializedArray<byte>(Math.Max(patch.SegmentDiffs[x].LengthAfterPatch, segments[x].Length));
var patchDiff = patch.SegmentDiffs[x].Data;

fixed (byte* destinationPtr = &destination[0])
fixed (byte* currentSegmentPtr = segments[x].Span)
fixed (byte* patchPtr = patchDiff.Span)
{
S56DiffDecoder.Decode(currentSegmentPtr, patchPtr, destinationPtr, (nuint)patch.SegmentDiffs[x].Data.Length, out var numWritten);
segments[x] = new Memory<byte>(destination, 0, (int)numWritten);
}
if (patch.SegmentDiffs.Count <= x)
continue;

ApplyPatch(patches, x, segments);
}
}

Expand Down Expand Up @@ -218,38 +206,17 @@ public unsafe byte[] Apply(List<TblPatch> patches, TblType type, byte[]?[]? over
memoryStream.Write(segments[1].Length / 56);
foreach(var segment in segments)
memoryStream.Write(segment.Span);

return result;
}

foreach (var segment in segments)
{
memoryStream.Write(segment.Length);
memoryStream.Write(segment.Span);
memoryStream.AddPadding(P3PTblSegmentFinder.TblSegmentAlignment);
}
WriteSegment(memoryStream, segment, P3PTblSegmentFinder.TblSegmentAlignment);

return result;
}
}

/// <summary>
/// Creates a diff for an individual segment and adds it to the patch.
/// </summary>
private unsafe void DiffSegment<T>(TblPatch patch, PointerLengthTuple newSegment, PointerLengthTuple originalSegment, T resolver) where T : IEncoderFieldResolver
{
var destination = GC.AllocateUninitializedArray<byte>((int)S56DiffEncoder.CalculateMaxDestinationLength(newSegment.Length));
fixed (byte* destinationPtr = destination)
{
var numEncoded = S56DiffEncoder.Encode(originalSegment.Pointer, newSegment.Pointer,
destinationPtr, (nuint)originalSegment.Length, (nuint)newSegment.Length, resolver);
patch.SegmentDiffs.Add(new TblPatch.SegmentDiff()
{
Data = destination.AsMemory(0, (int)numEncoded),
LengthAfterPatch = newSegment.Length
});
}
}

public static unsafe Memory<byte>? GetSegment(byte[] data, TblType type, int segment)
{
var segmentCount = P3PTblSegmentFinder.GetSegmentCount(type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Persona.Merger.Patching.Tbl.FieldResolvers.P4G.AICalc;
using Persona.Merger.Patching.Tbl.FieldResolvers.P4G.Item;
using Persona.Merger.Patching.Tbl.FieldResolvers.P4G.Message;
using static Persona.Merger.Patching.Tbl.FieldResolvers.TblPatcherCommon;

namespace Persona.Merger.Patching.Tbl.FieldResolvers.P4G;

Expand Down Expand Up @@ -143,13 +144,7 @@ public unsafe byte[] Apply(List<TblPatch> patches, TblType type, byte[]?[]? over
P4GTblSegmentFinder.Populate(tblData, segmentCount, originalSegments);

// Convert original segments into Memory<T>.
var segments = new Memory<byte>[segmentCount];
for (int x = 0; x < segmentCount; x++)
{
ref var originalSegment = ref originalSegments[x];
var offset = originalSegment.Pointer - tblData;
segments[x] = new Memory<byte>(TblData, (int)offset, originalSegment.Length);
}
var segments = ConvertSegmentsToMemory(segmentCount, originalSegments, tblData, TblData);

// Apply Patch(es).
for (int x = 0; x < segmentCount; x++)
Expand All @@ -159,19 +154,13 @@ public unsafe byte[] Apply(List<TblPatch> patches, TblType type, byte[]?[]? over
segments[x] = new Memory<byte>(overrides[x]);
continue;
}

foreach (var patch in CollectionsMarshal.AsSpan(patches))
{
if (patch.SegmentDiffs.Count <= x) continue;
var destination = GC.AllocateUninitializedArray<byte>(Math.Max(patch.SegmentDiffs[x].LengthAfterPatch, segments[x].Length));
var patchDiff = patch.SegmentDiffs[x].Data;

fixed (byte* destinationPtr = &destination[0])
fixed (byte* currentSegmentPtr = segments[x].Span)
fixed (byte* patchPtr = patchDiff.Span)
{
S56DiffDecoder.Decode(currentSegmentPtr, patchPtr, destinationPtr, (nuint)patch.SegmentDiffs[x].Data.Length, out var numWritten);
segments[x] = new Memory<byte>(destination, 0, (int)numWritten);
}
if (patch.SegmentDiffs.Count <= x)
continue;

ApplyPatch(patches, x, segments);
}
}

Expand Down Expand Up @@ -203,34 +192,12 @@ public unsafe byte[] Apply(List<TblPatch> patches, TblType type, byte[]?[]? over
}

foreach (var segment in segments)
{
memoryStream.Write(segment.Length);
memoryStream.Write(segment.Span);
memoryStream.AddPadding(P4GTblSegmentFinder.TblSegmentAlignment);
}
WriteSegment(memoryStream, segment, P4GTblSegmentFinder.TblSegmentAlignment);

return result;
}
}

/// <summary>
/// Creates a diff for an individual segment and adds it to the patch.
/// </summary>
private unsafe void DiffSegment<T>(TblPatch patch, PointerLengthTuple newSegment, PointerLengthTuple originalSegment, T resolver) where T : IEncoderFieldResolver
{
var destination = GC.AllocateUninitializedArray<byte>((int)S56DiffEncoder.CalculateMaxDestinationLength(newSegment.Length));
fixed (byte* destinationPtr = destination)
{
var numEncoded = S56DiffEncoder.Encode(originalSegment.Pointer, newSegment.Pointer,
destinationPtr, (nuint)originalSegment.Length, (nuint)newSegment.Length, resolver);
patch.SegmentDiffs.Add(new TblPatch.SegmentDiff()
{
Data = destination.AsMemory(0, (int)numEncoded),
LengthAfterPatch = newSegment.Length
});
}
}

public static unsafe Memory<byte>? GetSegment(byte[] data, TblType type, int segment)
{
var segmentCount = P4GTblSegmentFinder.GetSegmentCount(type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using Reloaded.Memory.Streams;
using Sewer56.StructuredDiff;
using Sewer56.StructuredDiff.Interfaces;
using static Persona.Merger.Patching.Tbl.FieldResolvers.TblPatcherCommon;

namespace Persona.Merger.Patching.Tbl.FieldResolvers.P5R;

Expand Down Expand Up @@ -148,29 +149,11 @@ public unsafe byte[] Apply(List<TblPatch> patches)
P5RTblSegmentFinder.Populate(tblData, segmentCount, originalSegments);

// Convert original segments into Memory<T>.
var segments = new Memory<byte>[segmentCount];
for (int x = 0; x < segmentCount; x++)
{
ref var originalSegment = ref originalSegments[x];
var offset = originalSegment.Pointer - tblData;
segments[x] = new Memory<byte>(TblData, (int)offset, originalSegment.Length);
}
var segments = ConvertSegmentsToMemory(segmentCount, originalSegments, tblData, TblData);

// Apply Patch(es).
for (int x = 0; x < segmentCount; x++)
foreach (var patch in CollectionsMarshal.AsSpan(patches))
{
var destination = GC.AllocateUninitializedArray<byte>(Math.Max(patch.SegmentDiffs[x].LengthAfterPatch, segments[x].Length));
var patchDiff = patch.SegmentDiffs[x].Data;

fixed (byte* destinationPtr = &destination[0])
fixed (byte* currentSegmentPtr = segments[x].Span)
fixed (byte* patchPtr = patchDiff.Span)
{
S56DiffDecoder.Decode(currentSegmentPtr, patchPtr, destinationPtr, (nuint)patch.SegmentDiffs[x].Data.Length, out var numWritten);
segments[x] = new Memory<byte>(destination, 0, (int)numWritten);
}
}
ApplyPatch(patches, x, segments);

// Produce new file.
var fileSize = 0;
Expand All @@ -189,24 +172,6 @@ public unsafe byte[] Apply(List<TblPatch> patches)
return result;
}
}

/// <summary>
/// Creates a diff for an individual segment and adds it to the patch.
/// </summary>
private unsafe void DiffSegment<T>(TblPatch patch, PointerLengthTuple newSegment, PointerLengthTuple originalSegment, T resolver) where T : IEncoderFieldResolver
{
var destination = GC.AllocateUninitializedArray<byte>((int)S56DiffEncoder.CalculateMaxDestinationLength(newSegment.Length));
fixed (byte* destinationPtr = destination)
{
var numEncoded = S56DiffEncoder.Encode(originalSegment.Pointer, newSegment.Pointer,
destinationPtr, (nuint)originalSegment.Length, (nuint)newSegment.Length, resolver);
patch.SegmentDiffs.Add(new TblPatch.SegmentDiff()
{
Data = destination.AsMemory(0, (int)numEncoded),
LengthAfterPatch = newSegment.Length
});
}
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
using System.Runtime.InteropServices;
using Persona.Merger.Utilities;
using Reloaded.Memory.Streams;
using Sewer56.StructuredDiff;
using Sewer56.StructuredDiff.Interfaces;

namespace Persona.Merger.Patching.Tbl.FieldResolvers;

/// <summary>
/// Common functionality used in multiple TBL patchers.
/// </summary>
internal class TblPatcherCommon
{
/// <summary>
/// Converts a list of segments and their respective slices to Memory{byte} objects.
/// </summary>
internal static unsafe Memory<byte>[] ConvertSegmentsToMemory(int segmentCount, PointerLengthTuple* originalSegments, byte* tblData, byte[] tblDataArr)
{
var segments = new Memory<byte>[segmentCount];
for (int x = 0; x < segmentCount; x++)
{
ref var originalSegment = ref originalSegments[x];
var offset = originalSegment.Pointer - tblData;
segments[x] = new Memory<byte>(tblDataArr, (int)offset, originalSegment.Length);
}

return segments;
}

/// <summary>
/// Applies a given list of table patches to the current file's TBL segments.
/// </summary>
internal static unsafe void ApplyPatch(List<TblPatch> patches, int x, Memory<byte>[] segments)
{
foreach (var patch in CollectionsMarshal.AsSpan(patches))
{
var destination = GC.AllocateUninitializedArray<byte>(Math.Max(patch.SegmentDiffs[x].LengthAfterPatch, segments[x].Length));
var patchDiff = patch.SegmentDiffs[x].Data;

fixed (byte* destinationPtr = &destination[0])
fixed (byte* currentSegmentPtr = segments[x].Span)
fixed (byte* patchPtr = patchDiff.Span)
{
S56DiffDecoder.Decode(currentSegmentPtr, patchPtr, destinationPtr, (nuint)patch.SegmentDiffs[x].Data.Length,
out var numWritten);
segments[x] = new Memory<byte>(destination, 0, (int)numWritten);
}
}
}

/// <summary>
/// Writes the segment to the stream.
/// </summary>
internal static void WriteSegment(ExtendedMemoryStream memoryStream, Memory<byte> segment, int alignment)
{
memoryStream.Write(segment.Length);
memoryStream.Write(segment.Span);
memoryStream.AddPadding(alignment);
}

/// <summary>
/// Creates a diff for an individual segment and adds it to the patch.
/// </summary>
internal static unsafe void DiffSegment<T>(TblPatch patch, PointerLengthTuple newSegment, PointerLengthTuple originalSegment, T resolver) where T : IEncoderFieldResolver
{
var destination = GC.AllocateUninitializedArray<byte>((int)S56DiffEncoder.CalculateMaxDestinationLength(newSegment.Length));
fixed (byte* destinationPtr = destination)
{
var numEncoded = S56DiffEncoder.Encode(originalSegment.Pointer, newSegment.Pointer,
destinationPtr, (nuint)originalSegment.Length, (nuint)newSegment.Length, resolver);
patch.SegmentDiffs.Add(new TblPatch.SegmentDiff()
{
Data = destination.AsMemory(0, (int)numEncoded),
LengthAfterPatch = newSegment.Length
});
}
}
}
7 changes: 3 additions & 4 deletions p5rpc.modloader/Merging/BfMerger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,9 @@ await Task.Run(async () =>
if (aiCalc == null)
return null;

if(_game == Game.P4G)
return P4GTblPatcher.GetSegment(aiCalc.Value.ToArray(), Persona.Merger.Patching.Tbl.FieldResolvers.P4G.TblType.AiCalc, index);
else
return P3PTblPatcher.GetSegment(aiCalc.Value.ToArray(), Persona.Merger.Patching.Tbl.FieldResolvers.P3P.TblType.AiCalc, index);
return _game == Game.P4G ?
P4GTblPatcher.GetSegment(aiCalc.Value.ToArray(), Persona.Merger.Patching.Tbl.FieldResolvers.P4G.TblType.AiCalc, index) :
P3PTblPatcher.GetSegment(aiCalc.Value.ToArray(), Persona.Merger.Patching.Tbl.FieldResolvers.P3P.TblType.AiCalc, index);
}

private async ValueTask CacheBf(Dictionary<string, List<ICriFsRedirectorApi.BindFileInfo>> pathToFileMap, string route, string[] cpks, List<string> flowPaths, string bindDirectory)
Expand Down

0 comments on commit 21b18e5

Please sign in to comment.