mirror of
https://github.com/xivdev/Penumbra.git
synced 2026-02-22 15:57:46 +01:00
Merge remote-tracking branch 'refs/remotes/pmgr/master'
This commit is contained in:
commit
528e3226b5
2 changed files with 33 additions and 11 deletions
|
|
@ -3,6 +3,7 @@ using Dalamud.Hooking;
|
||||||
using Iced.Intel;
|
using Iced.Intel;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using Penumbra.String.Classes;
|
using Penumbra.String.Classes;
|
||||||
|
using Swan;
|
||||||
|
|
||||||
namespace Penumbra.Interop.Hooks.ResourceLoading;
|
namespace Penumbra.Interop.Hooks.ResourceLoading;
|
||||||
|
|
||||||
|
|
@ -10,9 +11,10 @@ public sealed class PapRewriter(PapRewriter.PapResourceHandlerPrototype papResou
|
||||||
{
|
{
|
||||||
public unsafe delegate int PapResourceHandlerPrototype(void* self, byte* path, int length);
|
public unsafe delegate int PapResourceHandlerPrototype(void* self, byte* path, int length);
|
||||||
|
|
||||||
private readonly PeSigScanner _scanner = new();
|
private readonly PeSigScanner _scanner = new();
|
||||||
private readonly Dictionary<nint, AsmHook> _hooks = [];
|
private readonly Dictionary<nint, AsmHook> _hooks = [];
|
||||||
private readonly List<nint> _nativeAllocList = [];
|
private readonly Dictionary<(nint, Register, ulong), nint> _nativeAllocPaths = [];
|
||||||
|
private readonly List<nint> _nativeAllocCaves = [];
|
||||||
|
|
||||||
public void Rewrite(string sig, string name)
|
public void Rewrite(string sig, string name)
|
||||||
{
|
{
|
||||||
|
|
@ -25,8 +27,12 @@ public sealed class PapRewriter(PapRewriter.PapResourceHandlerPrototype papResou
|
||||||
foreach (var hookPoint in hookPoints)
|
foreach (var hookPoint in hookPoints)
|
||||||
{
|
{
|
||||||
var stackAccesses = ScanStackAccesses(funcInstructions, hookPoint).ToList();
|
var stackAccesses = ScanStackAccesses(funcInstructions, hookPoint).ToList();
|
||||||
var stringAllocation = NativeAlloc(Utf8GamePath.MaxGamePathLength);
|
var stringAllocation = NativeAllocPath(
|
||||||
|
address, hookPoint.MemoryBase, hookPoint.MemoryDisplacement64,
|
||||||
|
Utf8GamePath.MaxGamePathLength
|
||||||
|
);
|
||||||
WriteToAlloc(stringAllocation, Utf8GamePath.MaxGamePathLength, name);
|
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.
|
// 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.
|
// 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.
|
// Pretty scuffed, this might need a refactoring at some point.
|
||||||
|
|
@ -44,7 +50,7 @@ public sealed class PapRewriter(PapRewriter.PapResourceHandlerPrototype papResou
|
||||||
var targetRegister = hookPoint.Op0Register.ToString().ToLower();
|
var targetRegister = hookPoint.Op0Register.ToString().ToLower();
|
||||||
var hookAddress = new IntPtr((long)detourPoint.IP);
|
var hookAddress = new IntPtr((long)detourPoint.IP);
|
||||||
|
|
||||||
var caveAllocation = NativeAlloc(16);
|
var caveAllocation = NativeAllocCave(16);
|
||||||
var hook = new AsmHook(
|
var hook = new AsmHook(
|
||||||
hookAddress,
|
hookAddress,
|
||||||
[
|
[
|
||||||
|
|
@ -137,13 +143,24 @@ public sealed class PapRewriter(PapRewriter.PapResourceHandlerPrototype papResou
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe nint NativeAlloc(nuint size)
|
private unsafe nint NativeAllocCave(nuint size)
|
||||||
{
|
{
|
||||||
var caveLoc = (nint)NativeMemory.Alloc(size);
|
var caveLoc = (nint)NativeMemory.Alloc(size);
|
||||||
_nativeAllocList.Add(caveLoc);
|
_nativeAllocCaves.Add(caveLoc);
|
||||||
|
|
||||||
return caveLoc;
|
return caveLoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a bit conked but, if we identify a path by:
|
||||||
|
// 1) The function it belongs to (starting address, 'funcAddress')
|
||||||
|
// 2) The stack register (not strictly necessary - should always be rbp - but abundance of caution, so I don't hit myself in the future)
|
||||||
|
// 3) The displacement on the stack
|
||||||
|
// Then we ensure we have a unique identifier for the specific variable location of that specific function
|
||||||
|
// This is useful because sometimes the stack address is reused within the same function for different GetResourceAsync calls
|
||||||
|
private unsafe nint NativeAllocPath(nint funcAddress, Register stackRegister, ulong stackDisplacement, nuint size)
|
||||||
|
{
|
||||||
|
return _nativeAllocPaths.GetOrAdd((funcAddress, stackRegister, stackDisplacement), _ => (nint)NativeMemory.Alloc(size));
|
||||||
|
}
|
||||||
|
|
||||||
private static unsafe void NativeFree(nint mem)
|
private static unsafe void NativeFree(nint mem)
|
||||||
=> NativeMemory.Free((void*)mem);
|
=> NativeMemory.Free((void*)mem);
|
||||||
|
|
@ -160,10 +177,15 @@ public sealed class PapRewriter(PapRewriter.PapResourceHandlerPrototype papResou
|
||||||
|
|
||||||
_hooks.Clear();
|
_hooks.Clear();
|
||||||
|
|
||||||
foreach (var mem in _nativeAllocList)
|
foreach (var mem in _nativeAllocCaves)
|
||||||
NativeFree(mem);
|
NativeFree(mem);
|
||||||
|
|
||||||
_nativeAllocList.Clear();
|
_nativeAllocCaves.Clear();
|
||||||
|
|
||||||
|
foreach (var mem in _nativeAllocPaths.Values)
|
||||||
|
NativeFree(mem);
|
||||||
|
|
||||||
|
_nativeAllocPaths.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
[Conditional("DEBUG")]
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
"Description": "Runtime mod loader and manager.",
|
"Description": "Runtime mod loader and manager.",
|
||||||
"InternalName": "Penumbra",
|
"InternalName": "Penumbra",
|
||||||
"AssemblyVersion": "1.1.1.2",
|
"AssemblyVersion": "1.1.1.2",
|
||||||
"TestingAssemblyVersion": "1.2.0.12",
|
"TestingAssemblyVersion": "1.2.0.13",
|
||||||
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
"RepoUrl": "https://github.com/xivdev/Penumbra",
|
||||||
"ApplicableVersion": "any",
|
"ApplicableVersion": "any",
|
||||||
"DalamudApiLevel": 9,
|
"DalamudApiLevel": 9,
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
"LoadRequiredState": 2,
|
"LoadRequiredState": 2,
|
||||||
"LoadSync": true,
|
"LoadSync": true,
|
||||||
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.1.1.2/Penumbra.zip",
|
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/1.1.1.2/Penumbra.zip",
|
||||||
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/testing_1.2.0.12/Penumbra.zip",
|
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/testing_1.2.0.13/Penumbra.zip",
|
||||||
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.1.1.2/Penumbra.zip",
|
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/1.1.1.2/Penumbra.zip",
|
||||||
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
|
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue