Compare commits

...

2 commits

Author SHA1 Message Date
uberhalit
d6312c6b0a added legacy support for death penalties 2020-11-03 15:31:17 +01:00
uberhalit
2344e280d4 updated to game version 1.5.0.0 2020-11-03 14:58:47 +01:00
4 changed files with 99 additions and 23 deletions

View file

@ -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

View file

@ -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_LEGACY = 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,6 +345,20 @@ 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.
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 |
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 |
@ -354,10 +369,26 @@ namespace SekiroFpsUnlockAndMore
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
};
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
};
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,

View file

@ -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;
@ -65,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";
@ -359,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)
{
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;
@ -521,15 +536,36 @@ namespace SekiroFpsUnlockAndMore
Debug.WriteLine("deathPenalties1 original instruction set: " + BitConverter.ToString(_patch_deathpenalties1_enable).Replace('-', ' '));
if (_patch_deathpenalties1_enable != null)
{
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))
{
ulong instrLength = (ulong)GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH;
if (!_isLegacyVersion)
_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)
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('-', ' '));
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
_offset_deathpenalties2 = 0x0;
@ -539,8 +575,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 +1124,17 @@ namespace SekiroFpsUnlockAndMore
{
WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties1, GameData.PATCH_DEATHPENALTIES1_DISABLE);
WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties2, GameData.PATCH_DEATHPENALTIES2_DISABLE);
if (!_isLegacyVersion && _offset_deathpenalties3 != 0x0)
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);
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;

View file

@ -18,5 +18,5 @@ using System.Runtime.InteropServices;
ResourceDictionaryLocation.SourceAssembly
)]
[assembly: AssemblyVersion("1.2.5.1")]
[assembly: AssemblyFileVersion("1.2.5.1")]
[assembly: AssemblyVersion("1.2.5.2")]
[assembly: AssemblyFileVersion("1.2.5.2")]