mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
feat: basic .text scan cache
This currently saves cached jsons in the working directory, we might wanna change that
This commit is contained in:
parent
f473c0e6d6
commit
eca2b7f5ee
2 changed files with 57 additions and 7 deletions
|
|
@ -106,7 +106,12 @@ namespace Dalamud
|
||||||
Service<ServiceContainer>.Set();
|
Service<ServiceContainer>.Set();
|
||||||
|
|
||||||
// Initialize the process information.
|
// Initialize the process information.
|
||||||
Service<SigScanner>.Set(new SigScanner(true));
|
var info = Service<DalamudStartInfo>.Get();
|
||||||
|
var cacheDir = new DirectoryInfo(Path.Combine(info.WorkingDirectory!, "cachedSigs"));
|
||||||
|
if (!cacheDir.Exists)
|
||||||
|
cacheDir.Create();
|
||||||
|
|
||||||
|
Service<SigScanner>.Set(new SigScanner(true, new FileInfo(Path.Combine(cacheDir.FullName, $"{info.GameVersion}.json"))));
|
||||||
Service<HookManager>.Set();
|
Service<HookManager>.Set();
|
||||||
|
|
||||||
// Signal the main game thread to continue
|
// Signal the main game thread to continue
|
||||||
|
|
@ -117,7 +122,7 @@ namespace Dalamud
|
||||||
// Initialize FFXIVClientStructs function resolver
|
// Initialize FFXIVClientStructs function resolver
|
||||||
using (Timings.Start("CS Resolver Init"))
|
using (Timings.Start("CS Resolver Init"))
|
||||||
{
|
{
|
||||||
FFXIVClientStructs.Resolver.Initialize();
|
FFXIVClientStructs.Resolver.InitializeParallel();
|
||||||
Log.Information("[T1] FFXIVClientStructs initialized!");
|
Log.Information("[T1] FFXIVClientStructs initialized!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -390,7 +395,10 @@ namespace Dalamud
|
||||||
Service<AntiDebug>.GetNullable()?.Dispose();
|
Service<AntiDebug>.GetNullable()?.Dispose();
|
||||||
Service<DalamudAtkTweaks>.GetNullable()?.Dispose();
|
Service<DalamudAtkTweaks>.GetNullable()?.Dispose();
|
||||||
Service<HookManager>.GetNullable()?.Dispose();
|
Service<HookManager>.GetNullable()?.Dispose();
|
||||||
Service<SigScanner>.GetNullable()?.Dispose();
|
|
||||||
|
var sigScanner = Service<SigScanner>.Get();
|
||||||
|
sigScanner.Save();
|
||||||
|
sigScanner.Dispose();
|
||||||
|
|
||||||
SerilogEventSink.Instance.LogLine -= SerilogOnLogLine;
|
SerilogEventSink.Instance.LogLine -= SerilogOnLogLine;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.IoC.Internal;
|
using Dalamud.IoC.Internal;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Game
|
namespace Dalamud.Game
|
||||||
|
|
@ -16,17 +18,22 @@ namespace Dalamud.Game
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[PluginInterface]
|
[PluginInterface]
|
||||||
[InterfaceVersion("1.0")]
|
[InterfaceVersion("1.0")]
|
||||||
public sealed class SigScanner : IDisposable
|
public class SigScanner : IDisposable
|
||||||
{
|
{
|
||||||
|
private readonly FileInfo? cacheFile;
|
||||||
|
|
||||||
private IntPtr moduleCopyPtr;
|
private IntPtr moduleCopyPtr;
|
||||||
private long moduleCopyOffset;
|
private long moduleCopyOffset;
|
||||||
|
|
||||||
|
private Dictionary<string, IntPtr>? textCache;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="SigScanner"/> class using the main module of the current process.
|
/// Initializes a new instance of the <see cref="SigScanner"/> class using the main module of the current process.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="doCopy">Whether or not to copy the module upon initialization for search operations to use, as to not get disturbed by possible hooks.</param>
|
/// <param name="doCopy">Whether or not to copy the module upon initialization for search operations to use, as to not get disturbed by possible hooks.</param>
|
||||||
public SigScanner(bool doCopy = false)
|
/// <param name="cacheFile">File used to cached signatures.</param>
|
||||||
: this(Process.GetCurrentProcess().MainModule!, doCopy)
|
public SigScanner(bool doCopy = false, FileInfo? cacheFile = null)
|
||||||
|
: this(Process.GetCurrentProcess().MainModule!, doCopy, cacheFile)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,8 +42,10 @@ namespace Dalamud.Game
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="module">The ProcessModule to be used for scanning.</param>
|
/// <param name="module">The ProcessModule to be used for scanning.</param>
|
||||||
/// <param name="doCopy">Whether or not to copy the module upon initialization for search operations to use, as to not get disturbed by possible hooks.</param>
|
/// <param name="doCopy">Whether or not to copy the module upon initialization for search operations to use, as to not get disturbed by possible hooks.</param>
|
||||||
public SigScanner(ProcessModule module, bool doCopy = false)
|
/// <param name="cacheFile">File used to cached signatures.</param>
|
||||||
|
public SigScanner(ProcessModule module, bool doCopy = false, FileInfo? cacheFile = null)
|
||||||
{
|
{
|
||||||
|
this.cacheFile = cacheFile;
|
||||||
this.Module = module;
|
this.Module = module;
|
||||||
this.Is32BitProcess = !Environment.Is64BitProcess;
|
this.Is32BitProcess = !Environment.Is64BitProcess;
|
||||||
this.IsCopy = doCopy;
|
this.IsCopy = doCopy;
|
||||||
|
|
@ -49,6 +58,9 @@ namespace Dalamud.Game
|
||||||
|
|
||||||
Log.Verbose($"Module base: 0x{this.TextSectionBase.ToInt64():X}");
|
Log.Verbose($"Module base: 0x{this.TextSectionBase.ToInt64():X}");
|
||||||
Log.Verbose($"Module size: 0x{this.TextSectionSize:X}");
|
Log.Verbose($"Module size: 0x{this.TextSectionSize:X}");
|
||||||
|
|
||||||
|
if (cacheFile != null)
|
||||||
|
this.Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -294,6 +306,12 @@ namespace Dalamud.Game
|
||||||
/// <returns>The real offset of the found signature.</returns>
|
/// <returns>The real offset of the found signature.</returns>
|
||||||
public IntPtr ScanText(string signature)
|
public IntPtr ScanText(string signature)
|
||||||
{
|
{
|
||||||
|
if (this.textCache != null && this.textCache.TryGetValue(signature, out var address))
|
||||||
|
{
|
||||||
|
Log.Information("Found signature {Signature} in cache: {Address}", signature, address);
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
var mBase = this.IsCopy ? this.moduleCopyPtr : this.TextSectionBase;
|
var mBase = this.IsCopy ? this.moduleCopyPtr : this.TextSectionBase;
|
||||||
|
|
||||||
var scanRet = Scan(mBase, this.TextSectionSize, signature);
|
var scanRet = Scan(mBase, this.TextSectionSize, signature);
|
||||||
|
|
@ -306,6 +324,8 @@ namespace Dalamud.Game
|
||||||
if (insnByte == 0xE8 || insnByte == 0xE9)
|
if (insnByte == 0xE8 || insnByte == 0xE9)
|
||||||
return ReadJmpCallSig(scanRet);
|
return ReadJmpCallSig(scanRet);
|
||||||
|
|
||||||
|
this.textCache?.Add(signature, scanRet);
|
||||||
|
|
||||||
return scanRet;
|
return scanRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -337,6 +357,17 @@ namespace Dalamud.Game
|
||||||
Marshal.FreeHGlobal(this.moduleCopyPtr);
|
Marshal.FreeHGlobal(this.moduleCopyPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save the current state of the cache.
|
||||||
|
/// </summary>
|
||||||
|
internal void Save()
|
||||||
|
{
|
||||||
|
if (this.cacheFile == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
File.WriteAllText(this.cacheFile.FullName, JsonConvert.SerializeObject(this.textCache));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper for ScanText to get the correct address for IDA sigs that mark the first JMP or CALL location.
|
/// Helper for ScanText to get the correct address for IDA sigs that mark the first JMP or CALL location.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -479,5 +510,16 @@ namespace Dalamud.Game
|
||||||
|
|
||||||
this.moduleCopyOffset = this.moduleCopyPtr.ToInt64() - this.Module.BaseAddress.ToInt64();
|
this.moduleCopyOffset = this.moduleCopyPtr.ToInt64() - this.Module.BaseAddress.ToInt64();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void Load()
|
||||||
|
{
|
||||||
|
if (this.cacheFile is not { Exists: true })
|
||||||
|
{
|
||||||
|
this.textCache = new();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.textCache = JsonConvert.DeserializeObject<Dictionary<string, IntPtr>>(File.ReadAllText(this.cacheFile.FullName)) ?? new Dictionary<string, IntPtr>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue