feat: add wndproc nullref fix

This commit is contained in:
goaaats 2022-05-26 01:43:10 +02:00
parent 3cf47f7ec4
commit baad575c53
No known key found for this signature in database
GPG key ID: 49E2AA8C6A76498B
7 changed files with 112 additions and 3 deletions

View file

@ -7,6 +7,7 @@ using System.Threading;
using Dalamud.Configuration.Internal;
using Dalamud.Data;
using Dalamud.Fixes;
using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.Command;
@ -102,6 +103,10 @@ namespace Dalamud
Service<SigScanner>.Set(new SigScanner(true));
Service<HookManager>.Set();
// Initialize game fixes
var gameFixes = Service<GameFixes>.Set();
gameFixes.Apply();
// Initialize FFXIVClientStructs function resolver
FFXIVClientStructs.Resolver.Initialize();
Log.Information("[T1] FFXIVClientStructs initialized!");
@ -347,6 +352,8 @@ namespace Dalamud
Service<Framework>.GetNullable()?.ExplicitDispose();
Service<ClientState>.GetNullable()?.ExplicitDispose();
Service<GameFixes>.GetNullable()?.ExplicitDispose();
this.unloadSignal?.Dispose();
Service<WinSockHandlers>.GetNullable()?.Dispose();

View file

@ -212,7 +212,7 @@ namespace Dalamud
var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose);
Log.Logger = new LoggerConfiguration()
.WriteTo.Async(a => a.File(logPath))
.WriteTo.Async(a => a.File(logPath, fileSizeLimitBytes: null, buffered: false, flushToDiskInterval: TimeSpan.FromSeconds(1)))
.WriteTo.Sink(SerilogEventSink.Instance)
.MinimumLevel.ControlledBy(levelSwitch)
.CreateLogger();

View file

@ -0,0 +1,43 @@
using System;
using System.Linq;
using Serilog;
namespace Dalamud.Fixes;
/// <summary>
/// Class responsible for executing game fixes.
/// </summary>
internal class GameFixes : IDisposable
{
private readonly IGameFix[] fixes =
{
new WndProcNullRefFix(),
};
/// <summary>
/// Apply all game fixes.
/// </summary>
public void Apply()
{
foreach (var gameFix in this.fixes)
{
try
{
gameFix.Apply();
}
catch (Exception ex)
{
Log.Error(ex, "Could not apply game fix: {FixName}", gameFix.GetType().FullName);
}
}
}
/// <inheritdoc/>
public void Dispose()
{
foreach (var disposable in this.fixes.OfType<IDisposable>())
{
disposable.Dispose();
}
}
}

14
Dalamud/Fixes/IGameFix.cs Normal file
View file

@ -0,0 +1,14 @@
using System;
namespace Dalamud.Fixes;
/// <summary>
/// Base interface to be implemented by game fixes.
/// </summary>
internal interface IGameFix
{
/// <summary>
/// Apply the patch to the game.
/// </summary>
public void Apply();
}

View file

@ -0,0 +1,45 @@
using System;
using Dalamud.Game;
using Dalamud.Hooking;
using Serilog;
namespace Dalamud.Fixes;
/// <summary>
/// This fix is for the following issue:
/// Null reference in the game's WndProc function when certain window messages arrive
/// before an object on the game's input manager is initialized.
/// </summary>
internal class WndProcNullRefFix : IGameFix, IDisposable
{
private AsmHook? wndProcHook;
/// <inheritdoc/>
public void Apply()
{
var sigScanner = Service<SigScanner>.Get();
if (!sigScanner.TryScanText("E8 ?? ?? ?? ?? 48 83 38 00 74 14", out var patchAddress))
{
Log.Error("Failed to find WndProc patch address");
return;
}
Log.Information($"Applying WndProcNullRefFix at {patchAddress:X}");
var patchAsm = new byte[]
{
0x48, 0x85, 0xc0, // test rax, rax
0x74, 0x15, // jz +0x1A
};
this.wndProcHook = new AsmHook(patchAddress, patchAsm, "WndProcNullRefFix");
this.wndProcHook.Enable();
}
/// <inheritdoc/>
public void Dispose()
{
this.wndProcHook?.Dispose();
}
}

View file

@ -1,7 +1,7 @@
using System.Numerics;
using Dalamud.Game.ClientState.Keys;
using Dalamud.Game.Gui.Internal;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Windowing;
using ImGuiNET;