mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 18:27:23 +01:00
feat: delay main thread continuation until GameFixes are applied
This is a temporary workaround until we have infrastructure to intercept winapi in C++
This commit is contained in:
parent
28102b405b
commit
d2335274ee
8 changed files with 67 additions and 18 deletions
|
|
@ -59,7 +59,7 @@ bool is_full_dumps()
|
|||
return check_env_var("DALAMUD_IS_VEH_FULL");
|
||||
}
|
||||
|
||||
DllExport DWORD WINAPI Initialize(LPVOID lpParam)
|
||||
DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
ConsoleSetup(L"Dalamud Boot");
|
||||
|
|
@ -97,7 +97,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam)
|
|||
if (result != 0)
|
||||
return result;
|
||||
|
||||
typedef void (CORECLR_DELEGATE_CALLTYPE* custom_component_entry_point_fn)(LPVOID);
|
||||
typedef void (CORECLR_DELEGATE_CALLTYPE* custom_component_entry_point_fn)(LPVOID, HANDLE);
|
||||
custom_component_entry_point_fn entrypoint_fn = reinterpret_cast<custom_component_entry_point_fn>(entrypoint_vfn);
|
||||
|
||||
// ============================== VEH ======================================== //
|
||||
|
|
@ -121,7 +121,7 @@ DllExport DWORD WINAPI Initialize(LPVOID lpParam)
|
|||
// ============================== Dalamud ==================================== //
|
||||
|
||||
printf("Initializing Dalamud... ");
|
||||
entrypoint_fn(lpParam);
|
||||
entrypoint_fn(lpParam, hMainThreadContinue);
|
||||
printf("Done!\n");
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include "pch.h"
|
||||
|
||||
DllExport DWORD WINAPI Initialize(LPVOID lpParam);
|
||||
DllExport DWORD WINAPI Initialize(LPVOID lpParam, HANDLE hMainThreadContinue);
|
||||
|
||||
struct RewrittenEntryPointParameters {
|
||||
void* pAllocation;
|
||||
|
|
@ -379,8 +379,9 @@ DllExport void WINAPI RewrittenEntryPoint(RewrittenEntryPointParameters& params)
|
|||
params.hMainThread = CreateThread(nullptr, 0, [](void* p) -> DWORD {
|
||||
try {
|
||||
std::string loadInfo;
|
||||
auto& params = *reinterpret_cast<RewrittenEntryPointParameters*>(p);
|
||||
{
|
||||
auto& params = *reinterpret_cast<RewrittenEntryPointParameters*>(p);
|
||||
|
||||
|
||||
// Restore original entry point.
|
||||
// Use WriteProcessMemory instead of memcpy to avoid having to fiddle with VirtualProtect.
|
||||
|
|
@ -390,12 +391,12 @@ DllExport void WINAPI RewrittenEntryPoint(RewrittenEntryPointParameters& params)
|
|||
loadInfo = params.pLoadInfo;
|
||||
|
||||
// Let the game initialize.
|
||||
SetEvent(params.hMainThreadContinue);
|
||||
//SetEvent(params.hMainThreadContinue);
|
||||
}
|
||||
|
||||
wait_for_game_window();
|
||||
//wait_for_game_window();
|
||||
|
||||
Initialize(&loadInfo[0]);
|
||||
Initialize(&loadInfo[0], params.hMainThreadContinue);
|
||||
return 0;
|
||||
} catch (const std::exception& e) {
|
||||
MessageBoxA(nullptr, std::format("Failed to load Dalamud.\n\nError: {}", e.what()).c_str(), "Dalamud.Boot", MB_OK | MB_ICONERROR);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ namespace Dalamud
|
|||
|
||||
private readonly ManualResetEvent unloadSignal;
|
||||
private readonly ManualResetEvent finishUnloadSignal;
|
||||
private readonly IntPtr mainThreadContinueEvent;
|
||||
private MonoMod.RuntimeDetour.Hook processMonoHook;
|
||||
private bool hasDisposedPlugins = false;
|
||||
|
||||
|
|
@ -61,7 +62,8 @@ namespace Dalamud
|
|||
/// <param name="loggingLevelSwitch">LoggingLevelSwitch to control Serilog level.</param>
|
||||
/// <param name="finishSignal">Signal signalling shutdown.</param>
|
||||
/// <param name="configuration">The Dalamud configuration.</param>
|
||||
public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch, ManualResetEvent finishSignal, DalamudConfiguration configuration)
|
||||
/// <param name="mainThreadContinueEvent">Event used to signal the main thread to continue.</param>
|
||||
public Dalamud(DalamudStartInfo info, LoggingLevelSwitch loggingLevelSwitch, ManualResetEvent finishSignal, DalamudConfiguration configuration, IntPtr mainThreadContinueEvent)
|
||||
{
|
||||
this.ApplyProcessPatch();
|
||||
|
||||
|
|
@ -76,6 +78,8 @@ namespace Dalamud
|
|||
|
||||
this.finishUnloadSignal = finishSignal;
|
||||
this.finishUnloadSignal.Reset();
|
||||
|
||||
this.mainThreadContinueEvent = mainThreadContinueEvent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -107,6 +111,13 @@ namespace Dalamud
|
|||
var gameFixes = Service<GameFixes>.Set();
|
||||
gameFixes.Apply();
|
||||
|
||||
Log.Information("[T1] GameFixes OK!");
|
||||
|
||||
// Signal the main game thread to continue
|
||||
NativeFunctions.SetEvent(this.mainThreadContinueEvent);
|
||||
|
||||
Log.Information("[T1] Game thread continued!");
|
||||
|
||||
// Initialize FFXIVClientStructs function resolver
|
||||
FFXIVClientStructs.Resolver.Initialize();
|
||||
Log.Information("[T1] FFXIVClientStructs initialized!");
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ namespace Dalamud
|
|||
/// A delegate used during initialization of the CLR from Dalamud.Boot.
|
||||
/// </summary>
|
||||
/// <param name="infoPtr">Pointer to a serialized <see cref="DalamudStartInfo"/> data.</param>
|
||||
public delegate void InitDelegate(IntPtr infoPtr);
|
||||
/// <param name="mainThreadContinueEvent">Event used to signal the main thread to continue.</param>
|
||||
public delegate void InitDelegate(IntPtr infoPtr, IntPtr mainThreadContinueEvent);
|
||||
|
||||
/// <summary>
|
||||
/// A delegate used from VEH handler on exception which CoreCLR will fast fail by default.
|
||||
|
|
@ -43,12 +44,13 @@ namespace Dalamud
|
|||
/// Initialize Dalamud.
|
||||
/// </summary>
|
||||
/// <param name="infoPtr">Pointer to a serialized <see cref="DalamudStartInfo"/> data.</param>
|
||||
public static void Initialize(IntPtr infoPtr)
|
||||
/// <param name="mainThreadContinueEvent">Event used to signal the main thread to continue.</param>
|
||||
public static void Initialize(IntPtr infoPtr, IntPtr mainThreadContinueEvent)
|
||||
{
|
||||
var infoStr = Marshal.PtrToStringUTF8(infoPtr);
|
||||
var info = JsonConvert.DeserializeObject<DalamudStartInfo>(infoStr);
|
||||
|
||||
new Thread(() => RunThread(info)).Start();
|
||||
new Thread(() => RunThread(info, mainThreadContinueEvent)).Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -106,7 +108,8 @@ namespace Dalamud
|
|||
/// Initialize all Dalamud subsystems and start running on the main thread.
|
||||
/// </summary>
|
||||
/// <param name="info">The <see cref="DalamudStartInfo"/> containing information needed to initialize Dalamud.</param>
|
||||
private static void RunThread(DalamudStartInfo info)
|
||||
/// <param name="mainThreadContinueEvent">Event used to signal the main thread to continue.</param>
|
||||
private static void RunThread(DalamudStartInfo info, IntPtr mainThreadContinueEvent)
|
||||
{
|
||||
// Setup logger
|
||||
var levelSwitch = InitLogging(info.WorkingDirectory);
|
||||
|
|
@ -142,11 +145,12 @@ namespace Dalamud
|
|||
if (!Util.IsLinux())
|
||||
InitSymbolHandler(info);
|
||||
|
||||
var dalamud = new Dalamud(info, levelSwitch, finishSignal, configuration);
|
||||
var dalamud = new Dalamud(info, levelSwitch, finishSignal, configuration, mainThreadContinueEvent);
|
||||
Log.Information("Starting a session..");
|
||||
|
||||
// Run session
|
||||
dalamud.LoadTier1();
|
||||
|
||||
dalamud.WaitForUnload();
|
||||
|
||||
dalamud.Dispose();
|
||||
|
|
|
|||
|
|
@ -46,8 +46,10 @@ internal class WndProcNullRefFix : IGameFix, IDisposable
|
|||
|
||||
Log.Information($"Applying WndProcNullRefFix at {patchAddress:X} with o1 {this.object1Address:X}, o2 {this.object2Address:X}");
|
||||
|
||||
this.wndProcHook = new Hook<WndProcDelegate>(patchAddress, this.WndProcDetour);
|
||||
this.wndProcHook = new Hook<WndProcDelegate>(patchAddress, this.WndProcDetour, true);
|
||||
Log.Information("Set up hook");
|
||||
this.wndProcHook.Enable();
|
||||
Log.Information("Enabled hook");
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
|
||||
|
||||
#define BOOT_AGING
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using CheapLoc;
|
||||
using Dalamud.Configuration.Internal;
|
||||
using Dalamud.Game.ClientState.Conditions;
|
||||
|
|
@ -29,7 +34,6 @@ using ImGuiNET;
|
|||
using ImGuiScene;
|
||||
using PInvoke;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Dalamud.Interface.Internal
|
||||
{
|
||||
/// <summary>
|
||||
|
|
@ -350,10 +354,25 @@ namespace Dalamud.Interface.Internal
|
|||
|
||||
#endregion
|
||||
|
||||
private bool signaledBoot = false;
|
||||
|
||||
private void OnDraw()
|
||||
{
|
||||
this.frameCount++;
|
||||
|
||||
#if BOOT_AGING
|
||||
if (this.frameCount > 500 && !this.signaledBoot)
|
||||
{
|
||||
this.signaledBoot = true;
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
using var client = new HttpClient();
|
||||
await client.PostAsync("http://localhost:1415/aging/success", new StringContent(string.Empty));
|
||||
});
|
||||
}
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
this.DrawHiddenDevMenuOpener();
|
||||
|
|
|
|||
|
|
@ -1393,6 +1393,18 @@ namespace Dalamud
|
|||
WriteCombine = 0x400,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// See https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-setevent
|
||||
/// Sets the specified event object to the signaled state.
|
||||
/// </summary>
|
||||
/// <param name="hEvent">A handle to the event object. The CreateEvent or OpenEvent function returns this handle.</param>
|
||||
/// <returns>
|
||||
/// If the function succeeds, the return value is nonzero.
|
||||
/// If the function fails, the return value is zero. To get extended error information, call GetLastError.
|
||||
/// </returns>
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool SetEvent(IntPtr hEvent);
|
||||
|
||||
/// <summary>
|
||||
/// See https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-freelibrary.
|
||||
/// Frees the loaded dynamic-link library (DLL) module and, if necessary, decrements its reference count. When the reference
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ int InitializeClrAndGetEntryPoint(
|
|||
dotnet_path,
|
||||
};
|
||||
|
||||
printf("Loading coreclr... ");;
|
||||
printf("Loading coreclr... ");
|
||||
if ((result = g_clr->load_runtime(runtimeconfig_path, &runtime_parameters)) != 0)
|
||||
{
|
||||
printf("\nError: Failed to load coreclr (err=%d)\n", result);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue