mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Fix IMC adding new variants.
This commit is contained in:
parent
98b4b29ff5
commit
7540694050
3 changed files with 59 additions and 32 deletions
|
|
@ -70,6 +70,9 @@ public unsafe class ImcFile : MetaBaseFile
|
|||
public readonly int NumParts;
|
||||
public bool ChangesSinceLoad = true;
|
||||
|
||||
public ReadOnlySpan< ImcEntry > Span
|
||||
=> new(( ImcEntry* )( Data + PreambleSize ), ( Length - PreambleSize ) / sizeof( ImcEntry ));
|
||||
|
||||
private static int CountInternal( byte* data )
|
||||
=> *( ushort* )data;
|
||||
|
||||
|
|
@ -89,24 +92,15 @@ public unsafe class ImcFile : MetaBaseFile
|
|||
|
||||
private static ImcEntry* VariantPtr( byte* data, int partIdx, int variantIdx )
|
||||
{
|
||||
if( variantIdx == 0 )
|
||||
{
|
||||
return DefaultPartPtr( data, partIdx );
|
||||
}
|
||||
|
||||
--variantIdx;
|
||||
var flag = 1 << partIdx;
|
||||
|
||||
if( ( PartMask( data ) & flag ) == 0 || variantIdx >= CountInternal( data ) )
|
||||
if( ( PartMask( data ) & flag ) == 0 || variantIdx > CountInternal( data ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var numParts = BitOperations.PopCount( PartMask( data ) );
|
||||
var ptr = ( ImcEntry* )( data + PreambleSize );
|
||||
ptr += numParts;
|
||||
ptr += variantIdx * numParts;
|
||||
ptr += partIdx;
|
||||
ptr += variantIdx * numParts + partIdx;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
@ -139,21 +133,22 @@ public unsafe class ImcFile : MetaBaseFile
|
|||
return true;
|
||||
}
|
||||
|
||||
var oldCount = Count;
|
||||
*( ushort* )Data = ( ushort )numVariants;
|
||||
if( ActualLength > Length )
|
||||
{
|
||||
PluginLog.Warning( "Adding too many variants to IMC, size exceeded." );
|
||||
return false;
|
||||
var newLength = ( ( ( ActualLength - 1 ) >> 7 ) + 1 ) << 7;
|
||||
PluginLog.Verbose( "Resized IMC {Path} from {Length} to {NewLength}.", Path, Length, newLength );
|
||||
ResizeResources( newLength );
|
||||
}
|
||||
|
||||
var defaultPtr = ( ImcEntry* )( Data + PreambleSize );
|
||||
var endPtr = defaultPtr + ( numVariants + 1 ) * NumParts;
|
||||
for( var ptr = defaultPtr + NumParts; ptr < endPtr; ptr += NumParts )
|
||||
for( var i = oldCount + 1; i < numVariants + 1; ++i )
|
||||
{
|
||||
Functions.MemCpyUnchecked( ptr, defaultPtr, NumParts * sizeof( ImcEntry ) );
|
||||
Functions.MemCpyUnchecked( defaultPtr + i, defaultPtr, NumParts * sizeof( ImcEntry ) );
|
||||
}
|
||||
|
||||
PluginLog.Verbose( "Expanded imc from {Count} to {NewCount} variants.", Count, numVariants );
|
||||
*( ushort* )Data = ( ushort )numVariants;
|
||||
PluginLog.Verbose( "Expanded IMC {Path} from {Count} to {NewCount} variants.", Path, oldCount, numVariants );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -240,7 +235,7 @@ public unsafe class ImcFile : MetaBaseFile
|
|||
}
|
||||
|
||||
var requiredLength = ActualLength;
|
||||
resource->SetData( (IntPtr) Data, Length );
|
||||
resource->SetData( ( IntPtr )Data, Length );
|
||||
if( length >= requiredLength )
|
||||
{
|
||||
Functions.MemCpyUnchecked( ( void* )data, Data, requiredLength );
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using Dalamud.Memory;
|
||||
using Penumbra.GameData.Util;
|
||||
|
||||
namespace Penumbra.Meta.Files;
|
||||
|
||||
|
|
@ -44,6 +45,31 @@ public unsafe class MetaBaseFile : IDisposable
|
|||
Data = null;
|
||||
}
|
||||
|
||||
// Resize memory while retaining data.
|
||||
protected void ResizeResources( int newLength )
|
||||
{
|
||||
if( newLength == Length )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var data = ( byte* )MemoryHelper.GameAllocateDefault( ( ulong )newLength );
|
||||
if( newLength > Length )
|
||||
{
|
||||
Functions.MemCpyUnchecked( data, Data, Length );
|
||||
Functions.MemSet( data + Length, 0, newLength - Length );
|
||||
}
|
||||
else
|
||||
{
|
||||
Functions.MemCpyUnchecked( data, Data, newLength );
|
||||
}
|
||||
|
||||
ReleaseUnmanagedResources();
|
||||
GC.AddMemoryPressure( newLength );
|
||||
Data = data;
|
||||
Length = newLength;
|
||||
}
|
||||
|
||||
// Manually free memory.
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ public partial class MetaManager
|
|||
public readonly Dictionary< ImcManipulation, Mod.Mod > Manipulations = new();
|
||||
|
||||
private readonly ModCollection _collection;
|
||||
private readonly ResourceLoader.ResourceLoadCustomizationDelegate? _previousDelegate;
|
||||
private static int _imcManagerCount;
|
||||
private static ResourceLoader.ResourceLoadCustomizationDelegate? _previousDelegate;
|
||||
|
||||
|
||||
public MetaManagerImc( ModCollection collection )
|
||||
|
|
@ -97,25 +98,30 @@ public partial class MetaManager
|
|||
|
||||
Files.Clear();
|
||||
Manipulations.Clear();
|
||||
RestoreDelegate();
|
||||
}
|
||||
|
||||
[Conditional( "USE_IMC" )]
|
||||
private unsafe void SetupDelegate()
|
||||
private static unsafe void SetupDelegate()
|
||||
{
|
||||
Penumbra.ResourceLoader.ResourceLoadCustomization = ImcLoadHandler;
|
||||
Penumbra.ResourceLoader.ResourceLoaded += ImcResourceHandler;
|
||||
}
|
||||
|
||||
[Conditional( "USE_IMC" )]
|
||||
private unsafe void RestoreDelegate()
|
||||
{
|
||||
if( Penumbra.ResourceLoader.ResourceLoadCustomization == ImcLoadHandler )
|
||||
if( _imcManagerCount++ == 0 )
|
||||
{
|
||||
Penumbra.ResourceLoader.ResourceLoadCustomization = _previousDelegate;
|
||||
Penumbra.ResourceLoader.ResourceLoadCustomization = ImcLoadHandler;
|
||||
Penumbra.ResourceLoader.ResourceLoaded += ImcResourceHandler;
|
||||
}
|
||||
}
|
||||
|
||||
Penumbra.ResourceLoader.ResourceLoaded -= ImcResourceHandler;
|
||||
[Conditional( "USE_IMC" )]
|
||||
private static unsafe void RestoreDelegate()
|
||||
{
|
||||
if( --_imcManagerCount == 0 )
|
||||
{
|
||||
if( Penumbra.ResourceLoader.ResourceLoadCustomization == ImcLoadHandler )
|
||||
{
|
||||
Penumbra.ResourceLoader.ResourceLoadCustomization = _previousDelegate;
|
||||
}
|
||||
|
||||
Penumbra.ResourceLoader.ResourceLoaded -= ImcResourceHandler;
|
||||
}
|
||||
}
|
||||
|
||||
private FullPath CreateImcPath( Utf8GamePath path )
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue