From 0e884dfb64baaa131b0786228231f07caab976a4 Mon Sep 17 00:00:00 2001 From: uberhalit Date: Thu, 18 Apr 2019 11:03:50 +0200 Subject: [PATCH 01/10] typos --- README.md | 6 +++--- SekiroFpsUnlockAndMore/GameData.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 44f6724..471b610 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Patches games memory while running, does not modify any game files. Works with e * display hidden death/kill counters and optionally log them to file to display in OBS on stream * game modifications * prevent dragonrot from increasing upon death - * disable death penalties like loosing Send or experience + * disable death penalties like losing Sen or experience * global game speed modifier (increase or decrease) * player speed modifier (increase or decrease) * automatically patch game on startup @@ -139,7 +139,7 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s 10. [![On Stream Display with OBS](https://camo.githubusercontent.com/007910d42ace53ee0db0ea8b61d525751b9d48a6/68747470733a2f2f692e696d6775722e636f6d2f4c39546e6f34462e706e67)](#) ### On 'Disable camera auto rotate on movement': -This will completely disable the automatic camera rotation adjustments when you are moving. This is mostly intended for mouse users, enabling it on non-native windows controllers will not work perfectly (some rotation adjustments will be left) and you will temporary lose the ability to slow-tilt (deadzones). Disabling the automatic camera adjustments makes little sense on controllers. If you changed your input device or made a mistake while selecting it simply close the utility, delete the `SekiroFpsUnlockAndMore.xml` file and restart the mod. +This will completely disable the automatic camera rotation adjustments when you are moving. This is mostly intended for mouse users, enabling it on non-native windows controllers will not work perfectly (some rotation adjustments will be left) and you will temporary lose the ability to slow-tilt (deadzones). Disabling the automatic camera adjustments makes little sense on controllers. If you changed your input device or made a mistake while selecting it simply close the utility, delete the `SekiroFpsUnlockAndMore.xml` file, restart the game and mod. ### On 'Disable camera reset on lock-on': If you press your target lock-on key and no target is in sight the game will reset and center the camera position and disable your input while it's doing so. Ticking this checkbox will remove this behaviour of the game. @@ -229,7 +229,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Version History -* v1.2.3.0 (2019-04-15) +* v1.2.3.0 (2019-04-18) * Added option to prevent increase of dragonrot upon death * Added option to disable Sen and experience penalties upon death * Increased maximum custom resolution width to 7680 diff --git a/SekiroFpsUnlockAndMore/GameData.cs b/SekiroFpsUnlockAndMore/GameData.cs index b971a03..acde00c 100644 --- a/SekiroFpsUnlockAndMore/GameData.cs +++ b/SekiroFpsUnlockAndMore/GameData.cs @@ -250,7 +250,7 @@ namespace SekiroFpsUnlockAndMore /** - Whole dragonrot routine upon death is guarded by a conditional jump, there may be some events in the game where a true death shall not increase the diseases so it's skippable as a whole. + Whole dragonrot routine upon death is guarded by a conditional jump, there may be some events in the game where a true death shall not increase the disease so it's skippable as a whole. We replace conditional jump with non-conditional one. 00000001411891E8 | 45:33C0 | xor r8d,r8d | 00000001411891EB | BA 27250000 | mov edx,2527 | @@ -278,7 +278,7 @@ namespace SekiroFpsUnlockAndMore internal const string PATTERN_DRAGONROT_EFFECT = "45 ?? ?? BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 0F 85 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 4C ?? ?? 4C ?? ?? ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 45 ?? ?? BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 0F 84 ?? ?? ?? ?? 48 8D"; internal const int PATTERN_DRAGONROT_EFFECT_OFFSET = 13; internal static readonly byte[] PATCH_DRAGONROT_EFFECT_DISABLE = new byte[4] { 0x90, 0x90, 0x90, 0xE9 }; // nop; jmp - internal static readonly byte[] PATCH_DRAGONROT_EFFECT_ENABLE = new byte[4] { 0x84, 0xC0, 0x0F, 0x85 }; // jne + internal static readonly byte[] PATCH_DRAGONROT_EFFECT_ENABLE = new byte[4] { 0x84, 0xC0, 0x0F, 0x85 }; // test al,al; jne /** From 3d2b894f901c306230b446725ad244c3d9d8b5d9 Mon Sep 17 00:00:00 2001 From: uberhalit Date: Tue, 23 Apr 2019 13:31:02 +0200 Subject: [PATCH 02/10] updated to game version 1.3.0.0 improved speed of pattern scan --- SekiroFpsUnlockAndMore/GameData.cs | 230 +++++++++++------- SekiroFpsUnlockAndMore/MainWindow.xaml.cs | 3 +- SekiroFpsUnlockAndMore/PatternScan.cs | 7 +- .../Properties/AssemblyInfo.cs | 4 +- 4 files changed, 144 insertions(+), 100 deletions(-) diff --git a/SekiroFpsUnlockAndMore/GameData.cs b/SekiroFpsUnlockAndMore/GameData.cs index acde00c..bbcd378 100644 --- a/SekiroFpsUnlockAndMore/GameData.cs +++ b/SekiroFpsUnlockAndMore/GameData.cs @@ -7,13 +7,19 @@ 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.2.0.0"; + internal const string PROCESS_EXE_VERSION = "1.3.0.0"; + internal static readonly string[] PROCESS_EXE_VERSION_SUPPORTED = new string[1] + { + "1.2.0.0" + }; /** fFrameTick determines default frame rate limit in seconds. - 000000014116168D | C743 18 8988883C | mov dword ptr ds:[rbx+18],3C888889 | fFrameTick - 0000000141161694 | 4C:89AB 70020000 | mov qword ptr ds:[rbx+270],r13 | + 0000000141161FCD | C743 18 8988883C | mov dword ptr ds:[rbx+18],3C888889 | fFrameTick + 0000000141161FD4 | 4C:89AB 70020000 | mov qword ptr ds:[rbx+270],r13 | + + 0000000141161694 (Version 1.2.0.0) */ internal const string PATTERN_FRAMELOCK = "88 88 3C 4C 89 AB"; // first byte can can be 88/90 instead of 89 due to precision loss on floating point numbers internal const int PATTERN_FRAMELOCK_OFFSET = -1; // offset to byte array from found position @@ -25,11 +31,13 @@ namespace SekiroFpsUnlockAndMore Reference pointer pFrametimeRunningSpeed to speed table entry that gets used in calculations. Add or remove multiplications of 4bytes to pFrametimeRunningSpeed address to use a higher or lower fFrametimeCriticalRunningSpeed from table. fFrametimeCriticalRunningSpeed should be roughly half the frame rate: 30 @ 60FPS limit, 50 @ 100FPS limit... - 00000001407D4DFD | F3:0F58D0 | addss xmm2,xmm0 | - 00000001407D4E01 | 0FC6D2 00 | shufps xmm2,xmm2,0 | - 00000001407D4E05 | 0F51C2 | sqrtps xmm0,xmm2 | - 00000001407D4E08 | F3:0F5905 90309202 | mulss xmm0,dword ptr ds:[1430F7EA0] | pFrametimeRunningSpeed->fFrametimeCriticalRunningSpeed - 00000001407D4E10 | 0F2FF8 | comiss xmm7,xmm0 | + 00000001407D4F3D | F3:0F58D0 | addss xmm2,xmm0 | + 00000001407D4F41 | 0FC6D2 00 | shufps xmm2,xmm2,0 | + 00000001407D4F45 | 0F51C2 | sqrtps xmm0,xmm2 | + 00000001407D4F48 | F3:0F5905 E8409202 | mulss xmm0,dword ptr ds:[1430F9038] | pFrametimeRunningSpeed->fFrametimeCriticalRunningSpeed + 00000001407D4F50 | 0F2FF8 | comiss xmm7,xmm0 | + + 00000001407D4E08 (Version 1.2.0.0) */ internal const string PATTERN_FRAMELOCK_SPEED_FIX = "F3 0F 58 ?? 0F C6 ?? 00 0F 51 ?? F3 0F 59 ?? ?? ?? ?? ?? 0F 2F"; internal const int PATTERN_FRAMELOCK_SPEED_FIX_OFFSET = 15; @@ -97,10 +105,12 @@ namespace SekiroFpsUnlockAndMore /** Reference pointer pCurrentResolutionWidth to iInternalGameWidth (and iInternalGameHeight which is +4 bytes). - 000000014114AC85 | 0F57D2 | xorps xmm2,xmm2 | - 000000014114AC88 | 890D 92147D02 | mov dword ptr ds:[14391C120],ecx | pCurrentResolutionWidth->iInternalGameWidth - 000000014114AC8E | 0F57C9 | xorps xmm1,xmm1 | - 000000014114AC91 | 8915 8D147D02 | mov dword ptr ds:[14391C124],edx | pCurrentResolutionHeight->iInternalGameHeight + 000000014114B5C5 | 0F57D2 | xorps xmm2,xmm2 | + 000000014114B5C8 | 890D 521B7D02 | mov dword ptr ds:[14391D120],ecx | + 000000014114B5CE | 0F57C9 | xorps xmm1,xmm1 | + 000000014114B5D1 | 8915 4D1B7D02 | mov dword ptr ds:[14391D124],edx | + + 000000014114AC88 (Version 1.2.0.0) */ internal const string PATTERN_RESOLUTION_POINTER = "0F 57 D2 89 0D ?? ?? ?? ?? 0F 57 C9"; internal const int PATTERN_RESOLUTION_POINTER_OFFSET = 3; @@ -119,11 +129,11 @@ namespace SekiroFpsUnlockAndMore /** Conditional jump instruction that determines if 16/9 scaling for game is enforced or not, overwrite with non conditional JMP so widescreen won't get clinched. - 0000000140129678 | 85C9 | test ecx,ecx | - 000000014012967A | 74 47 | je sekiro.1401296C3 | calculation for screen scaling - 000000014012967C | 47:8B94C7 1C020000 | mov r10d,dword ptr ds:[r15+r8*8+21C] | resolution scaling calculation method within jump... - 0000000140129684 | 45:85D2 | test r10d,r10d | - 0000000140129687 | 74 3A | je sekiro.1401296C3 | + 0000000140129678 | 85C9 | test ecx,ecx | + 000000014012967A | 74 47 | je sekiro.1401296C3 | calculation for screen scaling + 000000014012967C | 47:8B94C7 1C020000 | mov r10d,dword ptr ds:[r15+r8*8+21C] | resolution scaling calculation method within jump... + 0000000140129684 | 45:85D2 | test r10d,r10d | + 0000000140129687 | 74 3A | je sekiro.1401296C3 | */ internal const string PATTERN_RESOLUTION_SCALING_FIX = "85 C9 74 ?? 47 8B ?? ?? ?? ?? ?? ?? 45 ?? ?? 74"; internal static readonly byte[] PATCH_RESOLUTION_SCALING_FIX_ENABLE = new byte[3] { 0x90, 0x90, 0xEB }; // nop; jmp @@ -133,9 +143,11 @@ namespace SekiroFpsUnlockAndMore /** Reference pointer pFovTableEntry to FOV entry in game FOV table that gets used in FOV calculations. Overwrite pFovTableEntry address to use a higher or lower fFOV from table. FOV is in radians while default is 1.0deg (0.0174533rad), to increase by 25% you'd write 1.25deg (0.0218166rad) as fFov. - 0000000140739548 | F3:0F1008 | movss xmm1,dword ptr ds:[rax] | - 000000014073954C | F3:0F590D 0CE79B02 | mulss xmm1,dword ptr ds:[1430F7C60] | pFovTableEntry->fFov - 0000000140739554 | F3:0F5C4E 50 | subss xmm1,dword ptr ds:[rsi+50] | + 00000001407395A8 | F3:0F1008 | movss xmm1,dword ptr ds:[rax] | + 00000001407395AC | F3:0F590D 44F89B02 | mulss xmm1,dword ptr ds:[1430F8DF8] | pFovTableEntry->fFov + 00000001407395B4 | F3:0F5C4E 50 | subss xmm1,dword ptr ds:[rsi+50] | + + 000000014073954C (Version 1.2.0.0) */ // credits to 'jackfuste' for original offset internal const string PATTERN_FOVSETTING = "F3 0F 10 08 F3 0F 59 0D ?? ?? ?? ?? F3 0F 5C 4E"; @@ -145,13 +157,15 @@ namespace SekiroFpsUnlockAndMore /** Reference pointer pPlayerStatsRelated to PlayerStats pointer, offset in struct to iPlayerDeaths. - 00000001407AAC92 | 0FB648 7A | movzx ecx,byte ptr ds:[rax+7A] | - 00000001407AAC96 | 888B F7000000 | mov byte ptr ds:[rbx+F7],cl | - 00000001407AAC9C | 48:8B05 4DD03903 | mov rax,qword ptr ds:[143B47CF0] | - 00000001407AACA3 | 8B88 8C000000 | mov ecx,dword ptr ds:[rax+8C] | - 00000001407AACA9 | 898B F8000000 | mov dword ptr ds:[rbx+F8],ecx | - 00000001407AACAF | 48:8B05 3AD03903 | mov rax,qword ptr ds:[143B47CF0] | pPlayerStatsRelated->[PlayerStats+0x90]->iPlayerDeaths - 00000001407AACB6 | 8B88 90000000 | mov ecx,dword ptr ds:[rax+90] | offset pPlayerStats->iPlayerDeaths + 00000001407AAD51 | 0FB648 7A | movzx ecx,byte ptr ds:[rax+7A] | + 00000001407AAD55 | 888B F7000000 | mov byte ptr ds:[rbx+F7],cl | + 00000001407AAD5B | 48:8B05 CEDF3903 | mov rax,qword ptr ds:[143B48D30] | + 00000001407AAD62 | 8B88 8C000000 | mov ecx,dword ptr ds:[rax+8C] | + 00000001407AAD68 | 898B F8000000 | mov dword ptr ds:[rbx+F8],ecx | + 00000001407AAD6E | 48:8B05 BBDF3903 | mov rax,qword ptr ds:[143B48D30] | pPlayerStatsRelated->[PlayerStats+0x90]->iPlayerDeaths + 00000001407AAD75 | 8B88 90000000 | mov ecx,dword ptr ds:[rax+90] | offset pPlayerStats->iPlayerDeaths + + 00000001407AACAF (Version 1.2.0.0) */ // credits to 'Me_TheCat' for original offset internal const string PATTERN_PLAYER_DEATHS = "0F B6 48 ?? 88 8B ?? ?? 00 00 48 8B 05 ?? ?? ?? ?? 8B 88 ?? ?? 00 00 89 8B ?? ?? 00 00 48 8B 05 ?? ?? ?? ?? 8B 88 ?? ?? 00 00"; @@ -162,9 +176,11 @@ namespace SekiroFpsUnlockAndMore /** Reference pointer pTotalKills to iTotalKills, does not get updated on every kill but mostly on every 2nd, includes own player deaths... - 0000000141151838 | 48:8D0D A9A5B302 | lea rcx,qword ptr ds:[143C8BDE8] | pTotalKills->iTotalKills - 000000014115183F | 891481 | mov dword ptr ds:[rcx+rax*4],edx | - 0000000141151842 | C3 | ret | + 0000000141152178 | 48:8D0D A9ACB302 | lea rcx,qword ptr ds:[143C8CE28] | pTotalKills->iTotalKills + 000000014115217F | 891481 | mov dword ptr ds:[rcx+rax*4],edx | + 0000000141152182 | C3 | ret | + + 0000000141151838 (Version 1.2.0.0) */ // credits to 'Me_TheCat' for original offset internal const string PATTERN_TOTAL_KILLS = "48 8D 0D ?? ?? ?? ?? 89 14 81 C3"; @@ -173,11 +189,13 @@ namespace SekiroFpsUnlockAndMore /** Controls camera pitch. xmm4 holds new pitch from a calculation while rps+170 holds current one from mouse so we overwrite xmm4 with the old pitch value. - 000000014073AF26 | 0F29A5 70080000 | movaps xmmword ptr ss:[rbp+870],xmm4 | code inject overwrite from here - 000000014073AF2D | 0F29A5 80080000 | movaps xmmword ptr ss:[rbp+880],xmm4 | jump back here from code inject - 000000014073AF34 | 0F29A6 70010000 | movaps xmmword ptr ds:[rsi+170],xmm4 | camPitch, newCamPitch - 000000014073AF3B | EB 1C | jmp sekiro.14073AF59 | - 000000014073AF3D | F3:0F108E 74010000 | movss xmm1,dword ptr ds:[rsi+174] | + 000000014073AF86 | 0F29A5 70080000 | movaps xmmword ptr ss:[rbp+870],xmm4 | code inject overwrite from here + 000000014073AF8D | 0F29A5 80080000 | movaps xmmword ptr ss:[rbp+880],xmm4 | jump back here from code inject + 000000014073AF94 | 0F29A6 70010000 | movaps xmmword ptr ds:[rsi+170],xmm4 | camPitch, newCamPitch + 000000014073AF9B | EB 1C | jmp sekiro.14073AFB9 | + 000000014073AF9D | F3:0F108E 74010000 | movss xmm1,dword ptr ds:[rsi+174] | + + 000000014073AF26 (Version 1.2.0.0) */ internal const string PATTERN_CAMADJUST_PITCH = "0F 29 ?? ?? ?? 00 00 0F 29 ?? ?? ?? 00 00 0F 29 ?? ?? ?? 00 00 EB ?? F3"; internal const int INJECT_CAMADJUST_PITCH_OVERWRITE_LENGTH = 7; @@ -188,10 +206,12 @@ namespace SekiroFpsUnlockAndMore }; /** Controls automatic camera yaw adjust on move on Z-axis. xmm0 holds new yaw while rsi+174 holds current one prior movement so we overwrite xmm0 with the old yaw value. - 000000014073AF4C | E8 6F60FFFF | call sekiro.140730FC0 | - 000000014073AF51 | F3:0F1186 74010000 | movss dword ptr ds:[rsi+174],xmm0 | camYaw, newCamYaw | code inject overwrite from here - 000000014073AF59 | 80BE A3020000 00 | cmp byte ptr ds:[rsi+2A3],0 | jump back here from code inject - 000000014073AF60 | 0F84 2F020000 | je sekiro.14073B195 | + 000000014073AFAC | E8 6F60FFFF | call sekiro.140731020 | + 000000014073AFB1 | F3:0F1186 74010000 | movss dword ptr ds:[rsi+174],xmm0 | camYaw, newCamYaw | code inject overwrite from here + 000000014073AFB9 | 80BE A3020000 00 | cmp byte ptr ds:[rsi+2A3],0 | jump back here from code inject + 000000014073AFC0 | 0F84 2F020000 | je sekiro.14073B1F5 | + + 000000014073AF51 (Version 1.2.0.0) */ internal const string PATTERN_CAMADJUST_YAW_Z = "E8 ?? ?? ?? ?? F3 ?? ?? ?? ?? ?? 00 00 80 ?? ?? ?? 00 00 00 0F 84"; internal const int PATTERN_CAMADJUST_YAW_Z_OFFSET = 5; @@ -210,9 +230,17 @@ namespace SekiroFpsUnlockAndMore 000000014073B482 | F3:0F1085 E4120000 | movss xmm0,dword ptr ss:[rbp+12E4] | jump back here from code inject 000000014073B48A | E8 91BDFFFF | call sekiro.140737220 | 000000014073B48F | 0F28D0 | movaps xmm2,xmm0 | + + 000000014073B4D6 | F3:0F1000 | movss xmm0,dword ptr ds:[rax] | newCamPitch | code inject overwrite from here + 000000014073B4DA | F3:0F1186 70010000 | movss dword ptr ds:[rsi+170],xmm0 | camePitch + 000000014073B4E2 | F3:0F1085 E4120000 | movss xmm0,dword ptr ss:[rbp+12E4] | jump back here from code inject + 000000014073B4EA | E8 91BDFFFF | call sekiro.140737280 | + 000000014073B4EF | 0F28D0 | movaps xmm2,xmm0 | + + 000000014073B47A (Version 1.2.0.0) */ // thanks to 'Cielos' for original offset - internal const string PATTERN_CAMADJUST_PITCH_XY = "F3 ?? ?? ?? F3 ?? ?? ?? ?? ?? 00 00 F3 ?? ?? ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 0F"; + internal const string PATTERN_CAMADJUST_PITCH_XY = "F3 ?? ?? ?? F3 ?? ?? ?? 70 01 00 00 F3 ?? ?? ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 0F"; internal const int INJECT_CAMADJUST_PITCH_XY_OVERWRITE_LENGTH = 12; internal static readonly byte[] INJECT_CAMADJUST_PITCH_XY_SHELLCODE = new byte[] { @@ -223,9 +251,11 @@ namespace SekiroFpsUnlockAndMore }; /** Controls automatic camera yaw adjust on move on XY-axis. xmm0 new yaw while rsi+174 holds current one prior movement so we overwrite xmm0 with the old yaw value. - 000000014073B564 | E8 B7BCFFFF | call sekiro.140737220 | - 000000014073B569 | F3:0F1186 74010000 | movss dword ptr ds:[rsi+174],xmm0 | camYaw, newCamYaw | code inject overwrite from here - 000000014073B571 | E9 9A020000 | jmp sekiro.14073B810 | jump back here from code inject + 000000014073B5C4 | E8 B7BCFFFF | call sekiro.140737280 | + 000000014073B5C9 | F3:0F1186 74010000 | movss dword ptr ds:[rsi+174],xmm0 | camYaw, newCamYaw | code inject overwrite from here + 000000014073B5D1 | E9 9A020000 | jmp sekiro.14073B870 | jump back here from code inject + + 000000014073B569 (Version 1.2.0.0) */ // thanks to 'Cielos' for original offset internal const string PATTERN_CAMADJUST_YAW_XY = "E8 ?? ?? ?? ?? F3 0F 11 86 ?? ?? 00 00 E9"; @@ -240,8 +270,10 @@ namespace SekiroFpsUnlockAndMore /** When user presses button to lock on target but no target is in range a camera reset is triggered to center cam position. This boolean indicates if we need to reset or not. - 000000014073AD97 | C686 A3020000 01 | mov byte ptr ds:[rsi+2A3],1 | Sets bool to indicate we need to reset camera and block user input til cam is reset - 000000014073AD9E | F3:0F108E B4020000 | movss xmm1,dword ptr ds:[rsi+2B4] | + 000000014073ADF7 | C686 A3020000 01 | mov byte ptr ds:[rsi+2A3],1 | Sets bool to indicate we need to reset camera and block user input til cam is reset + 000000014073ADFE | F3:0F108E B4020000 | movss xmm1,dword ptr ds:[rsi+2B4] | + + 000000014073AD97 (Version 1.2.0.0) */ internal const string PATTERN_CAMRESET_LOCKON = "C6 86 ?? ?? 00 00 ?? F3 0F 10 8E ?? ?? 00 00"; internal const int PATTERN_CAMRESET_LOCKON_OFFSET = 6; @@ -252,29 +284,31 @@ namespace SekiroFpsUnlockAndMore /** Whole dragonrot routine upon death is guarded by a conditional jump, there may be some events in the game where a true death shall not increase the disease so it's skippable as a whole. We replace conditional jump with non-conditional one. - 00000001411891E8 | 45:33C0 | xor r8d,r8d | - 00000001411891EB | BA 27250000 | mov edx,2527 | - 00000001411891F0 | E8 AB8353FF | call sekiro.1406C15A0 | - 00000001411891F5 | 84C0 | test al,al | - 00000001411891F7 | 0F85 E6010000 | jne sekiro.1411893E3 | handle dragonrot? - 00000001411891FD | 48:8B0D 44A09B02 | mov rcx,qword ptr ds:[143B43248] | dragonrot routine... - 0000000141189204 | 48:85C9 | test rcx,rcx | - 0000000141189207 | 75 2E | jne sekiro.141189237 | - 0000000141189209 | 48:8D0D 19929B02 | lea rcx,qword ptr ds:[143B42429] | - 0000000141189210 | E8 5B178100 | call sekiro.14199A970 | - 0000000141189215 | 4C:8BC8 | mov r9,rax | - 0000000141189218 | 4C:8D05 510EF601 | lea r8,qword ptr ds:[1430EA070] | - 000000014118921F | BA B1000000 | mov edx,B1 | - 0000000141189224 | 48:8D0D 85216601 | lea rcx,qword ptr ds:[1427EB3B0] | - 000000014118922B | E8 808F8000 | call sekiro.1419921B0 | - 0000000141189230 | 48:8B0D 11A09B02 | mov rcx,qword ptr ds:[143B43248] | - 0000000141189237 | 45:33C0 | xor r8d,r8d | - 000000014118923A | BA 28250000 | mov edx,2528 | - 000000014118923F | E8 5C8353FF | call sekiro.1406C15A0 | - 0000000141189244 | 84C0 | test al,al | - 0000000141189246 | 0F84 B2000000 | je sekiro.1411892FE | increase dragonrot level on NPCs? - 000000014118924C | 48:8D8424 90000000 | lea rax,qword ptr ss:[rsp+90] | executes after a certain deaths threshold has been reached... - */ + 0000000141189D18 | 45:33C0 | xor r8d,r8d | + 0000000141189D1B | BA 27250000 | mov edx,2527 | + 0000000141189D20 | E8 DB7853FF | call sekiro.1406C1600 | + 0000000141189D25 | 84C0 | test al,al | + 0000000141189D27 | 0F85 E6010000 | jne sekiro.141189F13 | handle dragonrot? + 0000000141189D2D | 48:8B0D 54A59B02 | mov rcx,qword ptr ds:[143B44288] | dragonrot routine... + 0000000141189D34 | 48:85C9 | test rcx,rcx | + 0000000141189D37 | 75 2E | jne sekiro.141189D67 | + 0000000141189D39 | 48:8D0D 29979B02 | lea rcx,qword ptr ds:[143B43469] | + 0000000141189D40 | E8 5B178100 | call sekiro.14199B4A0 | + 0000000141189D45 | 4C:8BC8 | mov r9,rax | + 0000000141189D48 | 4C:8D05 5914F601 | lea r8,qword ptr ds:[1430EB1A8] | + 0000000141189D4F | BA B1000000 | mov edx,B1 | + 0000000141189D54 | 48:8D0D 55266601 | lea rcx,qword ptr ds:[1427EC3B0] | + 0000000141189D5B | E8 808F8000 | call sekiro.141992CE0 | + 0000000141189D60 | 48:8B0D 21A59B02 | mov rcx,qword ptr ds:[143B44288] | + 0000000141189D67 | 45:33C0 | xor r8d,r8d | + 0000000141189D6A | BA 28250000 | mov edx,2528 | + 0000000141189D6F | E8 8C7853FF | call sekiro.1406C1600 | + 0000000141189D74 | 84C0 | test al,al | + 0000000141189D76 | 0F84 B2000000 | je sekiro.141189E2E | increase dragonrot level on NPCs? + 0000000141189D7C | 48:8D8424 90000000 | lea rax,qword ptr ss:[rsp+90] | executes after a certain deaths threshold has been reached... + + 00000001411891F7 (Version 1.2.0.0) + */ internal const string PATTERN_DRAGONROT_EFFECT = "45 ?? ?? BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 0F 85 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 4C ?? ?? 4C ?? ?? ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 45 ?? ?? BA ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 0F 84 ?? ?? ?? ?? 48 8D"; internal const int PATTERN_DRAGONROT_EFFECT_OFFSET = 13; internal static readonly byte[] PATCH_DRAGONROT_EFFECT_DISABLE = new byte[4] { 0x90, 0x90, 0x90, 0xE9 }; // nop; jmp @@ -283,11 +317,13 @@ 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. - 0000000141189044 | F344:0F2CE9 | cvttss2si r13d,xmm1 | - 0000000141189049 | 41:8BD5 | mov edx,r13d | - 000000014118904C | 48:8BCB | mov rcx,rbx | - 000000014118904F | E8 CC244EFF | call sekiro.14066B520 | -> ManipulatePlayerValues() - 0000000141189054 | 8BAB 60010000 | mov ebp,dword ptr ds:[rbx+160] | + 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] | + + 000000014118904F (Version 1.2.0.0) */ internal const string PATTERN_DEATHPENALTIES1 = "F3 ?? 0F 2C ?? 41 ?? ?? 48 ?? ?? E8 ?? ?? ?? ?? 8B"; internal const int PATTERN_DEATHPENALTIES1_OFFSET = 11; @@ -295,13 +331,15 @@ 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. - 0000000141189138 | 8B00 | mov eax,dword ptr ds:[rax] | - 000000014118913A | 8983 60010000 | mov dword ptr ds:[rbx+160],eax | OnDeath() ability points (AP) decrease - 0000000141189140 | 45:2BFD | sub r15d,r13d | - 0000000141189143 | 44:89BC24 90000000 | mov dword ptr ss:[rsp+90],r15d | virtual Sen decrease - shows how many Sen got lost after death - 000000014118914B | 2BE9 | sub ebp,ecx | - 000000014118914D | 89AC24 94000000 | mov dword ptr ss:[rsp+94],ebp | virtual AP decrease - shows how many APs got lost after death - 0000000141189154 | E8 371C73FF | call sekiro.1408BAD90 | + 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 = "8B ?? 89 83 ?? ?? ?? ?? 45 ?? ?? 44 89 ?? 24 ?? ?? 00 00 2B ?? 89 ?? 24 ?? ?? 00 00 E8"; internal const int PATTERN_DEATHPENALTIES2_OFFSET = 2; @@ -316,11 +354,13 @@ namespace SekiroFpsUnlockAndMore /** - 000000014069AE2E | 0F84 DD000000 | je sekiro.14069AF11 | - 000000014069AE34 | 84DB | test bl,bl | - 000000014069AE36 | 0F85 D5000000 | jne sekiro.14069AF11 | handle death increase? - 000000014069AE3C | 48:8BCF | mov rcx,rdi | - 000000014069AE3F | E8 BCA9FEFF | call sekiro.140685800 | -> IncreaseDeaths() + 000000014069AE8E | 0F84 DD000000 | je sekiro.14069AF71 | + 000000014069AE94 | 84DB | test bl,bl | + 000000014069AE96 | 0F85 D5000000 | jne sekiro.14069AF71 | handle death increase? + 000000014069AE9C | 48:8BCF | mov rcx,rdi | + 000000014069AE9F | E8 BCA9FEFF | call sekiro.140685860 | -> IncreaseDeaths() + + 000000014069AE36 (Version 1.2.0.0) */ internal const string PATTERN_DEATHSCOUNTER = "0F 84 ?? ?? ?? ?? 84 DB 0F 85 ?? ?? ?? ?? 48 8B ?? E8"; internal const int PATTERN_DEATHSCOUNTER_OFFSET = 6; @@ -330,9 +370,11 @@ namespace SekiroFpsUnlockAndMore /** Reference pointer pTimeRelated to TimescaleManager pointer, offset in struct to fTimescale which acts as a global speed scale for almost all ingame calculations. - 0000000141149E87 | 48:8B05 3A24B402 | mov rax,qword ptr ds:[143C8C2C8] | pTimeRelated->[TimescaleManager+0x360]->fTimescale - 0000000141149E8E | F3:0F1088 60030000 | movss xmm1,dword ptr ds:[rax+360] | offset TimescaleManager->fTimescale - 0000000141149E96 | F3:0F5988 68020000 | mulss xmm1,dword ptr ds:[rax+268] | + 000000014114A7C7 | 48:8B05 3A2BB402 | mov rax,qword ptr ds:[143C8D308] | pTimeRelated->[TimescaleManager+0x360]->fTimescale + 000000014114A7CE | F3:0F1088 60030000 | movss xmm1,dword ptr ds:[rax+360] | offset TimescaleManager->fTimescale + 000000014114A7D6 | F3:0F5988 68020000 | mulss xmm1,dword ptr ds:[rax+268] | + + 0000000141149E87 (Version 1.2.0.0) */ // credits to 'Zullie the Witch' for original offset internal const string PATTERN_TIMESCALE = "48 8B 05 ?? ?? ?? ?? F3 0F 10 88 ?? ?? ?? ?? F3 0F"; @@ -342,11 +384,13 @@ namespace SekiroFpsUnlockAndMore /** Reference pointer pPlayerStructRelated1 to 4 more pointers up to player data class, offset in struct to fTimescalePlayer which acts as a speed scale for the player character. - 00000001406BF1D7 | 48:8B1D 128C4A03 | mov rbx,qword ptr ds:[143B67DF0] | pPlayerStructRelated1->[pPlayerStructRelated2+0x88]->[pPlayerStructRelated3+0x1FF8]->[pPlayerStructRelated4+0x28]->[pPlayerStructRelated5+0xD00]->fTimescalePlayer - 00000001406BF1DE | 48:85DB | test rbx,rbx | - 00000001406BF1E1 | 74 3C | je sekiro.1406BF21F | - 00000001406BF1E3 | 8B17 | mov edx,dword ptr ds:[rdi] | - 00000001406BF1E5 | 81FA 10270000 | cmp edx,2710 | + 00000001406BF237 | 48:8B1D F29B4A03 | mov rbx,qword ptr ds:[143B68E30] | pPlayerStructRelated1->[pPlayerStructRelated2+0x88]->[pPlayerStructRelated3+0x1FF8]->[pPlayerStructRelated4+0x28]->[pPlayerStructRelated5+0xD00]->fTimescalePlayer + 00000001406BF23E | 48:85DB | test rbx,rbx | + 00000001406BF241 | 74 3C | je sekiro.1406BF27F | + 00000001406BF243 | 8B17 | mov edx,dword ptr ds:[rdi] | + 00000001406BF245 | 81FA 10270000 | cmp edx,2710 | + + 00000001406BF1D7 (Version 1.2.0.0) */ // credits to 'Zullie the Witch' for original offset internal const string PATTERN_TIMESCALE_PLAYER = "48 8B 1D ?? ?? ?? ?? 48 85 DB 74 ?? 8B ?? 81 FA"; diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs index 6e7eb83..ca272e6 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs @@ -314,7 +314,7 @@ namespace SekiroFpsUnlockAndMore } string gameFileVersion = FileVersionInfo.GetVersionInfo(procList[0].MainModule.FileName).FileVersion; - if (gameFileVersion != GameData.PROCESS_EXE_VERSION && !_settingsService.ApplicationSettings.gameVersionNotify) + if (gameFileVersion != GameData.PROCESS_EXE_VERSION && Array.IndexOf(GameData.PROCESS_EXE_VERSION_SUPPORTED, gameFileVersion) < 0 && !_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); @@ -507,6 +507,7 @@ namespace SekiroFpsUnlockAndMore long lpPlayerStructRelated1 = patternScan.FindPattern(GameData.PATTERN_TIMESCALE_PLAYER); Debug.WriteLine("lpPlayerStructRelated1 found at: 0x" + lpPlayerStructRelated1.ToString("X")); + if (IsValidAddress(lpPlayerStructRelated1)) { long lpPlayerStructRelated2 = DereferenceStaticX64Pointer(_gameAccessHwndStatic, lpPlayerStructRelated1, GameData.PATTERN_TIMESCALE_PLAYER_INSTRUCTION_LENGTH); diff --git a/SekiroFpsUnlockAndMore/PatternScan.cs b/SekiroFpsUnlockAndMore/PatternScan.cs index 61df0a6..f28e7f7 100644 --- a/SekiroFpsUnlockAndMore/PatternScan.cs +++ b/SekiroFpsUnlockAndMore/PatternScan.cs @@ -72,13 +72,12 @@ namespace SekiroFpsUnlockAndMore long ix; int iy; bool bFound = false; - int patternLength = bPattern.Length; - int dataLength = bData.Length - patternLength; + int dataLength = bData.Length - bPattern.Length; for (ix = 0; ix < dataLength; ix++) { bFound = true; - for (iy = 0; iy < patternLength; iy++) + for (iy = bPattern.Length - 1; iy > -1; iy--) { if (szMask[iy] != 'x' || bPattern[iy] == bData[ix + iy]) continue; @@ -87,7 +86,7 @@ namespace SekiroFpsUnlockAndMore } if (bFound) - return Convert.ToInt64((long) dwStart + ix); + return dwStart + ix; } return 0; diff --git a/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs b/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs index 3bdd610..52350e9 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.3.0")] -[assembly: AssemblyFileVersion("1.2.3.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.2.3.1")] +[assembly: AssemblyFileVersion("1.2.3.1")] \ No newline at end of file From 1436dc281d72bdac0ab340c20ccadb61010a61a9 Mon Sep 17 00:00:00 2001 From: uberhalit Date: Tue, 23 Apr 2019 13:32:14 +0200 Subject: [PATCH 03/10] updated readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 471b610..305006c 100644 --- a/README.md +++ b/README.md @@ -229,6 +229,8 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Version History +* v1.2.3.1 (2019-04-23) + * added game version 1.03 (1.3.0.0) to supported versions * v1.2.3.0 (2019-04-18) * Added option to prevent increase of dragonrot upon death * Added option to disable Sen and experience penalties upon death From e158678422f34da1825474e94f6046cacb0cefae Mon Sep 17 00:00:00 2001 From: uberhalit Date: Fri, 26 Apr 2019 19:33:12 +0200 Subject: [PATCH 04/10] added hotkey to toggle speed modifiers added game version 1.04 to supported versions --- README.md | 15 ++++++++----- SekiroFpsUnlockAndMore.sln.DotSettings.user | 6 ------ SekiroFpsUnlockAndMore/GameData.cs | 5 +++-- SekiroFpsUnlockAndMore/MainWindow.xaml | 1 + SekiroFpsUnlockAndMore/MainWindow.xaml.cs | 24 ++++++++++++++++++--- 5 files changed, 35 insertions(+), 16 deletions(-) delete mode 100644 SekiroFpsUnlockAndMore.sln.DotSettings.user diff --git a/README.md b/README.md index 305006c..0946889 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Patches games memory while running, does not modify any game files. Works with e * automatically patch game on startup * seamlessly switch between windowed, borderless and borderless fullscreen * hotkey for patching while in (borderless) window mode +* hotkey for toggling speed modifier while in (borderless) window mode ## Usage @@ -68,12 +69,13 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s 6. Press the yellow star icon in the menu bar to create a new Profile (1) 7. [![Vertical sync Off and Preferred refresh rate Highest available](https://camo.githubusercontent.com/531be3614b0742e9065f8c2a19df7e31afcdc7ed/68747470733a2f2f692e696d6775722e636f6d2f6f75664a7239632e706e67)](#) 8. Name it `Sekiro` and select it in dropdown -9. Press the blue window icon with the plus symbol to add an application to this profile (2) +9. Press the blue window icon with the plus symbol to add an application to this profile (2) 10. Change file type to `Application Absolute Path`, navigate to your `sekiro.exe` and select it 11. [![Application Absolute Path](https://camo.githubusercontent.com/0bb8ace024658dfcb31c5f3347df1505854819ec/68747470733a2f2f692e696d6775722e636f6d2f545669495357562e706e67)](#) 12. Make sure that the file path to the game is correct (3) 13. Under `2 - Sync and Refresh` set `Prefered Refreshrate` to `Highest available` and `Vertical Sync` to `Force off` (4) 14. Hit `Apply changes` and you are good to go (5) +15. The success rate of these steps depend on your GPU and monitor combination, most will work fine however some (mostly older ones) wont, if your monitor is still locked at 60Hz in fullscreen after this then your only option remaining is to play in windowed mode. ### Follow these steps on AMD: 1. Right click on Desktop -> `Display settings` @@ -151,11 +153,10 @@ This option will remove the effect dragonrot has on NPCs, if an NPC already got Like 'Unseen Aid' you will not lose any Sen or Experience upon death with this option enabled. Dragonrot will not be modified, check the option above to prevent dragonrot from increasing. ### On 'Game speed': -Slow down the game to beat a boss like a game journalist or speed it up and become gud. Game speed acts as a global time scale and is used by the game itself to create a dramatic effect in a few cutscenes. All game physics (even opening the menu) will be affected equally: all time-critical windows like dodge and deflect will be proportionally prolonged or shortened while the amount of damage given and taken as well as all other damage physics will be unaltered. A hit from an enemy on 150% game speed will do the exact same damage as on 80%, the deflect window on 50% is exactly twice as long as on 100% and so on. Of course, Sekiro himself will be affected by the speed too so even though a time window might me different now, the speed which you can react on it is different too. -Be aware that both speed modifications can potentially crash the game in certain cutscenes and NPC interactions so use them with caution. +Slow down the game to beat a boss like a game journalist or speed it up and become gud. Game speed acts as a global time scale and is used by the game itself to create a dramatic effect in a few cutscenes. All game physics (even opening the menu) will be affected equally: all time-critical windows like dodge and deflect will be proportionally prolonged or shortened while the amount of damage given and taken as well as all other damage physics will be unaltered. A hit from an enemy on 150% game speed will do the exact same damage as on 80%, the deflect window on 50% is exactly twice as long as on 100% and so on. Of course, Sekiro himself will be affected by the speed too so even though a time window might be different now, the speed which you can react on it is different too. Can be toggled by pressing CTRL+M. Be aware that both speed modifications can potentially crash the game in certain cutscenes and NPC interactions so use them with caution. ### On 'Player speed': -This modifier enables you to control Sekiro's speed independently from general game speed. Combat physics however are not guaranteed to stay the same on every setting. For example if you increase player speed you will be able to react to an attack faster but your own 'deflect' window is shorter now because you move faster. Use this to explore the world or to keep player speed near normal while decreasing general game speed. Grappling as well as jumping is handled by game speed while falling damage is calculated based on player speed so take care when grappling to a lower level with a low game speed and high player speed as this could instantly kill you as the game thinks you fell to death. +This modifier enables you to control Sekiro's speed independently from general game speed. Combat physics however are not guaranteed to stay the same on every setting. For example if you increase player speed you will be able to react to an attack faster but your own 'deflect' window is shorter now because you move faster. Use this to explore the world or to keep player speed near normal while altering general game speed. Grappling as well as jumping is handled by game speed while falling damage is calculated based on player speed so take care when grappling to a lower level with a low game speed and high player speed as this could instantly kill you as the game thinks you fell to death. Be aware that both speed modifications can potentially crash the game in certain cutscenes and NPC interactions so use them with caution. ## Troubleshooting: @@ -219,6 +220,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file * the game has forced VSYNC so unlocking the frame rate when your monitor has 60Hz will do nothing. You'll have to disable VSYNC in Nvidia Control Panel or AMD Radeon Settings first, see Usage * in fullscreen the game forces the monitor to 60 Hz so you'll have to handle this with driver override too, see Usage +* if your monitor does not support Hz override (Preferred Refreshrate missing and Profile Inspector won't work either) you won't be able to play at a higher refresh rate in fullscreen, play in windowed mode as an alternative * your monitor has to natively support your custom resolution otherwise it won't show up correctly * if a custom resolution is used it has to be added and selected before enabling borderless window * due to how the game renders the HUD is limited to 16:9 even on 21:9 resolutions @@ -229,6 +231,9 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Version History +* v1.2.3.2 (2019-04-26) + * added hotkey to toggle speed modifiers (CTRL+M) + * added game version 1.04 (1.4.0.0) to supported versions * v1.2.3.1 (2019-04-23) * added game version 1.03 (1.3.0.0) to supported versions * v1.2.3.0 (2019-04-18) @@ -268,7 +273,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file * FOV will now stick even between loads * Fixed a potential issue with unlimited frame rate unlock * Fixed a potential issue when user tried to enable borderless while in minimized fullscreen - * Improved initial load time til game is patchable + * Improved initial load time till game is patchable * v1.0.2.0 (2019-03-26) * Added option to reduce FOV (request) * Added option to stretch borderless window to fullscreen regardless of window resolution diff --git a/SekiroFpsUnlockAndMore.sln.DotSettings.user b/SekiroFpsUnlockAndMore.sln.DotSettings.user deleted file mode 100644 index 708f005..0000000 --- a/SekiroFpsUnlockAndMore.sln.DotSettings.user +++ /dev/null @@ -1,6 +0,0 @@ - - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="PATTERN_" Suffix="" Style="AA_BB" /> - <Policy Inspect="True" Prefix="WS_" Suffix="" Style="AA_BB"><ExtraRule Prefix="" Suffix="" Style="AA_BB" /></Policy> - 2 \ No newline at end of file diff --git a/SekiroFpsUnlockAndMore/GameData.cs b/SekiroFpsUnlockAndMore/GameData.cs index bbcd378..737e76e 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.3.0.0"; - internal static readonly string[] PROCESS_EXE_VERSION_SUPPORTED = new string[1] + internal const string PROCESS_EXE_VERSION = "1.4.0.0"; + internal static readonly string[] PROCESS_EXE_VERSION_SUPPORTED = new string[2] { + "1.3.0.0", "1.2.0.0" }; diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml b/SekiroFpsUnlockAndMore/MainWindow.xaml index 24e41c7..b0aff60 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml @@ -76,6 +76,7 @@ Custom resolution adds 21:9 support and overwrites a default resolution, hud will be limited to 16:9. Borderless window mode with custom resolution requires you to patch and set resolution first, then activate borderless afterwards. Disabling camera auto rotate is mostly intended for mouse users. + Both speed modifiers can be toggled by pressing hotkey CTRL+M. To enable Player Speed modification you have to be ingame first. See the link below for detailed information, guides, GSYNC support and an AMD fix. diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs index ca272e6..b52667c 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs @@ -100,8 +100,8 @@ namespace SekiroFpsUnlockAndMore this.sbInput.Text = _settingsService.ApplicationSettings.peasantInput ? "Controller" : "Mouse"; IntPtr hWnd = new WindowInteropHelper(this).Handle; - if (!RegisterHotKey(hWnd, 9009, MOD_CONTROL, VK_P)) - MessageBox.Show("Hotkey is already in use, it may not work.", "Sekiro FPS Unlocker and more", MessageBoxButton.OK, MessageBoxImage.Warning); + if (!RegisterHotKey(hWnd, 9009, MOD_CONTROL, VK_M) || !RegisterHotKey(hWnd, 9010, MOD_CONTROL, VK_P)) + MessageBox.Show("A Hotkey is already in use, it may not work.", "Sekiro FPS Unlocker and more", MessageBoxButton.OK, MessageBoxImage.Warning); ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage); @@ -141,6 +141,7 @@ namespace SekiroFpsUnlockAndMore ComponentDispatcher.ThreadFilterMessage -= ComponentDispatcherThreadFilterMessage; IntPtr hWnd = new WindowInteropHelper(this).Handle; UnregisterHotKey(hWnd, 9009); + UnregisterHotKey(hWnd, 9010); if (_gameAccessHwnd != IntPtr.Zero) CloseHandle(_gameAccessHwnd); } @@ -153,7 +154,23 @@ namespace SekiroFpsUnlockAndMore if (handled) return; if (msg.message != WM_HOTKEY_MSG_ID) return; - if (msg.wParam.ToInt32() == 9009) // patch game + if (msg.wParam.ToInt32() == 9009) // toggle speed modifier + { + if (this.cbGameSpeed.IsEnabled && this.cbPlayerSpeed.IsEnabled) + { + if (this.cbGameSpeed.IsChecked == false) + { + this.cbGameSpeed.IsChecked = true; + this.cbPlayerSpeed.IsChecked = true; + } + else + { + this.cbGameSpeed.IsChecked = false; + this.cbPlayerSpeed.IsChecked = false; + } + } + } + else if (msg.wParam.ToInt32() == 9010) // patch game { handled = true; PatchGame(); @@ -1724,6 +1741,7 @@ namespace SekiroFpsUnlockAndMore private const int WM_HOTKEY_MSG_ID = 0x0312; private const int MOD_CONTROL = 0x0002; + private const uint VK_M = 0x004D; private const uint VK_P = 0x0050; private const uint PROCESS_ALL_ACCESS = 0x001F0FFF; private const int GWL_STYLE = -16; From 50d043c75a540ede7efe7efa80c34479d19c16cb Mon Sep 17 00:00:00 2001 From: uberhalit Date: Thu, 2 May 2019 18:42:20 +0200 Subject: [PATCH 05/10] added feature to increase emblem cap on upgrades changed way to obtain kills, fixes slow stats updates improved pattern scan algorithm --- README.md | 10 ++- SekiroFpsUnlockAndMore/GameData.cs | 76 ++++++++++++++---- SekiroFpsUnlockAndMore/MainWindow.xaml | 15 ++-- SekiroFpsUnlockAndMore/MainWindow.xaml.cs | 80 ++++++++++++++++--- SekiroFpsUnlockAndMore/PatternScan.cs | 35 ++++++-- .../Properties/AssemblyInfo.cs | 4 +- SekiroFpsUnlockAndMore/SettingsService.cs | 2 + 7 files changed, 181 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 0946889..5055a65 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,9 @@ This option will remove the effect dragonrot has on NPCs, if an NPC already got ### On 'Disable death penalties (except dragonrot)': Like 'Unseen Aid' you will not lose any Sen or Experience upon death with this option enabled. Dragonrot will not be modified, check the option above to prevent dragonrot from increasing. +### On 'Increase spirit emblem cap. on upgrades': +Whenever you upgrade your prosthetic arm the maximum spirit emblem capacity will now be increased by 1 **permanently**. Deactivating this option will not remove the additional capacity gained by it. With the base 15 capacity and +5 capacity by skills the normal maximal capacity is 20, with this feature enabled you can reach up to 50 max capacity as there are 30 prosthetic upgrades. + ### On 'Game speed': Slow down the game to beat a boss like a game journalist or speed it up and become gud. Game speed acts as a global time scale and is used by the game itself to create a dramatic effect in a few cutscenes. All game physics (even opening the menu) will be affected equally: all time-critical windows like dodge and deflect will be proportionally prolonged or shortened while the amount of damage given and taken as well as all other damage physics will be unaltered. A hit from an enemy on 150% game speed will do the exact same damage as on 80%, the deflect window on 50% is exactly twice as long as on 100% and so on. Of course, Sekiro himself will be affected by the speed too so even though a time window might be different now, the speed which you can react on it is different too. Can be toggled by pressing CTRL+M. Be aware that both speed modifications can potentially crash the game in certain cutscenes and NPC interactions so use them with caution. @@ -163,6 +166,7 @@ Be aware that both speed modifications can potentially crash the game in certain * Utility can't seem to find the game? - Make sure your game exe is called `sekiro.exe` * Make sure you followed the appropriate steps and didn't skip any (especially not the deletion of the Sekiro profile!) * Try disabling `Fullscreen optimization` for Sekiro: right mouse click on `sekiro.exe -> Compatibility-> tick 'Disable fullscreen optimizations'` +* If you are using ReShade make sure your preset doesn't enforce 60 Hz, try removing ReShade and see if it solves the problem * Try adding the whole game folder and `Sekiro FPS Unlocker and more` to your antivirus's exclusion list * Try disabling `Steam Broadcast` (streaming via overlay) * Try to force disable VSYNC even when you are using GSYNC @@ -181,7 +185,7 @@ Be aware that both speed modifications can potentially crash the game in certain ## Preview -[![Sekiro FPS Unlocker and more](https://camo.githubusercontent.com/09e0d1ddd5c0216649cf20fcd7d92898492a04e6/68747470733a2f2f692e696d6775722e636f6d2f5774547632654d2e706e67)](#) +[![Sekiro FPS Unlocker and more](https://camo.githubusercontent.com/998730c9a8d472c8e426f61d0dde589661b4f378/68747470733a2f2f692e696d6775722e636f6d2f466249424271742e706e67)](#) ### Unlocked framerate [![Sekiro FPS Unlocker and more](https://camo.githubusercontent.com/53f52adb98a5111b31538466f91b58599d56d6d7/68747470733a2f2f692e696d6775722e636f6d2f4c4c524a5a554c2e706e67)](#) @@ -231,6 +235,10 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Version History +* v1.2.4.0 (2019-05-02) + * added feature to increase spirit emblem capacity on prosthetic upgrades + * changed way to obtain player kills, fixes slow stats updates + * improved pattern scan algorithm * v1.2.3.2 (2019-04-26) * added hotkey to toggle speed modifiers (CTRL+M) * added game version 1.04 (1.4.0.0) to supported versions diff --git a/SekiroFpsUnlockAndMore/GameData.cs b/SekiroFpsUnlockAndMore/GameData.cs index 737e76e..657000b 100644 --- a/SekiroFpsUnlockAndMore/GameData.cs +++ b/SekiroFpsUnlockAndMore/GameData.cs @@ -107,9 +107,9 @@ namespace SekiroFpsUnlockAndMore /** Reference pointer pCurrentResolutionWidth to iInternalGameWidth (and iInternalGameHeight which is +4 bytes). 000000014114B5C5 | 0F57D2 | xorps xmm2,xmm2 | - 000000014114B5C8 | 890D 521B7D02 | mov dword ptr ds:[14391D120],ecx | + 000000014114B5C8 | 890D 521B7D02 | mov dword ptr ds:[14391D120],ecx | iInternalGameWidth 000000014114B5CE | 0F57C9 | xorps xmm1,xmm1 | - 000000014114B5D1 | 8915 4D1B7D02 | mov dword ptr ds:[14391D124],edx | + 000000014114B5D1 | 8915 4D1B7D02 | mov dword ptr ds:[14391D124],edx | iInternalGameHeight 000000014114AC88 (Version 1.2.0.0) */ @@ -165,7 +165,7 @@ namespace SekiroFpsUnlockAndMore 00000001407AAD68 | 898B F8000000 | mov dword ptr ds:[rbx+F8],ecx | 00000001407AAD6E | 48:8B05 BBDF3903 | mov rax,qword ptr ds:[143B48D30] | pPlayerStatsRelated->[PlayerStats+0x90]->iPlayerDeaths 00000001407AAD75 | 8B88 90000000 | mov ecx,dword ptr ds:[rax+90] | offset pPlayerStats->iPlayerDeaths - + 00000001407AACAF (Version 1.2.0.0) */ // credits to 'Me_TheCat' for original offset @@ -176,16 +176,20 @@ namespace SekiroFpsUnlockAndMore /** - Reference pointer pTotalKills to iTotalKills, does not get updated on every kill but mostly on every 2nd, includes own player deaths... - 0000000141152178 | 48:8D0D A9ACB302 | lea rcx,qword ptr ds:[143C8CE28] | pTotalKills->iTotalKills - 000000014115217F | 891481 | mov dword ptr ds:[rcx+rax*4],edx | - 0000000141152182 | C3 | ret | - - 0000000141151838 (Version 1.2.0.0) - */ - // credits to 'Me_TheCat' for original offset - internal const string PATTERN_TOTAL_KILLS = "48 8D 0D ?? ?? ?? ?? 89 14 81 C3"; + Reference pointer pPlayerStatsRelated to 2 more PlayerStatsRelated pointer, offset in struct to iTotalKills. + 00000001407BFE25 | 48:69D8 18020000 | imul rbx,rax,218 | + 00000001407BFE2C | 48:8B05 FD8E3803 | mov rax,qword ptr ds:[143B48D30] | pPlayerStatsRelated->[PlayerStatsRelated1+0x08]->[PlayerStatsRelated2+0xDC]->iTotalKills + 00000001407BFE33 | 48:03D9 | add rbx,rcx | + 00000001407BFE36 | 48:897C24 20 | mov qword ptr ss:[rsp+20],rdi | + 00000001407BFE3B | 48:8B78 08 | mov rdi,qword ptr ds:[rax+8] | offset PlayerStatsRelated1->PlayerStatsRelated2 + + 0000000000000000 (Version 1.2.0.0) + */ + internal const string PATTERN_TOTAL_KILLS = "48 ?? D8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 ?? ?? 48 89 ?? ?? ?? 48 8B ?? 08"; + internal const int PATTERN_TOTAL_KILLS_OFFSET = 7; internal const int PATTERN_TOTAL_KILLS_INSTRUCTION_LENGTH = 7; + internal const int PATTERN_TOTAL_KILLS_POINTER1_OFFSET = 0x0008; + internal const int PATTERN_TOTAL_KILLS_POINTER2_OFFSET = 0x00DC; /** @@ -369,6 +373,48 @@ namespace SekiroFpsUnlockAndMore internal static readonly byte[] PATCH_DEATHSCOUNTER_ENABLE = new byte[4] { 0x84, 0xDB, 0x0F, 0x85 }; // test bl,bl; jne + /** + Whenever we upgrade a prosthetic or learn an ability the following function block will get called. + We inject a check to determine if case is prosthetic and set register affecting SkillEffect4 to 1 so that the upgrade increases our maximum spirit emblem capacity. + Type for struct SKILL_PARAM_ST is defined below. + 0000000140A84C29 | 48:85C0 | test rax,rax | + 0000000140A84C2C | 74 4A | je sekiro.140A84C78 | IncreaseSkill4OnUpgrade ? + 0000000140A84C2E | 0FB650 37 | movzx edx,byte ptr ds:[rax+37] | get SKILL_PARAM_ST.SkillEffect4 to edx | code inject overwrite from here + 0000000140A84C32 | 85D2 | test edx,edx | check if edx is 0 + 0000000140A84C34 | 74 42 | je sekiro.140A84C78 | if 0 jump here | jump back here from code inject + 0000000140A84C36 | 48:8B0D F3400C03 | mov rcx,qword ptr ds:[143B48D30] | increase skill4 on upgrade routine + 0000000140A84C3D | 48:8B49 08 | mov rcx,qword ptr ds:[rcx+8] | + 0000000140A84C41 | 48:85C9 | test rcx,rcx | + 0000000140A84C44 | 74 32 | je sekiro.140A84C78 | + 0000000140A84C46 | 48:81C1 46010000 | add rcx,146 | + 0000000140A84C4D | 66:0111 | add word ptr ds:[rcx],dx | increases Skill4 on upgrade, will get skipped if edx == 0 + + 0000000000000000 (Version 1.2.0.0) + + [StructLayout(LayoutKind.Explicit, Size = 0x0060)] + private struct SKILL_PARAM_ST + { + [FieldOffset(0x0030)] + private Int32 SkillFamily; // (Unk6) 2700000 for prosthetic upgrades + + [FieldOffset(0x0037)] + private UInt16 SkillEffect4; // (Unk10) controls how much spirit emblem capacity rises on acquisition of skill/upgrade + } + */ + internal const string PATTERN_EMBLEMUPGRADE = "48 85 C0 74 ?? 0F B6 50 37 85 D2 74 ?? 48 8B 0D"; + internal const int PATTERN_EMBLEMUPGRADE_OFFSET = 5; + internal const int INJECT_EMBLEMUPGRADE_OVERWRITE_LENGTH = 6; + internal static readonly byte[] INJECT_EMBLEMUPGRADE_SHELLCODE = new byte[] + { + 0x81, 0x78, 0x30, 0xE0, 0x32, 0x29, 0x00, // cmp dword ptr ds:[rax+30],2932E0 | if (SKILL_PARAM_ST.SkillFamily == 2700000) + 0x75, 0x07, // jne +7 | { + 0xBA, 0x01, 0x00, 0x00, 0x00, // mov edx,1 | edx = 1 + 0xEB, 0x04, // jmp +4 | } else { + 0x0F, 0xB6, 0x50, 0x37, // movzx edx,byte ptr ds:[rax+37] | edx = SKILL_PARAM_ST.SkillEffect4 } + 0x85, 0xD2 // test edx,edx | check if edx is 0 + }; + + /** Reference pointer pTimeRelated to TimescaleManager pointer, offset in struct to fTimescale which acts as a global speed scale for almost all ingame calculations. 000000014114A7C7 | 48:8B05 3A2BB402 | mov rax,qword ptr ds:[143C8D308] | pTimeRelated->[TimescaleManager+0x360]->fTimescale @@ -396,9 +442,9 @@ namespace SekiroFpsUnlockAndMore // credits to 'Zullie the Witch' for original offset internal const string PATTERN_TIMESCALE_PLAYER = "48 8B 1D ?? ?? ?? ?? 48 85 DB 74 ?? 8B ?? 81 FA"; internal const int PATTERN_TIMESCALE_PLAYER_INSTRUCTION_LENGTH = 7; - internal const int PATTERN_TIMESCALE_POINTER2_OFFSET = 0x88; + internal const int PATTERN_TIMESCALE_POINTER2_OFFSET = 0x0088; internal const int PATTERN_TIMESCALE_POINTER3_OFFSET = 0x1FF8; - internal const int PATTERN_TIMESCALE_POINTER4_OFFSET = 0x28; - internal const int PATTERN_TIMESCALE_POINTER5_OFFSET = 0xD00; + internal const int PATTERN_TIMESCALE_POINTER4_OFFSET = 0x0028; + internal const int PATTERN_TIMESCALE_POINTER5_OFFSET = 0x0D00; } } diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml b/SekiroFpsUnlockAndMore/MainWindow.xaml index b0aff60..74efa25 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SekiroFpsUnlockAndMore" mc:Ignorable="d" - Title="Sekiro FPS Unlocker and more v1.2.3" Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing"> + Title="Sekiro FPS Unlocker and more v1.2.4" Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing"> @@ -40,19 +40,20 @@ + - +