Implement reloading eqdp, gmp, awt, etc.

This commit is contained in:
pmgr 2021-02-21 03:39:36 +00:00
parent edc616da36
commit ab3cc6dc78
2 changed files with 63 additions and 1 deletions

View file

@ -1,6 +1,7 @@
using System;
using System.Runtime.InteropServices;
using Dalamud.Plugin;
using Penumbra.Structs;
using Reloaded.Hooks.Definitions.X64;
namespace Penumbra.Game
@ -13,13 +14,24 @@ namespace Penumbra.Game
[Function( CallingConventions.Microsoft )]
public unsafe delegate void* UnloadPlayerResourcesPrototype( IntPtr pResourceManager );
[Function( CallingConventions.Microsoft )]
public unsafe delegate void* LoadCharacterResourcesPrototype( CharacterResourceManager *pCharacterResourceManager );
[Function( CallingConventions.Microsoft )]
public unsafe delegate void* UnloadCharacterResourcePrototype( IntPtr resource );
public LoadPlayerResourcesPrototype LoadPlayerResources { get; }
public UnloadPlayerResourcesPrototype UnloadPlayerResources { get; }
public LoadCharacterResourcesPrototype LoadCharacterResources { get; }
public UnloadCharacterResourcePrototype UnloadCharacterResource { get; }
// Object addresses
private readonly IntPtr _playerResourceManagerAddress;
public IntPtr PlayerResourceManagerPtr => Marshal.ReadIntPtr( _playerResourceManagerAddress );
private readonly IntPtr _characterResourceManagerAddress;
public unsafe CharacterResourceManager* CharacterResourceManagerPtr =>
( CharacterResourceManager* )Marshal.ReadIntPtr( _characterResourceManagerAddress ).ToPointer();
public GameUtils( DalamudPluginInterface pluginInterface )
{
@ -30,17 +42,54 @@ namespace Penumbra.Game
"E8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? BA ?? ?? ?? ?? 41 B8 ?? ?? ?? ?? 48 8B 48 30 48 8B 01 FF 50 10 48 85 C0 74 0A " );
var unloadPlayerResourcesAddress =
scanner.ScanText( "41 55 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 4C 8B E9 48 83 C1 08" );
var loadCharacterResourcesAddress = scanner.ScanText( "E8 ?? ?? ?? 00 48 8D 8E ?? ?? 00 00 E8 ?? ?? ?? 00 33 D2" );
var unloadCharacterResourceAddress = scanner.ScanText( "E8 ?? ?? ?? FF 4C 89 37 48 83 C7 08 48 83 ED 01 75 ?? 48 8B CB" );
_playerResourceManagerAddress = scanner.GetStaticAddressFromSig( "0F 44 FE 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 05" );
_playerResourceManagerAddress = scanner.GetStaticAddressFromSig( "0F 44 FE 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 05" );
_characterResourceManagerAddress = scanner.GetStaticAddressFromSig( "48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? 00 48 8D 8E ?? ?? 00 00 E8 ?? ?? ?? 00 33 D2" );
LoadPlayerResources = Marshal.GetDelegateForFunctionPointer< LoadPlayerResourcesPrototype >( loadPlayerResourcesAddress );
UnloadPlayerResources = Marshal.GetDelegateForFunctionPointer< UnloadPlayerResourcesPrototype >( unloadPlayerResourcesAddress );
LoadCharacterResources = Marshal.GetDelegateForFunctionPointer< LoadCharacterResourcesPrototype >( loadCharacterResourcesAddress );
UnloadCharacterResource = Marshal.GetDelegateForFunctionPointer<UnloadCharacterResourcePrototype>( unloadCharacterResourceAddress );
}
public unsafe void ReloadPlayerResources()
{
ReloadCharacterResources();
UnloadPlayerResources( PlayerResourceManagerPtr );
LoadPlayerResources( PlayerResourceManagerPtr );
}
public unsafe string ResourceToPath( byte *resource ) =>
Marshal.PtrToStringAnsi( new IntPtr( *(char **)( resource + 9 * 8 ) ) );
public unsafe void ReloadCharacterResources()
{
var oldResources = new IntPtr[85];
var resources = new IntPtr(&CharacterResourceManagerPtr->Resources);
var pResources = (void **)resources.ToPointer();
Marshal.Copy( resources, oldResources, 0, 85 );
LoadCharacterResources( CharacterResourceManagerPtr );
for( var i = 0; i < 85; i++ )
{
if( oldResources[ i ].ToPointer() == pResources[ i ] )
{
PluginLog.Debug($"Unchanged resource: {ResourceToPath( ( byte* )oldResources[i].ToPointer() )}");
continue;
}
PluginLog.Debug( "Freeing " +
$"{ResourceToPath( ( byte* )oldResources[i].ToPointer() )}, replaced with " +
$"{ResourceToPath( ( byte* )pResources[i] )}" );
UnloadCharacterResource( oldResources[ i ] );
}
}
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Runtime.InteropServices;
namespace Penumbra.Structs
{
[StructLayout( LayoutKind.Sequential )]
public unsafe struct CharacterResourceManager
{
public void* VTable;
public IntPtr Resources; // Size: 85, I hate C#
}
}