From 258f7e9732229f754f086fa79126e4246a7eb0b1 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sun, 21 Jul 2024 00:13:43 +0200 Subject: [PATCH] Reinstate the inlined ApricotSoundPlay hook one layer hup. --- Penumbra.GameData | 2 +- .../Animation/ApricotListenerSoundPlay.cs | 42 ++++++++++++------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Penumbra.GameData b/Penumbra.GameData index a1e637f8..9f1816f1 160000 --- a/Penumbra.GameData +++ b/Penumbra.GameData @@ -1 +1 @@ -Subproject commit a1e637f835c1a42732825e8e0690aeef0024b101 +Subproject commit 9f1816f1b75003d01c5576769831c10f3d8948a7 diff --git a/Penumbra/Interop/Hooks/Animation/ApricotListenerSoundPlay.cs b/Penumbra/Interop/Hooks/Animation/ApricotListenerSoundPlay.cs index 2e05c1b6..361fcd4e 100644 --- a/Penumbra/Interop/Hooks/Animation/ApricotListenerSoundPlay.cs +++ b/Penumbra/Interop/Hooks/Animation/ApricotListenerSoundPlay.cs @@ -1,4 +1,3 @@ -using Dalamud.Hooking; using FFXIVClientStructs.FFXIV.Client.Game.Object; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using OtterGui.Services; @@ -11,33 +10,48 @@ using Penumbra.Services; namespace Penumbra.Interop.Hooks.Animation; /// Called for some sound effects caused by animations or VFX. -public sealed unsafe class ApricotListenerSoundPlay : FastHook +/// Actual function got inlined. +public sealed unsafe class ApricotListenerSoundPlayCaller : FastHook { private readonly GameState _state; private readonly CollectionResolver _collectionResolver; private readonly CrashHandlerService _crashHandler; - // TODO because of inlining. - public ApricotListenerSoundPlay(HookManager hooks, GameState state, CollectionResolver collectionResolver, CrashHandlerService crashHandler) + public ApricotListenerSoundPlayCaller(HookManager hooks, GameState state, CollectionResolver collectionResolver, + CrashHandlerService crashHandler) { _state = state; _collectionResolver = collectionResolver; _crashHandler = crashHandler; - Task = hooks.CreateHook("Apricot Listener Sound Play", Sigs.ApricotListenerSoundPlay, Detour, HookSettings.VfxIdentificationHooks); + Task = hooks.CreateHook("Apricot Listener Sound Play Caller", Sigs.ApricotListenerSoundPlayCaller, Detour, + true); //HookSettings.VfxIdentificationHooks); } - public delegate nint Delegate(nint a1, nint a2, nint a3, nint a4, nint a5, nint a6); + public delegate nint Delegate(nint a1, nint a2, float a3); [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - private nint Detour(nint a1, nint a2, nint a3, nint a4, nint a5, nint a6) + private nint Detour(nint a1, nint unused, float timeOffset) { - Penumbra.Log.Excessive($"[Apricot Listener Sound Play] Invoked on 0x{a1:X} with {a2}, {a3}, {a4}, {a5}, {a6}."); - if (a6 == nint.Zero) - return Task.Result.Original(a1, a2, a3, a4, a5, a6); + // Short-circuiting and sanity checks done by game. + var playTime = a1 == nint.Zero ? -1 : *(float*)(a1 + 0x250); + if (playTime < 0) + return Task.Result.Original(a1, unused, timeOffset); - // a6 is some instance of Apricot.IInstanceListenner, in some cases we can obtain the associated caster via vfunc 1. - var gameObject = (*(delegate* unmanaged**)a6)[1](a6); + var someIntermediate = *(nint*)(a1 + 0x1F8); + var flags = someIntermediate == nint.Zero ? (ushort)0 : *(ushort*)(someIntermediate + 0x49C); + if (((flags >> 13) & 1) == 0) + return Task.Result.Original(a1, unused, timeOffset); + + Penumbra.Log.Information( + $"[Apricot Listener Sound Play Caller] Invoked on 0x{a1:X} with {unused}, {timeOffset}."); + // Fetch the IInstanceListenner (sixth argument to inlined call of SoundPlay) + var apricotIInstanceListenner = *(nint*)(someIntermediate + 0x270); + if (apricotIInstanceListenner == nint.Zero) + return Task.Result.Original(a1, unused, timeOffset); + + // In some cases we can obtain the associated caster via vfunc 1. var newData = ResolveData.Invalid; + var gameObject = (*(delegate* unmanaged**)apricotIInstanceListenner)[1](apricotIInstanceListenner); if (gameObject != null) { newData = _collectionResolver.IdentifyCollection(gameObject, true); @@ -47,14 +61,14 @@ public sealed unsafe class ApricotListenerSoundPlay : FastHook