diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.github/README.md b/.github/README.md
new file mode 100644
index 0000000..fd1860e
--- /dev/null
+++ b/.github/README.md
@@ -0,0 +1,17 @@
+# Windows-Game-Patches
+
+[![MSBuild](https://github.com/illusion0001/Windows-Game-Patches/actions/workflows/msbuild.yml/badge.svg?branch=main)](https://github.com/illusion0001/Windows-Game-Patches/actions/workflows/msbuild.yml)
+
+[Latest Release](/../../../../illusion0001/Windows-Game-Patches/releases/latest)
+
+# Patches
+
+- **Bright Memory: Infinite**
+ - Disable TAA
+ - Disable Sharpness
+
+# Credits
+- [Lyall](https://github.com/Lyall) for Project Template.
+- [Ultimate ASI Loader](https://github.com/ThirteenAG/Ultimate-ASI-Loader) for ASI loading.
+- [inipp](https://github.com/mcmtroffaes/inipp) for ini reading.
+- [length-disassembler](https://github.com/Nomade040/length-disassembler) for length disassembly.
diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml
new file mode 100644
index 0000000..baff2a0
--- /dev/null
+++ b/.github/workflows/msbuild.yml
@@ -0,0 +1,102 @@
+name: MSBuild
+
+on:
+ push:
+ paths-ignore:
+ - "**/*.md"
+ - '**/*.txt'
+ pull_request:
+ paths-ignore:
+ - "**/*.md"
+ - '**/*.txt'
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.ref && github.event_name }}
+ cancel-in-progress: true
+
+env:
+ SOLUTION_FILE_PATH: .\Windows-Game-Patches.sln
+ BUILD_CONFIGURATION: Release
+
+permissions:
+ contents: write
+
+jobs:
+ build:
+ runs-on: windows-latest
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v3
+ with:
+ submodules: recursive
+ fetch-depth: 0
+
+ - name: Add MSBuild to PATH
+ uses: microsoft/setup-msbuild@main
+
+ - name: Setup environment variables
+ run: |
+ $cmdOutput = Split-Path -Path $pwd -Leaf
+ echo "project_name=$cmdOutput" >> $Env:GITHUB_ENV
+ echo "commit_ver=1.0.$(git rev-list HEAD --count)" >> $Env:GITHUB_ENV
+
+ - name: Build
+ run: |
+ msbuild /m /p:Configuration=${{ env.BUILD_CONFIGURATION }} /p:Platform=x64 ${{ env.SOLUTION_FILE_PATH }}
+ echo "zip_name=${{ env.project_name }}-${{ env.commit_ver }}" >> $Env:GITHUB_ENV
+
+ - name: Generate Filehash
+ run: |
+ $AlgorithmType = "SHA512"
+ $folderPath = ".\${{ env.BUILD_CONFIGURATION }}\"
+ $files = Get-ChildItem "$folderPath" -Filter "*.asi"
+ foreach ($file in $files) {
+ $hash = Get-FileHash -Algorithm $AlgorithmType -Path $file.FullName | Format-List
+ $hash | Out-File -Encoding utf8 -FilePath "$folderPath\$($file.BaseName).$AlgorithmType"
+ $hash | Out-File -Append -Encoding utf8 -FilePath "$folderPath\AllHash.$AlgorithmType"
+ echo $hash
+ }
+
+ curl -fLOS https://github.com/ThirteenAG/Ultimate-ASI-Loader/releases/download/x64-latest/version.zip
+ Expand-Archive -Path version.zip -DestinationPath ".\${{ env.BUILD_CONFIGURATION }}\"
+ $hash = Get-FileHash -Algorithm $AlgorithmType -Path ".\${{ env.BUILD_CONFIGURATION }}\version.dll" | Format-List
+ $hash | Out-File -Encoding utf8 -FilePath ".\${{ env.BUILD_CONFIGURATION }}\version.$AlgorithmType"
+ $hash | Out-File -Append -Encoding utf8 -FilePath ".\${{ env.BUILD_CONFIGURATION }}\AllHash.$AlgorithmType"
+ echo $hash
+ $compress = @{
+ Path = ".\${{ env.BUILD_CONFIGURATION }}\*.asi", ".\${{ env.BUILD_CONFIGURATION }}\*.dll", ".\${{ env.BUILD_CONFIGURATION }}\*.$AlgorithmType"
+ CompressionLevel = "NoCompression"
+ DestinationPath = ".\${{ env.zip_name }}.zip"
+ }
+ Compress-Archive @compress
+
+ $hashMarkdown = @'
+
+ Plugin Hashes (Click to Expand)
+
+ ```yaml
+ {0}
+ ```
+
+
+ '@ -f (Get-Content "$folderPath\AllHash.$AlgorithmType" | Out-String)
+ $hashMarkdown | Out-File -Encoding utf8 -FilePath hash.md
+ Get-Content hash.md
+
+ - name: Upload Artifact
+ uses: actions/upload-artifact@v3
+ with:
+ name: ${{ env.zip_name }}
+ path: |
+ ${{ env.BUILD_CONFIGURATION }}/*.asi
+ ${{ env.BUILD_CONFIGURATION }}/*.SHA512
+
+ - name: Create Release
+ if: |
+ github.event_name == 'workflow_dispatch' &&
+ github.repository == 'illusion0001/Windows-Game-Patches'
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: gh release create ${{ env.commit_ver }} ${{ env.ZIP_NAME }}.zip --target ${{ GITHUB.SHA }} -t "${{ env.commit_ver }}" -F hash.md
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8182614
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,37 @@
+# Prerequisites
+*.d
+
+# Compiled Object files
+*.slo
+*.lo
+*.o
+*.obj
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Compiled Dynamic libraries
+*.so
+*.dylib
+*.dll
+
+# Fortran module files
+*.mod
+*.smod
+
+# Compiled Static libraries
+*.lai
+*.la
+*.a
+*.lib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# Visual Studio
+/**/.vs
+/**/Debug
+/**/Release
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..81d05ae
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "external/inipp"]
+ path = external/inipp
+ url = https://github.com/mcmtroffaes/inipp.git
+[submodule "external/length-disassembler"]
+ path = external/length-disassembler
+ url = https://github.com/Nomade040/length-disassembler.git
diff --git a/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.sln b/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.sln
new file mode 100644
index 0000000..132ef01
--- /dev/null
+++ b/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33424.131
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BrightMemoryInfinite.NoTAA", "BrightMemoryInfinite.NoTAA.vcxproj", "{AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Debug|x64.ActiveCfg = Debug|x64
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Debug|x64.Build.0 = Debug|x64
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Debug|x86.ActiveCfg = Debug|Win32
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Debug|x86.Build.0 = Debug|Win32
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Release|x64.ActiveCfg = Release|x64
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Release|x64.Build.0 = Release|x64
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Release|x86.ActiveCfg = Release|Win32
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {CDD207AD-54BC-44A9-933A-5DFEDBD97F44}
+ EndGlobalSection
+EndGlobal
diff --git a/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj b/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj
new file mode 100644
index 0000000..eb84aff
--- /dev/null
+++ b/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj
@@ -0,0 +1,179 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {ab7a871d-2a06-48c6-863f-b8a0fe8f8e0b}
+ BrightMemoryInfiniteNoTAA
+ 10.0.22000.0
+
+
+
+ DynamicLibrary
+ true
+ ClangCL
+ Unicode
+
+
+ DynamicLibrary
+ false
+ ClangCL
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ ClangCL
+ Unicode
+
+
+ DynamicLibrary
+ false
+ ClangCL
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \..\include\;$(IncludePath)
+ .asi
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+
+
+ \..\include\;$(IncludePath)
+ .asi
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+
+
+ .asi
+
+
+ .asi
+
+
+
+ Level3
+ true
+ UNICODE;_CRT_SECURE_NO_WARNINGS;_USRDLL
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ UNICODE;_CRT_SECURE_NO_WARNINGS;_USRDLL
+ true
+ Use
+ pch.h
+
+
+ Windows
+ true
+ true
+ true
+ false
+
+
+
+
+ Level3
+ true
+ UNICODE;_CRT_SECURE_NO_WARNINGS;_USRDLL
+ true
+ NotUsing
+ pch.h
+ ..\include\;..\external\;%(AdditionalIncludeDirectories)
+ Default
+
+
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ UNICODE;_CRT_SECURE_NO_WARNINGS;_USRDLL
+ true
+ NotUsing
+ pch.h
+ ..\include\;..\external\;%(AdditionalIncludeDirectories)
+ Default
+
+
+
+
+ Windows
+ true
+ true
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj.filters b/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj.filters
new file mode 100644
index 0000000..4222594
--- /dev/null
+++ b/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj.filters
@@ -0,0 +1,32 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj.user b/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/BrightMemoryInfinite.NoTAA/BrightMemoryInfinite.NoTAA.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/BrightMemoryInfinite.NoTAA/dllmain.cpp b/BrightMemoryInfinite.NoTAA/dllmain.cpp
new file mode 100644
index 0000000..3880ded
--- /dev/null
+++ b/BrightMemoryInfinite.NoTAA/dllmain.cpp
@@ -0,0 +1,161 @@
+#include "stdafx.h"
+#include "helper.hpp"
+
+using namespace std;
+
+HMODULE baseModule = GetModuleHandle(NULL);
+
+#define GAME_NAME "BrightMemoryInfinite"
+#define xstr(s) str(s)
+#define str(s) #s
+
+inipp::Ini ini;
+FILE* fp_log;
+time_t sec;
+
+#define LOG(fmt,...) \
+{ \
+ time(&sec); \
+ fprintf(fp_log, "%s: %.24s " fmt "\n", __FUNCTION__, ctime(&sec), __VA_ARGS__); \
+}
+
+// INI Variables
+bool bDisableTAA;
+bool bDisableSharpness;
+
+void LoggingInit(void)
+{
+ const char* log_path = GAME_NAME ".log";
+ time(&sec);
+ fp_log = fopen(log_path, "w");
+ if (fp_log != NULL)
+ {
+ LOG("Log file opened at %s", log_path);
+ }
+ else
+ {
+ MessageBox(0, L"Failed to open log file.", (wchar_t*)GAME_NAME, MB_ICONWARNING);
+ }
+}
+
+void ReadConfig(void)
+{
+ string sExePath;
+ string sExeName;
+ string sGameName;
+ // Get game name and exe path
+ LPWSTR exePath = new WCHAR[_MAX_PATH];
+ GetModuleFileNameW(baseModule, exePath, _MAX_PATH);
+ wstring exePathWString(exePath);
+ sExePath = string(exePathWString.begin(), exePathWString.end());
+ wstring wsGameName = Memory::GetVersionProductName();
+ sExeName = sExePath.substr(sExePath.find_last_of("/\\") + 1);
+ sGameName = string(wsGameName.begin(), wsGameName.end());
+
+ LOG("Game Name: %s", sGameName.c_str());
+ LOG("Game Path: %s", sExePath.c_str());
+
+ // Initialize config
+ // UE4 games use launchers so config path is relative to launcher
+ std::string config_path = GAME_NAME ".ini";
+ std::ifstream iniFile(config_path);
+ if (!iniFile)
+ {
+ // no ini, lets generate one.
+ LOG("Failed to load config file.");
+ string ini_defaults = "[Settings]\n"
+ str(bDisableTAA)" = true\n"
+ str(bDisableSharpness)" = true\n";
+ std::ofstream iniFile(config_path);
+ iniFile << ini_defaults;
+ bDisableTAA = true;
+ bDisableSharpness = true;
+ LOG("Created default config file.");
+ }
+ else
+ {
+ ini.parse(iniFile);
+ inipp::get_value(ini.sections["Settings"], str(bDisableTAA), bDisableTAA);
+ inipp::get_value(ini.sections["Settings"], str(bDisableSharpness), bDisableSharpness);
+ }
+
+ // Log config parse
+ LOG("%s: %s (%i)", str(bDisableTAA), bDisableTAA ? "true" : "false", bDisableTAA);
+ LOG("%s: %s (%i)", str(bDisableSharpness), bDisableSharpness ? "true" : "false", bDisableSharpness);
+}
+
+void ShowPatchInfo(uint32_t Patch_Length, size_t Patch_Size, uint64_t Patch_Addr, const char* Patch_Name)
+{
+ LOG("Patch Name: %s", Patch_Name);
+ LOG("Hook length: %u bytes", Patch_Length);
+ LOG("Patch length: %llu bytes", Patch_Size);
+ LOG("Hook address: 0x%016llx", Patch_Addr);
+}
+
+void DisableTAA(void)
+{
+ uint8_t* DisableTAAResult = Memory::PatternScan(baseModule, "8B 04 8E 83 F8 ?? 77 ?? 89 83 ?? ?? ?? ??");
+ if (DisableTAAResult)
+ {
+ const char xor_eax_eax[] = { '\x31', '\xc0', '\x90' };
+ uint64_t DisableTAAAddress = ((uintptr_t)DisableTAAResult);
+ uint32_t DisableTAALength = Memory::GetHookLength((char*)DisableTAAAddress, 14);
+ Memory::PatchBytes((uintptr_t)DisableTAAAddress, xor_eax_eax, sizeof(xor_eax_eax));
+ ShowPatchInfo(DisableTAALength, sizeof(xor_eax_eax), (uintptr_t)DisableTAAAddress, str(bDisableTAA));
+ }
+ else
+ {
+ LOG("Pattern scan failed.");
+ }
+}
+
+void DisableSharpness(void)
+{
+ uint8_t* DisableSharpnessResult = Memory::PatternScan(baseModule, "F3 44 0F 10 40 04 44 0F 2F C6 73 ?? 45 0F 57 C0 EB ??");
+ if (DisableSharpnessResult)
+ {
+ const char xor_xmm8[] = { '\x45', '\x0F', '\x57', '\xC0', '\x90', '\x90' };
+ uint64_t DisableSharpnessAddress = ((uintptr_t)DisableSharpnessResult);
+ uint32_t DisableSharpnessLength = Memory::GetHookLength((char*)DisableSharpnessAddress, 18);
+ Memory::PatchBytes((uintptr_t)DisableSharpnessAddress, xor_xmm8, sizeof(xor_xmm8));
+ ShowPatchInfo(DisableSharpnessLength, sizeof(xor_xmm8), (uintptr_t)DisableSharpnessAddress, str(bDisableSharpness));
+ }
+ else
+ {
+ LOG("Pattern scan failed.");
+ }
+}
+
+DWORD __stdcall Main(void*)
+{
+ bDisableTAA = false;
+ bDisableSharpness = false;
+ LoggingInit();
+ ReadConfig();
+ if (bDisableTAA)
+ DisableTAA();
+ if (bDisableSharpness)
+ DisableSharpness();
+ LOG("Shutting down " str(fp_log) " file handle.");
+ fclose(fp_log);
+ return true;
+}
+
+BOOL APIENTRY DllMain( HMODULE hModule,
+ DWORD ul_reason_for_call,
+ LPVOID lpReserved
+ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ {
+ CreateThread(NULL, 0, Main, 0, NULL, 0);
+ }
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
diff --git a/BrightMemoryInfinite.NoTAA/stdafx.cpp b/BrightMemoryInfinite.NoTAA/stdafx.cpp
new file mode 100644
index 0000000..fd4f341
--- /dev/null
+++ b/BrightMemoryInfinite.NoTAA/stdafx.cpp
@@ -0,0 +1 @@
+#include "stdafx.h"
diff --git a/Windows-Game-Patches.sln b/Windows-Game-Patches.sln
new file mode 100644
index 0000000..79c4e63
--- /dev/null
+++ b/Windows-Game-Patches.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.5.33424.131
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BrightMemoryInfinite.NoTAA", "BrightMemoryInfinite.NoTAA\BrightMemoryInfinite.NoTAA.vcxproj", "{AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Debug|x86 = Debug|x86
+ Release|x64 = Release|x64
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Debug|x64.ActiveCfg = Debug|x64
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Debug|x64.Build.0 = Debug|x64
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Debug|x86.ActiveCfg = Debug|Win32
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Debug|x86.Build.0 = Debug|Win32
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Release|x64.ActiveCfg = Release|x64
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Release|x64.Build.0 = Release|x64
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Release|x86.ActiveCfg = Release|Win32
+ {AB7A871D-2A06-48C6-863F-B8A0FE8F8E0B}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {B182B24E-F786-4017-940D-5B814AFEE867}
+ EndGlobalSection
+EndGlobal
diff --git a/Windows-Game-Patches.vcxproj b/Windows-Game-Patches.vcxproj
new file mode 100644
index 0000000..f52028a
--- /dev/null
+++ b/Windows-Game-Patches.vcxproj
@@ -0,0 +1,134 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {42d74197-0533-448e-ba7a-e60ab40a2e81}
+ WindowsGamePatches
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Windows-Game-Patches.vcxproj.filters b/Windows-Game-Patches.vcxproj.filters
new file mode 100644
index 0000000..a8a6563
--- /dev/null
+++ b/Windows-Game-Patches.vcxproj.filters
@@ -0,0 +1,17 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;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
+
+
+
\ No newline at end of file
diff --git a/Windows-Game-Patches.vcxproj.user b/Windows-Game-Patches.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/Windows-Game-Patches.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/external/inipp b/external/inipp
new file mode 160000
index 0000000..c61e699
--- /dev/null
+++ b/external/inipp
@@ -0,0 +1 @@
+Subproject commit c61e699682d3f1091209c2179f1d03f5fc593327
diff --git a/external/length-disassembler b/external/length-disassembler
new file mode 160000
index 0000000..e8b3454
--- /dev/null
+++ b/external/length-disassembler
@@ -0,0 +1 @@
+Subproject commit e8b3454604a09779f7e622279739e73b171a9c67
diff --git a/include/helper.hpp b/include/helper.hpp
new file mode 100644
index 0000000..5841491
--- /dev/null
+++ b/include/helper.hpp
@@ -0,0 +1,242 @@
+#include "stdafx.h"
+#include
+
+using namespace std;
+
+// TODO: Find out where this came from
+namespace Memory
+{
+ template
+ void Write(uintptr_t* writeAddress, T value)
+ {
+ DWORD oldProtect;
+ VirtualProtect((LPVOID)(writeAddress), sizeof(T), PAGE_EXECUTE_WRITECOPY, &oldProtect);
+ *(reinterpret_cast(writeAddress)) = value;
+ VirtualProtect((LPVOID)(writeAddress), sizeof(T), oldProtect, &oldProtect);
+ }
+
+ void PatchBytes(uintptr_t address, const char* pattern, unsigned int numBytes)
+ {
+ DWORD oldProtect;
+ VirtualProtect((LPVOID)address, numBytes, PAGE_EXECUTE_READWRITE, &oldProtect);
+ memcpy((LPVOID)address, pattern, numBytes);
+ VirtualProtect((LPVOID)address, numBytes, oldProtect, &oldProtect);
+ }
+
+ void ReadBytes(const uintptr_t address, void* const buffer, const SIZE_T size)
+ {
+ memcpy(buffer, reinterpret_cast(address), size);
+ }
+
+ uintptr_t ReadMultiLevelPointer(uintptr_t base, const std::vector& offsets)
+ {
+ MEMORY_BASIC_INFORMATION mbi;
+ for (auto& offset : offsets)
+ {
+ if (!VirtualQuery(reinterpret_cast(base), &mbi, sizeof(MEMORY_BASIC_INFORMATION)) || mbi.Protect & (PAGE_NOACCESS | PAGE_GUARD))
+ return 0;
+
+ base = *reinterpret_cast(base) + offset;
+ }
+
+ return base;
+ }
+
+ int GetHookLength(char* src, int minLen)
+ {
+ int lengthHook = 0;
+ const int size = 15;
+ char buffer[size];
+
+ memcpy(buffer, src, size);
+
+ // must be >= 14
+ while (lengthHook <= minLen)
+ lengthHook += ldisasm(&buffer[lengthHook], true);
+
+ return lengthHook;
+ }
+
+ bool DetourFunction32(void* src, void* dst, int len)
+ {
+ if (len < 5) return false;
+
+ DWORD curProtection;
+ VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);
+
+ memset(src, 0x90, len);
+
+ uintptr_t relativeAddress = ((uintptr_t)dst - (uintptr_t)src) - 5;
+
+ *(BYTE*)src = 0xE9;
+ *(uintptr_t*)((uintptr_t)src + 1) = relativeAddress;
+
+ DWORD temp;
+ VirtualProtect(src, len, curProtection, &temp);
+
+ return true;
+ }
+
+ void* DetourFunction64(void* pSource, void* pDestination, int dwLen)
+ {
+ DWORD MinLen = 14;
+
+ if (dwLen < MinLen) return NULL;
+
+ BYTE stub[] = {
+ 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [$+6]
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // ptr
+ };
+
+ void* pTrampoline = VirtualAlloc(0, dwLen + sizeof(stub), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
+
+ DWORD dwOld = 0;
+ VirtualProtect(pSource, dwLen, PAGE_EXECUTE_READWRITE, &dwOld);
+
+ DWORD64 retto = (DWORD64)pSource + dwLen;
+
+ // trampoline
+ memcpy(stub + 6, &retto, 8);
+ memcpy((void*)((DWORD_PTR)pTrampoline), pSource, dwLen);
+ memcpy((void*)((DWORD_PTR)pTrampoline + dwLen), stub, sizeof(stub));
+
+ // orig
+ memcpy(stub + 6, &pDestination, 8);
+ memcpy(pSource, stub, sizeof(stub));
+
+ for (int i = MinLen; i < dwLen; i++)
+ {
+ *(BYTE*)((DWORD_PTR)pSource + i) = 0x90;
+ }
+
+ VirtualProtect(pSource, dwLen, dwOld, &dwOld);
+ return (void*)((DWORD_PTR)pTrampoline);
+ }
+
+ static HMODULE GetThisDllHandle()
+ {
+ MEMORY_BASIC_INFORMATION info;
+ size_t len = VirtualQueryEx(GetCurrentProcess(), (void*)GetThisDllHandle, &info, sizeof(info));
+ assert(len == sizeof(info));
+ return len ? (HMODULE)info.AllocationBase : NULL;
+ }
+
+ // CSGOSimple's pattern scan
+ // https://github.com/OneshotGH/CSGOSimple-master/blob/master/CSGOSimple/helpers/utils.cpp
+ std::uint8_t* PatternScan(void* module, const char* signature)
+ {
+ static auto pattern_to_byte = [](const char* pattern) {
+ auto bytes = std::vector{};
+ auto start = const_cast(pattern);
+ auto end = const_cast(pattern) + strlen(pattern);
+
+ for (auto current = start; current < end; ++current) {
+ if (*current == '?') {
+ ++current;
+ if (*current == '?')
+ ++current;
+ bytes.push_back(-1);
+ }
+ else {
+ bytes.push_back(strtoul(current, ¤t, 16));
+ }
+ }
+ return bytes;
+ };
+
+ auto dosHeader = (PIMAGE_DOS_HEADER)module;
+ auto ntHeaders = (PIMAGE_NT_HEADERS)((std::uint8_t*)module + dosHeader->e_lfanew);
+
+ auto sizeOfImage = ntHeaders->OptionalHeader.SizeOfImage;
+ auto patternBytes = pattern_to_byte(signature);
+ auto scanBytes = reinterpret_cast(module);
+
+ auto s = patternBytes.size();
+ auto d = patternBytes.data();
+
+ for (auto i = 0ul; i < sizeOfImage - s; ++i) {
+ bool found = true;
+ for (auto j = 0ul; j < s; ++j) {
+ if (scanBytes[i + j] != d[j] && d[j] != -1) {
+ found = false;
+ break;
+ }
+ }
+ if (found) {
+ return &scanBytes[i];
+ }
+ }
+ return nullptr;
+ }
+
+ std::string GetVersionString()
+ {
+ auto hInst = GetModuleHandle(NULL);
+ auto hResInfo = FindResourceW(hInst, MAKEINTRESOURCE(1), RT_VERSION);
+ if (!hResInfo) return {};
+ auto dwSize = SizeofResource(hInst, hResInfo);
+ if (!dwSize) return {};
+ auto hResData = LoadResource(hInst, hResInfo);
+ char* pRes = static_cast(LockResource(hResData));
+ if (!pRes) return {};
+
+ std::vector ResCopy(pRes, pRes + dwSize);
+
+ VS_FIXEDFILEINFO* pvFileInfo;
+ UINT uiFileInfoLen;
+
+ if (!VerQueryValueA(ResCopy.data(), "\\", reinterpret_cast(&pvFileInfo), &uiFileInfoLen))
+ return "(unknown)";
+
+ char buf[25];
+ int len = sprintf(buf, "%hu.%hu.%hu.%hu",
+ HIWORD(pvFileInfo->dwFileVersionMS),
+ LOWORD(pvFileInfo->dwFileVersionMS),
+ HIWORD(pvFileInfo->dwFileVersionLS),
+ LOWORD(pvFileInfo->dwFileVersionLS)
+ );
+
+ return std::string(buf, len);
+ }
+
+ vector string_to_ints(const string& s, char delimiter) {
+ vector tokens;
+ string token;
+ istringstream tokenStream(s);
+ while (getline(tokenStream, token, delimiter)) {
+ tokens.push_back(stoi(token));
+ }
+ return tokens;
+ }
+
+
+ std::wstring GetVersionProductName()
+ {
+ struct LANGCODEPAGE {
+ WORD wLang;
+ WORD wCode;
+ } *lpTranslate;
+
+ UINT cbTranslate;
+
+ HMODULE baseModule = GetModuleHandle(NULL);
+
+ auto exePath = new WCHAR[_MAX_PATH];
+ GetModuleFileName(baseModule, exePath, _MAX_PATH);
+ auto size = GetFileVersionInfoSize(exePath, NULL);
+ std::vector buffer(size);
+ GetFileVersionInfo(exePath, NULL, size, buffer.data());
+ VerQueryValue(buffer.data(), L"VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate);
+
+ if (cbTranslate < sizeof(LANGCODEPAGE)) {
+ return L"";
+ }
+
+ wchar_t query[512];
+ _snwprintf(query, sizeof(query), L"\\StringFileInfo\\%04x%04x\\ProductName", lpTranslate[0].wLang, lpTranslate[0].wCode);
+ wchar_t const* p;
+ UINT n_chars;
+ VerQueryValue(buffer.data(), query, (LPVOID*)&p, &n_chars);
+ return std::wstring(p, p + n_chars);
+ }
+}
diff --git a/include/stdafx.h b/include/stdafx.h
new file mode 100644
index 0000000..5fbfdb9
--- /dev/null
+++ b/include/stdafx.h
@@ -0,0 +1,19 @@
+#pragma once
+#pragma comment(lib,"Version.lib")
+
+#define WIN32_LEAN_AND_MEAN
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "inipp/inipp/inipp.h"
+#include "length-disassembler/headerOnly/ldisasm.h"