diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs
index e6f77eadf..d2f8c4aa1 100644
--- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs
+++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs
@@ -355,17 +355,17 @@ internal sealed class DalamudConfiguration : IServiceType
/// Gets or sets hitch threshold for game network up in milliseconds.
///
public double GameNetworkUpHitch { get; set; } = 30;
-
+
///
/// Gets or sets hitch threshold for game network down in milliseconds.
///
public double GameNetworkDownHitch { get; set; } = 30;
-
+
///
/// Gets or sets hitch threshold for framework update in milliseconds.
///
public double FrameworkUpdateHitch { get; set; } = 50;
-
+
///
/// Gets or sets hitch threshold for ui builder in milliseconds.
///
@@ -428,7 +428,7 @@ internal sealed class DalamudConfiguration : IServiceType
{
ThreadSafety.AssertMainThread();
- File.WriteAllText(this.configPath, JsonConvert.SerializeObject(this, SerializerSettings));
+ Util.WriteAllTextSafe(this.configPath, JsonConvert.SerializeObject(this, SerializerSettings));
this.DalamudConfigurationSaved?.Invoke(this);
}
}
diff --git a/Dalamud/Configuration/PluginConfigurations.cs b/Dalamud/Configuration/PluginConfigurations.cs
index b917a9e79..957a7c99e 100644
--- a/Dalamud/Configuration/PluginConfigurations.cs
+++ b/Dalamud/Configuration/PluginConfigurations.cs
@@ -1,5 +1,6 @@
using System.IO;
+using Dalamud.Utility;
using Newtonsoft.Json;
namespace Dalamud.Configuration;
@@ -32,7 +33,7 @@ public sealed class PluginConfigurations
/// Plugin name.
public void Save(IPluginConfiguration config, string pluginName)
{
- File.WriteAllText(this.GetConfigFile(pluginName).FullName, SerializeConfig(config));
+ Util.WriteAllTextSafe(this.GetConfigFile(pluginName).FullName, SerializeConfig(config));
}
///
diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj
index 5b796e7b0..beb14c61e 100644
--- a/Dalamud/Dalamud.csproj
+++ b/Dalamud/Dalamud.csproj
@@ -125,6 +125,17 @@
$(OutputPath)TEMP_gitver.txt
+
+
+
+
+
+
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(DalamudGitCommitCount), @"\t|\n|\r", ""))
+
+
+
@@ -171,6 +182,10 @@
<_Parameter1>GitHash
<_Parameter2>$(BuildHash)
+
+ <_Parameter1>GitCommitCount
+ <_Parameter2>$(CommitCount)
+
<_Parameter1>GitHashClientStructs
<_Parameter2>$(BuildHashClientStructs)
diff --git a/Dalamud/Game/Config/GameConfig.cs b/Dalamud/Game/Config/GameConfig.cs
index 4310ca4a8..81112cd79 100644
--- a/Dalamud/Game/Config/GameConfig.cs
+++ b/Dalamud/Game/Config/GameConfig.cs
@@ -39,7 +39,7 @@ public sealed class GameConfig : IServiceType
public GameConfigSection UiConfig { get; private set; }
///
- /// Gets the collection of config options that are control mode specific. (Mouse & Keyboard / Gamepad).
+ /// Gets the collection of config options that are control mode specific. (Mouse and Keyboard / Gamepad).
///
public GameConfigSection UiControl { get; private set; }
diff --git a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs
index 3e88780eb..e75d9c180 100644
--- a/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs
+++ b/Dalamud/Hooking/Internal/FunctionPointerVariableHook.cs
@@ -58,7 +58,14 @@ internal class FunctionPointerVariableHook : Hook
unsafe
{
- var pfnThunkBytes = (byte*)NativeFunctions.HeapAlloc(HookManager.NoFreeExecutableHeap, 0, 12);
+ // Note: WINE seemingly tries to clean up all heap allocations on process exit.
+ // We want our allocation to be kept there forever, until no running thread remains.
+ // Therefore we're using VirtualAlloc instead of HeapCreate/HeapAlloc.
+ var pfnThunkBytes = (byte*)NativeFunctions.VirtualAlloc(
+ 0,
+ 12,
+ NativeFunctions.AllocationType.Reserve | NativeFunctions.AllocationType.Commit,
+ MemoryProtection.ExecuteReadWrite);
if (pfnThunkBytes == null)
{
throw new OutOfMemoryException("Failed to allocate memory for import hooks.");
diff --git a/Dalamud/Hooking/Internal/HookManager.cs b/Dalamud/Hooking/Internal/HookManager.cs
index d26bcefa0..303802ff6 100644
--- a/Dalamud/Hooking/Internal/HookManager.cs
+++ b/Dalamud/Hooking/Internal/HookManager.cs
@@ -16,13 +16,6 @@ namespace Dalamud.Hooking.Internal;
[ServiceManager.EarlyLoadedService]
internal class HookManager : IDisposable, IServiceType
{
- ///
- /// Handle to an executable heap that we shall never free anything unless we can be absolutely sure that nothing is
- /// referencing to it anymore.
- ///
- internal static readonly nint NoFreeExecutableHeap =
- NativeFunctions.HeapCreate(NativeFunctions.HeapOptions.CreateEnableExecute, 0, 0);
-
private static readonly ModuleLog Log = new("HM");
[ServiceManager.ServiceConstructor]
diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs
index 3c6059b77..3da633c86 100644
--- a/Dalamud/Interface/Internal/DalamudInterface.cs
+++ b/Dalamud/Interface/Internal/DalamudInterface.cs
@@ -706,7 +706,7 @@ internal class DalamudInterface : IDisposable, IServiceType
{
this.OpenProfiler();
}
-
+
if (ImGui.MenuItem("Open Hitch Settings"))
{
this.OpenHitchSettings();
@@ -768,7 +768,7 @@ internal class DalamudInterface : IDisposable, IServiceType
ImGui.MenuItem(Util.AssemblyVersion, false);
ImGui.MenuItem(startInfo.GameVersion?.ToString() ?? "Unknown version", false);
- ImGui.MenuItem($"D: {Util.GetGitHash()} CS: {Util.GetGitHashClientStructs()} [{FFXIVClientStructs.Interop.Resolver.Version}]", false);
+ ImGui.MenuItem($"D: {Util.GetGitHash()}[{Util.GetGitCommitCount()}] CS: {Util.GetGitHashClientStructs()}[{FFXIVClientStructs.Interop.Resolver.Version}]", false);
ImGui.MenuItem($"CLR: {Environment.Version}", false);
ImGui.EndMenu();
@@ -944,7 +944,7 @@ internal class DalamudInterface : IDisposable, IServiceType
{
ImGui.PushFont(InterfaceManager.MonoFont);
- ImGui.BeginMenu(Util.GetGitHash(), false);
+ ImGui.BeginMenu($"{Util.GetGitHash()}({Util.GetGitCommitCount()})", false);
ImGui.BeginMenu(this.FrameCount.ToString("000000"), false);
ImGui.BeginMenu(ImGui.GetIO().Framerate.ToString("000"), false);
ImGui.BeginMenu($"W:{Util.FormatBytes(GC.GetTotalMemory(false))}", false);
diff --git a/Dalamud/Plugin/Internal/Types/LocalPluginManifest.cs b/Dalamud/Plugin/Internal/Types/LocalPluginManifest.cs
index 0f5348ddd..52cc55b23 100644
--- a/Dalamud/Plugin/Internal/Types/LocalPluginManifest.cs
+++ b/Dalamud/Plugin/Internal/Types/LocalPluginManifest.cs
@@ -68,7 +68,7 @@ internal record LocalPluginManifest : PluginManifest
/// Save a plugin manifest to file.
///
/// Path to save at.
- public void Save(FileInfo manifestFile) => File.WriteAllText(manifestFile.FullName, JsonConvert.SerializeObject(this, Formatting.Indented));
+ public void Save(FileInfo manifestFile) => Util.WriteAllTextSafe(manifestFile.FullName, JsonConvert.SerializeObject(this, Formatting.Indented));
///
/// Loads a plugin manifest from file.
diff --git a/Dalamud/Utility/Util.cs b/Dalamud/Utility/Util.cs
index 5fb2784af..7837e1bab 100644
--- a/Dalamud/Utility/Util.cs
+++ b/Dalamud/Utility/Util.cs
@@ -28,6 +28,7 @@ namespace Dalamud.Utility;
public static class Util
{
private static string? gitHashInternal;
+ private static int? gitCommitCountInternal;
private static string? gitHashClientStructsInternal;
private static ulong moduleStartAddr;
@@ -114,6 +115,26 @@ public static class Util
return gitHashInternal;
}
+ ///
+ /// Gets the amount of commits in the current branch, or null if undetermined.
+ ///
+ /// The amount of commits in the current branch.
+ public static int? GetGitCommitCount()
+ {
+ if (gitCommitCountInternal != null)
+ return gitCommitCountInternal.Value;
+
+ var asm = typeof(Util).Assembly;
+ var attrs = asm.GetCustomAttributes();
+
+ var value = attrs.First(a => a.Key == "GitCommitCount").Value;
+ if (value == null)
+ return null;
+
+ gitCommitCountInternal = int.Parse(value);
+ return gitCommitCountInternal.Value;
+ }
+
///
/// Gets the git hash value from the assembly
/// or null if it cannot be found.
@@ -568,6 +589,22 @@ public static class Util
}
}
+ ///
+ /// Overwrite text in a file by first writing it to a temporary file, and then
+ /// moving that file to the path specified.
+ ///
+ /// The path of the file to write to.
+ /// The text to write.
+ internal static void WriteAllTextSafe(string path, string text)
+ {
+ var tmpPath = path + ".tmp";
+ if (File.Exists(tmpPath))
+ File.Delete(tmpPath);
+
+ File.WriteAllText(tmpPath, text);
+ File.Move(tmpPath, path, true);
+ }
+
private static unsafe void ShowValue(ulong addr, IEnumerable path, Type type, object value)
{
if (type.IsPointer)
diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs
index 9e97396f9..74345c974 160000
--- a/lib/FFXIVClientStructs
+++ b/lib/FFXIVClientStructs
@@ -1 +1 @@
-Subproject commit 9e97396f98c20eff17a71aacb24296efcaa04808
+Subproject commit 74345c97468f310d555929f4e40c844556bc64e7