diff --git a/.github/README.md b/.github/README.md
index 3b363c2..7315b91 100644
--- a/.github/README.md
+++ b/.github/README.md
@@ -37,6 +37,18 @@
- `winmm.dll`
- `BrightMemoryInfinite.NoTAA.asi`
+### **Death Stranding (original and Director's Cut)**
+ - Force AA mode (None, FXAA or TAA)
+ - Skip savegame checks (for savegame transfer between different versions/profiles)
+
+#### Installation
+
+- **Note:** ***Please make sure any executable hex edits are removed/reverted first***.
+ - Extract the following contents of the release zip in to the the game root folder.
+ - `version.dll`
+ - `version.ini`
+ - `DeathStranding.Fix.asi`
+
### **Elden Ring**
- Force TAA off
- Disable Chromatic Aberration (thanks to [techiew](https://github.com/techiew/EldenRingMods) for the original fix)
diff --git a/Windows-Game-Patches.sln b/Windows-Game-Patches.sln
index ab73e12..35dfe97 100644
--- a/Windows-Game-Patches.sln
+++ b/Windows-Game-Patches.sln
@@ -21,6 +21,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Remnant2.NoTAA", "source\Re
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EldenRing.NoTAA", "source\EldenRing.NoTAA\EldenRing.NoTAA.vcxproj", "{0A040A3E-FA06-4978-A089-298177D4F133}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeathStranding.Fix", "source\DeathStranding.Fix\DeathStranding.Fix.vcxproj", "{978C20F5-8939-458B-B124-B48BB16CCB98}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -101,6 +103,14 @@ Global
{0A040A3E-FA06-4978-A089-298177D4F133}.Release|x64.Build.0 = Release|x64
{0A040A3E-FA06-4978-A089-298177D4F133}.Release|x86.ActiveCfg = Release|Win32
{0A040A3E-FA06-4978-A089-298177D4F133}.Release|x86.Build.0 = Release|Win32
+ {978C20F5-8939-458B-B124-B48BB16CCB98}.Debug|x64.ActiveCfg = Debug|x64
+ {978C20F5-8939-458B-B124-B48BB16CCB98}.Debug|x64.Build.0 = Debug|x64
+ {978C20F5-8939-458B-B124-B48BB16CCB98}.Debug|x86.ActiveCfg = Debug|Win32
+ {978C20F5-8939-458B-B124-B48BB16CCB98}.Debug|x86.Build.0 = Debug|Win32
+ {978C20F5-8939-458B-B124-B48BB16CCB98}.Release|x64.ActiveCfg = Release|x64
+ {978C20F5-8939-458B-B124-B48BB16CCB98}.Release|x64.Build.0 = Release|x64
+ {978C20F5-8939-458B-B124-B48BB16CCB98}.Release|x86.ActiveCfg = Release|Win32
+ {978C20F5-8939-458B-B124-B48BB16CCB98}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/source/DeathStranding.Fix/DeathStranding.Fix.sln b/source/DeathStranding.Fix/DeathStranding.Fix.sln
new file mode 100644
index 0000000..5c950d1
--- /dev/null
+++ b/source/DeathStranding.Fix/DeathStranding.Fix.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}") = "DeathStranding.Fix", "DeathStranding.Fix.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/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj b/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj
new file mode 100644
index 0000000..dca5540
--- /dev/null
+++ b/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj
@@ -0,0 +1,196 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {978C20F5-8939-458B-B124-B48BB16CCB98}
+ DeathStrandingFix
+ 10.0.22000.0
+ DeathStranding.Fix
+
+
+
+ DynamicLibrary
+ true
+ v143
+ Unicode
+
+
+ DynamicLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ DynamicLibrary
+ true
+ ClangCL
+ Unicode
+
+
+ DynamicLibrary
+ false
+ ClangCL
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \..\include\;$(IncludePath)
+ .asi
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+
+
+ \..\include\;$(IncludePath)
+ .asi
+ $(SolutionDir)$(Configuration)\
+ $(Configuration)\
+
+
+ .asi
+ $(Configuration)\
+
+
+ .asi
+ $(Configuration)\
+
+
+
+ Level3
+ true
+ UNICODE;_UNICODE;_CRT_SECURE_NO_WARNINGS;_USRDLL
+ true
+ NotUsing
+ pch.h
+ ..\..\include\;..\..\external\;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ true
+ true
+ UNICODE;_UNICODE;_CRT_SECURE_NO_WARNINGS;_USRDLL
+ true
+ NotUsing
+ pch.h
+ ..\..\include\;..\..\external\;%(AdditionalIncludeDirectories)
+
+
+ Windows
+ true
+ true
+ true
+ false
+
+
+
+
+ Level3
+ true
+ UNICODE;_UNICODE;_USRDLL
+ true
+ NotUsing
+ pch.h
+ ..\..\include\;..\..\external\;%(AdditionalIncludeDirectories)
+ Default
+
+
+ NotSet
+
+
+ Windows
+ true
+ false
+
+
+
+
+ Level3
+ true
+ false
+ true
+ UNICODE;_UNICODE;_USRDLL
+ true
+ NotUsing
+ pch.h
+ ..\..\include\;..\..\external\;%(AdditionalIncludeDirectories)
+ Default
+
+
+ Disabled
+ NotSet
+
+
+ Windows
+ true
+ true
+ true
+ false
+
+
+ call $(MSBuildStartupDirectory)\set_git_ver.cmd
+
+
+ copy NUL $(OutDirFullPath)$(ProjectName)_version.dll
+copy $(ProjectDir)version.ini $(OutDirFullPath)$(ProjectName)_version.ini
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj.filters b/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj.filters
new file mode 100644
index 0000000..780a707
--- /dev/null
+++ b/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj.filters
@@ -0,0 +1,38 @@
+
+
+
+
+ {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
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj.user b/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/source/DeathStranding.Fix/DeathStranding.Fix.vcxproj.user
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/source/DeathStranding.Fix/dllmain.cpp b/source/DeathStranding.Fix/dllmain.cpp
new file mode 100644
index 0000000..a9d0ec6
--- /dev/null
+++ b/source/DeathStranding.Fix/dllmain.cpp
@@ -0,0 +1,127 @@
+#include "stdafx.h"
+#include "helper.hpp"
+#include "memory.hpp"
+#include "git_ver.h"
+
+HMODULE baseModule = GetModuleHandle(NULL);
+
+#define wstr(s) L#s
+#define wxstr(s) wstr(s)
+#define _PROJECT_NAME L"DeathStranding.Fix"
+#define _PROJECT_LOG_PATH _PROJECT_NAME L".log"
+
+wchar_t exePath[_MAX_PATH] = { 0 };
+
+// INI Variables
+uint32_t uForceAAMode;
+bool bSkipSavegameChecks;
+
+void ReadConfig(void)
+{
+ inipp::Ini ini;
+ // Get game name and exe path
+ LOG(_PROJECT_NAME " Built: " __TIME__ " @ " __DATE__ "\n");
+ LOG(L"" GIT_COMMIT "\n");
+ LOG(L"" GIT_VER "\n");
+ LOG(L"" GIT_NUM "\n");
+ LOG(L"Game Name: %s\n", Memory::GetVersionProductName().c_str());
+ LOG(L"Game Path: %s\n", exePath);
+
+ // Initialize config
+ // UE4 games use launchers so config path is relative to launcher
+ std::wstring config_path = _PROJECT_NAME L".ini";
+ std::wifstream iniFile(config_path);
+ if (!iniFile)
+ {
+ // no ini, lets generate one.
+ LOG(L"Failed to load config file.\n");
+ std::wstring ini_defaults = L"[Settings]\n"
+ wstr(uForceAAMode)" = 0\n"
+ "; input corresponding numbers below\n"
+ "; Valid AA setting:\n"
+ "; None = 0\n"
+ "; FXAA = 1\n"
+ "; TAA = 2\n"
+ wstr(bSkipSavegameChecks)" = true\n";
+ std::wofstream iniFile(config_path);
+ iniFile << ini_defaults;
+ uForceAAMode = 0;
+ bSkipSavegameChecks = true;
+ LOG(L"Created default config file.\n");
+ }
+ else
+ {
+ ini.parse(iniFile);
+ inipp::get_value(ini.sections[L"Settings"], wstr(uForceAAMode), uForceAAMode);
+ inipp::get_value(ini.sections[L"Settings"], wstr(bSkipSavegameChecks), bSkipSavegameChecks);
+ }
+
+ // Log config parse
+ LOG(L"%s: %u\n", wstr(uForceAAMode), uForceAAMode);
+ LOG(L"%s: %s (%i)\n", wstr(bSkipSavegameChecks), GetBoolStr(bSkipSavegameChecks), bSkipSavegameChecks);
+}
+
+void ForceAAMode(void)
+{
+ // 83FB 02 | cmp ebx, 2
+ // 0F46C3 | cmovbe eax, ebx
+ // 8905 455D3D02 | mov dword ptr ds : [7FF63D0F500C] , eax
+
+ uintptr_t mov_AA_eax = FindAndPrintPatternW(L"83 ?? 02 0F 46 ?? 89 05 ?? ?? ?? ??", L"Find init AA sub", 6);
+ // mov_AA_eax = address of "mov dword ptr ds : [7FF63D0F500C] , eax",
+ uint32_t* AA_offset = reinterpret_cast(mov_AA_eax + 2);
+ // *AA_offset = BE(0x455D3D02) = 0x023D5D45
+ uint32_t* AA_setting = reinterpret_cast(mov_AA_eax + 6 + *AA_offset);
+ // AA_setting = address of AA setting, that is: sum of end of mov function (mov_AA_eax + 6) + mov offset (AA_offset) = 0x7FF63D0F500C
+ LOG(L"Offset of mov function: 0x%08llx (at address 0x%016llx)\n", *AA_offset, AA_offset);
+ LOG(L"Current AA setting: 0x%08llx (at address 0x%016llx)\n", *AA_setting, AA_setting);
+ *AA_setting = uForceAAMode;
+ LOG(L"Set new AA setting: 0x%08llx (at address 0x%016llx)\n", *AA_setting, AA_setting);
+}
+
+void SkipSavegameChecks(void)
+{
+ const unsigned char patch[] = { 0xEB, 0x05 };
+ // 84DB | test bl, bl
+ // 75 05 | jne ds.7FF72EADEB8C --> EB 05 | jmp ds.7FF72EADEB8C
+ // 41:C646 3A 11 | mov byte ptr ds : [r14 + 3A] , 11
+ WritePatchPattern(L"84 DB 75 05 41 C6 46 3A 11", patch, sizeof(patch), L"Skip Savegame Checks", 2);
+}
+
+DWORD __stdcall Main(void*)
+{
+ bLoggingEnabled = false;
+
+ wchar_t LogPath[_MAX_PATH] = { 0 };
+ wcscpy_s(exePath, _countof(exePath), GetRunningPath(exePath));
+ _snwprintf_s(LogPath, _countof(LogPath), _TRUNCATE, L"%s\\%s", exePath, L"" _PROJECT_LOG_PATH);
+ LoggingInit(L"" _PROJECT_NAME, LogPath);
+ ReadConfig();
+
+ ForceAAMode();
+ if (bSkipSavegameChecks)
+ SkipSavegameChecks();
+
+ LOG(L"Shutting down " wstr(fp_log) " file handle.\n");
+ 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/source/DeathStranding.Fix/version.ini b/source/DeathStranding.Fix/version.ini
new file mode 100644
index 0000000..2437813
--- /dev/null
+++ b/source/DeathStranding.Fix/version.ini
@@ -0,0 +1,11 @@
+[GlobalSets]
+LoadPlugins=1
+LoadFromScriptsOnly=0
+DontLoadFromDllMain=0
+FindModule=0
+UseD3D8to9=0
+DisableCrashDumps=0
+Direct3D8DisableMaximizedWindowedModeShim=0
+
+[FileLoader]
+OverloadFromFolder = update