mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-16 05:34:25 +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
|
|
@ -26,7 +26,7 @@ public sealed class EqdpCache(MetaFileManager manager, ModCollection collection)
|
||||||
Manager.SetFile(_eqdpFiles[i], index);
|
Manager.SetFile(_eqdpFiles[i], index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ResetFiles()
|
public void ResetFiles()
|
||||||
{
|
{
|
||||||
foreach (var t in CharacterUtilityData.EqdpIndices)
|
foreach (var t in CharacterUtilityData.EqdpIndices)
|
||||||
Manager.SetFile(null, t);
|
Manager.SetFile(null, t);
|
||||||
|
|
@ -62,7 +62,7 @@ public sealed class EqdpCache(MetaFileManager manager, ModCollection collection)
|
||||||
return Manager.TemporarilySetFile(_eqdpFiles[i], idx);
|
return Manager.TemporarilySetFile(_eqdpFiles[i], idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
foreach (var file in _eqdpFiles.OfType<ExpandedEqdpFile>())
|
foreach (var file in _eqdpFiles.OfType<ExpandedEqdpFile>())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
using Penumbra.GameData.Enums;
|
using Penumbra.GameData.Enums;
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.Services;
|
|
||||||
using Penumbra.Interop.Structs;
|
|
||||||
using Penumbra.Meta;
|
using Penumbra.Meta;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
|
|
@ -10,24 +8,11 @@ namespace Penumbra.Collections.Cache;
|
||||||
|
|
||||||
public sealed class EqpCache(MetaFileManager manager, ModCollection collection) : MetaCacheBase<EqpIdentifier, EqpEntry>(manager, collection)
|
public sealed class EqpCache(MetaFileManager manager, ModCollection collection) : MetaCacheBase<EqpIdentifier, EqpEntry>(manager, collection)
|
||||||
{
|
{
|
||||||
private ExpandedEqpFile? _eqpFile;
|
|
||||||
|
|
||||||
public override void SetFiles()
|
public override void SetFiles()
|
||||||
=> Manager.SetFile(_eqpFile, MetaIndex.Eqp);
|
{ }
|
||||||
|
|
||||||
public override void ResetFiles()
|
|
||||||
=> Manager.SetFile(null, MetaIndex.Eqp);
|
|
||||||
|
|
||||||
protected override void IncorporateChangesInternal()
|
protected override void IncorporateChangesInternal()
|
||||||
{
|
{ }
|
||||||
if (GetFile() is not { } file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var (identifier, (_, entry)) in this)
|
|
||||||
Apply(file, identifier, entry);
|
|
||||||
|
|
||||||
Penumbra.Log.Verbose($"{Collection.AnonymizedName}: Loaded {Count} delayed EQP manipulations.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe EqpEntry GetValues(CharacterArmor* armor)
|
public unsafe EqpEntry GetValues(CharacterArmor* armor)
|
||||||
=> GetSingleValue(armor[0].Set, EquipSlot.Head)
|
=> GetSingleValue(armor[0].Set, EquipSlot.Head)
|
||||||
|
|
@ -40,29 +25,14 @@ public sealed class EqpCache(MetaFileManager manager, ModCollection collection)
|
||||||
private EqpEntry GetSingleValue(PrimaryId id, EquipSlot slot)
|
private EqpEntry GetSingleValue(PrimaryId id, EquipSlot slot)
|
||||||
=> TryGetValue(new EqpIdentifier(id, slot), out var pair) ? pair.Entry : ExpandedEqpFile.GetDefault(Manager, id) & Eqp.Mask(slot);
|
=> TryGetValue(new EqpIdentifier(id, slot), out var pair) ? pair.Entry : ExpandedEqpFile.GetDefault(Manager, id) & Eqp.Mask(slot);
|
||||||
|
|
||||||
public MetaList.MetaReverter TemporarilySetFile()
|
public void Reset()
|
||||||
=> Manager.TemporarilySetFile(_eqpFile, MetaIndex.Eqp);
|
=> Clear();
|
||||||
|
|
||||||
public override void Reset()
|
|
||||||
{
|
|
||||||
if (_eqpFile == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_eqpFile.Reset(Keys.Select(identifier => identifier.SetId));
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ApplyModInternal(EqpIdentifier identifier, EqpEntry entry)
|
protected override void ApplyModInternal(EqpIdentifier identifier, EqpEntry entry)
|
||||||
{
|
{ }
|
||||||
if (GetFile() is { } file)
|
|
||||||
Apply(file, identifier, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void RevertModInternal(EqpIdentifier identifier)
|
protected override void RevertModInternal(EqpIdentifier identifier)
|
||||||
{
|
{ }
|
||||||
if (GetFile() is { } file)
|
|
||||||
Apply(file, identifier, ExpandedEqpFile.GetDefault(Manager, identifier.SetId));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Apply(ExpandedEqpFile file, EqpIdentifier identifier, EqpEntry entry)
|
public static bool Apply(ExpandedEqpFile file, EqpIdentifier identifier, EqpEntry entry)
|
||||||
{
|
{
|
||||||
|
|
@ -76,20 +46,5 @@ public sealed class EqpCache(MetaFileManager manager, ModCollection collection)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool _)
|
protected override void Dispose(bool _)
|
||||||
{
|
=> Clear();
|
||||||
_eqpFile?.Dispose();
|
|
||||||
_eqpFile = null;
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExpandedEqpFile? GetFile()
|
|
||||||
{
|
|
||||||
if (_eqpFile != null)
|
|
||||||
return _eqpFile;
|
|
||||||
|
|
||||||
if (!Manager.CharacterUtility.Ready)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return _eqpFile = new ExpandedEqpFile(Manager);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ public sealed class EstCache(MetaFileManager manager, ModCollection collection)
|
||||||
return Manager.TemporarilySetFile(file, idx);
|
return Manager.TemporarilySetFile(file, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ResetFiles()
|
public void ResetFiles()
|
||||||
{
|
{
|
||||||
Manager.SetFile(null, MetaIndex.FaceEst);
|
Manager.SetFile(null, MetaIndex.FaceEst);
|
||||||
Manager.SetFile(null, MetaIndex.HairEst);
|
Manager.SetFile(null, MetaIndex.HairEst);
|
||||||
|
|
@ -80,7 +80,7 @@ public sealed class EstCache(MetaFileManager manager, ModCollection collection)
|
||||||
: EstFile.GetDefault(Manager, identifier);
|
: EstFile.GetDefault(Manager, identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
_estFaceFile?.Reset();
|
_estFaceFile?.Reset();
|
||||||
_estHairFile?.Reset();
|
_estHairFile?.Reset();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
using Penumbra.GameData.Structs;
|
using Penumbra.GameData.Structs;
|
||||||
using Penumbra.Interop.Services;
|
|
||||||
using Penumbra.Interop.Structs;
|
|
||||||
using Penumbra.Meta;
|
using Penumbra.Meta;
|
||||||
using Penumbra.Meta.Files;
|
using Penumbra.Meta.Files;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
|
|
@ -9,48 +7,20 @@ namespace Penumbra.Collections.Cache;
|
||||||
|
|
||||||
public sealed class GmpCache(MetaFileManager manager, ModCollection collection) : MetaCacheBase<GmpIdentifier, GmpEntry>(manager, collection)
|
public sealed class GmpCache(MetaFileManager manager, ModCollection collection) : MetaCacheBase<GmpIdentifier, GmpEntry>(manager, collection)
|
||||||
{
|
{
|
||||||
private ExpandedGmpFile? _gmpFile;
|
|
||||||
|
|
||||||
public override void SetFiles()
|
public override void SetFiles()
|
||||||
=> Manager.SetFile(_gmpFile, MetaIndex.Gmp);
|
{ }
|
||||||
|
|
||||||
public override void ResetFiles()
|
|
||||||
=> Manager.SetFile(null, MetaIndex.Gmp);
|
|
||||||
|
|
||||||
protected override void IncorporateChangesInternal()
|
protected override void IncorporateChangesInternal()
|
||||||
{
|
{ }
|
||||||
if (GetFile() is not { } file)
|
|
||||||
return;
|
|
||||||
|
|
||||||
foreach (var (identifier, (_, entry)) in this)
|
public void Reset()
|
||||||
Apply(file, identifier, entry);
|
=> Clear();
|
||||||
|
|
||||||
Penumbra.Log.Verbose($"{Collection.AnonymizedName}: Loaded {Count} delayed GMP manipulations.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public MetaList.MetaReverter TemporarilySetFile()
|
|
||||||
=> Manager.TemporarilySetFile(_gmpFile, MetaIndex.Gmp);
|
|
||||||
|
|
||||||
public override void Reset()
|
|
||||||
{
|
|
||||||
if (_gmpFile == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_gmpFile.Reset(Keys.Select(identifier => identifier.SetId));
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ApplyModInternal(GmpIdentifier identifier, GmpEntry entry)
|
protected override void ApplyModInternal(GmpIdentifier identifier, GmpEntry entry)
|
||||||
{
|
{ }
|
||||||
if (GetFile() is { } file)
|
|
||||||
Apply(file, identifier, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void RevertModInternal(GmpIdentifier identifier)
|
protected override void RevertModInternal(GmpIdentifier identifier)
|
||||||
{
|
{ }
|
||||||
if (GetFile() is { } file)
|
|
||||||
Apply(file, identifier, ExpandedGmpFile.GetDefault(Manager, identifier.SetId));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Apply(ExpandedGmpFile file, GmpIdentifier identifier, GmpEntry entry)
|
public static bool Apply(ExpandedGmpFile file, GmpIdentifier identifier, GmpEntry entry)
|
||||||
{
|
{
|
||||||
|
|
@ -63,20 +33,5 @@ public sealed class GmpCache(MetaFileManager manager, ModCollection collection)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool _)
|
protected override void Dispose(bool _)
|
||||||
{
|
=> Clear();
|
||||||
_gmpFile?.Dispose();
|
|
||||||
_gmpFile = null;
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ExpandedGmpFile? GetFile()
|
|
||||||
{
|
|
||||||
if (_gmpFile != null)
|
|
||||||
return _gmpFile;
|
|
||||||
|
|
||||||
if (!Manager.CharacterUtility.Ready)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
return _gmpFile = new ExpandedGmpFile(Manager);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,6 @@ public abstract class MetaCacheBase<TIdentifier, TEntry>
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void SetFiles();
|
public abstract void SetFiles();
|
||||||
public abstract void Reset();
|
|
||||||
public abstract void ResetFiles();
|
|
||||||
|
|
||||||
public bool ApplyMod(IMod source, TIdentifier identifier, TEntry entry)
|
public bool ApplyMod(IMod source, TIdentifier identifier, TEntry entry)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ public sealed class ImcCache(MetaFileManager manager, ModCollection collection)
|
||||||
Collection._cache!.ForceFile(path, PathDataHandler.CreateImc(path.Path, Collection));
|
Collection._cache!.ForceFile(path, PathDataHandler.CreateImc(path.Path, Collection));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ResetFiles()
|
public void ResetFiles()
|
||||||
{
|
{
|
||||||
foreach (var (path, _) in _imcFiles)
|
foreach (var (path, _) in _imcFiles)
|
||||||
Collection._cache!.ForceFile(path, FullPath.Empty);
|
Collection._cache!.ForceFile(path, FullPath.Empty);
|
||||||
|
|
@ -56,7 +56,7 @@ public sealed class ImcCache(MetaFileManager manager, ModCollection collection)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
foreach (var (path, (file, set)) in _imcFiles)
|
foreach (var (path, (file, set)) in _imcFiles)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -148,9 +148,6 @@ public class MetaCache(MetaFileManager manager, ModCollection collection)
|
||||||
public MetaList.MetaReverter? TemporarilySetEqdpFile(GenderRace genderRace, bool accessory)
|
public MetaList.MetaReverter? TemporarilySetEqdpFile(GenderRace genderRace, bool accessory)
|
||||||
=> Eqdp.TemporarilySetFile(genderRace, accessory);
|
=> Eqdp.TemporarilySetFile(genderRace, accessory);
|
||||||
|
|
||||||
public MetaList.MetaReverter TemporarilySetGmpFile()
|
|
||||||
=> Gmp.TemporarilySetFile();
|
|
||||||
|
|
||||||
public MetaList.MetaReverter TemporarilySetCmpFile()
|
public MetaList.MetaReverter TemporarilySetCmpFile()
|
||||||
=> Rsp.TemporarilySetFile();
|
=> Rsp.TemporarilySetFile();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,6 @@ public sealed class RspCache(MetaFileManager manager, ModCollection collection)
|
||||||
public override void SetFiles()
|
public override void SetFiles()
|
||||||
=> Manager.SetFile(_cmpFile, MetaIndex.HumanCmp);
|
=> Manager.SetFile(_cmpFile, MetaIndex.HumanCmp);
|
||||||
|
|
||||||
public override void ResetFiles()
|
|
||||||
=> Manager.SetFile(null, MetaIndex.HumanCmp);
|
|
||||||
|
|
||||||
protected override void IncorporateChangesInternal()
|
protected override void IncorporateChangesInternal()
|
||||||
{
|
{
|
||||||
if (GetFile() is not { } file)
|
if (GetFile() is not { } file)
|
||||||
|
|
@ -30,7 +27,7 @@ public sealed class RspCache(MetaFileManager manager, ModCollection collection)
|
||||||
public MetaList.MetaReverter TemporarilySetFile()
|
public MetaList.MetaReverter TemporarilySetFile()
|
||||||
=> Manager.TemporarilySetFile(_cmpFile, MetaIndex.HumanCmp);
|
=> Manager.TemporarilySetFile(_cmpFile, MetaIndex.HumanCmp);
|
||||||
|
|
||||||
public override void Reset()
|
public void Reset()
|
||||||
{
|
{
|
||||||
if (_cmpFile == null)
|
if (_cmpFile == null)
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -100,10 +100,6 @@ public partial class ModCollection
|
||||||
return idx >= 0 ? utility.TemporarilyResetResource(idx) : null;
|
return idx >= 0 ? utility.TemporarilyResetResource(idx) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public MetaList.MetaReverter TemporarilySetGmpFile(CharacterUtility utility)
|
|
||||||
=> _cache?.Meta.TemporarilySetGmpFile()
|
|
||||||
?? utility.TemporarilyResetResource(MetaIndex.Gmp);
|
|
||||||
|
|
||||||
public MetaList.MetaReverter TemporarilySetCmpFile(CharacterUtility utility)
|
public MetaList.MetaReverter TemporarilySetCmpFile(CharacterUtility utility)
|
||||||
=> _cache?.Meta.TemporarilySetCmpFile()
|
=> _cache?.Meta.TemporarilySetCmpFile()
|
||||||
?? utility.TemporarilyResetResource(MetaIndex.HumanCmp);
|
?? utility.TemporarilyResetResource(MetaIndex.HumanCmp);
|
||||||
|
|
|
||||||
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 FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
|
||||||
using OtterGui.Services;
|
using OtterGui.Services;
|
||||||
using Penumbra.GameData;
|
using Penumbra.Collections;
|
||||||
using Penumbra.Interop.PathResolving;
|
using Penumbra.GameData;
|
||||||
|
using Penumbra.Interop.PathResolving;
|
||||||
namespace Penumbra.Interop.Hooks.Meta;
|
|
||||||
|
namespace Penumbra.Interop.Hooks.Meta;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GMP. This gets called every time when changing visor state, and it accesses the gmp file itself,
|
/// 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.
|
/// 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)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||||
private byte Detour(DrawObject* drawObject, ushort modelId, byte visorState)
|
private byte Detour(DrawObject* drawObject, ushort modelId, byte visorState)
|
||||||
{
|
{
|
||||||
var collection = _collectionResolver.IdentifyCollection(drawObject, true);
|
_metaState.GmpCollection = _collectionResolver.IdentifyCollection(drawObject, true);
|
||||||
using var gmp = _metaState.ResolveGmpData(collection.ModCollection);
|
_metaState.UndividedGmpId = modelId;
|
||||||
var ret = Task.Result.Original.Invoke(drawObject, modelId, visorState);
|
var ret = Task.Result.Original.Invoke(drawObject, modelId, visorState);
|
||||||
Penumbra.Log.Excessive($"[Setup Visor] Invoked on {(nint)drawObject:X} with {modelId}, {visorState} -> {ret}.");
|
Penumbra.Log.Information($"[Setup Visor] Invoked on {(nint)drawObject:X} with {modelId}, {visorState} -> {ret}.");
|
||||||
|
_metaState.GmpCollection = ResolveData.Invalid;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -95,9 +95,6 @@ public sealed unsafe class MetaState : IDisposable
|
||||||
_ => DisposableContainer.Empty,
|
_ => DisposableContainer.Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
public MetaList.MetaReverter ResolveGmpData(ModCollection collection)
|
|
||||||
=> collection.TemporarilySetGmpFile(_characterUtility);
|
|
||||||
|
|
||||||
public MetaList.MetaReverter ResolveRspData(ModCollection collection)
|
public MetaList.MetaReverter ResolveRspData(ModCollection collection)
|
||||||
=> collection.TemporarilySetCmpFile(_characterUtility);
|
=> collection.TemporarilySetCmpFile(_characterUtility);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,30 +102,19 @@ public unsafe class MetaList : IDisposable
|
||||||
ResetResourceInternal();
|
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 static readonly MetaReverter Disabled = new(null!) { Disposed = true };
|
||||||
|
|
||||||
public readonly MetaList MetaList;
|
public readonly MetaList MetaList = metaList;
|
||||||
public readonly nint Data;
|
public readonly nint Data = data;
|
||||||
public readonly int Length;
|
public readonly int Length = length;
|
||||||
public readonly bool Resetter;
|
public readonly bool Resetter;
|
||||||
public bool Disposed;
|
public bool Disposed;
|
||||||
|
|
||||||
public MetaReverter(MetaList metaList, nint data, int length)
|
|
||||||
{
|
|
||||||
MetaList = metaList;
|
|
||||||
Data = data;
|
|
||||||
Length = length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MetaReverter(MetaList metaList)
|
public MetaReverter(MetaList metaList)
|
||||||
{
|
: this(metaList, nint.Zero, 0)
|
||||||
MetaList = metaList;
|
=> Resetter = true;
|
||||||
Data = nint.Zero;
|
|
||||||
Length = 0;
|
|
||||||
Resetter = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,10 @@ namespace Penumbra.Meta.Files;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public unsafe class ExpandedEqpGmpBase : MetaBaseFile
|
public unsafe class ExpandedEqpGmpBase : MetaBaseFile
|
||||||
{
|
{
|
||||||
protected const int BlockSize = 160;
|
public const int BlockSize = 160;
|
||||||
protected const int NumBlocks = 64;
|
public const int NumBlocks = 64;
|
||||||
protected const int EntrySize = 8;
|
public const int EntrySize = 8;
|
||||||
protected const int MaxSize = BlockSize * NumBlocks * EntrySize;
|
public const int MaxSize = BlockSize * NumBlocks * EntrySize;
|
||||||
|
|
||||||
public const int Count = BlockSize * NumBlocks;
|
public const int Count = BlockSize * NumBlocks;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue