From 2344e280d4d2e043dc88b172a729db4db0fccde0 Mon Sep 17 00:00:00 2001 From: uberhalit Date: Tue, 3 Nov 2020 14:58:47 +0100 Subject: [PATCH 1/2] updated to game version 1.5.0.0 --- README.md | 3 ++ SekiroFpsUnlockAndMore/GameData.cs | 52 ++++++++++++------- SekiroFpsUnlockAndMore/MainWindow.xaml.cs | 16 +++++- .../Properties/AssemblyInfo.cs | 4 +- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 6b5d61e..92c82b0 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,9 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Version History +* v1.2.5.2 (2020-11-02) + * updated death penalties code to latest version 1.05 + * added game version 1.05 (1.5.0.0) to supported versions * v1.2.5.1 (2020-02-04) * added support for windows' high contrast mode (thanks to [khvorov45](https://github.com/khvorov45) for pointing it out) * focus of the game won't be stolen anymore when OBS and the utility try to write/read the stats log files at the same time diff --git a/SekiroFpsUnlockAndMore/GameData.cs b/SekiroFpsUnlockAndMore/GameData.cs index b8afa89..5853dac 100644 --- a/SekiroFpsUnlockAndMore/GameData.cs +++ b/SekiroFpsUnlockAndMore/GameData.cs @@ -7,9 +7,10 @@ namespace SekiroFpsUnlockAndMore internal const string PROCESS_NAME = "sekiro"; internal const string PROCESS_TITLE = "Sekiro"; internal const string PROCESS_DESCRIPTION = "Shadows Die Twice"; - internal const string PROCESS_EXE_VERSION = "1.4.0.0"; - internal static readonly string[] PROCESS_EXE_VERSION_SUPPORTED = new string[2] + internal const string PROCESS_EXE_VERSION = "1.5.0.0"; + internal static readonly string[] PROCESS_EXE_VERSION_SUPPORTED = new string[3] { + "1.4.0.0", "1.3.0.0", "1.2.0.0" }; @@ -329,12 +330,12 @@ namespace SekiroFpsUnlockAndMore /** - sekiro.14066B520 is used to increase and decrease various player values, in this case it's used to decrease Sen so we skip the call. - 0000000141189B74 | F344:0F2CE9 | cvttss2si r13d,xmm1 | - 0000000141189B79 | 41:8BD5 | mov edx,r13d | - 0000000141189B7C | 48:8BCB | mov rcx,rbx | - 0000000141189B7F | E8 FC194EFF | call sekiro.14066B580 | -> ManipulatePlayerValues() - 0000000141189B84 | 8BAB 60010000 | mov ebp,dword ptr ds:[rbx+160] | + sekiro.14066DA30 is used to increase and decrease various player values, in this case it's used to decrease Sen so we skip the call. + 00000001411D32F7 | F344:0F2CE9 | cvttss2si r13d,xmm1 | + 00000001411D32FC | 41:8BD5 | mov edx,r13d | + 00000001411D32FF | 48:8BCF | mov rcx,rdi | + 00000001411D3302 | E8 29A749FF | call sekiro.14066DA30 | -> ManipulatePlayerValues() + 00000001411D3307 | 8B87 60010000 | mov eax,dword ptr ds:[rdi+160] | 000000014118904F (Version 1.2.0.0) */ @@ -344,25 +345,36 @@ namespace SekiroFpsUnlockAndMore internal static readonly byte[] PATCH_DEATHPENALTIES1_DISABLE = new byte[5] { 0x90, 0x90, 0x90, 0x90, 0x90 }; // nop /** Here ability points (AP) are decreased and virtual Sen & AP decrease is set. The later 2 values will be shown after death as an indicator on how much of each has been lost. - 0000000141189C68 | 8B00 | mov eax,dword ptr ds:[rax] | - 0000000141189C6A | 8983 60010000 | mov dword ptr ds:[rbx+160],eax | OnDeath() ability points (AP) decrease - 0000000141189C70 | 45:2BFD | sub r15d,r13d | - 0000000141189C73 | 44:89BC24 90000000 | mov dword ptr ss:[rsp+90],r15d | virtual Sen decrease - shows how many Sen got lost after death - 0000000141189C7B | 2BE9 | sub ebp,ecx | - 0000000141189C7D | 89AC24 94000000 | mov dword ptr ss:[rsp+94],ebp | virtual AP decrease - shows how many APs got lost after death - 0000000141189C84 | E8 071673FF | call sekiro.1408BB290 | + To not have the "Unseen Aid" screen shown everytime we overwrite an additional instruction. + 00000001411D33BB | E8 E0110000 | call sekiro.1411D45A0 | -> OnDeath() ability points (AP) decrease + 00000001411D33C0 | 45:2BE5 | sub r12d,r13d | + 00000001411D33C3 | 44:89A424 A0000000 | mov dword ptr ss:[rsp+A0],r12d | virtual Sen decrease - shows how many Sen got lost after death + 00000001411D33CB | 8B8424 90000000 | mov eax,dword ptr ss:[rsp+90] | current AP + 00000001411D33D2 | 2BC3 | sub eax,ebx | + 00000001411D33D4 | 898424 A4000000 | mov dword ptr ss:[rsp+A4],eax | virtual AP decrease - shows how many APs got lost after death + 00000001411D33DB | E8 002B6FFF | call sekiro.1408C5EE0 | + 00000001411D33E0 | 48:8B8C24 A0000000 | mov rcx,qword ptr ss:[rsp+A0] | + 00000001411D33E8 | 48:8908 | mov qword ptr ds:[rax],rcx | checks if we have lost virtual sen and if not shows "Unseen Aid" screen next spawn + 00000001411D33EB | 48:8B0D 562BB802 | mov rcx,qword ptr ds:[143D55F48] | + 00000001411D33F2 | 48:85C9 | test rcx,rcx | 000000014118913A (Version 1.2.0.0) */ - internal const string PATTERN_DEATHPENALTIES2 = "8B ?? 89 83 ?? ?? ?? ?? 45 ?? ?? 44 89 ?? 24 ?? ?? 00 00 2B ?? 89 ?? 24 ?? ?? 00 00 E8"; - internal const int PATTERN_DEATHPENALTIES2_OFFSET = 2; - internal const int PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH = 26; - internal static readonly byte[] PATCH_DEATHPENALTIES2_DISABLE = new byte[26] // nop + internal const string PATTERN_DEATHPENALTIES2 = "E8 ?? ?? ?? ?? 45 ?? ?? 44 89 ?? 24 ?? ?? 00 00 8B ?? 24 ?? ?? 00 00 2B ?? 89 ?? 24 ?? ?? 00 00 E8 ?? ?? ?? ?? 48 ?? ?? 24 ?? ?? 00 00 48 ?? ?? 48"; + internal const int PATTERN_DEATHPENALTIES2_OFFSET = 0; + internal const int PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH = 32; + internal static readonly byte[] PATCH_DEATHPENALTIES2_DISABLE = new byte[32] // nop { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90 + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 + }; + internal const int PATTERN_DEATHPENALTIES3_OFFSET = 45; + internal const int PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH = 3; + internal static readonly byte[] PATCH_DEATHPENALTIES3_DISABLE = new byte[3] // nop + { + 0x90, 0x90, 0x90 }; diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs index babe961..69f0d64 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs @@ -33,6 +33,7 @@ namespace SekiroFpsUnlockAndMore internal long _offset_dragonrot_routine = 0x0; internal long _offset_deathpenalties1 = 0x0; internal long _offset_deathpenalties2 = 0x0; + internal long _offset_deathpenalties3 = 0x0; internal long _offset_deathscounter_routine = 0x0; internal long _offset_timescale = 0x0; internal long _offset_timescale_player = 0x0; @@ -40,6 +41,7 @@ namespace SekiroFpsUnlockAndMore internal byte[] _patch_deathpenalties1_enable; internal byte[] _patch_deathpenalties2_enable; + internal byte[] _patch_deathpenalties3_enable; internal MemoryCaveGenerator _memoryCaveGenerator; internal SettingsService _settingsService; @@ -529,7 +531,15 @@ namespace SekiroFpsUnlockAndMore if (!ReadProcessMemory(_gameAccessHwnd, _offset_deathpenalties2, _patch_deathpenalties2_enable, (ulong) GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH, out lpNumberOfBytesRead) || lpNumberOfBytesRead.ToInt32() != GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH) _patch_deathpenalties2_enable = null; else + { Debug.WriteLine("deathPenalties2 original instruction set: " + BitConverter.ToString(_patch_deathpenalties2_enable).Replace('-', ' ')); + _offset_deathpenalties3 = _offset_deathpenalties2 + GameData.PATTERN_DEATHPENALTIES3_OFFSET; + _patch_deathpenalties3_enable = new byte[GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH]; + if (!ReadProcessMemory(_gameAccessHwnd, _offset_deathpenalties3, _patch_deathpenalties3_enable, (ulong)GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH, out lpNumberOfBytesRead) || lpNumberOfBytesRead.ToInt32() != GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH) + _patch_deathpenalties2_enable = null; + else + Debug.WriteLine("deathPenalties3 original instruction set: " + BitConverter.ToString(_patch_deathpenalties3_enable).Replace('-', ' ')); + } } else _offset_deathpenalties2 = 0x0; @@ -539,8 +549,10 @@ namespace SekiroFpsUnlockAndMore { _offset_deathpenalties1 = 0x0; _offset_deathpenalties2 = 0x0; + _offset_deathpenalties3 = 0x0; _patch_deathpenalties1_enable = null; _patch_deathpenalties2_enable = null; + _patch_deathpenalties3_enable = null; } if (_settingsService.ApplicationSettings.hiddenDPs == ZUH_HIDDEN_DP) @@ -1086,13 +1098,15 @@ namespace SekiroFpsUnlockAndMore { WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties1, GameData.PATCH_DEATHPENALTIES1_DISABLE); WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties2, GameData.PATCH_DEATHPENALTIES2_DISABLE); + WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties3, GameData.PATCH_DEATHPENALTIES3_DISABLE); } else if (this.cbDeathPenalty.IsChecked == false) { - if (_initialStartup) + if (!_initialStartup) { WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties1, _patch_deathpenalties1_enable); WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties2, _patch_deathpenalties2_enable); + WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties3, _patch_deathpenalties3_enable); } if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White); return false; diff --git a/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs b/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs index 43099e5..4161cc5 100644 --- a/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs +++ b/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs @@ -18,5 +18,5 @@ using System.Runtime.InteropServices; ResourceDictionaryLocation.SourceAssembly )] -[assembly: AssemblyVersion("1.2.5.1")] -[assembly: AssemblyFileVersion("1.2.5.1")] \ No newline at end of file +[assembly: AssemblyVersion("1.2.5.2")] +[assembly: AssemblyFileVersion("1.2.5.2")] \ No newline at end of file From d6312c6b0af0bcdf987568e1490b7d842548ae99 Mon Sep 17 00:00:00 2001 From: uberhalit Date: Tue, 3 Nov 2020 15:31:17 +0100 Subject: [PATCH 2/2] added legacy support for death penalties --- SekiroFpsUnlockAndMore/GameData.cs | 21 +++++++- SekiroFpsUnlockAndMore/MainWindow.xaml.cs | 60 +++++++++++++++++------ 2 files changed, 64 insertions(+), 17 deletions(-) diff --git a/SekiroFpsUnlockAndMore/GameData.cs b/SekiroFpsUnlockAndMore/GameData.cs index 5853dac..2759131 100644 --- a/SekiroFpsUnlockAndMore/GameData.cs +++ b/SekiroFpsUnlockAndMore/GameData.cs @@ -8,7 +8,7 @@ namespace SekiroFpsUnlockAndMore internal const string PROCESS_TITLE = "Sekiro"; internal const string PROCESS_DESCRIPTION = "Shadows Die Twice"; internal const string PROCESS_EXE_VERSION = "1.5.0.0"; - internal static readonly string[] PROCESS_EXE_VERSION_SUPPORTED = new string[3] + internal static readonly string[] PROCESS_EXE_VERSION_SUPPORTED_LEGACY = new string[3] { "1.4.0.0", "1.3.0.0", @@ -358,6 +358,15 @@ namespace SekiroFpsUnlockAndMore 00000001411D33EB | 48:8B0D 562BB802 | mov rcx,qword ptr ds:[143D55F48] | 00000001411D33F2 | 48:85C9 | test rcx,rcx | + LEGACY + 0000000141189C68 | 8B00 | mov eax,dword ptr ds:[rax] | + 0000000141189C6A | 8983 60010000 | mov dword ptr ds:[rbx+160],eax | OnDeath() ability points (AP) decrease + 0000000141189C70 | 45:2BFD | sub r15d,r13d | + 0000000141189C73 | 44:89BC24 90000000 | mov dword ptr ss:[rsp+90],r15d | virtual Sen decrease - shows how many Sen got lost after death + 0000000141189C7B | 2BE9 | sub ebp,ecx | + 0000000141189C7D | 89AC24 94000000 | mov dword ptr ss:[rsp+94],ebp | virtual AP decrease - shows how many APs got lost after death + 0000000141189C84 | E8 071673FF | call sekiro.1408BB290 | + 000000014118913A (Version 1.2.0.0) */ internal const string PATTERN_DEATHPENALTIES2 = "E8 ?? ?? ?? ?? 45 ?? ?? 44 89 ?? 24 ?? ?? 00 00 8B ?? 24 ?? ?? 00 00 2B ?? 89 ?? 24 ?? ?? 00 00 E8 ?? ?? ?? ?? 48 ?? ?? 24 ?? ?? 00 00 48 ?? ?? 48"; @@ -376,6 +385,16 @@ namespace SekiroFpsUnlockAndMore { 0x90, 0x90, 0x90 }; + internal const string PATTERN_DEATHPENALTIES2_LEGACY = "8B ?? 89 83 ?? ?? ?? ?? 45 ?? ?? 44 89 ?? 24 ?? ?? 00 00 2B ?? 89 ?? 24 ?? ?? 00 00 E8"; + internal const int PATTERN_DEATHPENALTIES2_OFFSET_LEGACY = 2; + internal const int PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH_LEGACY = 26; + internal static readonly byte[] PATCH_DEATHPENALTIES2_DISABLE_LEGACY = new byte[26] // nop + { + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90 + }; /** diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs index 69f0d64..3ca8b1b 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs @@ -67,6 +67,7 @@ namespace SekiroFpsUnlockAndMore internal string _path_killsLog; internal RECT _windowRect; internal Size _screenSize; + internal bool _isLegacyVersion = false; internal const string _DATACAVE_SPEEDFIX_POINTER = "speedfixPointer"; internal const string _DATACAVE_FOV_POINTER = "fovPointer"; @@ -361,12 +362,24 @@ namespace SekiroFpsUnlockAndMore } string gameFileVersion = FileVersionInfo.GetVersionInfo(procList[0].MainModule.FileName).FileVersion; - if (gameFileVersion != GameData.PROCESS_EXE_VERSION && Array.IndexOf(GameData.PROCESS_EXE_VERSION_SUPPORTED, gameFileVersion) < 0 && !_settingsService.ApplicationSettings.gameVersionNotify) + if (gameFileVersion != GameData.PROCESS_EXE_VERSION) { - MessageBox.Show(string.Format("Unknown game version '{0}'.\nSome functions might not work properly or even crash the game. " + - "Check for updates on this utility regularly following the link at the bottom.", gameFileVersion), "Sekiro FPS Unlocker and more", MessageBoxButton.OK, MessageBoxImage.Warning); - ClearConfiguration(); - _settingsService.ApplicationSettings.gameVersionNotify = true; + if (Array.IndexOf(GameData.PROCESS_EXE_VERSION_SUPPORTED_LEGACY, gameFileVersion) < 0) + { + if (!_settingsService.ApplicationSettings.gameVersionNotify) + { + MessageBox.Show(string.Format("Unknown game version '{0}'.\nSome functions might not work properly or even crash the game. " + + "Check for updates on this utility regularly following the link at the bottom.", gameFileVersion), "Sekiro FPS Unlocker and more", MessageBoxButton.OK, MessageBoxImage.Warning); + ClearConfiguration(); + _settingsService.ApplicationSettings.gameVersionNotify = true; + SaveConfiguration(); + } + } + else + { + _isLegacyVersion = true; + _settingsService.ApplicationSettings.gameVersionNotify = false; + } } else _settingsService.ApplicationSettings.gameVersionNotify = false; @@ -523,22 +536,35 @@ namespace SekiroFpsUnlockAndMore Debug.WriteLine("deathPenalties1 original instruction set: " + BitConverter.ToString(_patch_deathpenalties1_enable).Replace('-', ' ')); if (_patch_deathpenalties1_enable != null) { - _offset_deathpenalties2 = patternScan.FindPattern(GameData.PATTERN_DEATHPENALTIES2) + GameData.PATTERN_DEATHPENALTIES2_OFFSET; + if (!_isLegacyVersion) + _offset_deathpenalties2 = patternScan.FindPattern(GameData.PATTERN_DEATHPENALTIES2) + GameData.PATTERN_DEATHPENALTIES2_OFFSET; + else + _offset_deathpenalties2 = patternScan.FindPattern(GameData.PATTERN_DEATHPENALTIES2_LEGACY) + GameData.PATTERN_DEATHPENALTIES2_OFFSET_LEGACY; Debug.WriteLine("lpDeathPenalties2 found at: 0x" + _offset_deathpenalties2.ToString("X")); if (IsValidAddress(_offset_deathpenalties2)) { - _patch_deathpenalties2_enable = new byte[GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH]; - if (!ReadProcessMemory(_gameAccessHwnd, _offset_deathpenalties2, _patch_deathpenalties2_enable, (ulong) GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH, out lpNumberOfBytesRead) || lpNumberOfBytesRead.ToInt32() != GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH) + ulong instrLength = (ulong)GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH; + if (!_isLegacyVersion) + _patch_deathpenalties2_enable = new byte[GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH]; + else + { + _patch_deathpenalties2_enable = new byte[GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH_LEGACY]; + instrLength = (ulong)GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH_LEGACY; + } + if (!ReadProcessMemory(_gameAccessHwnd, _offset_deathpenalties2, _patch_deathpenalties2_enable, instrLength, out lpNumberOfBytesRead) || lpNumberOfBytesRead.ToInt32() != (long)instrLength) _patch_deathpenalties2_enable = null; else { Debug.WriteLine("deathPenalties2 original instruction set: " + BitConverter.ToString(_patch_deathpenalties2_enable).Replace('-', ' ')); - _offset_deathpenalties3 = _offset_deathpenalties2 + GameData.PATTERN_DEATHPENALTIES3_OFFSET; - _patch_deathpenalties3_enable = new byte[GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH]; - if (!ReadProcessMemory(_gameAccessHwnd, _offset_deathpenalties3, _patch_deathpenalties3_enable, (ulong)GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH, out lpNumberOfBytesRead) || lpNumberOfBytesRead.ToInt32() != GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH) - _patch_deathpenalties2_enable = null; - else - Debug.WriteLine("deathPenalties3 original instruction set: " + BitConverter.ToString(_patch_deathpenalties3_enable).Replace('-', ' ')); + if (!_isLegacyVersion) + { + _offset_deathpenalties3 = _offset_deathpenalties2 + GameData.PATTERN_DEATHPENALTIES3_OFFSET; + _patch_deathpenalties3_enable = new byte[GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH]; + if (!ReadProcessMemory(_gameAccessHwnd, _offset_deathpenalties3, _patch_deathpenalties3_enable, (ulong)GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH, out lpNumberOfBytesRead) || lpNumberOfBytesRead.ToInt32() != GameData.PATCH_DEATHPENALTIES3_INSTRUCTION_LENGTH) + _patch_deathpenalties2_enable = null; + else + Debug.WriteLine("deathPenalties3 original instruction set: " + BitConverter.ToString(_patch_deathpenalties3_enable).Replace('-', ' ')); + } } } else @@ -1098,7 +1124,8 @@ namespace SekiroFpsUnlockAndMore { WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties1, GameData.PATCH_DEATHPENALTIES1_DISABLE); WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties2, GameData.PATCH_DEATHPENALTIES2_DISABLE); - WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties3, GameData.PATCH_DEATHPENALTIES3_DISABLE); + if (!_isLegacyVersion && _offset_deathpenalties3 != 0x0) + WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties3, GameData.PATCH_DEATHPENALTIES3_DISABLE); } else if (this.cbDeathPenalty.IsChecked == false) { @@ -1106,7 +1133,8 @@ namespace SekiroFpsUnlockAndMore { WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties1, _patch_deathpenalties1_enable); WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties2, _patch_deathpenalties2_enable); - WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties3, _patch_deathpenalties3_enable); + if (!_isLegacyVersion && _offset_deathpenalties3 != 0x0) + WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties3, _patch_deathpenalties3_enable); } if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White); return false;