diff --git a/DoW Mod Manager.sln b/DoW Mod Manager.sln
index 5b73c6a..c70e328 100644
--- a/DoW Mod Manager.sln
+++ b/DoW Mod Manager.sln
@@ -1,20 +1,45 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30011.22
+# Visual Studio Version 17
+VisualStudioVersion = 17.3.32804.467
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoW Mod Manager", "DoW Mod Manager\DoW Mod Manager.csproj", "{071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UNI_EXT", "UNI_EXT\UNI_EXT.vcxproj", "{67138EE0-0823-4524-9453-4E9892296669}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Debug|x64.Build.0 = Debug|Any CPU
+ {071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Debug|x86.Build.0 = Debug|Any CPU
{071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Release|x64.ActiveCfg = Release|Any CPU
+ {071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Release|x64.Build.0 = Release|Any CPU
+ {071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Release|x86.ActiveCfg = Release|Any CPU
+ {071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}.Release|x86.Build.0 = Release|Any CPU
+ {67138EE0-0823-4524-9453-4E9892296669}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {67138EE0-0823-4524-9453-4E9892296669}.Debug|x64.ActiveCfg = Debug|x64
+ {67138EE0-0823-4524-9453-4E9892296669}.Debug|x64.Build.0 = Debug|x64
+ {67138EE0-0823-4524-9453-4E9892296669}.Debug|x86.ActiveCfg = Debug|Win32
+ {67138EE0-0823-4524-9453-4E9892296669}.Debug|x86.Build.0 = Debug|Win32
+ {67138EE0-0823-4524-9453-4E9892296669}.Release|Any CPU.ActiveCfg = Release|Win32
+ {67138EE0-0823-4524-9453-4E9892296669}.Release|Any CPU.Build.0 = Release|Win32
+ {67138EE0-0823-4524-9453-4E9892296669}.Release|x64.ActiveCfg = Release|x64
+ {67138EE0-0823-4524-9453-4E9892296669}.Release|x64.Build.0 = Release|x64
+ {67138EE0-0823-4524-9453-4E9892296669}.Release|x86.ActiveCfg = Release|Win32
+ {67138EE0-0823-4524-9453-4E9892296669}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/DoW Mod Manager/DoW Mod Manager.csproj b/DoW Mod Manager/DoW Mod Manager.csproj
index 3561e4a..78f215d 100644
--- a/DoW Mod Manager/DoW Mod Manager.csproj
+++ b/DoW Mod Manager/DoW Mod Manager.csproj
@@ -7,7 +7,7 @@
{071DFF9E-1A7F-4F94-A1CE-4B5CB931D8EE}
WinExe
DoW_Mod_Manager
- DoW Mod Manager v2.3.1.0
+ DoW Mod Manager v2.4.0.0
v4.8
512
true
@@ -118,6 +118,7 @@
SystemPerformanceManagerForm.cs
+
AboutForm.cs
diff --git a/DoW Mod Manager/FogRemover.cs b/DoW Mod Manager/FogRemover.cs
index b68c250..7bfa24c 100644
--- a/DoW Mod Manager/FogRemover.cs
+++ b/DoW Mod Manager/FogRemover.cs
@@ -74,12 +74,14 @@ private static bool CheckToggleMemory(int addr, byte[] checkVal, byte[] setVal,
{
byte[] lpBuffer = new byte[checkVal.Length];
- if (!ReadProcessMemory(pHandle, addr, lpBuffer, lpBuffer.Length, out int lpNumberOfBytesRead)
+ int lpNumberOfBytesRead, lpflOldProtect, _;
+
+ if (!ReadProcessMemory(pHandle, addr, lpBuffer, lpBuffer.Length, out lpNumberOfBytesRead)
|| lpNumberOfBytesRead != lpBuffer.Length
|| !((IEnumerable)lpBuffer).SequenceEqual(checkVal))
return false;
- VirtualProtectEx(pHandle, addr, setVal.Length, PAGE_EXECUTE_READWRITE, out int lpflOldProtect);
+ VirtualProtectEx(pHandle, addr, setVal.Length, PAGE_EXECUTE_READWRITE, out lpflOldProtect);
int returnCode = WriteProcessMemory(pHandle, addr, setVal, setVal.Length, out _) ? 1 : 0;
VirtualProtectEx(pHandle, addr, setVal.Length, lpflOldProtect, out _);
diff --git a/DoW Mod Manager/LatestStable/DoW Mod Manager.exe b/DoW Mod Manager/LatestStable/DoW Mod Manager.exe
index 501217c..13d91cc 100644
Binary files a/DoW Mod Manager/LatestStable/DoW Mod Manager.exe and b/DoW Mod Manager/LatestStable/DoW Mod Manager.exe differ
diff --git a/DoW Mod Manager/LatestStable/version b/DoW Mod Manager/LatestStable/version
index 7118006..ac84e1c 100644
--- a/DoW Mod Manager/LatestStable/version
+++ b/DoW Mod Manager/LatestStable/version
@@ -1 +1 @@
-2.3.1.0
\ No newline at end of file
+2.4.0.0
\ No newline at end of file
diff --git a/DoW Mod Manager/ModManagerForm.Designer.cs b/DoW Mod Manager/ModManagerForm.Designer.cs
index d6661e7..46aba8b 100644
--- a/DoW Mod Manager/ModManagerForm.Designer.cs
+++ b/DoW Mod Manager/ModManagerForm.Designer.cs
@@ -58,6 +58,7 @@ private void InitializeComponent()
this.checkForErrorsButton = new System.Windows.Forms.Button();
this.noFogCheckbox = new System.Windows.Forms.CheckBox();
this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel();
+ this.loadUNI_EXTDLLCheckBox = new System.Windows.Forms.CheckBox();
this.panel2 = new System.Windows.Forms.Panel();
this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
@@ -283,8 +284,8 @@ private void InitializeComponent()
// gameLAAStatusLabel
//
this.gameLAAStatusLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
- this.gameLAAStatusLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.gameLAAStatusLabel.Location = new System.Drawing.Point(8, 73);
+ this.gameLAAStatusLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.gameLAAStatusLabel.Location = new System.Drawing.Point(8, 77);
this.gameLAAStatusLabel.Margin = new System.Windows.Forms.Padding(3);
this.gameLAAStatusLabel.Name = "gameLAAStatusLabel";
this.gameLAAStatusLabel.Size = new System.Drawing.Size(210, 15);
@@ -294,8 +295,8 @@ private void InitializeComponent()
// graphicsConfigLAAStatusLabel
//
this.graphicsConfigLAAStatusLabel.Anchor = System.Windows.Forms.AnchorStyles.Top;
- this.graphicsConfigLAAStatusLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.graphicsConfigLAAStatusLabel.Location = new System.Drawing.Point(8, 89);
+ this.graphicsConfigLAAStatusLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.graphicsConfigLAAStatusLabel.Location = new System.Drawing.Point(8, 91);
this.graphicsConfigLAAStatusLabel.Margin = new System.Windows.Forms.Padding(3);
this.graphicsConfigLAAStatusLabel.Name = "graphicsConfigLAAStatusLabel";
this.graphicsConfigLAAStatusLabel.Size = new System.Drawing.Size(210, 15);
@@ -462,13 +463,26 @@ private void InitializeComponent()
this.flowLayoutPanel1.Controls.Add(this.highpolyCheckBox);
this.flowLayoutPanel1.Controls.Add(this.optimizationsCheckBox);
this.flowLayoutPanel1.Controls.Add(this.noFogCheckbox);
+ this.flowLayoutPanel1.Controls.Add(this.loadUNI_EXTDLLCheckBox);
this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.flowLayoutPanel1.Location = new System.Drawing.Point(12, 32);
this.flowLayoutPanel1.Margin = new System.Windows.Forms.Padding(0);
this.flowLayoutPanel1.Name = "flowLayoutPanel1";
- this.flowLayoutPanel1.Size = new System.Drawing.Size(328, 110);
+ this.flowLayoutPanel1.Size = new System.Drawing.Size(330, 123);
this.flowLayoutPanel1.TabIndex = 28;
//
+ // loadUNI_EXTDLLCheckBox
+ //
+ this.loadUNI_EXTDLLCheckBox.AutoSize = true;
+ this.loadUNI_EXTDLLCheckBox.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(200)))), ((int)(((byte)(200)))), ((int)(((byte)(200)))));
+ this.loadUNI_EXTDLLCheckBox.Location = new System.Drawing.Point(5, 103);
+ this.loadUNI_EXTDLLCheckBox.Margin = new System.Windows.Forms.Padding(5, 0, 0, 0);
+ this.loadUNI_EXTDLLCheckBox.Name = "loadUNI_EXTDLLCheckBox";
+ this.loadUNI_EXTDLLCheckBox.Size = new System.Drawing.Size(318, 17);
+ this.loadUNI_EXTDLLCheckBox.TabIndex = 28;
+ this.loadUNI_EXTDLLCheckBox.Text = "UNI_EXT.DLL: Load experimental UNI_EXT.DLL into memory";
+ this.loadUNI_EXTDLLCheckBox.UseVisualStyleBackColor = true;
+ //
// panel2
//
this.panel2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
@@ -481,7 +495,7 @@ private void InitializeComponent()
this.panel2.Controls.Add(this.settingsButton);
this.panel2.Location = new System.Drawing.Point(341, 32);
this.panel2.Name = "panel2";
- this.panel2.Size = new System.Drawing.Size(245, 110);
+ this.panel2.Size = new System.Drawing.Size(245, 118);
this.panel2.TabIndex = 29;
//
// flowLayoutPanel2
@@ -586,6 +600,7 @@ private void InitializeComponent()
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;
private System.Windows.Forms.Panel panel2;
+ private System.Windows.Forms.CheckBox loadUNI_EXTDLLCheckBox;
private System.Windows.Forms.Button open_folder_button;
private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
}
diff --git a/DoW Mod Manager/ModManagerForm.cs b/DoW Mod Manager/ModManagerForm.cs
index 1e1ae91..832d444 100644
--- a/DoW Mod Manager/ModManagerForm.cs
+++ b/DoW Mod Manager/ModManagerForm.cs
@@ -7,9 +7,11 @@
using System.Security.Permissions;
using System.Reflection;
using System.Threading;
+using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime;
using SSNoFog;
+using SSUNI_EXTTDLL;
namespace DoW_Mod_Manager
{
@@ -52,6 +54,7 @@ public enum Action { None, CreateNativeImage, CreateNativeImageAndDeleteJITProfi
public const string NO_MOVIES = "NoMovies";
public const string FORCE_HIGH_POLY = "ForceHighPoly";
public const string NO_FOG = "RemoveMapFog";
+ public const string UNI_EXTDLL = "LoadUNI_EXTDLL";
public const string DOW_OPTIMIZATIONS = "DowOptimizations";
public const string AUTOUPDATE = "Autoupdate";
public const string MULTITHREADED_JIT = "MultithreadedJIT";
@@ -64,13 +67,18 @@ public enum Action { None, CreateNativeImage, CreateNativeImageAndDeleteJITProfi
private bool _isMessageBoxOnScreen = false;
private bool _isOldGame;
private bool _IsNoFogTooltipShown = false;
+ private bool _IsUNI_EXTDLLNoFogTooltipShown = false;
private string _dowProcessName = "";
private readonly ToolTip _disabledNoFogTooltip = new ToolTip();
- private Control _currentToolTipControl;
+ private readonly ToolTip _disabledLoadUNI_EXTDLLCheckBoxTooltip = new ToolTip();
+ private Control _currentToolTipControl;
private ModMergerForm modMerger = null;
+ public static int _maxDefeatedRaces = 0x0A;
+
public readonly string CurrentDir = Directory.GetCurrentDirectory();
public readonly string CurrentGameEXE = "";
+ public readonly bool IsUNI_EXTDLL = false;
public readonly string GraphicsConfigEXE = "GraphicsConfig.exe";
public string[] ModuleFilePaths;
public string[] ModFolderPaths;
@@ -89,6 +97,7 @@ public enum Action { None, CreateNativeImage, CreateNativeImageAndDeleteJITProfi
[NO_MOVIES] = 1,
[FORCE_HIGH_POLY] = 0,
[NO_FOG] = 0,
+ [UNI_EXTDLL] = 0,
[DOW_OPTIMIZATIONS] = 0,
[AUTOUPDATE] = 1,
[MULTITHREADED_JIT] = 0,
@@ -154,9 +163,11 @@ public ModManagerForm()
highpolyCheckBox.Checked = settings[FORCE_HIGH_POLY] == 1;
optimizationsCheckBox.Checked = settings[DOW_OPTIMIZATIONS] == 1;
noFogCheckbox.Checked = settings[NO_FOG] == 1;
+ loadUNI_EXTDLLCheckBox.Checked = settings[UNI_EXTDLL] == 1;
CurrentGameEXE = GetCurrentGameEXE();
CheckForGraphicsConfigEXE();
+ IsUNI_EXTDLL = FindUNI_EXTDLL();
currentDirTextBox.Text = CurrentDir;
SetUpAllNecessaryMods();
@@ -181,13 +192,26 @@ public ModManagerForm()
highpolyCheckBox.CheckedChanged += new EventHandler(HighpolyCheckBox_CheckedChanged);
optimizationsCheckBox.CheckedChanged += new EventHandler(OptimizationsCheckBox_CheckedChanged);
noFogCheckbox.CheckedChanged += new EventHandler(NoFogCheckboxCheckedChanged);
+ loadUNI_EXTDLLCheckBox.CheckedChanged += new EventHandler(loadUNI_EXTDLLCheckBox_CheckedChanged);
- // Disable no Fog checkbox if it's not Soulstorm because it only works on Soulstorm at all.
+ // Disable no Fog checkbox and UNI_EXTDLL checkbox if it's not Soulstorm because it only works on Soulstorm at all.
if (CurrentGameEXE != GameExecutable.SOULSTORM)
{
noFogCheckbox.Enabled = false;
noFogCheckbox.Checked = false;
+ loadUNI_EXTDLLCheckBox.Enabled = false;
+ loadUNI_EXTDLLCheckBox.Checked = false;
+
flowLayoutPanel1.MouseMove += new MouseEventHandler(noFogCheckbox_hover);
+ flowLayoutPanel1.MouseMove += new MouseEventHandler(loadUNI_EXTDLLCheckBox_hover);
+ }
+ // Also disable UNI_EXTDLL checkbox if UNI_EXT.DLL is not found.
+ else if (!IsUNI_EXTDLL)
+ {
+ loadUNI_EXTDLLCheckBox.Enabled = false;
+ loadUNI_EXTDLLCheckBox.Checked = false;
+
+ flowLayoutPanel1.MouseMove += new MouseEventHandler(loadUNI_EXTDLLNot_Found_CheckBox_hover);
}
// Perform Autoupdate
@@ -207,12 +231,45 @@ public ModManagerForm()
}
///
- /// This function shows a tooltip, should the disable fog checkbox be disabled due to a wrong game version used.
+ /// This function shows a tooltip, should the load Uni_ext.dll checkbox be disabled due to a wrong game version used.
/// It has to be done since using normal tooltips won't work on disabled controls.
///
///
///
- private void noFogCheckbox_hover(object sender, MouseEventArgs e)
+ private void loadUNI_EXTDLLCheckBox_hover(object sender, MouseEventArgs e)
+ {
+ Control parent = sender as Control;
+
+ if (parent == null)
+ return;
+
+ Control ctrl = parent.GetChildAtPoint(e.Location);
+ if (ctrl != null)
+ {
+ if (ctrl == loadUNI_EXTDLLCheckBox && !_IsUNI_EXTDLLNoFogTooltipShown)
+ {
+ _disabledLoadUNI_EXTDLLCheckBoxTooltip.Show(
+ "Load UNI_EXT.DLL only works in Dawn of War: Soulstorm",
+ loadUNI_EXTDLLCheckBox,
+ loadUNI_EXTDLLCheckBox.Width / 2,
+ loadUNI_EXTDLLCheckBox.Height / 2);
+ _IsUNI_EXTDLLNoFogTooltipShown = true;
+ }
+ }
+ else
+ {
+ _disabledLoadUNI_EXTDLLCheckBoxTooltip.Hide(loadUNI_EXTDLLCheckBox);
+ _IsUNI_EXTDLLNoFogTooltipShown = false;
+ }
+ }
+
+ ///
+ /// This function shows a tooltip, should the load Uni_ext.dll checkbox be disabled due to a wrong game version used.
+ /// It has to be done since using normal tooltips won't work on disabled controls.
+ ///
+ ///
+ ///
+ private void loadUNI_EXTDLLNot_Found_CheckBox_hover(object sender, MouseEventArgs e)
{
Control parent = sender as Control;
@@ -221,6 +278,39 @@ private void noFogCheckbox_hover(object sender, MouseEventArgs e)
Control ctrl = parent.GetChildAtPoint(e.Location);
if (ctrl != null)
+ {
+ if (ctrl == loadUNI_EXTDLLCheckBox && !_IsUNI_EXTDLLNoFogTooltipShown)
+ {
+ _disabledLoadUNI_EXTDLLCheckBoxTooltip.Show(
+ "File UNI_EXT.DLL is missing",
+ loadUNI_EXTDLLCheckBox,
+ loadUNI_EXTDLLCheckBox.Width / 2,
+ loadUNI_EXTDLLCheckBox.Height / 2);
+ _IsUNI_EXTDLLNoFogTooltipShown = true;
+ }
+ }
+ else
+ {
+ _disabledLoadUNI_EXTDLLCheckBoxTooltip.Hide(loadUNI_EXTDLLCheckBox);
+ _IsUNI_EXTDLLNoFogTooltipShown = false;
+ }
+ }
+
+ ///
+ /// This function shows a tooltip, should the disable fog checkbox be disabled due to a wrong game version used.
+ /// It has to be done since using normal tooltips won't work on disabled controls.
+ ///
+ ///
+ ///
+ private void noFogCheckbox_hover(object sender, MouseEventArgs e)
+ {
+ var parent = sender as Control;
+ if (parent == null)
+ {
+ return;
+ }
+ var ctrl = parent.GetChildAtPoint(e.Location);
+ if (ctrl != null)
{
if (ctrl == noFogCheckbox && !_IsNoFogTooltipShown)
{
@@ -332,6 +422,7 @@ private void ReadSettingsFromDoWModManagerINI()
case MULTITHREADED_JIT:
case AOT_COMPILATION:
case NO_FOG:
+ case UNI_EXTDLL:
if (value == 0 || value == 1)
settings[setting] = value;
else
@@ -365,11 +456,27 @@ private void ReselectSavedMod()
}
///
- /// This method scans for either the Soulstorm, Dark Crusade, Winter Assault or Original version of the game.
+ /// This method scans for UNI_EXT.DLL file.
///
/// string
// Request the inlining of this method
[MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private bool FindUNI_EXTDLL()
+ {
+ if (File.Exists(CurrentDir + "\\UNI_EXT.DLL"))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// This method scans for either the Soulstorm, Dark Crusade, Winter Assault or Original version of the game.
+ ///
+ /// string
+ // Request the inlining of this method
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private string GetCurrentGameEXE()
{
if (File.Exists(CurrentDir + "\\" + GameExecutable.SOULSTORM))
@@ -636,7 +743,8 @@ private void ModManagerForm_Closing(object sender, EventArgs e)
sw.WriteLine($"{AUTOUPDATE}={settings[AUTOUPDATE]}");
sw.WriteLine($"{MULTITHREADED_JIT}={settings[MULTITHREADED_JIT]}");
sw.WriteLine($"{AOT_COMPILATION}={settings[AOT_COMPILATION]}");
- sw.Write($"{NO_FOG}={settings[NO_FOG]}");
+ sw.WriteLine($"{NO_FOG}={settings[NO_FOG]}");
+ sw.WriteLine($"{UNI_EXTDLL}={settings[UNI_EXTDLL]}");
}
// If Timer Resolution was lowered we have to keep DoW Mod Manager alive or Timer Resolution will be reset
@@ -895,12 +1003,12 @@ private void StartGameWithOptions(string modName)
arguments += " -nomovies";
if (settings[FORCE_HIGH_POLY] == 1)
arguments += " -forcehighpoly";
-
+
Process proc = new Process();
proc.StartInfo.FileName = CurrentGameEXE;
proc.StartInfo.Arguments = arguments;
proc.Start();
-
+
_dowProcessName = proc.ProcessName;
// Create new thread to change the process CPU affinity after the game has started.
@@ -958,6 +1066,34 @@ private void StartGameWithOptions(string modName)
}
).Start();
}
+
+ // Create a new thread for UNI_EXTDLL which manipulates the process memory after the game has started.
+ if (settings[UNI_EXTDLL] == 1)
+ {
+ new Thread(() =>
+ {
+ int timeOutCounter = 0;
+ string procName = _dowProcessName;
+
+ // We will try 30 times and then Thread will be terminated regardless
+ while (timeOutCounter < 30)
+ {
+ Thread.Sleep(1000);
+ try
+ {
+ Process[] dow = Process.GetProcessesByName(procName);
+ UNI_EXTDLLLoader.UNI_EXTdllInjector(dow[0], CurrentDir + "\\UNI_EXT.DLL");
+ break; // We've done what we intended to do
+ }
+ catch (Exception)
+ {
+ timeOutCounter++;
+ }
+ }
+ }
+ ).Start();
+ }
+
}
///
@@ -1031,6 +1167,19 @@ private void NoFogCheckboxCheckedChanged(object sender, EventArgs e)
settings[NO_FOG] = 0;
}
+ ///
+ /// This checkbox loads UNI_EXT.DLL to program memory.
+ ///
+ ///
+ ///
+ private void loadUNI_EXTDLLCheckBox_CheckedChanged(object sender, EventArgs e)
+ {
+ if (loadUNI_EXTDLLCheckBox.Checked)
+ settings[UNI_EXTDLL] = 1;
+ else
+ settings[UNI_EXTDLL] = 0;
+ }
+
///
/// This method collects and displays the list of required mods for a selected mod in order to function correctly.
///
@@ -1340,7 +1489,7 @@ private void HomePageLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEv
}
///
- /// This event handles the case when the no fog checkbox is disabled, to show a tooltip why it is disabled.
+ /// This event handles the case when the no fog checkbox and UNI_EXT.dll is disabled, to show a tooltip why it is disabled.
///
///
///
@@ -1355,10 +1504,17 @@ private void ModManagerForm_MouseMove(object sender, MouseEventArgs e)
_disabledNoFogTooltip.Show(toolTipString, control, control.Width / 2, control.Height / 2);
_currentToolTipControl = control;
}
+ if (!control.Enabled && control == loadUNI_EXTDLLCheckBox)
+ {
+ string toolTipString = _disabledLoadUNI_EXTDLLCheckBoxTooltip.GetToolTip(control);
+ _disabledLoadUNI_EXTDLLCheckBoxTooltip.Show(toolTipString, control, control.Width / 2, control.Height / 2);
+ _currentToolTipControl = control;
+ }
}
else
{
if (_currentToolTipControl != null) _disabledNoFogTooltip.Hide(_currentToolTipControl);
+ if (_currentToolTipControl != null) _disabledLoadUNI_EXTDLLCheckBoxTooltip.Hide(_currentToolTipControl);
_currentToolTipControl = null;
}
}
diff --git a/DoW Mod Manager/Properties/AssemblyInfo.cs b/DoW Mod Manager/Properties/AssemblyInfo.cs
index a09062a..adfe8c0 100644
--- a/DoW Mod Manager/Properties/AssemblyInfo.cs
+++ b/DoW Mod Manager/Properties/AssemblyInfo.cs
@@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("2.3.1.0")]
-[assembly: AssemblyFileVersion("2.3.1.0")]
+[assembly: AssemblyVersion("2.4.0.0")]
+[assembly: AssemblyFileVersion("2.4.0.0")]
diff --git a/DoW Mod Manager/SettingsManagerForm.cs b/DoW Mod Manager/SettingsManagerForm.cs
index a7cae85..383f209 100644
--- a/DoW Mod Manager/SettingsManagerForm.cs
+++ b/DoW Mod Manager/SettingsManagerForm.cs
@@ -882,34 +882,34 @@ private void WriteSettings(bool localINI, bool playercgfLUA)
modManager.ChangeSetting(ModManagerForm.FORCE_HIGH_POLY, 0);
disableHighPoly = false;
}
+ }
- void SearchForThatString(ref string[] strArray)
- {
- bool weFoundIt = false;
+ void SearchForThatString(ref string[] strArray)
+ {
+ bool weFoundIt = false;
- for (int i = 0; i < strArray.Length; i++)
+ for (int i = 0; i < strArray.Length; i++)
+ {
+ if (strArray[i].StartsWith("allowhwcursor"))
{
- if (strArray[i].StartsWith("allowhwcursor"))
- {
- strArray[i] = ALLOWHWCURSOR + " " + settings[ALLOWHWCURSOR];
- weFoundIt = true;
- break; // We found what we searched for
- }
+ strArray[i] = ALLOWHWCURSOR + " " + settings[ALLOWHWCURSOR];
+ weFoundIt = true;
+ break; // We found what we searched for
}
+ }
- if (!weFoundIt)
+ if (!weFoundIt)
+ {
+ using (StreamWriter sw = File.CreateText(DRIVER_SETTINGS_FILE))
{
- using (StreamWriter sw = File.CreateText(DRIVER_SETTINGS_FILE))
- {
- // TODO - maybe just write the new line ;-)
+ // TODO - maybe just write the new line ;-)
- // Write all that was in file before
- for (int i = 0; i < strArray.Length; i++)
- sw.WriteLine(strArray[i]);
+ // Write all that was in file before
+ for (int i = 0; i < strArray.Length; i++)
+ sw.WriteLine(strArray[i]);
- // And then add this new line
- sw.WriteLine(ALLOWHWCURSOR + " " + settings[ALLOWHWCURSOR]);
- }
+ // And then add this new line
+ sw.WriteLine(ALLOWHWCURSOR + " " + settings[ALLOWHWCURSOR]);
}
}
}
diff --git a/DoW Mod Manager/SystemPerformanceManagerForm.cs b/DoW Mod Manager/SystemPerformanceManagerForm.cs
index b97d62a..9684b98 100644
--- a/DoW Mod Manager/SystemPerformanceManagerForm.cs
+++ b/DoW Mod Manager/SystemPerformanceManagerForm.cs
@@ -222,7 +222,7 @@ private void SetPowerPlanButton_Click(object sender, EventArgs e)
{
Guid powerPlanGUID = new Guid(GUID_BALANCED);
- switch (powerPlanComboBox.SelectedItem)
+ switch (powerPlanComboBox.SelectedItem.ToString())
{
case NAME_ULTIMATE_PERFORMANCE:
if (ultimatePerformanceGUIDIndex == 2)
diff --git a/DoW Mod Manager/UNIEXTDLLLoader.cs b/DoW Mod Manager/UNIEXTDLLLoader.cs
new file mode 100644
index 0000000..cf7bc62
--- /dev/null
+++ b/DoW Mod Manager/UNIEXTDLLLoader.cs
@@ -0,0 +1,245 @@
+// DLL injection function available https://github.com/ihack4falafel/DLL-Injection
+// Made by ihack4falafel
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Runtime.ConstrainedExecution;
+using System.Security;
+using System.Text;
+using DoW_Mod_Manager;
+
+namespace SSUNI_EXTTDLL
+{
+ public static class UNI_EXTDLLLoader
+ {
+ [Flags]
+ public enum ProcessAccessFlags : uint
+ {
+ All = 0x001F0FFF,
+ Terminate = 0x00000001,
+ CreateThread = 0x00000002,
+ VirtualMemoryOperation = 0x00000008,
+ VirtualMemoryRead = 0x00000010,
+ VirtualMemoryWrite = 0x00000020,
+ DuplicateHandle = 0x00000040,
+ CreateProcess = 0x000000080,
+ SetQuota = 0x00000100,
+ SetInformation = 0x00000200,
+ QueryInformation = 0x00000400,
+ QueryLimitedInformation = 0x00001000,
+ Synchronize = 0x00100000
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern IntPtr OpenProcess(
+ ProcessAccessFlags processAccess,
+ bool bInheritHandle,
+ int processId);
+ public static IntPtr OpenProcess(Process proc, ProcessAccessFlags flags)
+ {
+ return OpenProcess(flags, false, proc.Id);
+ }
+
+ // VirtualAllocEx signture https://www.pinvoke.net/default.aspx/kernel32.virtualallocex
+ [Flags]
+ public enum AllocationType
+ {
+ Commit = 0x1000,
+ Reserve = 0x2000,
+ Decommit = 0x4000,
+ Release = 0x8000,
+ Reset = 0x80000,
+ Physical = 0x400000,
+ TopDown = 0x100000,
+ WriteWatch = 0x200000,
+ LargePages = 0x20000000
+ }
+
+ // VirtualFreeEx signture https://www.pinvoke.net/default.aspx/kernel32.virtualfreeex
+ [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
+ static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
+ int dwSize, AllocationType dwFreeType);
+
+ [Flags]
+ public enum MemoryProtection
+ {
+ Execute = 0x10,
+ ExecuteRead = 0x20,
+ ExecuteReadWrite = 0x40,
+ ExecuteWriteCopy = 0x80,
+ NoAccess = 0x01,
+ ReadOnly = 0x02,
+ ReadWrite = 0x04,
+ WriteCopy = 0x08,
+ GuardModifierflag = 0x100,
+ NoCacheModifierflag = 0x200,
+ WriteCombineModifierflag = 0x400
+ }
+
+ [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
+ static extern IntPtr VirtualAllocEx(
+ IntPtr hProcess,
+ IntPtr lpAddress,
+ IntPtr dwSize,
+ AllocationType flAllocationType,
+ MemoryProtection flProtect);
+
+ // WriteProcessMemory signture https://www.pinvoke.net/default.aspx/kernel32/WriteProcessMemory.html
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern bool WriteProcessMemory(
+ IntPtr hProcess,
+ IntPtr lpBaseAddress,
+ [MarshalAs(UnmanagedType.AsAny)] object lpBuffer,
+ int dwSize,
+ out IntPtr lpNumberOfBytesWritten);
+
+ // GetProcAddress signture https://www.pinvoke.net/default.aspx/kernel32.getprocaddress
+ [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
+ static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
+
+ // GetModuleHandle signture http://pinvoke.net/default.aspx/kernel32.GetModuleHandle
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
+ public static extern IntPtr GetModuleHandle(string lpModuleName);
+
+ // CreateRemoteThread signture https://www.pinvoke.net/default.aspx/kernel32.createremotethread
+ [DllImport("kernel32.dll")]
+ static extern IntPtr CreateRemoteThread(
+ IntPtr hProcess,
+ IntPtr lpThreadAttributes,
+ uint dwStackSize,
+ IntPtr lpStartAddress,
+ IntPtr lpParameter,
+ uint dwCreationFlags,
+ IntPtr lpThreadId);
+
+ // CloseHandle signture https://www.pinvoke.net/default.aspx/kernel32.closehandle
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [SuppressUnmanagedCodeSecurity]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool CloseHandle(IntPtr hObject);
+
+ public static void UNI_EXTdllInjector(Process process, string DllPath)
+ {
+ IntPtr Size = (IntPtr)DllPath.Length;
+ string message = "";
+
+ // Open handle to the target process
+ IntPtr ProcHandle = OpenProcess(
+ ProcessAccessFlags.All,
+ false,
+ process.Id);
+ if (ProcHandle == null)
+ {
+ ThemedMessageBox.Show("[!] Handle to target process could not be obtained!", "UNI_EXT.DLL messages");
+
+ System.Environment.Exit(1);
+ }
+ else
+ {
+ message += "[+] Handle (0x" + ProcHandle + ") to target process has been obtained.\n";
+ }
+
+ // Allocate DLL space
+ IntPtr DllSpace = VirtualAllocEx(
+ ProcHandle,
+ IntPtr.Zero,
+ Size,
+ AllocationType.Reserve | AllocationType.Commit,
+ MemoryProtection.ExecuteReadWrite);
+
+ if (DllSpace == null)
+ {
+ ThemedMessageBox.Show(message+"[!] DLL space allocation failed.", "UNI_EXT.DLL messages");
+ System.Environment.Exit(1);
+ }
+ else
+ {
+ message += "[+] DLL space (0x" + DllSpace + ") allocation is successful.\n";
+ }
+
+ // Write DLL content to VAS of target process
+ IntPtr bytesread;
+ byte[] bytes = Encoding.ASCII.GetBytes(DllPath);
+ bool DllWrite = WriteProcessMemory(
+ ProcHandle,
+ DllSpace,
+ bytes,
+ (int)bytes.Length,
+ out bytesread
+ );
+
+ if (DllWrite == false)
+ {
+ ThemedMessageBox.Show(message + "[!] Writing DLL content to target process failed.", "UNI_EXT.DLL messages");
+ System.Environment.Exit(1);
+ }
+ else
+ {
+ message += "[+] Writing DLL content to target process is successful.\n";
+ }
+
+ // Get handle to Kernel32.dll and get address for LoadLibraryA
+ IntPtr Kernel32Handle = GetModuleHandle("Kernel32.dll");
+ IntPtr LoadLibraryAAddress = GetProcAddress(Kernel32Handle, "LoadLibraryA");
+
+ if (LoadLibraryAAddress == null)
+ {
+ ThemedMessageBox.Show(message + "[!] Obtaining an addess to LoadLibraryA function has failed.", "UNI_EXT.DLL messages");
+ System.Environment.Exit(1);
+ }
+ else
+ {
+ message += "[+] LoadLibraryA function address (0x" + LoadLibraryAAddress + ") has been obtained.\n";
+ }
+
+ // Create remote thread in the target process
+ IntPtr RemoteThreadHandle = CreateRemoteThread(
+ ProcHandle,
+ IntPtr.Zero,
+ 0,
+ LoadLibraryAAddress,
+ DllSpace,
+ 0,
+ IntPtr.Zero
+ );
+
+ if (RemoteThreadHandle == null)
+ {
+ ThemedMessageBox.Show(message + "[!] Obtaining a handle to remote thread in target process failed.", "UNI_EXT.DLL messages");
+ System.Environment.Exit(1);
+ }
+ else
+ {
+ message += "[+] Obtaining a handle to remote thread (0x" + RemoteThreadHandle + ") in target process is successful.\n";
+ System.Threading.Thread.Sleep(3000);
+ //ThemedMessageBox.Show(message + "[+] Obtaining a handle to remote thread (0x" + RemoteThreadHandle + ") in target process is successful.", "UNI_EXT.DLL messages");
+ }
+
+ // Deallocate memory assigned to DLL
+ bool FreeDllSpace = VirtualFreeEx(
+ ProcHandle,
+ DllSpace,
+ 0,
+ AllocationType.Release);
+ if (FreeDllSpace == false)
+ {
+ ThemedMessageBox.Show(message + "[!] Failed to release DLL memory in target process.", "UNI_EXT.DLL messages");
+ System.Environment.Exit(1);
+ }
+ else
+ {
+ message += "[+] Successfully released DLL memory in target process.\n";
+ //ThemedMessageBox.Show(message + "[+] Successfully released DLL memory in target process.", "UNI_EXT.DLL messages");
+ }
+
+ // Close remote thread handle
+ CloseHandle(RemoteThreadHandle);
+
+ // Close target process handle
+ CloseHandle(ProcHandle);
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/DoW Mod Manager/WinApiCalls.cs b/DoW Mod Manager/WinApiCalls.cs
index a3b81a0..31c7e22 100644
--- a/DoW Mod Manager/WinApiCalls.cs
+++ b/DoW Mod Manager/WinApiCalls.cs
@@ -47,14 +47,14 @@ public static class WinApiCalls
public static TimerCaps QueryTimerResolution()
{
TimerCaps caps = new TimerCaps();
- _ = NtQueryTimerResolution(out caps.PeriodMin, out caps.PeriodMax, out caps.PeriodCurrent);
+ var _ = NtQueryTimerResolution(out caps.PeriodMin, out caps.PeriodMax, out caps.PeriodCurrent);
return caps;
}
public static ulong SetTimerResolution(uint timerResolutionIn100nsUnits, bool doSet = true)
{
uint currentRes = 0;
- _ = NtSetTimerResolution(timerResolutionIn100nsUnits, doSet, ref currentRes);
+ var _ = NtSetTimerResolution(timerResolutionIn100nsUnits, doSet, ref currentRes);
return currentRes;
}
diff --git a/UNI_EXT/Patch.cpp b/UNI_EXT/Patch.cpp
new file mode 100644
index 0000000..5f4a476
--- /dev/null
+++ b/UNI_EXT/Patch.cpp
@@ -0,0 +1,139 @@
+// Based on slashdiablo-maphack implementation
+// https://github.com/planqi/slashdiablo-maphack
+
+#include "Patch.h"
+#include "SoulstormVersion.h"
+
+std::vector Patch::Patches;
+
+Patch::Patch(PatchType type, Dll dll, Offsets offsets, int function, int length)
+ : type(type), dll(dll), offsets(offsets), substitutions({ 0 }), function(function), length(length) {
+ oldCode = new BYTE[length];
+ injected = false;
+ Patches.push_back(this);
+}
+
+Patch::Patch(PatchType type, Dll dll, Offsets offsets, Substitutions substitutions, int length)
+ : type(type), dll(dll), offsets(offsets), substitutions(substitutions), function(NULL), length(length) {
+ oldCode = new BYTE[length];
+ injected = false;
+ Patches.push_back(this);
+}
+
+int Patch::GetDllOffset(Dll dll, int offset) {
+ const wchar_t* szDlls[] = { L"SOULSTORM.exe", L"UserInterface.dll", L"WXPMod.dll" };
+ //Attempt to get the module of the given DLL
+ HMODULE hModule = GetModuleHandle(szDlls[dll]);
+
+ //If DLL hasn't been loaded, then load it up!
+ if (!hModule) {
+ hModule = LoadLibrary(szDlls[dll]);
+ }
+
+ //If the DLL isn't there, or failed to load, return.
+ if (!hModule)
+ return false;
+
+ //Check if it is an ordinal, if so, get the proper address.
+ if (offset < 0)
+ return (DWORD)GetProcAddress(hModule, (LPCSTR)(-offset));
+
+ //If just regular offset, add the two and be done!
+ return ((DWORD)hModule) + offset;
+}
+
+bool Patch::WriteBytes(int address, int len, BYTE* bytes) {
+ DWORD dwOld;
+
+ if (!VirtualProtect((void*)address, len, PAGE_READWRITE, &dwOld))
+ return FALSE;
+
+ ::memcpy((void*)address, bytes, len);
+ return !!VirtualProtect((void*)address, len, dwOld, &dwOld);
+}
+
+bool Patch::Install() {
+
+ //Check if we have already installed this patch.
+ if (IsInstalled())
+ return true;
+
+ //Initalize variables for the exactly commands we are injecting.
+ BYTE* code = new BYTE[length];
+ DWORD protect;
+
+ // Select an offset based on Soulstorm version
+ int offset = *(&offsets._steam + SoulstormVersion::GetGameVersionID());
+
+ //Get the proper address that we are patching
+ int address = GetDllOffset(dll, offset);
+
+ //Read the old code to allow proper patch removal
+ ReadProcessMemory(GetCurrentProcess(), (void*)address, oldCode, length, NULL);
+
+ //Set the code with all NOPs by default
+ memset(code, 0x90, length);
+
+ if (type == Overwrite) {
+ for (int i = 0; i < length; i++)
+ {
+ code[i] = substitutions._steam[i];
+ }
+ }
+ else if (type != NOP) {
+ //Set the opcode
+ code[0] = type;
+
+ //Set the address to redirect to
+ if (type == Call || type == Jump) {
+ *(DWORD*)&code[1] = function - (address + 5);
+ }
+ else {
+ code[1] = function;
+ }
+ }
+
+ //Write the patch in
+ VirtualProtect((VOID*)address, length, PAGE_EXECUTE_READWRITE, &protect);
+ memcpy_s((VOID*)address, length, code, length);
+ VirtualProtect((VOID*)address, length, protect, &protect);
+/*
+ DWORD old;
+ DWORD base = (DWORD)GetModuleHandle(NULL);
+ DWORD offset = 0x81F350;
+
+ char* ptr = reinterpret_cast(base + offset);
+ const size_t length = 4;
+ char buffer[length] = { 0x0A, 0x00, 0x00, 0x00 };
+
+ VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old);
+ memcpy(ptr, buffer, length);
+ VirtualProtect(ptr, length, old, nullptr);
+ */
+ //Set that we successfully patched
+ injected = true;
+
+ return true;
+}
+
+bool Patch::Remove() {
+ if (!IsInstalled())
+ return true;
+
+ // Select an offset based on D2 version
+ int offset = *(&offsets._steam);
+
+ //Get the proper address
+ int address = GetDllOffset(dll, offset);
+ DWORD protect;
+
+ //Revert to the previous code
+ VirtualProtect((VOID*)address, length, PAGE_EXECUTE_READWRITE, &protect);
+ memcpy_s((VOID*)address, length, oldCode, length);
+ VirtualProtect((VOID*)address, length, protect, &protect);
+
+
+ injected = false;
+
+ return true;
+}
\ No newline at end of file
diff --git a/UNI_EXT/Patch.h b/UNI_EXT/Patch.h
new file mode 100644
index 0000000..a96b3b5
--- /dev/null
+++ b/UNI_EXT/Patch.h
@@ -0,0 +1,45 @@
+// Based on slashdiablo-maphack implementation
+// https://github.com/planqi/slashdiablo-maphack
+
+#pragma once
+#include
+#include
+#include
+
+class Patch;
+
+enum Dll { SOULSTORM = 0, USERINTERFACE, WXPMOD };
+enum PatchType { Jump = 0xE9, Call = 0xE8, NOP = 0x90, Push = 0x6A, Overwrite };
+
+struct Offsets {
+ int _steam;
+ int _cdversion;
+};
+
+// substitutions have a limit of characters
+struct Substitutions {
+ int _steam[100];
+};
+
+class Patch {
+private:
+ static std::vector Patches;
+ Dll dll;
+ PatchType type;
+ Offsets offsets;
+ Substitutions substitutions;
+ int length, function;
+ BYTE* oldCode;
+ bool injected;
+public:
+ Patch(PatchType type, Dll dll, Offsets offsets, int function, int length);
+ Patch(PatchType type, Dll dll, Offsets offsets, Substitutions substitutions, int length);
+
+ bool Install();
+ bool Remove();
+
+ bool IsInstalled() { return injected; };
+
+ static int GetDllOffset(Dll dll, int offset);
+ static bool WriteBytes(int address, int len, BYTE* bytes);
+};
\ No newline at end of file
diff --git a/UNI_EXT/ReadMe.txt b/UNI_EXT/ReadMe.txt
new file mode 100644
index 0000000..9df1183
--- /dev/null
+++ b/UNI_EXT/ReadMe.txt
@@ -0,0 +1,48 @@
+========================================================================
+ DYNAMIC LINK LIBRARY : UNI_EXT Project Overview
+========================================================================
+
+AppWizard has created this UNI_EXT DLL for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your UNI_EXT application.
+
+
+UNI_EXT.vcxproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+UNI_EXT.vcxproj.filters
+ This is the filters file for VC++ projects generated using an Application Wizard.
+ It contains information about the association between the files in your project
+ and the filters. This association is used in the IDE to show grouping of files with
+ similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+ "Source Files" filter).
+
+UNI_EXT.cpp
+ This is the main DLL source file.
+
+ When created, this DLL does not export any symbols. As a result, it
+ will not produce a .lib file when it is built. If you wish this project
+ to be a project dependency of some other project, you will either need to
+ add code to export some symbols from the DLL so that an export library
+ will be produced, or you can set the Ignore Input Library property to Yes
+ on the General propert page of the Linker folder in the project's Property
+ Pages dialog box.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named UNI_EXT.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/UNI_EXT/SoulstormIntercepts.cpp b/UNI_EXT/SoulstormIntercepts.cpp
new file mode 100644
index 0000000..2fa88e1
--- /dev/null
+++ b/UNI_EXT/SoulstormIntercepts.cpp
@@ -0,0 +1,437 @@
+#include
+#include "SoulstormPointers.h"
+
+//DWORD patch_clip_region;
+//DWORD* base_address;
+DWORD return_address;
+
+/*
+int __declspec(naked) Metamap_Action_Selector_Function()
+{
+ __asm
+ {
+ push offset AD3A84;
+ call sub_66DE90;
+ call sub_777BD0;
+// pushad;
+// call GameLoop;
+// popad;
+
+// pop eax;
+// sub esp, 0x20;
+// mov[esp + 0xC], ecx;
+// push eax;
+// ret;
+ }
+}
+*/
+int __stdcall runAction(int)
+{
+ /*
+ int v4, v5, v11, v58;
+ char v6;
+ int(__thiscall *v7)(int);
+ const wchar_t* v49;
+ const char *v50;
+ float v51;
+
+ v4 = SOULSTORM_sub_96EAA0();
+ v5 = ((int(__thiscall *)(int))SOULSTORM_sub_96F440)(v4);
+ v6 = (*(int(__thiscall **)(int))(*(DWORD *)v5 + 636))(v5);
+ v7 = *(int(__thiscall **)(int))(*(DWORD *)v5 + 640);
+
+ v11 = *(DWORD *)(a1 + 376);
+
+ v58 = SOULSTORM_sub_7761C0(v6, (char)v7);
+ SOULSTORM_sub_66DE90(SOULSTORM_dieActionString_I, v58);
+ SOULSTORM_runAnimationOnMetaMapMenuModel(*v49, *v50, v51);
+ return 0;
+ */
+
+ __asm
+ {
+ //push ebp
+ /*
+ push 0x0FFFFFFFF
+ push SOULSTORM_FrameHandler3Jump
+ mov eax, fs : 0
+ push eax
+ mov fs : 0, esp
+ sub esp, 0x50
+ */
+
+
+ push ebx
+ push ebp
+ push esi
+ push edi
+
+
+ mov esi, ecx
+ call SOULSTORM_sub_96EAA0
+ mov ecx, eax
+ call SOULSTORM_sub_96F440
+ mov edi, eax
+ mov eax, [edi]
+ mov edx, [eax + 0x27C]
+ mov ecx, edi
+ call edx
+ mov bl, al
+ mov eax, [edi]
+ mov edx, [eax + 0x280]
+ mov ecx, edi
+ mov byte ptr[esp - 0x8], bl
+ call edx
+ mov byte ptr[esp - 0x4], al
+
+ mov eax, [esp - 0x4]
+ mov edx, [esp - 0x8]
+ mov ecx, [esi + 0x178]
+ push eax
+ push edx
+ call SOULSTORM_toggleOverlayFunction
+
+
+
+ sub esp, 0x0C
+
+ mov ecx, esp
+ mov [esp + 0x7C], esp
+ lea edx, [esp + 0x7C]
+ push edx
+ push SOULSTORM_dieActionString_I
+ call SOULSTORM_findMotionByGivenName
+ mov ecx, [esi + 0x178]
+ call SOULSTORM_runMotionOnMetaMapMenuModel
+ //add esp, 0x1C
+
+ fld SOULSTORM_flt_C1F44C
+ sub esp, 0x0C
+ mov eax, esp
+ fstp dword ptr[esp + 0x4]
+ mov [esp + 0x7C], esp
+ push esi
+ push SOULSTORM_setOverlayEnabledFunction
+ push eax
+ call SOULSTORM_setPointerToArgument2Function
+ add esp, 0x0C
+ mov ecx, esi
+ call SOULSTORM_sub_787020
+
+ //pop ebp
+ //pop esi
+ //retn 4
+ /*
+ mov fs : 0, ecx
+ add esp, 0x5C
+ */
+ pop edi
+ pop esi
+ pop ebp
+ //mov large fs : 0, ecx
+ pop ebx
+ //add esp, 0x50
+ //retn 4
+
+
+ }
+ /*
+ // setOverlayEnabledFunction function
+ __asm
+ {
+ mov ecx, [esi + 0x178]
+ call SOULSTORM_sub_776140
+ //mov ecx, esi
+ //call SOULSTORM_setOverlayEnabledFunction
+ retn 4
+ }
+ */
+ /*
+ // definitionEnterMetamapScreenFunction
+ __asm
+ {
+ push ebx
+ mov ebx, [esp - 0x0C]
+ push esi
+ push ebx
+ mov esi, ecx
+ call SOULSTORM_sub_787340
+
+ mov eax, [esp + 0x24 - 0x18]
+ push eax
+ mov ecx, esi
+ call SOULSTORM_NewCampaignGameStart
+ pop esi
+ pop ebx
+ retn 8
+ }
+ */
+ /*
+ // runMotionOnMetaMapMenuModel function
+ __asm
+ {
+ //sub esp, 0x50
+ //sub esp, 0x0C
+ push esi
+ mov esi, ecx
+ //mov ecx, esp
+ //sub esp, 0x0C
+ //mov [esp + 0x7C], esp
+ //lea eax, [esp + 0x7C]
+ lea edx, [esi + 0x50]
+ push edx
+ //lea eax, [esi + 0x40]
+ //push eax
+ //mov eax, [esp + 0x7C]
+ //push eax
+ push SOULSTORM_dieActionString_I
+ call SOULSTORM_findMotionByGivenName
+ mov ecx, [esi + 0x178]
+ //call SOULSTORM_runMotionOnMetaMapMenuModel
+ fld SOULSTORM_flt_C1F44C_I
+ //add esp, 0x0C
+ //mov eax, esp
+ //fstp dword ptr[esp + 8]
+ //mov[esp + 0x7C], esp
+ //push esi
+ //mov ecx, esi
+ //call SOULSTORM_sub_78EC00
+ //add esp, 0x4
+ pop esi
+ ret
+ }
+
+ /*
+ // bigger chunk of runAnimationOnMetaMapMenuModel function
+ __asm
+ {
+ push esi
+ sub esp, 0x0C
+ mov ecx, esp
+ mov [esp + 0x7C], esp
+ lea edx, [esp + 0x7C]
+ push edx
+ push SOULSTORM_dieActionString_I
+ call SOULSTORM_sub_66DE90
+ mov ecx, [esi + 0x178]
+ call SOULSTORM_runAnimationOnMetaMapMenuModel
+ fld SOULSTORM_flt_C1F44C_I
+ sub esp, 0x0C
+ mov eax, esp
+ fstp dword ptr[esp + 8]
+ mov [esp + 0x7C], esp
+ push esi
+ push SOULSTORM_sub_78EC00
+ push eax
+ call SOULSTORM_sub_78F540
+ add esp, 0x0C
+ mov ecx, esi
+ call SOULSTORM_sub_787020
+ mov [esi + 0x183], 1
+ mov ecx, SOULSTORM_off_C1F448_I
+ push 0
+ push ecx
+ call SOULSTORM_sub_75EC70
+ mov [esi + 0x182], 1
+ pop esi
+ ret 4
+ }
+ */
+}
+
+// NOT WORKING
+int __stdcall runActionOnModel(int)
+{
+ __asm
+ {
+ push ebx
+ push esi
+ push edi
+
+ mov esi, ecx
+ call SOULSTORM_sub_96EAA0
+ mov ecx, eax
+ call SOULSTORM_sub_96F440
+ mov ecx, [esi + 0x178]
+ test ecx, ecx
+ mov edi, [esp + 0x10]
+ mov ebx, eax
+ jz skip1
+ push 1
+ push edi
+ call SOULSTORM_runZoomAnimation
+skip1:
+ //add esp, 0x4
+ pop edi
+ pop esi
+ pop ebx
+ retn 4
+ }
+}
+
+// PARTIALLY WORKING
+// copy of function from definitionButtonInspectClicked button
+int __stdcall definitionButtonInspectClicked(int)
+{
+ __asm
+ {
+ push esi
+ mov esi, ecx
+ push SOULSTORM_String
+ lea eax, [esi + 0x50]
+ push SOULSTORM_a_root_sidebars
+ push eax
+ call USERINTERFACE_Invoke_SwfWidget_UI__QAAPBDPBD0ZZ
+ add esp, 0x10
+ /*
+ add esp, 4
+ mov ecx, esp
+ push esi
+ push SOULSTORM_loc_78E070
+ push ecx
+ call SOULSTORM_setPointerToArgument2Function
+ add esp, 0x0C
+
+ mov ecx, esi
+ call SOULSTORM_sub_787320
+ */
+ mov edx, [esi + 0x38]
+ push edx
+ mov ecx, esi
+ //call runActionOnModel
+ call SOULSTORM_openAnotherGFXFile
+ pop esi
+ retn 4
+ }
+}
+
+// WORKING
+// copy of function from ToggleArmy button
+int __stdcall definitionButtonToggleArmyClicked(int)
+{
+ __asm
+ {
+ push 1
+ push SOULSTORM_aD_I //"%d"
+ add ecx, 0x50 //'P'
+ push SOULSTORM_a_root_showst_0_I //"_root.ShowStatsArmy"
+ push ecx
+ call USERINTERFACE_Invoke_SwfWidget_UI__QAAPBDPBD0ZZ
+ add esp, 0x10
+ retn 4
+ }
+
+}
+
+int __stdcall prepareAction(int)
+{
+ __asm
+ {
+ //mov eax, [esp + 0x0C]
+ //push eax
+ mov esi, ecx
+ mov ecx, esi
+ call runAction
+ //sub esp, 0x4
+ }
+}
+
+int __declspec(naked) new_BindButtonClickedEntry_Function()
+{
+ // save address to return in the future
+ // save stack
+ __asm
+ {
+ pop return_address
+ //push SOULSTORM_aOnsidebarexite
+ //mov ecx, edi
+ //call ebx
+
+ //pushad
+ }
+
+ __asm
+ {
+ push esi
+ lea ecx, [esp + 0x24 - 0x10]
+ //lea edx, [esp + 0x24 - 0x10]
+ //push definitionButtonInspectClicked
+ //push SOULSTORM_definitionEnterMetamapScreenFunction
+ push runAction
+ //push prepareAction
+ //push edx
+ push ecx
+ call SOULSTORM_sub_78F520
+ //call SOULSTORM_sub_78F4C0
+ add esp, 0x0C
+ push eax
+ push SOULSTORM_aDeepStrike_I
+ mov ecx, edi
+ call ebx
+ //}
+
+ //restore stack
+ //restore overwritten code
+ __asm
+ //{
+ //popad
+ push esi
+ lea edx, [esp + 0x24 - 0x10]
+ // call SOULSTORM_sub_96EAA0
+/*
+ push esi
+ lea edx, [esp + 0x24 - 0x8]
+ push SOULSTORM_loc_78DBD0
+ push edx
+ call SOULSTORM_sub_78F520
+ add esp, 0x0C
+ push eax
+ push SOULSTORM_aOnsidebarexite
+ mov ecx, edi
+ call ebx
+*/
+ push return_address
+ ret
+ }
+}
+
+
+// funciton that disables stuff in load game screen
+int __declspec(naked) test_function()
+{
+ // save address to return in the future
+ // save stack
+ __asm
+ {
+ pop return_address
+ //pushad
+ }
+
+ __asm
+ {
+ jmp SOULSTORM_loc_6CC271
+
+ push return_address
+ ret
+ }
+}
+
+// funciton that disables stuff in load game screen
+int __declspec(naked) test_function2()
+{
+ // save address to return in the future
+ // save stack
+ __asm
+ {
+ pop return_address
+ //pushad
+ }
+
+ __asm
+ {
+ jmp SOULSTORM_loc_6CB20B
+
+ push return_address
+ ret
+ }
+}
\ No newline at end of file
diff --git a/UNI_EXT/SoulstormIntercepts.h b/UNI_EXT/SoulstormIntercepts.h
new file mode 100644
index 0000000..12375c7
--- /dev/null
+++ b/UNI_EXT/SoulstormIntercepts.h
@@ -0,0 +1,8 @@
+#pragma once
+int Metamap_Action_Selector_Function();
+
+int new_BindButtonClickedEntry_Function();
+
+int test_function();
+
+int test_function2();
\ No newline at end of file
diff --git a/UNI_EXT/SoulstormPointers.h b/UNI_EXT/SoulstormPointers.h
new file mode 100644
index 0000000..0b244d8
--- /dev/null
+++ b/UNI_EXT/SoulstormPointers.h
@@ -0,0 +1,118 @@
+// Based on slashdiablo-maphack implementation
+// https://github.com/planqi/slashdiablo-maphack
+
+#pragma once
+#include "SoulstormVersion.h"
+#include "Patch.h"
+
+#ifdef _DEFINE_PTRS
+#define FUNCPTR(dll, name, callingret, args, ...) \
+ static Offsets f##dll##_##name##_offsets = { __VA_ARGS__ }; \
+ __declspec(naked) callingret dll##_##name##args \
+ { \
+ static DWORD f##dll##_##name = NULL; \
+ if(f##dll##_##name == NULL) \
+ { \
+ __asm { pushad } \
+ f##dll##_##name = Patch::GetDllOffset(dll, *(&f##dll##_##name##_offsets._steam + SoulstormVersion::GetGameVersionID())); \
+ __asm { popad } \
+ } \
+ __asm jmp [f##dll##_##name] \
+ }
+
+#define ASMPTR(dll, name, ...) \
+ DWORD* Asm_##dll##_##name##(VOID) \
+ { \
+ static DWORD f##Asm_##dll##_##name = NULL; \
+ if(f##Asm_##dll##_##name## == NULL) \
+ { \
+ static Offsets f##Asm_##_##name##_offsets = { __VA_ARGS__ }; \
+ static int address = *(&f##Asm_##_##name##_offsets._steam + SoulstormVersion::GetGameVersionID()); \
+ f##Asm_##dll##_##name## = Patch::GetDllOffset(dll, address); \
+ } \
+ return #f##Asm_##dll##_##name; \
+ }
+
+#define VARPTR(dll, name, type, ...) \
+ type** Var_##dll##_##name##(VOID) \
+ { \
+ static DWORD f##Var_##dll##_##name = NULL; \
+ if(f##Var_##dll##_##name## == NULL) \
+ { \
+ static Offsets f##Var_##_##name##_offsets = { __VA_ARGS__ }; \
+ static int address = *(&f##Var_##_##name##_offsets._steam + SoulstormVersion::GetGameVersionID()); \
+ f##Var_##dll##_##name## = Patch::GetDllOffset(dll, address); \
+ } \
+ return (type**)#f##Var_##dll##_##name; \
+ }
+
+#else
+#define FUNCPTR(dll, name, callingret, args, ...) extern callingret dll##_##name##args;
+#define ASMPTR(dll, name, ...) extern DWORD* Asm_##dll##_##name##(VOID); static DWORD dll##_##name = *Asm_##dll##_##name##();
+#define VARPTR(dll, name, type, ...) extern type** Var_##dll##_##name##(VOID); static type* p##_##dll##_##name = (type*)*Var_##dll##_##name##();
+#endif
+
+//offsets are in format _steam, _cd
+
+//for function new_BindButtonClickedEntry_Function
+FUNCPTR(SOULSTORM, sub_78F520, int* __stdcall, (int, int, int), 0x38F520, -1)
+
+ASMPTR(SOULSTORM, buttonToggleArmyClicked_I, 0x38DB80, -1)
+ASMPTR(SOULSTORM, aToggleArmy_I, 0x6D4058, -1)
+ASMPTR(SOULSTORM, aDeepStrike_I, 0x6D4020, -1)
+
+//for function definitionButtonToggleArmyClicked
+FUNCPTR(USERINTERFACE, Invoke_SwfWidget_UI__QAAPBDPBD0ZZ, char const* __cdecl, (char const*, char const*, ...), 0x4CEB0, -1)
+
+ASMPTR(SOULSTORM, aD_I, 0x7455BC, -1)
+ASMPTR(SOULSTORM, a_root_showst_0_I, 0x6D3AA4, -1)
+
+//for function runAction
+FUNCPTR(SOULSTORM, findMotionByGivenName, int __stdcall, (int, int), 0x26DE90, -1)
+FUNCPTR(SOULSTORM, runMotionOnMetaMapMenuModel, int __stdcall, (int, int, int), 0x377BD0, -1)
+FUNCPTR(SOULSTORM, sub_78F540, int __stdcall, (int, int, int), 0x38F540, -1)
+FUNCPTR(SOULSTORM, sub_787020, int __stdcall, (int, int, int), 0x387020, -1)
+FUNCPTR(SOULSTORM, sub_75EC70, int __stdcall, (int, int, int), 0x35EC70, -1)
+
+ASMPTR(SOULSTORM, dieActionString_I, 0x6D3A84, -1)
+ASMPTR(SOULSTORM, flt_C1F44C_I, 0x81F44C, -1)
+ASMPTR(SOULSTORM, sub_78EC00, 0x38EC00, -1)
+ASMPTR(SOULSTORM, off_C1F448_I, 0x81F448, -1)
+
+// run standard metamap action
+FUNCPTR(SOULSTORM, sub_776140, int __stdcall, (void), 0x376140, -1)
+FUNCPTR(SOULSTORM, setOverlayEnabledFunction, int __stdcall, (void), 0x38EC00, -1)
+
+// definition for definitionEnterMetamapScreenFunction?
+FUNCPTR(SOULSTORM, definitionEnterMetamapScreenFunction, int __stdcall, (int, int), 0x391990, -1)
+FUNCPTR(SOULSTORM, sub_78F4C0, int __stdcall, (int, int, int), 0x38F4C0, -1)
+
+// definition for definitionButtonEndTurnClicked function
+FUNCPTR(SOULSTORM, setPointerToArgument2Function, int __cdecl, (int, int, int), 0x38F540, -1)
+FUNCPTR(SOULSTORM, sub_787320, int __stdcall, (int, int), 0x387320, -1)
+FUNCPTR(SOULSTORM, openAnotherGFXFile, int __stdcall, (int), 0x38EC70, -1)
+FUNCPTR(SOULSTORM, runZoomAnimation, int __stdcall, (int, int), 0x378080, -1)
+FUNCPTR(SOULSTORM, sub_96EAA0, int, (void), 0x56EAA0, -1)
+FUNCPTR(SOULSTORM, sub_96F440, int, (void), 0x56F440, -1)
+FUNCPTR(SOULSTORM, NewCampaignGameStart, int __stdcall, (int), 0x3912E0, -1)
+FUNCPTR(SOULSTORM, sub_787340, int __stdcall, (int), 0x387340, -1)
+FUNCPTR(SOULSTORM, toggleOverlayFunction, int __stdcall, (char, char), 0x3761C0, -1)
+
+ASMPTR(SOULSTORM, String, 0x70DB8B, -1)
+ASMPTR(SOULSTORM, a_root_sidebarh, 0x6D3174, -1)
+ASMPTR(SOULSTORM, loc_78E070, 0x38E070, -1)
+ASMPTR(SOULSTORM, FrameHandler3Jump, 0x668D1C, -1)
+ASMPTR(SOULSTORM, flt_C1F44C, 0x81F44C, -1)
+
+ASMPTR(SOULSTORM, a_root_sidebars, 0x6D3188, -1)
+
+ASMPTR(SOULSTORM, loc_6CC271, 0x2CC271, -1)
+ASMPTR(SOULSTORM, loc_6CB20B, 0x2CB20B, -1)
+
+FUNCPTR(SOULSTORM, loc_78DBD0, int __stdcall, (int), 0x38DBD0, -1)
+
+ASMPTR(SOULSTORM, aOnsidebarexite, 0x6D33B4, -1)
+
+#undef FUNCPTR
+#undef ASMPTR
+#undef VARPTR
diff --git a/UNI_EXT/SoulstormVersion.cpp b/UNI_EXT/SoulstormVersion.cpp
new file mode 100644
index 0000000..24f3148
--- /dev/null
+++ b/UNI_EXT/SoulstormVersion.cpp
@@ -0,0 +1,95 @@
+// Based on slashdiablo-maphack implementation
+// https://github.com/planqi/slashdiablo-maphack
+
+#include "SoulstormVersion.h"
+#include
+
+#pragma comment(lib,"Version.lib")
+
+VersionID SoulstormVersion::versionID = INVALID;
+
+void SoulstormVersion::Init() {
+ std::string version = GetGameVersionString();
+
+ if (version == "1.3.310.7442") {
+ versionID = VERSION_STEAM;
+ }
+ else if (version == "1.4.0.0") {
+ versionID = VERSION_CD;
+ }
+ else {
+ versionID = INVALID;
+ MessageBox(NULL, L"Game version not detected or is unsupported!", L"Failed to Detect Game Version", MB_OK);
+ exit(0);
+ }
+}
+
+VersionID SoulstormVersion::GetGameVersionID() {
+ if (versionID == INVALID) {
+ Init();
+ }
+ return versionID;
+}
+
+// Taken from StackOverflow user crashmstr
+std::string SoulstormVersion::GetGameVersionString() {
+ LPCWSTR szVersionFile = L"Soulstorm.exe";
+ DWORD verHandle = 0;
+ UINT size = 0;
+ LPBYTE lpBuffer = NULL;
+ DWORD verSize = GetFileVersionInfoSize(szVersionFile, &verHandle);
+
+ std::string returnValue;
+
+ if (verSize != NULL)
+ {
+ LPSTR verData = new char[verSize];
+
+ if (GetFileVersionInfo(szVersionFile, verHandle, verSize, verData))
+ {
+ if (VerQueryValue(verData, L"\\", (VOID FAR* FAR*)&lpBuffer, &size))
+ {
+ if (size)
+ {
+ VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer;
+ if (verInfo->dwSignature == 0xfeef04bd)
+ {
+ char szBuffer[MAX_PATH];
+ // Doesn't matter if you are on 32 bit or 64 bit,
+ // DWORD is always 32 bits, so first two revision numbers
+ // come from dwFileVersionMS, last two come from dwFileVersionLS
+ sprintf_s(szBuffer, "%d.%d.%d.%d",
+ (verInfo->dwFileVersionMS >> 16) & 0xffff,
+ (verInfo->dwFileVersionMS >> 0) & 0xffff,
+ (verInfo->dwFileVersionLS >> 16) & 0xffff,
+ (verInfo->dwFileVersionLS >> 0) & 0xffff
+ );
+
+ returnValue = std::string(szBuffer);
+ //std::string message = returnValue + "\n";
+ //MessageBoxA(NULL, message.c_str(), "DLL Injected", MB_OK);
+ }
+ }
+ }
+ }
+ delete[] verData;
+ }
+ return returnValue;
+}
+
+std::string SoulstormVersion::GetHumanReadableVersion() {
+ std::string returnValue;
+
+ switch (GetGameVersionID()) {
+ case VERSION_STEAM:
+ returnValue = "steam";
+ break;
+// case VERSION_113d:
+// returnValue = "1.13d";
+// break;
+ default:
+ returnValue = "unknown";
+ }
+
+ return returnValue;
+}
\ No newline at end of file
diff --git a/UNI_EXT/SoulstormVersion.h b/UNI_EXT/SoulstormVersion.h
new file mode 100644
index 0000000..dd2d7bf
--- /dev/null
+++ b/UNI_EXT/SoulstormVersion.h
@@ -0,0 +1,25 @@
+// Based on slashdiablo-maphack implementation
+// https://github.com/planqi/slashdiablo-maphack
+
+#pragma once
+
+#ifndef _SOULSTORMVERSION_H
+#define _SOULSTORMVERSION_H
+
+#include
+
+enum VersionID {
+ INVALID = -1,
+ VERSION_STEAM = 0,
+ VERSION_CD
+};
+
+namespace SoulstormVersion {
+ extern VersionID versionID;
+ VersionID GetGameVersionID();
+ void Init();
+ std::string GetGameVersionString();
+ std::string GetHumanReadableVersion();
+};
+
+#endif
\ No newline at end of file
diff --git a/UNI_EXT/UNI_EXT.cpp b/UNI_EXT/UNI_EXT.cpp
new file mode 100644
index 0000000..cc86b85
--- /dev/null
+++ b/UNI_EXT/UNI_EXT.cpp
@@ -0,0 +1,92 @@
+// UNI_EXT.cpp : Defines the exported functions for the DLL application.
+// Based on slashdiablo-maphack implementation
+// https://github.com/planqi/slashdiablo-maphack
+
+#define _DEFINE_PTRS
+#include "stdafx.h"
+#include "SoulstormPointers.h"
+#include "UNI_EXT.h"
+#include "Patch.h"
+#include "SoulstormIntercepts.h"
+
+string UNI_EXT::path;
+HINSTANCE UNI_EXT::instance;
+
+Patch* patches[] = {
+
+//*** FINISHED PATCHES ***
+
+ // increase maximum number of defeated races in campaign commander screen
+ new Patch(Overwrite, SOULSTORM, { 0x81F350, 0x6BDD24 }, { 0x0A, 0x00, 0x00, 0x00 }, 4),
+
+ // increase maximum number of honor guard units in campaign metamap screen
+ new Patch(Overwrite, SOULSTORM,{ 0x81F454, 0x6BDE28 },{ 0x12, 0x00, 0x00, 0x00 }, 4),
+
+ // increase maximum number of honor guard units in campaign commander screen
+ new Patch(Overwrite, SOULSTORM,{ 0x81F348, 0x6BDD1C },{ 0x12, 0x00, 0x00, 0x00 }, 4),
+
+ // fog remover coded in UNI_EXT.dll
+ /*
+ new Patch(Overwrite, SOULSTORM,{ 0x4282F0, -1 },{ 217, 238, 15, 31, 64, 0 }, 6),
+ new Patch(Overwrite, SOULSTORM,{ 0x6F54C8, -1 },{ 0, 0, 0, 68 }, 4),
+ new Patch(Overwrite, SOULSTORM,{ 0x42A33A, -1 },{ 221, 216, 15, 31, 64, 0 }, 6),
+ */
+ //*** END OF FINISHED PATCHES
+
+ // modify SWFwidget bind from 'ToggleArmy' to 'deep_strike'
+ //new Patch(Overwrite, SOULSTORM,{ 0x391C4E, -1 },{ 0x20, 0x40, 0xAD, 0x00
+
+ // insert new FSCommand
+ // Runs "die" action on metamap_main_menu model
+ //new Patch(Call, SOULSTORM,{ 0x391C79, -1 }, (int)new_BindButtonClickedEntry_Function, 29),
+ //new Patch(Call, SOULSTORM,{ 0x391C8D, -1 }, (int)new_BindButtonClickedEntry_Function, 5),
+ new Patch(Call, SOULSTORM,{ 0x391C39, -1 }, (int)new_BindButtonClickedEntry_Function, 5),
+ //new Patch(Call, SOULSTORM,{ 0x391C96, -1 }, (int)new_BindButtonClickedEntry_Function, 5),
+
+ //
+ //new Patch(Overwrite, WXPMOD,{ 0x241E18, -1 },{ 0xC6, 0x45, 0xFC, 0x25 }, 4),
+ //new Patch(Overwrite, WXPMOD,{ 0x241C65, -1 },{ 0xC6, 0x45, 0xFC, 0x25 }, 4),
+ //new Patch(Overwrite, WXPMOD,{ 0x24137C, -1 },{ 0xC1, 0xE8, 0x25 }, 3),
+
+ // disable stuff in load game screen
+ //new Patch(Call, SOULSTORM,{ 0x2CC067, -1 }, (int)test_function, 5),
+
+ // disable stuff in critical location function
+ //new Patch(Call, SOULSTORM,{ 0x2CB1D2, -1 }, (int)test_function2, 5),
+
+ //new Patch(Overwrite, SOULSTORM,{ 0x241E18, -1 },{ 0x0F, 0x84, 0x74, 0x01, 0x00, 0x00 }, 6),
+ // enable action 'die' in 'metamap.gfx' every time it's loaded
+ //new Patch(Overwrite, SOULSTORM,{ 0x3913C6, -1 },{ 0x90, 0x90 }, 2),
+ //new Patch(Overwrite, SOULSTORM,{ 0x3919A0, -1 },{ 0x90, 0x90 }, 2),
+
+ // modify campaign model starting action from 'die' to 'idle'
+ //new Patch(Overwrite, SOULSTORM,{ 0x3913D7, -1 },{ 0x74, 0xBD, 0xB3, 0x00 }, 4),
+
+ // create new strings in code
+ //new Patch(Overwrite, SOULSTORM,{ 0x6D2447, -1 },{ 0x00, 't','h','r','o','w','n' }, 7),
+ // modify runZoomAnimation? function to use new string
+ //new Patch(Overwrite, SOULSTORM,{ 0x378108, -1 },{ 0x48, 0x24 }, 2),
+
+ //new Patch(Overwrite, SOULSTORM,{ 0x39C590, -1 }, (int)Metamap_Action_Selector_Function, 2),
+ //new Patch(Call, SOULSTORM,{ 0x378104, -1 }, (int)Animation_Selector_Function, 5),
+};
+
+
+void UNI_EXT::Startup(HINSTANCE instance)
+{
+ // code that rewrites variable in program memory
+ // increased defeated races number
+
+ for (int n = 0; n < (sizeof(patches) / sizeof(Patch*)); n++) {
+ patches[n]->Install();
+ }
+
+// MessageBoxA(NULL, "DLL Injected", "DLL Injected", MB_OK);
+// CreateThread(0, 0, MainThread, instance, 0, 0);
+
+}
+
+bool UNI_EXT::Shutdown()
+{
+ return true;
+}
\ No newline at end of file
diff --git a/UNI_EXT/UNI_EXT.h b/UNI_EXT/UNI_EXT.h
new file mode 100644
index 0000000..4c0fe9e
--- /dev/null
+++ b/UNI_EXT/UNI_EXT.h
@@ -0,0 +1,16 @@
+// Based on slashdiablo-maphack implementation
+// https://github.com/planqi/slashdiablo-maphack
+
+#pragma once
+#include "stdafx.h"
+#include
+using namespace std;
+
+namespace UNI_EXT {
+ extern string path;
+ extern HINSTANCE instance;
+
+ extern void Startup(HINSTANCE instance);
+
+ extern bool Shutdown();
+}
diff --git a/UNI_EXT/UNI_EXT.vcxproj b/UNI_EXT/UNI_EXT.vcxproj
new file mode 100644
index 0000000..7f54678
--- /dev/null
+++ b/UNI_EXT/UNI_EXT.vcxproj
@@ -0,0 +1,190 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {67138EE0-0823-4524-9453-4E9892296669}
+ Win32Proj
+ UNI_EXT
+ 8.1
+
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v140
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)\DoW Mod Manager\bin\Debug
+
+
+ true
+
+
+ false
+ $(SolutionDir)\DoW Mod Manager\bin\Release
+
+
+ false
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;UNI_EXT_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ /WHOLEARCHIVE %(AdditionalOptions)
+
+
+
+
+
+
+ Level3
+ Disabled
+ _DEBUG;_WINDOWS;_USRDLL;UNI_EXT_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;UNI_EXT_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+ %(AdditionalDependencies)
+
+
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ NDEBUG;_WINDOWS;_USRDLL;UNI_EXT_EXPORTS;%(PreprocessorDefinitions)
+ true
+
+
+ Windows
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/UNI_EXT/UNI_EXT.vcxproj.filters b/UNI_EXT/UNI_EXT.vcxproj.filters
new file mode 100644
index 0000000..d71cdb7
--- /dev/null
+++ b/UNI_EXT/UNI_EXT.vcxproj.filters
@@ -0,0 +1,63 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/UNI_EXT/dllmain.cpp b/UNI_EXT/dllmain.cpp
new file mode 100644
index 0000000..db7f654
--- /dev/null
+++ b/UNI_EXT/dllmain.cpp
@@ -0,0 +1,22 @@
+// dllmain.cpp : Defines the entry point for the DLL application.
+#include "stdafx.h"
+#include "UNI_EXT.h"
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ UNI_EXT::Startup(hModule);
+ break;
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ UNI_EXT::Shutdown();
+ break;
+ }
+ return TRUE;
+}
diff --git a/UNI_EXT/stdafx.cpp b/UNI_EXT/stdafx.cpp
new file mode 100644
index 0000000..30b2865
--- /dev/null
+++ b/UNI_EXT/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// UNI_EXT.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/UNI_EXT/stdafx.h b/UNI_EXT/stdafx.h
new file mode 100644
index 0000000..f3a0737
--- /dev/null
+++ b/UNI_EXT/stdafx.h
@@ -0,0 +1,16 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include
+
+
+
+// TODO: reference additional headers your program requires here
diff --git a/UNI_EXT/targetver.h b/UNI_EXT/targetver.h
new file mode 100644
index 0000000..87c0086
--- /dev/null
+++ b/UNI_EXT/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include