mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
Fix AddonLifecycle OnSetup hook (#1860)
* Fix AddonLifecycle OnSetup hook * Fix namespace of AddonSetupHook
This commit is contained in:
parent
9815087e54
commit
e6c721a123
3 changed files with 90 additions and 25 deletions
|
|
@ -32,8 +32,7 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
|||
private readonly nint disallowedReceiveEventAddress;
|
||||
|
||||
private readonly AddonLifecycleAddressResolver address;
|
||||
private readonly CallHook<AtkUnitBase.Delegates.OnSetup> onAddonSetupHook;
|
||||
private readonly CallHook<AtkUnitBase.Delegates.OnSetup> onAddonSetup2Hook;
|
||||
private readonly AddonSetupHook<AtkUnitBase.Delegates.OnSetup> onAddonSetupHook;
|
||||
private readonly Hook<AddonFinalizeDelegate> onAddonFinalizeHook;
|
||||
private readonly CallHook<AtkUnitBase.Delegates.Draw> onAddonDrawHook;
|
||||
private readonly CallHook<AtkUnitBase.Delegates.Update> onAddonUpdateHook;
|
||||
|
|
@ -43,9 +42,6 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
|||
[ServiceManager.ServiceConstructor]
|
||||
private AddonLifecycle(TargetSigScanner sigScanner)
|
||||
{
|
||||
// TODO: Service is currently non-functional pending DT changes. NOP'd.
|
||||
return;
|
||||
|
||||
this.address = new AddonLifecycleAddressResolver();
|
||||
this.address.Setup(sigScanner);
|
||||
|
||||
|
|
@ -53,8 +49,7 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
|||
|
||||
var refreshAddonAddress = (nint)RaptureAtkUnitManager.StaticVirtualTablePointer->RefreshAddon;
|
||||
|
||||
this.onAddonSetupHook = new CallHook<AtkUnitBase.Delegates.OnSetup>(this.address.AddonSetup, this.OnAddonSetup);
|
||||
this.onAddonSetup2Hook = new CallHook<AtkUnitBase.Delegates.OnSetup>(this.address.AddonSetup2, this.OnAddonSetup);
|
||||
this.onAddonSetupHook = new AddonSetupHook<AtkUnitBase.Delegates.OnSetup>(this.address.AddonSetup, this.OnAddonSetup);
|
||||
this.onAddonFinalizeHook = Hook<AddonFinalizeDelegate>.FromAddress(this.address.AddonFinalize, this.OnAddonFinalize);
|
||||
this.onAddonDrawHook = new CallHook<AtkUnitBase.Delegates.Draw>(this.address.AddonDraw, this.OnAddonDraw);
|
||||
this.onAddonUpdateHook = new CallHook<AtkUnitBase.Delegates.Update>(this.address.AddonUpdate, this.OnAddonUpdate);
|
||||
|
|
@ -62,7 +57,6 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
|||
this.onAddonRequestedUpdateHook = new CallHook<AtkUnitBase.Delegates.OnRequestedUpdate>(this.address.AddonOnRequestedUpdate, this.OnRequestedUpdate);
|
||||
|
||||
this.onAddonSetupHook.Enable();
|
||||
this.onAddonSetup2Hook.Enable();
|
||||
this.onAddonFinalizeHook.Enable();
|
||||
this.onAddonDrawHook.Enable();
|
||||
this.onAddonUpdateHook.Enable();
|
||||
|
|
@ -85,14 +79,12 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
|||
/// <inheritdoc/>
|
||||
void IInternalDisposableService.DisposeService()
|
||||
{
|
||||
// TODO: Service is currently non-functional pending DT changes.
|
||||
// this.onAddonSetupHook.Dispose();
|
||||
// this.onAddonSetup2Hook.Dispose();
|
||||
// this.onAddonFinalizeHook.Dispose();
|
||||
// this.onAddonDrawHook.Dispose();
|
||||
// this.onAddonUpdateHook.Dispose();
|
||||
// this.onAddonRefreshHook.Dispose();
|
||||
// this.onAddonRequestedUpdateHook.Dispose();
|
||||
this.onAddonSetupHook.Dispose();
|
||||
this.onAddonFinalizeHook.Dispose();
|
||||
this.onAddonDrawHook.Dispose();
|
||||
this.onAddonUpdateHook.Dispose();
|
||||
this.onAddonRefreshHook.Dispose();
|
||||
this.onAddonRequestedUpdateHook.Dispose();
|
||||
|
||||
foreach (var receiveEventListener in this.ReceiveEventListeners)
|
||||
{
|
||||
|
|
@ -106,9 +98,6 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
|||
/// <param name="listener">The listener to register.</param>
|
||||
internal void RegisterListener(AddonLifecycleEventListener listener)
|
||||
{
|
||||
// TODO: Service is currently non-functional pending DT changes. NOP'd.
|
||||
return;
|
||||
|
||||
this.framework.RunOnTick(() =>
|
||||
{
|
||||
this.EventListeners.Add(listener);
|
||||
|
|
@ -131,9 +120,6 @@ internal unsafe class AddonLifecycle : IInternalDisposableService
|
|||
/// <param name="listener">The listener to unregister.</param>
|
||||
internal void UnregisterListener(AddonLifecycleEventListener listener)
|
||||
{
|
||||
// TODO: Service is currently non-functional pending DT changes. NOP'd.
|
||||
return;
|
||||
|
||||
// Set removed state to true immediately, then lazily remove it from the EventListeners list on next Framework Update.
|
||||
listener.Removed = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||
|
||||
namespace Dalamud.Game.Addon.Lifecycle;
|
||||
|
||||
|
|
@ -47,8 +47,7 @@ internal unsafe class AddonLifecycleAddressResolver : BaseAddressResolver
|
|||
/// <param name="sig">The signature scanner to facilitate setup.</param>
|
||||
protected override void Setup64Bit(ISigScanner sig)
|
||||
{
|
||||
this.AddonSetup = sig.ScanText("41 FF D1 48 8B 93 ?? ?? ?? ?? 80 8B"); // TODO: verify
|
||||
this.AddonSetup2 = sig.ScanText("41 FF D1 48 8B 03 48 8B CB"); // TODO: verify
|
||||
this.AddonSetup = sig.ScanText("4C 8B 88 ?? ?? ?? ?? 66 44 39 BB");
|
||||
this.AddonFinalize = sig.ScanText("E8 ?? ?? ?? ?? 48 83 EF 01 75 D5");
|
||||
this.AddonDraw = sig.ScanText("FF 90 ?? ?? ?? ?? 83 EB 01 79 C4 48 81 EF ?? ?? ?? ?? 48 83 ED 01");
|
||||
this.AddonUpdate = sig.ScanText("FF 90 ?? ?? ?? ?? 40 88 AF ?? ?? ?? ?? 45 33 D2");
|
||||
|
|
|
|||
80
Dalamud/Game/Addon/Lifecycle/AddonSetupHook.cs
Normal file
80
Dalamud/Game/Addon/Lifecycle/AddonSetupHook.cs
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
using Reloaded.Hooks.Definitions;
|
||||
|
||||
namespace Dalamud.Game.Addon.Lifecycle;
|
||||
|
||||
/// <summary>
|
||||
/// This class represents a callsite hook used to replace the address of the OnSetup function in r9.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Delegate signature for this hook.</typeparam>
|
||||
internal class AddonSetupHook<T> : IDisposable where T : Delegate
|
||||
{
|
||||
private readonly Reloaded.Hooks.AsmHook asmHook;
|
||||
|
||||
private T? detour;
|
||||
private bool activated;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AddonSetupHook{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="address">Address of the instruction to replace.</param>
|
||||
/// <param name="detour">Delegate to invoke.</param>
|
||||
internal AddonSetupHook(nint address, T detour)
|
||||
{
|
||||
this.detour = detour;
|
||||
|
||||
var detourPtr = Marshal.GetFunctionPointerForDelegate(this.detour);
|
||||
var code = new[]
|
||||
{
|
||||
"use64",
|
||||
$"mov r9, 0x{detourPtr:X8}",
|
||||
};
|
||||
|
||||
var opt = new AsmHookOptions
|
||||
{
|
||||
PreferRelativeJump = true,
|
||||
Behaviour = Reloaded.Hooks.Definitions.Enums.AsmHookBehaviour.DoNotExecuteOriginal,
|
||||
MaxOpcodeSize = 5,
|
||||
};
|
||||
|
||||
this.asmHook = new Reloaded.Hooks.AsmHook(code, (nuint)address, opt);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not the hook is enabled.
|
||||
/// </summary>
|
||||
public bool IsEnabled => this.asmHook.IsEnabled;
|
||||
|
||||
/// <summary>
|
||||
/// Starts intercepting a call to the function.
|
||||
/// </summary>
|
||||
public void Enable()
|
||||
{
|
||||
if (!this.activated)
|
||||
{
|
||||
this.activated = true;
|
||||
this.asmHook.Activate();
|
||||
return;
|
||||
}
|
||||
|
||||
this.asmHook.Enable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops intercepting a call to the function.
|
||||
/// </summary>
|
||||
public void Disable()
|
||||
{
|
||||
this.asmHook.Disable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove a hook from the current process.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.asmHook.Disable();
|
||||
this.detour = null;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue