diff --git a/Penumbra.GameData/Actors/ActorManager.Data.cs b/Penumbra.GameData/Actors/ActorManager.Data.cs index 77bd13bf..5dd6d696 100644 --- a/Penumbra.GameData/Actors/ActorManager.Data.cs +++ b/Penumbra.GameData/Actors/ActorManager.Data.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using Dalamud; using Dalamud.Data; +using Dalamud.Game; using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.Enums; @@ -229,10 +230,10 @@ public sealed partial class ActorManager : IDisposable private readonly Func _toParentIdx; - [Signature("0F B7 0D ?? ?? ?? ?? C7 85", ScanType = ScanType.StaticAddress)] + [Signature(Sigs.InspectTitleId, ScanType = ScanType.StaticAddress)] private static unsafe ushort* _inspectTitleId = null!; - [Signature("0F B7 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B D0", ScanType = ScanType.StaticAddress)] + [Signature(Sigs.InspectWorldId, ScanType = ScanType.StaticAddress)] private static unsafe ushort* _inspectWorldId = null!; private static unsafe ushort InspectTitleId diff --git a/Penumbra.GameData/Signatures.cs b/Penumbra.GameData/Signatures.cs new file mode 100644 index 00000000..9f13bdf1 --- /dev/null +++ b/Penumbra.GameData/Signatures.cs @@ -0,0 +1,91 @@ +namespace Penumbra.GameData; + +public static class Sigs +{ + // ResourceLoader.Debug + public const string ResourceHandleDestructor = "48 89 5C 24 ?? 57 48 83 EC ?? 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 B8"; + public const string ResourceManager = "48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 32 C0"; + + // ResourceLoader.Replacement + public const string GetResourceSync = "E8 ?? ?? 00 00 48 8D 8F ?? ?? 00 00 48 89 87 ?? ?? 00 00"; + public const string GetResourceAsync = "E8 ?? ?? ?? 00 48 8B D8 EB ?? F0 FF 83 ?? ?? 00 00"; + public const string ReadFile = "E8 ?? ?? ?? ?? 84 C0 0F 84 ?? 00 00 00 4C 8B C3 BA 05"; + public const string ReadSqPack = "E8 ?? ?? ?? ?? EB 05 E8 ?? ?? ?? ?? 84 C0 0F 84 ?? 00 00 00 4C 8B C3"; + + // ResourceLoader.TexMdl + public const string CheckFileState = "E8 ?? ?? ?? ?? 48 85 c0 74 ?? 45 0f b6 ce 48 89 44 24"; + public const string LoadTexFileLocal = "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 30 49 8B F0 44 88 4C 24 20"; + public const string LoadMdlFileLocal = "40 55 53 56 57 41 56 41 57 48 8D 6C 24 D1 48 81 EC 98 00 00 00"; + public const string LoadTexFileExtern = "E8 ?? ?? ?? ?? 0F B6 E8 48 8B CB E8"; + public const string LoadMdlFileExtern = "E8 ?? ?? ?? ?? EB 02 B0 F1"; + + // CutsceneCharacters + public const string CopyCharacter = "E8 ?? ?? ?? ?? 0F B6 9F ?? ?? ?? ?? 48 8D 8F"; + + // IdentifiedCollectionCache + public const string CharacterDestructor = + "48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 48 8D 05 ?? ?? ?? ?? 48 89 81 ?? ?? ?? ?? 48 8D 05"; + + // PathResolver.AnimationState + public const string LoadCharacterSound = "4C 89 4C 24 ?? 55 57 41 56"; + public const string LoadTimelineResources = "E8 ?? ?? ?? ?? 83 7F ?? ?? 75 ?? 0F B6 87"; + public const string CharacterBaseLoadAnimation = "E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8B CF 44 8B C2 E8 ?? ?? ?? ?? 48 8B 05"; + public const string LoadSomePap = "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 41 8B D9 89 51"; + public const string LoadSomeAction = "E8 ?? ?? ?? ?? C6 83 ?? ?? ?? ?? ?? 8B 8E"; + public const string LoadCharacterVfx = "E8 ?? ?? ?? ?? 48 8B F8 48 8D 93"; + public const string LoadAreaVfx = "48 8B C4 53 55 56 57 41 56 48 81 EC"; + public const string ScheduleClipUpdate = "40 53 55 56 57 41 56 48 81 EC ?? ?? ?? ?? 48 8B F9"; + + // PathResolver.DrawObjectState + public const string CharacterBaseCreate = "E8 ?? ?? ?? ?? 48 85 C0 74 21 C7 40"; + + public const string CharacterBaseDestructor = + "E8 ?? ?? ?? ?? 40 F6 C7 01 74 3A 40 F6 C7 04 75 27 48 85 DB 74 2F 48 8B 05 ?? ?? ?? ?? 48 8B D3 48 8B 48 30"; + + public const string EnableDraw = "E8 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 85 C9 74 33 45 33 C0"; + public const string WeaponReload = "E8 ?? ?? ?? ?? 44 8B 9F"; + + // PathResolver.Meta + public const string UpdateModel = "48 8B ?? 56 48 83 ?? ?? ?? B9"; + public const string GetEqpIndirect = "40 ?? 48 83 ?? ?? ?? 81 ?? ?? ?? ?? ?? 48 8B ?? 74 ?? ?? 83 ?? ?? ?? ?? ?? ?? 74 ?? 4C"; + public const string SetupVisor = "48 8B ?? 53 55 57 48 83 ?? ?? 48 8B"; + public const string RspSetupCharacter = "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 88 54 24 ?? 57 41 56"; + public const string ChangeCustomize = "E8 ?? ?? ?? ?? 41 0F B6 C5 66 41 89 86"; + + // PathResolver.PathState + public const string HumanVTable = "48 8D 05 ?? ?? ?? ?? 48 89 03 48 8D 8B ?? ?? ?? ?? 44 89 83 ?? ?? ?? ?? 48 8B C1"; + + public const string WeaponVTable = + "48 8D 05 ?? ?? ?? ?? 48 89 03 B8 ?? ?? ?? ?? 66 89 83 ?? ?? ?? ?? 48 8B C3 48 89 8B ?? ?? ?? ?? 48 89 8B"; + + public const string DemiHumanVTable = "48 8D 05 ?? ?? ?? ?? 45 33 C0 48 89 03 BA"; + public const string MonsterVTable = "48 8D 05 ?? ?? ?? ?? 48 89 03 33 C0 48 89 83 ?? ?? ?? ?? 48 89 83 ?? ?? ?? ?? C7 83"; + + // PathResolver.Subfiles + public const string LoadMtrlTex = "4C 8B DC 49 89 5B ?? 49 89 73 ?? 55 57 41 55"; + + public const string LoadMtrlShpk = + "48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 44 0F B7 89"; + + public const string ApricotResourceLoad = "48 89 74 24 ?? 57 48 83 EC ?? 41 0F B6 F0 48 8B F9"; + + // CharacterUtility + public const string CharacterUtility = "48 8B 05 ?? ?? ?? ?? 83 B9"; + public const string LoadCharacterResources = "E8 ?? ?? ?? ?? 48 8D 8F ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 D2 45 33 C0"; + + // MetaFileManager + public const string GetFileSpace = "E8 ?? ?? ?? ?? 41 B9 ?? ?? ?? ?? 4C 8B C0"; + + // ResidentResourceManager + public const string ResidentResourceManager = "0F 44 FE 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 05"; + + public const string LoadPlayerResources = + "E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? BA ?? ?? ?? ?? 41 B8 ?? ?? ?? ?? 48 8B 48 30 48 8B 01 FF 50 10 48 85 C0 74 0A"; + + public const string UnloadPlayerResources = + "41 55 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 4C 8B E9 48 83 C1 08"; + + // ActorManager + public const string InspectTitleId = "0F B7 0D ?? ?? ?? ?? C7 85"; + public const string InspectWorldId = "0F B7 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B D0"; +} diff --git a/Penumbra/Interop/CharacterUtility.cs b/Penumbra/Interop/CharacterUtility.cs index 63d08bc0..de02f091 100644 --- a/Penumbra/Interop/CharacterUtility.cs +++ b/Penumbra/Interop/CharacterUtility.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using Dalamud.Utility.Signatures; +using Penumbra.GameData; namespace Penumbra.Interop; @@ -10,13 +11,13 @@ public unsafe partial class CharacterUtility : IDisposable public record struct InternalIndex( int Value ); // A static pointer to the CharacterUtility address. - [Signature( "48 8B 05 ?? ?? ?? ?? 83 B9", ScanType = ScanType.StaticAddress )] + [Signature( Sigs.CharacterUtility, ScanType = ScanType.StaticAddress )] private readonly Structs.CharacterUtility** _characterUtilityAddress = null; // Only required for migration anymore. public delegate void LoadResources( Structs.CharacterUtility* address ); - [Signature( "E8 ?? ?? ?? ?? 48 8D 8F ?? ?? ?? ?? E8 ?? ?? ?? ?? 33 D2 45 33 C0" )] + [Signature( Sigs.LoadCharacterResources )] public readonly LoadResources LoadCharacterResourcesFunc = null!; public void LoadCharacterResources() diff --git a/Penumbra/Interop/Loader/ResourceLoader.Debug.cs b/Penumbra/Interop/Loader/ResourceLoader.Debug.cs index 76eba25d..64ae0026 100644 --- a/Penumbra/Interop/Loader/ResourceLoader.Debug.cs +++ b/Penumbra/Interop/Loader/ResourceLoader.Debug.cs @@ -7,6 +7,7 @@ using FFXIVClientStructs.FFXIV.Client.System.Resource; using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle; using FFXIVClientStructs.STD; using Penumbra.Collections; +using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.String; using Penumbra.String.Classes; @@ -22,8 +23,7 @@ public unsafe partial class ResourceLoader public delegate IntPtr ResourceHandleDestructor( ResourceHandle* handle ); - [Signature( "48 89 5C 24 ?? 57 48 83 EC ?? 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 B8", - DetourName = nameof( ResourceHandleDestructorDetour ) )] + [Signature( Sigs.ResourceHandleDestructor, DetourName = nameof( ResourceHandleDestructorDetour ) )] public static Hook< ResourceHandleDestructor >? ResourceHandleDestructorHook; private IntPtr ResourceHandleDestructorDetour( ResourceHandle* handle ) @@ -37,7 +37,7 @@ public unsafe partial class ResourceLoader } // A static pointer to the SE Resource Manager - [Signature( "48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 32 C0", ScanType = ScanType.StaticAddress, UseFlags = SignatureUseFlags.Pointer )] + [Signature( Sigs.ResourceManager, ScanType = ScanType.StaticAddress, UseFlags = SignatureUseFlags.Pointer )] public static ResourceManager** ResourceManager; // Gather some debugging data about penumbra-loaded objects. diff --git a/Penumbra/Interop/Loader/ResourceLoader.Replacement.cs b/Penumbra/Interop/Loader/ResourceLoader.Replacement.cs index b4505ce7..b02cfff6 100644 --- a/Penumbra/Interop/Loader/ResourceLoader.Replacement.cs +++ b/Penumbra/Interop/Loader/ResourceLoader.Replacement.cs @@ -7,6 +7,7 @@ using Dalamud.Hooking; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.System.Resource; using Penumbra.Collections; +using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.Interop.Structs; using Penumbra.String; @@ -38,14 +39,14 @@ public unsafe partial class ResourceLoader public delegate ResourceHandle* GetResourceSyncPrototype( ResourceManager* resourceManager, ResourceCategory* pCategoryId, ResourceType* pResourceType, int* pResourceHash, byte* pPath, GetResourceParameters* pGetResParams ); - [Signature( "E8 ?? ?? 00 00 48 8D 8F ?? ?? 00 00 48 89 87 ?? ?? 00 00", DetourName = "GetResourceSyncDetour" )] - public Hook< GetResourceSyncPrototype > GetResourceSyncHook = null!; + [Signature( Sigs.GetResourceSync, DetourName = nameof( GetResourceSyncDetour ) )] + public readonly Hook< GetResourceSyncPrototype > GetResourceSyncHook = null!; public delegate ResourceHandle* GetResourceAsyncPrototype( ResourceManager* resourceManager, ResourceCategory* pCategoryId, ResourceType* pResourceType, int* pResourceHash, byte* pPath, GetResourceParameters* pGetResParams, bool isUnknown ); - [Signature( "E8 ?? ?? ?? 00 48 8B D8 EB ?? F0 FF 83 ?? ?? 00 00", DetourName = "GetResourceAsyncDetour" )] - public Hook< GetResourceAsyncPrototype > GetResourceAsyncHook = null!; + [Signature( Sigs.GetResourceAsync, DetourName = nameof( GetResourceAsyncDetour ) )] + public readonly Hook< GetResourceAsyncPrototype > GetResourceAsyncHook = null!; private ResourceHandle* GetResourceSyncDetour( ResourceManager* resourceManager, ResourceCategory* categoryId, ResourceType* resourceType, int* resourceHash, byte* path, GetResourceParameters* pGetResParams ) @@ -79,7 +80,7 @@ public unsafe partial class ResourceLoader return GetResourceHandler( true, *ResourceManager, &category, &type, &hash, path.Path, null, false ); } - internal ResourceHandle* GetResourceHandler( bool isSync, ResourceManager* resourceManager, ResourceCategory* categoryId, + private ResourceHandle* GetResourceHandler( bool isSync, ResourceManager* resourceManager, ResourceCategory* categoryId, ResourceType* resourceType, int* resourceHash, byte* path, GetResourceParameters* pGetResParams, bool isUnk ) { using var performance = Penumbra.Performance.Measure( PerformanceType.GetResourceHandler ); @@ -157,14 +158,14 @@ public unsafe partial class ResourceLoader public delegate byte ReadFileDelegate( ResourceManager* resourceManager, SeFileDescriptor* fileDescriptor, int priority, bool isSync ); - [Signature( "E8 ?? ?? ?? ?? 84 C0 0F 84 ?? 00 00 00 4C 8B C3 BA 05" )] - public ReadFileDelegate ReadFile = null!; + [Signature( Sigs.ReadFile )] + public readonly ReadFileDelegate ReadFile = null!; // We hook ReadSqPack to redirect rooted files to ReadFile. public delegate byte ReadSqPackPrototype( ResourceManager* resourceManager, SeFileDescriptor* pFileDesc, int priority, bool isSync ); - [Signature( "E8 ?? ?? ?? ?? EB 05 E8 ?? ?? ?? ?? 84 C0 0F 84 ?? 00 00 00 4C 8B C3", DetourName = nameof( ReadSqPackDetour ) )] - public Hook< ReadSqPackPrototype > ReadSqPackHook = null!; + [Signature( Sigs.ReadSqPack, DetourName = nameof( ReadSqPackDetour ) )] + public readonly Hook< ReadSqPackPrototype > ReadSqPackHook = null!; private byte ReadSqPackDetour( ResourceManager* resourceManager, SeFileDescriptor* fileDescriptor, int priority, bool isSync ) { diff --git a/Penumbra/Interop/Loader/ResourceLoader.TexMdl.cs b/Penumbra/Interop/Loader/ResourceLoader.TexMdl.cs index 415b18f7..7baced91 100644 --- a/Penumbra/Interop/Loader/ResourceLoader.TexMdl.cs +++ b/Penumbra/Interop/Loader/ResourceLoader.TexMdl.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Dalamud.Hooking; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle; +using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.String.Classes; @@ -26,8 +27,8 @@ public unsafe partial class ResourceLoader // We use it to check against our stored CRC64s and if it corresponds, we return the custom flag. public delegate IntPtr CheckFileStatePrototype( IntPtr unk1, ulong crc64 ); - [Signature( "E8 ?? ?? ?? ?? 48 85 c0 74 ?? 45 0f b6 ce 48 89 44 24", DetourName = nameof( CheckFileStateDetour ) )] - public Hook< CheckFileStatePrototype > CheckFileStateHook = null!; + [Signature( Sigs.CheckFileState, DetourName = nameof( CheckFileStateDetour ) )] + public readonly Hook< CheckFileStatePrototype > CheckFileStateHook = null!; private IntPtr CheckFileStateDetour( IntPtr ptr, ulong crc64 ) => _customFileCrc.Contains( crc64 ) ? CustomFileFlag : CheckFileStateHook.Original( ptr, crc64 ); @@ -36,20 +37,20 @@ public unsafe partial class ResourceLoader // We use the local functions for our own files in the extern hook. public delegate byte LoadTexFileLocalDelegate( ResourceHandle* handle, int unk1, IntPtr unk2, bool unk3 ); - [Signature( "48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 48 83 EC 30 49 8B F0 44 88 4C 24 20" )] - public LoadTexFileLocalDelegate LoadTexFileLocal = null!; + [Signature( Sigs.LoadTexFileLocal )] + public readonly LoadTexFileLocalDelegate LoadTexFileLocal = null!; public delegate byte LoadMdlFileLocalPrototype( ResourceHandle* handle, IntPtr unk1, bool unk2 ); - [Signature( "40 55 53 56 57 41 56 41 57 48 8D 6C 24 D1 48 81 EC 98 00 00 00" )] - public LoadMdlFileLocalPrototype LoadMdlFileLocal = null!; + [Signature( Sigs.LoadMdlFileLocal )] + public readonly LoadMdlFileLocalPrototype LoadMdlFileLocal = null!; // We hook the extern functions to just return the local one if given the custom flag as last argument. public delegate byte LoadTexFileExternPrototype( ResourceHandle* handle, int unk1, IntPtr unk2, bool unk3, IntPtr unk4 ); - [Signature( "E8 ?? ?? ?? ?? 0F B6 E8 48 8B CB E8", DetourName = nameof( LoadTexFileExternDetour ) )] - public Hook< LoadTexFileExternPrototype > LoadTexFileExternHook = null!; + [Signature( Sigs.LoadTexFileExtern, DetourName = nameof( LoadTexFileExternDetour ) )] + public readonly Hook< LoadTexFileExternPrototype > LoadTexFileExternHook = null!; private byte LoadTexFileExternDetour( ResourceHandle* resourceHandle, int unk1, IntPtr unk2, bool unk3, IntPtr ptr ) => ptr.Equals( CustomFileFlag ) @@ -59,8 +60,8 @@ public unsafe partial class ResourceLoader public delegate byte LoadMdlFileExternPrototype( ResourceHandle* handle, IntPtr unk1, bool unk2, IntPtr unk3 ); - [Signature( "E8 ?? ?? ?? ?? EB 02 B0 F1", DetourName = nameof( LoadMdlFileExternDetour ) )] - public Hook< LoadMdlFileExternPrototype > LoadMdlFileExternHook = null!; + [Signature( Sigs.LoadMdlFileExtern, DetourName = nameof( LoadMdlFileExternDetour ) )] + public readonly Hook< LoadMdlFileExternPrototype > LoadMdlFileExternHook = null!; private byte LoadMdlFileExternDetour( ResourceHandle* resourceHandle, IntPtr unk1, bool unk2, IntPtr ptr ) => ptr.Equals( CustomFileFlag ) diff --git a/Penumbra/Interop/MetaFileManager.cs b/Penumbra/Interop/MetaFileManager.cs index 880a0ee8..c49efa1e 100644 --- a/Penumbra/Interop/MetaFileManager.cs +++ b/Penumbra/Interop/MetaFileManager.cs @@ -1,6 +1,7 @@ using System; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.System.Memory; +using Penumbra.GameData; namespace Penumbra.Interop; @@ -13,7 +14,7 @@ public unsafe class MetaFileManager // Allocate in the games space for file storage. // We only need this if using any meta file. - [Signature( "E8 ?? ?? ?? ?? 41 B9 ?? ?? ?? ?? 4C 8B C0" )] + [Signature( Sigs.GetFileSpace )] private readonly IntPtr _getFileSpaceAddress = IntPtr.Zero; public IMemorySpace* GetFileSpace() diff --git a/Penumbra/Interop/ObjectReloader.cs b/Penumbra/Interop/ObjectReloader.cs index 31b2c6dc..36415696 100644 --- a/Penumbra/Interop/ObjectReloader.cs +++ b/Penumbra/Interop/ObjectReloader.cs @@ -7,7 +7,6 @@ using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; using Penumbra.Api; using Penumbra.Api.Enums; -using Penumbra.GameData.Enums; using Penumbra.Interop.Structs; namespace Penumbra.Interop; diff --git a/Penumbra/Interop/ResidentResourceManager.cs b/Penumbra/Interop/ResidentResourceManager.cs index 37ed1bfe..84063fa6 100644 --- a/Penumbra/Interop/ResidentResourceManager.cs +++ b/Penumbra/Interop/ResidentResourceManager.cs @@ -1,21 +1,24 @@ using Dalamud.Utility.Signatures; +using Penumbra.GameData; namespace Penumbra.Interop; public unsafe class ResidentResourceManager { + // A static pointer to the resident resource manager address. + [Signature( Sigs.ResidentResourceManager, ScanType = ScanType.StaticAddress )] + private readonly Structs.ResidentResourceManager** _residentResourceManagerAddress = null; + // Some attach and physics files are stored in the resident resource manager, and we need to manually trigger a reload of them to get them to apply. public delegate void* ResidentResourceDelegate( void* residentResourceManager ); - [Signature( "E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? BA ?? ?? ?? ?? 41 B8 ?? ?? ?? ?? 48 8B 48 30 48 8B 01 FF 50 10 48 85 C0 74 0A" )] - public ResidentResourceDelegate LoadPlayerResources = null!; + [Signature( Sigs.LoadPlayerResources )] + public readonly ResidentResourceDelegate LoadPlayerResources = null!; + + [Signature( Sigs.UnloadPlayerResources )] + public readonly ResidentResourceDelegate UnloadPlayerResources = null!; - [Signature( "41 55 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 4C 8B E9 48 83 C1 08" )] - public ResidentResourceDelegate UnloadPlayerResources = null!; - // A static pointer to the resident resource manager address. - [Signature( "0F 44 FE 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 05", ScanType = ScanType.StaticAddress )] - private readonly Structs.ResidentResourceManager** _residentResourceManagerAddress = null; public Structs.ResidentResourceManager* Address => *_residentResourceManagerAddress; diff --git a/Penumbra/Interop/Resolver/CutsceneCharacters.cs b/Penumbra/Interop/Resolver/CutsceneCharacters.cs index b055320a..7a3b9cf7 100644 --- a/Penumbra/Interop/Resolver/CutsceneCharacters.cs +++ b/Penumbra/Interop/Resolver/CutsceneCharacters.cs @@ -6,6 +6,7 @@ using Dalamud.Game.ClientState.Conditions; using Dalamud.Hooking; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.Game.Object; +using Penumbra.GameData; namespace Penumbra.Interop.Resolver; @@ -96,7 +97,7 @@ public class CutsceneCharacters : IDisposable private unsafe delegate ulong CopyCharacterDelegate( GameObject* target, GameObject* source, uint unk ); - [Signature( "E8 ?? ?? ?? ?? 0F B6 9F ?? ?? ?? ?? 48 8D 8F", DetourName = nameof( CopyCharacterDetour ) )] + [Signature( Sigs.CopyCharacter, DetourName = nameof( CopyCharacterDetour ) )] private readonly Hook< CopyCharacterDelegate > _copyCharacterHook = null!; private unsafe ulong CopyCharacterDetour( GameObject* target, GameObject* source, uint unk ) diff --git a/Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs b/Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs index a6692839..12fd6749 100644 --- a/Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs +++ b/Penumbra/Interop/Resolver/IdentifiedCollectionCache.cs @@ -6,6 +6,7 @@ using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.Game.Character; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Penumbra.Collections; +using Penumbra.GameData; using Penumbra.GameData.Actors; namespace Penumbra.Interop.Resolver; @@ -117,8 +118,7 @@ public unsafe class IdentifiedCollectionCache : IDisposable, IEnumerable< (IntPt private delegate void CharacterDestructorDelegate( Character* character ); - [Signature( "48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 48 8D 05 ?? ?? ?? ?? 48 89 81 ?? ?? ?? ?? 48 8D 05", - DetourName = nameof( CharacterDestructorDetour ) )] + [Signature( Sigs.CharacterDestructor, DetourName = nameof( CharacterDestructorDetour ) )] private Hook< CharacterDestructorDelegate > _characterDtorHook = null!; private void CharacterDestructorDetour( Character* character ) diff --git a/Penumbra/Interop/Resolver/PathResolver.AnimationState.cs b/Penumbra/Interop/Resolver/PathResolver.AnimationState.cs index 17823782..022074af 100644 --- a/Penumbra/Interop/Resolver/PathResolver.AnimationState.cs +++ b/Penumbra/Interop/Resolver/PathResolver.AnimationState.cs @@ -1,9 +1,10 @@ using System; -using System.Runtime.InteropServices; using Dalamud.Hooking; using Dalamud.Utility.Signatures; using Penumbra.Collections; +using Penumbra.GameData; using Penumbra.GameData.Enums; +using Penumbra.Interop.Structs; using Penumbra.String; using Penumbra.String.Classes; using Penumbra.Util; @@ -109,7 +110,7 @@ public unsafe partial class PathResolver // Characters load some of their voice lines or whatever with this function. private delegate IntPtr LoadCharacterSound( IntPtr character, int unk1, int unk2, IntPtr unk3, ulong unk4, int unk5, int unk6, ulong unk7 ); - [Signature( "4C 89 4C 24 ?? 55 57 41 56", DetourName = nameof( LoadCharacterSoundDetour ) )] + [Signature( Sigs.LoadCharacterSound, DetourName = nameof( LoadCharacterSoundDetour ) )] private readonly Hook< LoadCharacterSound > _loadCharacterSoundHook = null!; private IntPtr LoadCharacterSoundDetour( IntPtr character, int unk1, int unk2, IntPtr unk3, ulong unk4, int unk5, int unk6, ulong unk7 ) @@ -149,7 +150,7 @@ public unsafe partial class PathResolver // We can obtain the associated game object from the timelines 28'th vfunc and use that to apply the correct collection. private delegate ulong LoadTimelineResourcesDelegate( IntPtr timeline ); - [Signature( "E8 ?? ?? ?? ?? 83 7F ?? ?? 75 ?? 0F B6 87", DetourName = nameof( LoadTimelineResourcesDetour ) )] + [Signature( Sigs.LoadTimelineResources, DetourName = nameof( LoadTimelineResourcesDetour ) )] private readonly Hook< LoadTimelineResourcesDelegate > _loadTimelineResourcesHook = null!; private ulong LoadTimelineResourcesDetour( IntPtr timeline ) @@ -166,8 +167,7 @@ public unsafe partial class PathResolver // Make it aware of the correct collection to load the correct pap files. private delegate void CharacterBaseNoArgumentDelegate( IntPtr drawBase ); - [Signature( "E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8B CF 44 8B C2 E8 ?? ?? ?? ?? 48 8B 05", - DetourName = nameof( CharacterBaseLoadAnimationDetour ) )] + [Signature( Sigs.CharacterBaseLoadAnimation, DetourName = nameof( CharacterBaseLoadAnimationDetour ) )] private readonly Hook< CharacterBaseNoArgumentDelegate > _characterBaseLoadAnimationHook = null!; private void CharacterBaseLoadAnimationDetour( IntPtr drawObject ) @@ -186,8 +186,7 @@ public unsafe partial class PathResolver // Unknown what exactly this is but it seems to load a bunch of paps. private delegate void LoadSomePap( IntPtr a1, int a2, IntPtr a3, int a4 ); - [Signature( "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC ?? 41 8B D9 89 51", - DetourName = nameof( LoadSomePapDetour ) )] + [Signature( Sigs.LoadSomePap, DetourName = nameof( LoadSomePapDetour ) )] private readonly Hook< LoadSomePap > _loadSomePapHook = null!; private void LoadSomePapDetour( IntPtr a1, int a2, IntPtr a3, int a4 ) @@ -209,7 +208,7 @@ public unsafe partial class PathResolver } // Seems to load character actions when zoning or changing class, maybe. - [Signature( "E8 ?? ?? ?? ?? C6 83 ?? ?? ?? ?? ?? 8B 8E", DetourName = nameof( SomeActionLoadDetour ) )] + [Signature( Sigs.LoadSomeAction, DetourName = nameof( SomeActionLoadDetour ) )] private readonly Hook< CharacterBaseNoArgumentDelegate > _someActionLoadHook = null!; private void SomeActionLoadDetour( IntPtr gameObject ) @@ -221,25 +220,9 @@ public unsafe partial class PathResolver _animationLoadData = last; } - [StructLayout( LayoutKind.Explicit )] - private struct VfxParams - { - [FieldOffset( 0x118 )] - public uint GameObjectId; - - [FieldOffset( 0x11C )] - public byte GameObjectType; - - [FieldOffset( 0xD0 )] - public ushort TargetCount; - - [FieldOffset( 0x120 )] - public fixed ulong Target[16]; - } - private delegate IntPtr LoadCharacterVfxDelegate( byte* vfxPath, VfxParams* vfxParams, byte unk1, byte unk2, float unk3, int unk4 ); - [Signature( "E8 ?? ?? ?? ?? 48 8B F8 48 8D 93", DetourName = nameof( LoadCharacterVfxDetour ) )] + [Signature( Sigs.LoadCharacterVfx, DetourName = nameof( LoadCharacterVfxDetour ) )] private readonly Hook< LoadCharacterVfxDelegate > _loadCharacterVfxHook = null!; private global::Dalamud.Game.ClientState.Objects.Types.GameObject? GetOwnedObject( uint id ) @@ -288,7 +271,7 @@ public unsafe partial class PathResolver private delegate IntPtr LoadAreaVfxDelegate( uint vfxId, float* pos, GameObject* caster, float unk1, float unk2, byte unk3 ); - [Signature( "48 8B C4 53 55 56 57 41 56 48 81 EC", DetourName = nameof( LoadAreaVfxDetour ) )] + [Signature( Sigs.LoadAreaVfx, DetourName = nameof( LoadAreaVfxDetour ) )] private readonly Hook< LoadAreaVfxDelegate > _loadAreaVfxHook = null!; private IntPtr LoadAreaVfxDetour( uint vfxId, float* pos, GameObject* caster, float unk1, float unk2, byte unk3 ) @@ -314,20 +297,9 @@ public unsafe partial class PathResolver } - - [StructLayout( LayoutKind.Explicit )] - private struct ClipScheduler - { - [FieldOffset( 0 )] - public IntPtr* VTable; - - [FieldOffset( 0x38 )] - public IntPtr SchedulerTimeline; - } - private delegate void ScheduleClipUpdate( ClipScheduler* x ); - [Signature( "40 53 55 56 57 41 56 48 81 EC ?? ?? ?? ?? 48 8B F9", DetourName = nameof( ScheduleClipUpdateDetour ) )] + [Signature( Sigs.ScheduleClipUpdate, DetourName = nameof( ScheduleClipUpdateDetour ) )] private readonly Hook< ScheduleClipUpdate > _scheduleClipUpdateHook = null!; private void ScheduleClipUpdateDetour( ClipScheduler* x ) diff --git a/Penumbra/Interop/Resolver/PathResolver.DrawObjectState.cs b/Penumbra/Interop/Resolver/PathResolver.DrawObjectState.cs index 78a5ed0a..16c321d4 100644 --- a/Penumbra/Interop/Resolver/PathResolver.DrawObjectState.cs +++ b/Penumbra/Interop/Resolver/PathResolver.DrawObjectState.cs @@ -8,6 +8,7 @@ using FFXIVClientStructs.FFXIV.Client.Game.Object; using Penumbra.Api; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using OtterGui.Classes; +using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.String.Classes; using Penumbra.Util; @@ -134,7 +135,7 @@ public unsafe partial class PathResolver // and use the last game object that called EnableDraw to link them. private delegate IntPtr CharacterBaseCreateDelegate( uint a, IntPtr b, IntPtr c, byte d ); - [Signature( "E8 ?? ?? ?? ?? 48 85 C0 74 21 C7 40", DetourName = nameof( CharacterBaseCreateDetour ) )] + [Signature( Sigs.CharacterBaseCreate, DetourName = nameof( CharacterBaseCreateDetour ) )] private readonly Hook< CharacterBaseCreateDelegate > _characterBaseCreateHook = null!; private IntPtr CharacterBaseCreateDetour( uint a, IntPtr b, IntPtr c, byte d ) @@ -186,8 +187,7 @@ public unsafe partial class PathResolver // Remove DrawObjects from the list when they are destroyed. private delegate void CharacterBaseDestructorDelegate( IntPtr drawBase ); - [Signature( "E8 ?? ?? ?? ?? 40 F6 C7 01 74 3A 40 F6 C7 04 75 27 48 85 DB 74 2F 48 8B 05 ?? ?? ?? ?? 48 8B D3 48 8B 48 30", - DetourName = nameof( CharacterBaseDestructorDetour ) )] + [Signature( Sigs.CharacterBaseDestructor, DetourName = nameof( CharacterBaseDestructorDetour ) )] private readonly Hook< CharacterBaseDestructorDelegate > _characterBaseDestructorHook = null!; private void CharacterBaseDestructorDetour( IntPtr drawBase ) @@ -201,7 +201,7 @@ public unsafe partial class PathResolver // so we always keep track of the current GameObject to be able to link it to the DrawObject. private delegate void EnableDrawDelegate( IntPtr gameObject, IntPtr b, IntPtr c, IntPtr d ); - [Signature( "E8 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 85 C9 74 33 45 33 C0", DetourName = nameof( EnableDrawDetour ) )] + [Signature( Sigs.EnableDraw, DetourName = nameof( EnableDrawDetour ) )] private readonly Hook< EnableDrawDelegate > _enableDrawHook = null!; private void EnableDrawDetour( IntPtr gameObject, IntPtr b, IntPtr c, IntPtr d ) @@ -216,7 +216,7 @@ public unsafe partial class PathResolver // so we use that. private delegate void WeaponReloadFunc( IntPtr a1, uint a2, IntPtr a3, byte a4, byte a5, byte a6, byte a7 ); - [Signature( "E8 ?? ?? ?? ?? 44 8B 9F", DetourName = nameof( WeaponReloadDetour ) )] + [Signature( Sigs.WeaponReload, DetourName = nameof( WeaponReloadDetour ) )] private readonly Hook< WeaponReloadFunc > _weaponReloadHook = null!; public void WeaponReloadDetour( IntPtr a1, uint a2, IntPtr a3, byte a4, byte a5, byte a6, byte a7 ) diff --git a/Penumbra/Interop/Resolver/PathResolver.Meta.cs b/Penumbra/Interop/Resolver/PathResolver.Meta.cs index a618e705..0970347c 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Meta.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Meta.cs @@ -5,6 +5,7 @@ using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using OtterGui.Classes; using Penumbra.Collections; +using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.Util; using ObjectType = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.ObjectType; @@ -87,7 +88,7 @@ public unsafe partial class PathResolver private delegate void UpdateModelDelegate( IntPtr drawObject ); - [Signature( "48 8B ?? 56 48 83 ?? ?? ?? B9", DetourName = nameof( UpdateModelsDetour ) )] + [Signature( Sigs.UpdateModel, DetourName = nameof( UpdateModelsDetour ) )] private readonly Hook< UpdateModelDelegate > _updateModelsHook = null!; private void UpdateModelsDetour( IntPtr drawObject ) @@ -98,6 +99,7 @@ public unsafe partial class PathResolver { return; } + using var performance = Penumbra.Performance.Measure( PerformanceType.UpdateModels ); var collection = GetResolveData( drawObject ); @@ -124,8 +126,7 @@ public unsafe partial class PathResolver public static GenderRace GetHumanGenderRace( IntPtr human ) => ( GenderRace )( ( Human* )human )->RaceSexId; - [Signature( "40 ?? 48 83 ?? ?? ?? 81 ?? ?? ?? ?? ?? 48 8B ?? 74 ?? ?? 83 ?? ?? ?? ?? ?? ?? 74 ?? 4C", - DetourName = nameof( GetEqpIndirectDetour ) )] + [Signature( Sigs.GetEqpIndirect, DetourName = nameof( GetEqpIndirectDetour ) )] private readonly Hook< OnModelLoadCompleteDelegate > _getEqpIndirectHook = null!; private void GetEqpIndirectDetour( IntPtr drawObject ) @@ -136,6 +137,7 @@ public unsafe partial class PathResolver { return; } + using var performance = Penumbra.Performance.Measure( PerformanceType.GetEqp ); var resolveData = GetResolveData( drawObject ); using var eqp = resolveData.ModCollection.TemporarilySetEqpFile(); @@ -147,7 +149,7 @@ public unsafe partial class PathResolver // but it only applies a changed gmp file after a redraw for some reason. private delegate byte SetupVisorDelegate( IntPtr drawObject, ushort modelId, byte visorState ); - [Signature( "48 8B ?? 53 55 57 48 83 ?? ?? 48 8B", DetourName = nameof( SetupVisorDetour ) )] + [Signature( Sigs.SetupVisor, DetourName = nameof( SetupVisorDetour ) )] private readonly Hook< SetupVisorDelegate > _setupVisorHook = null!; private byte SetupVisorDetour( IntPtr drawObject, ushort modelId, byte visorState ) @@ -161,7 +163,7 @@ public unsafe partial class PathResolver // RSP private delegate void RspSetupCharacterDelegate( IntPtr drawObject, IntPtr unk2, float unk3, IntPtr unk4, byte unk5 ); - [Signature( "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 88 54 24 ?? 57 41 56", DetourName = nameof( RspSetupCharacterDetour ) )] + [Signature( Sigs.RspSetupCharacter, DetourName = nameof( RspSetupCharacterDetour ) )] private readonly Hook< RspSetupCharacterDelegate > _rspSetupCharacterHook = null!; private void RspSetupCharacterDetour( IntPtr drawObject, IntPtr unk2, float unk3, IntPtr unk4, byte unk5 ) @@ -183,7 +185,7 @@ public unsafe partial class PathResolver private bool _inChangeCustomize; private delegate bool ChangeCustomizeDelegate( IntPtr human, IntPtr data, byte skipEquipment ); - [Signature( "E8 ?? ?? ?? ?? 41 0F B6 C5 66 41 89 86", DetourName = nameof( ChangeCustomizeDetour ) )] + [Signature( Sigs.ChangeCustomize, DetourName = nameof( ChangeCustomizeDetour ) )] private readonly Hook< ChangeCustomizeDelegate > _changeCustomize = null!; private bool ChangeCustomizeDetour( IntPtr human, IntPtr data, byte skipEquipment ) diff --git a/Penumbra/Interop/Resolver/PathResolver.PathState.cs b/Penumbra/Interop/Resolver/PathResolver.PathState.cs index 2cf9cb4b..2b4aceca 100644 --- a/Penumbra/Interop/Resolver/PathResolver.PathState.cs +++ b/Penumbra/Interop/Resolver/PathResolver.PathState.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Runtime.CompilerServices; using Dalamud.Utility.Signatures; using Penumbra.Collections; +using Penumbra.GameData; using Penumbra.String; namespace Penumbra.Interop.Resolver; @@ -12,17 +13,16 @@ public unsafe partial class PathResolver { public class PathState : IDisposable { - [Signature( "48 8D 05 ?? ?? ?? ?? 48 89 03 48 8D 8B ?? ?? ?? ?? 44 89 83 ?? ?? ?? ?? 48 8B C1", ScanType = ScanType.StaticAddress )] + [Signature( Sigs.HumanVTable, ScanType = ScanType.StaticAddress )] public readonly IntPtr* HumanVTable = null!; - [Signature( "48 8D 05 ?? ?? ?? ?? 48 89 03 B8 ?? ?? ?? ?? 66 89 83 ?? ?? ?? ?? 48 8B C3 48 89 8B ?? ?? ?? ?? 48 89 8B", - ScanType = ScanType.StaticAddress )] + [Signature( Sigs.WeaponVTable, ScanType = ScanType.StaticAddress )] private readonly IntPtr* _weaponVTable = null!; - [Signature( "48 8D 05 ?? ?? ?? ?? 45 33 C0 48 89 03 BA", ScanType = ScanType.StaticAddress )] + [Signature( Sigs.DemiHumanVTable, ScanType = ScanType.StaticAddress )] private readonly IntPtr* _demiHumanVTable = null!; - [Signature( "48 8D 05 ?? ?? ?? ?? 48 89 03 33 C0 48 89 83 ?? ?? ?? ?? 48 89 83 ?? ?? ?? ?? C7 83", ScanType = ScanType.StaticAddress )] + [Signature( Sigs.MonsterVTable, ScanType = ScanType.StaticAddress )] private readonly IntPtr* _monsterVTable = null!; private readonly ResolverHooks _human; diff --git a/Penumbra/Interop/Resolver/PathResolver.Subfiles.cs b/Penumbra/Interop/Resolver/PathResolver.Subfiles.cs index cca76c70..c2743398 100644 --- a/Penumbra/Interop/Resolver/PathResolver.Subfiles.cs +++ b/Penumbra/Interop/Resolver/PathResolver.Subfiles.cs @@ -6,6 +6,7 @@ using Dalamud.Hooking; using Dalamud.Utility.Signatures; using FFXIVClientStructs.FFXIV.Client.System.Resource; using Penumbra.Collections; +using Penumbra.GameData; using Penumbra.GameData.Enums; using Penumbra.Interop.Loader; using Penumbra.Interop.Structs; @@ -159,7 +160,7 @@ public unsafe partial class PathResolver private delegate byte LoadMtrlFilesDelegate( IntPtr mtrlResourceHandle ); - [Signature( "4C 8B DC 49 89 5B ?? 49 89 73 ?? 55 57 41 55", DetourName = nameof( LoadMtrlTexDetour ) )] + [Signature( Sigs.LoadMtrlTex, DetourName = nameof( LoadMtrlTexDetour ) )] private readonly Hook< LoadMtrlFilesDelegate > _loadMtrlTexHook = null!; private byte LoadMtrlTexDetour( IntPtr mtrlResourceHandle ) @@ -171,8 +172,7 @@ public unsafe partial class PathResolver return ret; } - [Signature( "48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 44 0F B7 89", - DetourName = nameof( LoadMtrlShpkDetour ) )] + [Signature( Sigs.LoadMtrlShpk, DetourName = nameof( LoadMtrlShpkDetour ) )] private readonly Hook< LoadMtrlFilesDelegate > _loadMtrlShpkHook = null!; private byte LoadMtrlShpkDetour( IntPtr mtrlResourceHandle ) @@ -197,7 +197,7 @@ public unsafe partial class PathResolver private delegate byte ApricotResourceLoadDelegate( IntPtr handle, IntPtr unk1, byte unk2 ); - [Signature( "48 89 74 24 ?? 57 48 83 EC ?? 41 0F B6 F0 48 8B F9", DetourName = nameof( ApricotResourceLoadDetour ) )] + [Signature( Sigs.ApricotResourceLoad, DetourName = nameof( ApricotResourceLoadDetour ) )] private readonly Hook< ApricotResourceLoadDelegate > _apricotResourceLoadHook = null!; diff --git a/Penumbra/Interop/Structs/ClipScheduler.cs b/Penumbra/Interop/Structs/ClipScheduler.cs new file mode 100644 index 00000000..d968ffbe --- /dev/null +++ b/Penumbra/Interop/Structs/ClipScheduler.cs @@ -0,0 +1,14 @@ +using System; +using System.Runtime.InteropServices; + +namespace Penumbra.Interop.Structs; + +[StructLayout( LayoutKind.Explicit )] +public unsafe struct ClipScheduler +{ + [FieldOffset( 0 )] + public IntPtr* VTable; + + [FieldOffset( 0x38 )] + public IntPtr SchedulerTimeline; +} \ No newline at end of file diff --git a/Penumbra/Interop/Structs/VfxParams.cs b/Penumbra/Interop/Structs/VfxParams.cs new file mode 100644 index 00000000..644d5a9a --- /dev/null +++ b/Penumbra/Interop/Structs/VfxParams.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; + +namespace Penumbra.Interop.Structs; + +[StructLayout( LayoutKind.Explicit )] +public unsafe struct VfxParams +{ + [FieldOffset( 0x118 )] + public uint GameObjectId; + + [FieldOffset( 0x11C )] + public byte GameObjectType; + + [FieldOffset( 0xD0 )] + public ushort TargetCount; + + [FieldOffset( 0x120 )] + public fixed ulong Target[16]; +} \ No newline at end of file