mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-19 14:27:50 +01:00
Make GMP independent of file, cleanup unused functions.
This commit is contained in:
parent
c53f29c257
commit
943207cae8
14 changed files with 108 additions and 158 deletions
64
Penumbra/Interop/Hooks/Meta/GmpHook.cs
Normal file
64
Penumbra/Interop/Hooks/Meta/GmpHook.cs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
using OtterGui.Services;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
using Penumbra.Meta.Files;
|
||||
using Penumbra.Meta.Manipulations;
|
||||
|
||||
namespace Penumbra.Interop.Hooks.Meta;
|
||||
|
||||
public unsafe class GmpHook : FastHook<GmpHook.Delegate>
|
||||
{
|
||||
public delegate nint Delegate(nint gmpResource, uint dividedHeadId);
|
||||
|
||||
private readonly MetaState _metaState;
|
||||
|
||||
private static readonly Finalizer StablePointer = new();
|
||||
|
||||
public GmpHook(HookManager hooks, MetaState metaState)
|
||||
{
|
||||
_metaState = metaState;
|
||||
Task = hooks.CreateHook<Delegate>("GetGmpEntry", "E8 ?? ?? ?? ?? 48 85 C0 74 ?? 43 8D 0C", Detour, true);
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// This function returns a pointer to the correct block in the GMP file, if it exists - cf. <see cref="ExpandedEqpGmpBase"/>.
|
||||
/// To work around this, we just have a single stable ulong accessible and offset the pointer to this by the required distance,
|
||||
/// which is defined by the modulo of the original ID and the block size, if we return our own custom gmp entry.
|
||||
/// </remarks>
|
||||
private nint Detour(nint gmpResource, uint dividedHeadId)
|
||||
{
|
||||
nint ret;
|
||||
if (_metaState.GmpCollection is { Valid: true, ModCollection.MetaCache: { } cache }
|
||||
&& cache.Gmp.TryGetValue(new GmpIdentifier(_metaState.UndividedGmpId), out var entry))
|
||||
{
|
||||
if (entry.Entry.Enabled)
|
||||
{
|
||||
*StablePointer.Pointer = entry.Entry.Value;
|
||||
// This function already gets the original ID divided by the block size, so we can compute the modulo with a single multiplication and addition.
|
||||
// We then go backwards from our pointer because this gets added by the calling functions.
|
||||
ret = (nint)(StablePointer.Pointer - (_metaState.UndividedGmpId.Id - dividedHeadId * ExpandedEqpGmpBase.BlockSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = nint.Zero;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Task.Result.Original(gmpResource, dividedHeadId);
|
||||
}
|
||||
|
||||
Penumbra.Log.Excessive($"[GetGmpFlags] Invoked on 0x{gmpResource:X} with {dividedHeadId}, returned {ret:X10}.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary> Allocate and clean up our single stable ulong pointer. </summary>
|
||||
private class Finalizer
|
||||
{
|
||||
public readonly ulong* Pointer = (ulong*)Marshal.AllocHGlobal(8);
|
||||
|
||||
~Finalizer()
|
||||
{
|
||||
Marshal.FreeHGlobal((nint)Pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.GameData;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
|
||||
namespace Penumbra.Interop.Hooks.Meta;
|
||||
|
||||
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||
using OtterGui.Services;
|
||||
using Penumbra.Collections;
|
||||
using Penumbra.GameData;
|
||||
using Penumbra.Interop.PathResolving;
|
||||
|
||||
namespace Penumbra.Interop.Hooks.Meta;
|
||||
|
||||
/// <summary>
|
||||
/// GMP. This gets called every time when changing visor state, and it accesses the gmp file itself,
|
||||
/// but it only applies a changed gmp file after a redraw for some reason.
|
||||
|
|
@ -26,10 +27,11 @@ public sealed unsafe class SetupVisor : FastHook<SetupVisor.Delegate>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
private byte Detour(DrawObject* drawObject, ushort modelId, byte visorState)
|
||||
{
|
||||
var collection = _collectionResolver.IdentifyCollection(drawObject, true);
|
||||
using var gmp = _metaState.ResolveGmpData(collection.ModCollection);
|
||||
var ret = Task.Result.Original.Invoke(drawObject, modelId, visorState);
|
||||
Penumbra.Log.Excessive($"[Setup Visor] Invoked on {(nint)drawObject:X} with {modelId}, {visorState} -> {ret}.");
|
||||
_metaState.GmpCollection = _collectionResolver.IdentifyCollection(drawObject, true);
|
||||
_metaState.UndividedGmpId = modelId;
|
||||
var ret = Task.Result.Original.Invoke(drawObject, modelId, visorState);
|
||||
Penumbra.Log.Information($"[Setup Visor] Invoked on {(nint)drawObject:X} with {modelId}, {visorState} -> {ret}.");
|
||||
_metaState.GmpCollection = ResolveData.Invalid;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,9 +95,6 @@ public sealed unsafe class MetaState : IDisposable
|
|||
_ => DisposableContainer.Empty,
|
||||
};
|
||||
|
||||
public MetaList.MetaReverter ResolveGmpData(ModCollection collection)
|
||||
=> collection.TemporarilySetGmpFile(_characterUtility);
|
||||
|
||||
public MetaList.MetaReverter ResolveRspData(ModCollection collection)
|
||||
=> collection.TemporarilySetCmpFile(_characterUtility);
|
||||
|
||||
|
|
|
|||
|
|
@ -102,30 +102,19 @@ public unsafe class MetaList : IDisposable
|
|||
ResetResourceInternal();
|
||||
}
|
||||
|
||||
public sealed class MetaReverter : IDisposable
|
||||
public sealed class MetaReverter(MetaList metaList, nint data, int length) : IDisposable
|
||||
{
|
||||
public static readonly MetaReverter Disabled = new(null!) { Disposed = true };
|
||||
|
||||
public readonly MetaList MetaList;
|
||||
public readonly nint Data;
|
||||
public readonly int Length;
|
||||
public readonly MetaList MetaList = metaList;
|
||||
public readonly nint Data = data;
|
||||
public readonly int Length = length;
|
||||
public readonly bool Resetter;
|
||||
public bool Disposed;
|
||||
|
||||
public MetaReverter(MetaList metaList, nint data, int length)
|
||||
{
|
||||
MetaList = metaList;
|
||||
Data = data;
|
||||
Length = length;
|
||||
}
|
||||
|
||||
public MetaReverter(MetaList metaList)
|
||||
{
|
||||
MetaList = metaList;
|
||||
Data = nint.Zero;
|
||||
Length = 0;
|
||||
Resetter = true;
|
||||
}
|
||||
: this(metaList, nint.Zero, 0)
|
||||
=> Resetter = true;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue