From a4cd5695fb3e4908e7e51c19e2d42551acc27d19 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 22 Jul 2024 20:41:57 +0200 Subject: [PATCH] Fix some stuff. --- Penumbra/Api/Api/GameStateApi.cs | 23 +++++++++++++++---- .../Animation/ApricotListenerSoundPlay.cs | 2 +- .../Hooks/ResourceLoading/PapRewriter.cs | 10 +++++++- .../Hooks/ResourceLoading/ResourceLoader.cs | 18 +++++++-------- .../UI/ResourceWatcher/ResourceWatcher.cs | 3 +-- 5 files changed, 39 insertions(+), 17 deletions(-) diff --git a/Penumbra/Api/Api/GameStateApi.cs b/Penumbra/Api/Api/GameStateApi.cs index b035c886..c2cae32b 100644 --- a/Penumbra/Api/Api/GameStateApi.cs +++ b/Penumbra/Api/Api/GameStateApi.cs @@ -25,12 +25,14 @@ public class GameStateApi : IPenumbraApiGameState, IApiService, IDisposable _cutsceneService = cutsceneService; _resourceLoader = resourceLoader; _resourceLoader.ResourceLoaded += OnResourceLoaded; + _resourceLoader.PapRequested += OnPapRequested; _communicator.CreatedCharacterBase.Subscribe(OnCreatedCharacterBase, Communication.CreatedCharacterBase.Priority.Api); } public unsafe void Dispose() { _resourceLoader.ResourceLoaded -= OnResourceLoaded; + _resourceLoader.PapRequested -= OnPapRequested; _communicator.CreatedCharacterBase.Unsubscribe(OnCreatedCharacterBase); } @@ -67,14 +69,27 @@ public class GameStateApi : IPenumbraApiGameState, IApiService, IDisposable public PenumbraApiEc SetCutsceneParentIndex(int copyIdx, int newParentIdx) => _cutsceneService.SetParentIndex(copyIdx, newParentIdx) - ? PenumbraApiEc.Success + ? PenumbraApiEc.Success : PenumbraApiEc.InvalidArgument; private unsafe void OnResourceLoaded(ResourceHandle* handle, Utf8GamePath originalPath, FullPath? manipulatedPath, ResolveData resolveData) { - if (resolveData.AssociatedGameObject != nint.Zero) - GameObjectResourceResolved?.Invoke(resolveData.AssociatedGameObject, originalPath.ToString(), - manipulatedPath?.ToString() ?? originalPath.ToString()); + if (resolveData.AssociatedGameObject != nint.Zero && GameObjectResourceResolved != null) + { + var original = originalPath.ToString(); + GameObjectResourceResolved.Invoke(resolveData.AssociatedGameObject, original, + manipulatedPath?.ToString() ?? original); + } + } + + private void OnPapRequested(Utf8GamePath originalPath, FullPath? manipulatedPath, ResolveData resolveData) + { + if (resolveData.AssociatedGameObject != nint.Zero && GameObjectResourceResolved != null) + { + var original = originalPath.ToString(); + GameObjectResourceResolved.Invoke(resolveData.AssociatedGameObject, original, + manipulatedPath?.ToString() ?? original); + } } private void OnCreatedCharacterBase(nint gameObject, ModCollection collection, nint drawObject) diff --git a/Penumbra/Interop/Hooks/Animation/ApricotListenerSoundPlay.cs b/Penumbra/Interop/Hooks/Animation/ApricotListenerSoundPlay.cs index 361fcd4e..96a51027 100644 --- a/Penumbra/Interop/Hooks/Animation/ApricotListenerSoundPlay.cs +++ b/Penumbra/Interop/Hooks/Animation/ApricotListenerSoundPlay.cs @@ -42,7 +42,7 @@ public sealed unsafe class ApricotListenerSoundPlayCaller : FastHook> 13) & 1) == 0) return Task.Result.Original(a1, unused, timeOffset); - Penumbra.Log.Information( + Penumbra.Log.Excessive( $"[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); diff --git a/Penumbra/Interop/Hooks/ResourceLoading/PapRewriter.cs b/Penumbra/Interop/Hooks/ResourceLoading/PapRewriter.cs index 5a2b09bf..33b124c8 100644 --- a/Penumbra/Interop/Hooks/ResourceLoading/PapRewriter.cs +++ b/Penumbra/Interop/Hooks/ResourceLoading/PapRewriter.cs @@ -1,3 +1,4 @@ +using System.Text.Unicode; using Dalamud.Hooking; using Iced.Intel; using OtterGui; @@ -25,7 +26,7 @@ public sealed class PapRewriter(PapRewriter.PapResourceHandlerPrototype papResou { var stackAccesses = ScanStackAccesses(funcInstructions, hookPoint).ToList(); var stringAllocation = NativeAlloc(Utf8GamePath.MaxGamePathLength); - + WriteToAlloc(stringAllocation, Utf8GamePath.MaxGamePathLength, name); // We'll need to grab our true hook point; the location where we can change the path at our leisure. // This is going to be the first call instruction after our 'hookPoint', so, we'll find that. // Pretty scuffed, this might need a refactoring at some point. @@ -164,4 +165,11 @@ public sealed class PapRewriter(PapRewriter.PapResourceHandlerPrototype papResou _nativeAllocList.Clear(); } + + [Conditional("DEBUG")] + private static unsafe void WriteToAlloc(nint alloc, int size, string name) + { + var span = new Span((void*)alloc, size); + Utf8.TryWrite(span, $"Penumbra.{name}\0", out _); + } } diff --git a/Penumbra/Interop/Hooks/ResourceLoading/ResourceLoader.cs b/Penumbra/Interop/Hooks/ResourceLoading/ResourceLoader.cs index 002846fa..10821287 100644 --- a/Penumbra/Interop/Hooks/ResourceLoading/ResourceLoader.cs +++ b/Penumbra/Interop/Hooks/ResourceLoading/ResourceLoader.cs @@ -18,8 +18,8 @@ public unsafe class ResourceLoader : IDisposable, IService private readonly TexMdlService _texMdlService; private readonly PapHandler _papHandler; - private ResolveData _resolvedData = ResolveData.Invalid; - public event Action? PapRequested; + private ResolveData _resolvedData = ResolveData.Invalid; + public event Action? PapRequested; public ResourceLoader(ResourceService resources, FileReadService fileReadService, TexMdlService texMdlService) { @@ -42,23 +42,23 @@ public unsafe class ResourceLoader : IDisposable, IService if (!Utf8GamePath.FromPointer(path, out var gamePath)) return length; - var (resolvedPath, _) = _incMode.Value + var (resolvedPath, data) = _incMode.Value ? (null, ResolveData.Invalid) : _resolvedData.Valid ? (_resolvedData.ModCollection.ResolvePath(gamePath), _resolvedData) : ResolvePath(gamePath, ResourceCategory.Chara, ResourceType.Pap); - if (!resolvedPath.HasValue || !Utf8GamePath.FromByteString(resolvedPath.Value.InternalName, out var utf8ResolvedPath)) + if (!resolvedPath.HasValue) { - PapRequested?.Invoke(gamePath); + PapRequested?.Invoke(gamePath, null, data); return length; } - NativeMemory.Copy(utf8ResolvedPath.Path.Path, path, (nuint)utf8ResolvedPath.Length); - path[utf8ResolvedPath.Length] = 0; - PapRequested?.Invoke(gamePath); - return utf8ResolvedPath.Length; + PapRequested?.Invoke(gamePath, resolvedPath.Value, data); + NativeMemory.Copy(resolvedPath.Value.InternalName.Path, path, (nuint)resolvedPath.Value.InternalName.Length); + path[resolvedPath.Value.InternalName.Length] = 0; + return resolvedPath.Value.InternalName.Length; } /// Load a resource for a given path and a specific collection. diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs index a00b33c7..14d69489 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcher.cs @@ -11,7 +11,6 @@ using Penumbra.GameData.Enums; using Penumbra.Interop.Hooks.ResourceLoading; using Penumbra.Interop.Hooks.Resources; using Penumbra.Interop.Structs; -using Penumbra.Services; using Penumbra.String; using Penumbra.String.Classes; using Penumbra.UI.Classes; @@ -55,7 +54,7 @@ public sealed class ResourceWatcher : IDisposable, ITab, IUiService _newMaxEntries = _config.MaxResourceWatcherRecords; } - private void OnPapRequested(Utf8GamePath original) + private void OnPapRequested(Utf8GamePath original, FullPath? _1, ResolveData _2) { if (_ephemeral.EnableResourceLogging && FilterMatch(original.Path, out var match)) Penumbra.Log.Information($"[ResourceLoader] [REQ] {match} was requested asynchronously.");