mirror of
https://github.com/uberhalit/SekiroFpsUnlockAndMore.git
synced 2026-06-13 09:57:55 +00:00
Added game modifications
Added global Game Speed modifier Added Player Speed modifier Settings are saved and loaded from conf now 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 Refactor Cleanup
This commit is contained in:
parent
35dd34c9c5
commit
c8696f0a45
10 changed files with 1103 additions and 322 deletions
107
README.md
107
README.md
|
|
@ -1,30 +1,35 @@
|
|||
# Sekiro FPS Unlocker and more
|
||||
|
||||
A small utility to remove frame rate limit, add custom resolutions with 21/9 widescreen support, increase field of view (FOV) (credits to jackfuste) and borderless window mode for [Sekiro: Shadows Die Twice](https://www.sekirothegame.com/) written in C#.
|
||||
Patches games memory while running, does not modify any game files. works with every game version (legit steam & oh-not-so-legit), should work with all future updates.
|
||||
A small utility to remove frame rate limit, add custom resolutions with 21/9 widescreen support, change field of view (FOV), borderless window mode and various game modifications for [Sekiro: Shadows Die Twice](https://www.sekirothegame.com/) written in C#.
|
||||
Patches games memory while running, does not modify any game files. Wrks with every game version (legit steam & oh-not-so-legit), should work with all future updates. Also available [Nexus Mods](https://www.nexusmods.com/sekiro/mods/13/).
|
||||
|
||||
## Download
|
||||
|
||||
**[Get the latest release here](https://github.com/uberhalit/SekiroFpsUnlockAndMore/releases)**
|
||||
|
||||
### See it in action:
|
||||
[](https://giant.gfycat.com/DevotedArtisticKingsnake.webm)
|
||||
[](https://giant.gfycat.com/PhonyReadyGreatargus.webm)
|
||||
|
||||
## Features
|
||||
|
||||
* does not modify any game files, RAM patches only
|
||||
* works with legit, unmodified steam version as well as with unpacked, not-so-legit versions
|
||||
* GSYNC and FreeSync support even in borderless window mode
|
||||
* unlock frame rate (remove FPS limit) by setting a new custom limit or setting lock to unlimited
|
||||
* add a custom resolution, 21/9 widescreen supported (will overwrite the default 1920x1080 resolution, HUD limited to 16/9)
|
||||
* increase field of view (FOV) (credits to jackfuste)
|
||||
* unlock frame rate (remove FPS limit) by setting a new custom limit
|
||||
* add a custom resolution, 21/9 widescreen supported (will overwrite the default 1920x1080 / 1280x720 resolution, HUD limited to 16/9)
|
||||
* increase and decrease field of view (FOV)
|
||||
* set the game to borderless window mode
|
||||
* game modifications
|
||||
* global game speed modifier
|
||||
* player speed modifier
|
||||
* automatically patch game on startup
|
||||
* seamlessly switch between windowed, borderless and borderless fullscreen
|
||||
* hotkey for patching while in (borderless) window mode
|
||||
|
||||
## Usage
|
||||
|
||||
The following graphical guide has to be done if you want to unlock the game's framerate or play on a highter refresh rate in fullscreen. If you do not wish to use that feature you can scoll down further to the guides on all other features. The graphic setup has to be done only once but as the patcher hot-patches the memory **you have to start the patcher every time you want use any of its features**.
|
||||
|
||||
The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors so we have to override these.
|
||||
#### 60 Hz monitors: disable VSYNC via driver (use 'Enhanced Sync' on AMD) and use fullscreen, see guide below
|
||||
#### high refresh rate monitors: use borderless or force monitor to always use highest available refresh rate and then use fullscreen, see guide below
|
||||
|
|
@ -35,20 +40,31 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s
|
|||
3. **Make sure your monitor is set to the highest Refresh rate possible:**
|
||||
4. [](#)
|
||||
5. Navigate to `3D Settings -> Manage 3D settings -> Program Settings`
|
||||
6. Select Sekiro from the dropdown or add it manually if it's missing: `Add -> Select Sekiro -> Add Selected Program`
|
||||
7. **Set `Vertical sync` to `Off`**
|
||||
8. **Set `Preferred refresh rate` to `Highest available`**
|
||||
9. [](#)
|
||||
10. Hit apply and close Nvidia Control Panel
|
||||
11. Start `Sekiro FPS Unlocker and more` and set FPS lock to your desired framerate
|
||||
12. Start the game and use fullscreen or borderless window mode
|
||||
13. These steps will force disable vsync so it won't limit your fps to monitor refresh rate and also force the monitor to ignore the games request to run at 60 Hz if in fullscreen
|
||||
6. **Check if you already have a Sekiro Profile in dropdown and if so DELETE IT**
|
||||
7. Manually add Sekiro into a clean new profile: `Add -> Browse ->` Navigate to `sekiro.exe` and select it
|
||||
8. **Make sure that there is a file path to Sekiro and that it is indeed correct and you haven't loaded a premade (empty) profile**
|
||||
9. **Set `Preferred refresh rate` to `Highest available`**
|
||||
10. **Set `Vertical sync` to `Off`**
|
||||
11. [](#)
|
||||
12. Hit apply and close Nvidia Control Panel
|
||||
13. Start `Sekiro FPS Unlocker and more` and set FPS lock to your desired framerate
|
||||
14. Start the game and use fullscreen or borderless window mode
|
||||
15. These steps will force disable vsync so it won't limit your fps to monitor refresh rate and also force the monitor to ignore the games request to run at 60 Hz if in fullscreen
|
||||
#### If you do not have 'Preferred refresh rate' or 'Vertical sync' follow these steps (Nvidia):
|
||||
1. Download and extract the [Nvidia Inspector](https://www.techpowerup.com/download/nvidia-inspector/)
|
||||
2. Start the Nvidia Profile Inspector
|
||||
3. Under `2 - Sync and Refresh` set `Prefered Refreshrate` to `Highest available` and `Vertical Sync` to `Force off`
|
||||
4. [](#)
|
||||
5. Hit `Apply changes` and you are good to go
|
||||
1. **Delete the Sekiro Profile in Nvidia Control panel as otherwise it will block all settings from Profile Inspector**
|
||||
2. Hit apply and close the Nvidia Control panel
|
||||
3. Download and extract the [Nvidia Inspector](https://www.techpowerup.com/download/nvidia-inspector/)
|
||||
4. Start the Nvidia Profile Inspector
|
||||
5. **Check if there already is a profile for Sekiro and if so DELETE IT using the red 'X' button**
|
||||
6. Press the yellow start icon in the menu bar to create a new Profile (1)
|
||||
7. [](#)
|
||||
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)
|
||||
10. Change file type to `Application Absolute Path`, navigate to your `sekiro.exe` and select it
|
||||
11. [](#)
|
||||
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)
|
||||
|
||||
### Follow these steps on AMD:
|
||||
1. Right click on Desktop -> `Display settings`
|
||||
|
|
@ -64,34 +80,33 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s
|
|||
11. **Launch the game in windowed mode, then switch to fullscreen once in game**
|
||||
12. The last step is important as AMD somehow does not correctly disable VSYNC otherwise
|
||||
#### If you do not have 'Enhanced Sync' follow these steps (AMD):
|
||||
1. Try setting `Wait for Vertical Refresh` to `Off` instead:
|
||||
1. Try setting `Wait for Vertical Refresh` to `Always off` instead:
|
||||
2. [](#)
|
||||
3. Be aware however that it seems like AMDs latest drivers are buggy in that regard
|
||||
|
||||
### To play the game with GSYNC do these additional steps (Nvidia):
|
||||
1. Under Nvidia Control Panel navigate to `3D Settings -> Manage 3D settings -> Program Settings -> Sekiro`
|
||||
2. Set `Monitor Technology` to `G-SYNC`
|
||||
3. Make sure that `Preferred refresh rate` is still set to `Highest available`
|
||||
4. Make sure that `Vertical sync` is still set to `Off`
|
||||
3. Set `Vertical sync` to `Off` again as enabling G-SYNC re-enables it
|
||||
4. Make sure that `Preferred refresh rate` is still set to `Highest available`
|
||||
5. [](#)
|
||||
6. Don't forget to Apply and close Nvidia Control Panel
|
||||
7. Use a 3rd party frame rate limiter like [RTSS](https://www.guru3d.com/files-details/rtss-rivatuner-statistics-server-download.html) and set a frame rate limit just a few fps below your monitor refresh rate, on a 144Hz Monitor use 138
|
||||
8. Start `Sekiro FPS Unlocker and more` and set FPS lock to your monitors refresh rate
|
||||
9. Start the game and set it to Fullscreen
|
||||
10. Enjoy perfectly tearing free variable high refresh rates without VSYNC
|
||||
|
||||
The graphic setup has to be done only once but as the patcher hot-patches the memory **you have to start the patcher every time you want to unlock frame rate etc**.
|
||||
6. If you do not have `Preferred refresh rate` or `Vertical sync` see the guide above on how to use the Nvidia Profile Inspector
|
||||
7. Don't forget to Apply and close Nvidia Control Panel
|
||||
8. Use a 3rd party frame rate limiter like [RTSS](https://www.guru3d.com/files-details/rtss-rivatuner-statistics-server-download.html) and set a frame rate limit just a few fps below your monitor refresh rate, on a 144Hz Monitor use 138
|
||||
9. Start `Sekiro FPS Unlocker and more` and set FPS lock to your monitors refresh rate
|
||||
10. Start the game and set it to Fullscreen
|
||||
11. Enjoy perfectly tearing free variable high refresh rates without VSYNC
|
||||
|
||||
### To add a custom resolution
|
||||
1. Start the game
|
||||
2. Start `Sekiro FPS Unlocker and more`, set you desired resolution and enable it by ticking the check box
|
||||
3. Set your custom resolution in the graphical settings, be aware that the ingame HUD will be limited to 16/9
|
||||
3. Set your custom resolution in the graphical settings
|
||||
4. Be aware that your monitor has to natively support this resolution and the ingame HUD will be limited to 16/9
|
||||
|
||||
### To use the FOV changer
|
||||
1. Start the game
|
||||
2. Load up your save game
|
||||
3. Start `Sekiro FPS Unlocker and more`, set you desired FOV value and enable it by ticking the check box
|
||||
4. If you reload a save FOV will reset so patch game manually again
|
||||
|
||||
### To use borderless window mode:
|
||||
1. Start the game
|
||||
|
|
@ -100,19 +115,25 @@ The graphic setup has to be done only once but as the patcher hot-patches the me
|
|||
4. Start `Sekiro FPS Unlocker and more` and enable borderless window mode
|
||||
5. If you want fullscreen borderless enable `Fullscreen stretch`
|
||||
|
||||
### To use any of the game modifications
|
||||
1. Start the game
|
||||
2. Load up your save game
|
||||
3. Start `Sekiro FPS Unlocker and more` and expand `Game modifications`
|
||||
4. Set your desired values and then tick the checkbox you'd wish to enable
|
||||
|
||||
## Preview
|
||||
|
||||
[](#)
|
||||
[](#)
|
||||
|
||||
### Unlocked framerate
|
||||
[](#)
|
||||
[](#)
|
||||
|
||||
### Increased FOV and borderless window:
|
||||
[](#)
|
||||
### Increased FOV borderless window and 90% game speed:
|
||||
[](#)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* .NET Framework 4.0
|
||||
* .NET Framework 4.5
|
||||
* administrative privileges (for patching)
|
||||
* 64 bit OS
|
||||
|
||||
|
|
@ -130,7 +151,8 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|||
|
||||
## Credits
|
||||
|
||||
* jackfuste for FOV findings and running speed fix
|
||||
* Zullie the Witch#7202 for game speed and player speed modifier offsets
|
||||
* jackfuste for FOV offset and basic running speed fix
|
||||
* TyChii93#2376 for AMD and widescreen testing
|
||||
* [Darius Dan](http://www.dariusdan.com) for the icon
|
||||
|
||||
|
|
@ -139,12 +161,19 @@ 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
|
||||
* in fullscreen the game forces the monitor to 60 Hz so you'll have to handle this with driver override too, see Usage
|
||||
* your monitor has to support your custom resolution otherwise it won't show up correctly
|
||||
* due to how the game renders altering FOV will not move the HUD
|
||||
* the HUD is limited to 16/9 even on 21/9 resolutions
|
||||
* due to how the game renders altering HUD is limited to 16/9 even on 21/9 resolutions
|
||||
* the hotkey won't work if the game runs in exclusive, true fullscreen mode
|
||||
|
||||
## Version History
|
||||
|
||||
* v1.1.0 (2019-03-30)
|
||||
* Added game speed modifier (thanks to Zullie the Witch#7202 for offset)
|
||||
* Added player speed modifier (thanks to Zullie the Witch#7202 for offset)
|
||||
* Settings are saved and loaded from config file now
|
||||
* FOV will now stick even after save game load
|
||||
* 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
|
||||
* v1.0.2 (2019-03-26)
|
||||
* Added option to reduce FOV (request)
|
||||
* Added option to stretch borderless window to fullscreen regardless of window resolution
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
|
||||
</startup>
|
||||
</configuration>
|
||||
|
|
|
|||
187
SekiroFpsUnlockAndMore/GameData.cs
Normal file
187
SekiroFpsUnlockAndMore/GameData.cs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SekiroFpsUnlockAndMore
|
||||
{
|
||||
internal class GameData
|
||||
{
|
||||
internal const string PROCESS_NAME = "sekiro";
|
||||
internal const string PROCESS_TITLE = "Sekiro";
|
||||
internal const string PROCESS_DESCRIPTION = "Shadows Die Twice";
|
||||
|
||||
|
||||
/**
|
||||
<float>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 |
|
||||
*/
|
||||
internal const string PATTERN_FRAMELOCK = "88 88 3C 4C 89 AB"; // 88 88 3C 4C 89 AB // first byte (last in mem) can can be 88/90 instead of 89 due to precision loss on floating point numbers
|
||||
internal const string PATTERN_FRAMELOCK_MASK = "xxxxxx"; // mask for frame rate limiter signature scanning
|
||||
internal const int PATTERN_FRAMELOCK_OFFSET = -1; // offset to byte array from found position
|
||||
internal const string PATTERN_FRAMELOCK_FUZZY = "C7 43 00 00 00 00 00 4C 89 AB"; // C7 43 ?? ?? ?? ?? ?? 4C 89 AB
|
||||
internal const string PATTERN_FRAMELOCK_FUZZY_MASK = "xx?????xxx";
|
||||
internal const int PATTERN_FRAMELOCK_FUZZY_OFFSET = 3;
|
||||
|
||||
|
||||
/**
|
||||
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 <float>fFrametimeCriticalRunningSpeed from table
|
||||
fFrametimeCriticalRunningSpeed should be roughly half the frame rate: 30 @ 60FPS limit, 50 @ 100FPS limit...
|
||||
00000001407D4E08 | F3:0F5905 90309202 | mulss xmm0,dword ptr ds:[1430F7EA0] | pFrametimeRunningSpeed->fFrametimeCriticalRunningSpeed
|
||||
*/
|
||||
internal const string PATTERN_FRAMELOCK_SPEED_FIX = "F3 0F 59 05 00 30 92 02"; // F3 0F 59 05 ?? 30 92 02 | 0F 51 C2 F3 0F 59 05 ?? ?? ?? ?? 0F 2F F8
|
||||
internal const string PATTERN_FRAMELOCK_SPEED_FIX_MASK = "xxxx?xxx";
|
||||
internal const int PATTERN_FRAMELOCK_SPEED_FIX_OFFSET = 4;
|
||||
/**
|
||||
00000001430F7E10
|
||||
Key: Patch to pFrametimeRunningSpeed last byte
|
||||
Value: Value resolve in float table from pFrametimeRunningSpeed->fFrametimeCriticalRunningSpeed
|
||||
Hardcoded cause lazy -> if anyone knows how the table is calculated then tell me and I'll buy you a beer
|
||||
*/
|
||||
internal static Dictionary<byte[], float> PATCH_FRAMELOCK_SPEED_FIX_MATRIX = new Dictionary<byte[], float>
|
||||
{
|
||||
{ new byte[1] {0x68}, 15f },
|
||||
{ new byte[1] {0x6C}, 16f },
|
||||
{ new byte[1] {0x70}, 16.6667f },
|
||||
{ new byte[1] {0x74}, 18f },
|
||||
{ new byte[1] {0x78}, 18.6875f },
|
||||
{ new byte[1] {0x7C}, 18.8516f },
|
||||
{ new byte[1] {0x80}, 20f },
|
||||
{ new byte[1] {0x84}, 24f },
|
||||
{ new byte[1] {0x88}, 25f },
|
||||
{ new byte[1] {0x8C}, 27.5f },
|
||||
{ new byte[1] {0x90}, 30f },
|
||||
{ new byte[1] {0x94}, 32f },
|
||||
{ new byte[1] {0x98}, 38.5f },
|
||||
{ new byte[1] {0x9C}, 40f },
|
||||
{ new byte[1] {0xA0}, 48f },
|
||||
{ new byte[1] {0xA4}, 49.5f },
|
||||
{ new byte[1] {0xA8}, 50f },
|
||||
{ new byte[1] {0xAC}, 57.2958f },
|
||||
{ new byte[1] {0xB0}, 60f },
|
||||
{ new byte[1] {0xB4}, 64f },
|
||||
{ new byte[1] {0xB8}, 66.75f },
|
||||
{ new byte[1] {0xBC}, 67f },
|
||||
{ new byte[1] {0xC0}, 78.8438f },
|
||||
{ new byte[1] {0xC4}, 80f },
|
||||
{ new byte[1] {0xC8}, 84f },
|
||||
{ new byte[1] {0xCC}, 90f },
|
||||
{ new byte[1] {0xD0}, 93.8f },
|
||||
{ new byte[1] {0xD4}, 100f },
|
||||
{ new byte[1] {0xD8}, 120f },
|
||||
{ new byte[1] {0xDC}, 127f },
|
||||
{ new byte[1] {0xE0}, 128f },
|
||||
{ new byte[1] {0xE4}, 130f },
|
||||
{ new byte[1] {0xE8}, 140f },
|
||||
{ new byte[1] {0xEC}, 144f },
|
||||
{ new byte[1] {0xF0}, 150f }
|
||||
};
|
||||
internal static byte[] PATCH_FRAMELOCK_SPEED_FIX_DISABLE = new byte[1] { 0x90 }; // 30f
|
||||
|
||||
/// <summary>
|
||||
/// Finds closest valid speed fix value for a frame rate limit.
|
||||
/// </summary>
|
||||
/// <param name="frameLimit">The set frame rate limit.</param>
|
||||
/// <returns>The byte patch of the closest speed fix.</returns>
|
||||
internal static byte[] FindSpeedFixForRefreshRate(int frameLimit)
|
||||
{
|
||||
float idealSpeedFix = frameLimit / 2f;
|
||||
KeyValuePair<byte[], float> closestSpeedFix = new KeyValuePair<byte[], float>(PATCH_FRAMELOCK_SPEED_FIX_DISABLE, 30f);
|
||||
foreach (var speedFix in PATCH_FRAMELOCK_SPEED_FIX_MATRIX.OrderBy(kvp => kvp.Value))
|
||||
{
|
||||
if (Math.Abs(idealSpeedFix - speedFix.Value) < Math.Abs(idealSpeedFix - closestSpeedFix.Value))
|
||||
closestSpeedFix = speedFix;
|
||||
}
|
||||
return closestSpeedFix.Key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reference pointer pCurrentResolutionWidth to <int>iInternalGameWidth (and <int>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
|
||||
*/
|
||||
internal const string PATTERN_RESOLUTION_POINTER = "0F 57 D2 89 0D 00 00 00 00 0F 57 C9"; // 0F 57 D2 89 0D ?? ?? ?? ?? 0F 57 C9
|
||||
internal const string PATTERN_RESOLUTION_POINTER_MASK = "xxxxx????xxx";
|
||||
internal const int PATTERN_RESOLUTION_POINTER_OFFSET = 3;
|
||||
internal const int PATTERN_RESOLUTION_POINTER_INSTRUCTION_LENGTH = 6;
|
||||
|
||||
|
||||
/**
|
||||
DATA SECTION. All resolutions are listed in memory as <int>width1 <int>height1 <int>width2 <int>height2 ...
|
||||
Overwrite an unused one with desired new one. Some glitches, 1920x1080 and 1280x720 works best
|
||||
*/
|
||||
internal const string PATTERN_RESOLUTION_DEFAULT = "80 07 00 00 38 04 00 00"; // 1920x1080
|
||||
internal const string PATTERN_RESOLUTION_DEFAULT_720 = "40 06 00 00 84 03 00 00"; // 1280x720
|
||||
internal const string PATTERN_RESOLUTION_DEFAULT_MASK = "xxxxxxxx";
|
||||
internal static byte[] PATCH_RESOLUTION_DEFAULT_DISABLE = new byte[8] { 0x80, 0x07, 0x00, 0x00, 0x38, 0x04, 0x00, 0x00 };
|
||||
internal static byte[] PATCH_RESOLUTION_DEFAULT_DISABLE_720 = new byte[8] { 0x40, 0x06, 0x00, 0x00, 0x84, 0x03, 0x00, 0x00 };
|
||||
|
||||
|
||||
/**
|
||||
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
|
||||
000000014012967A | 74 47 | je sekiro.1401296C3 | conditional jump
|
||||
000000014012967C | 47:8B94C7 1C020000 | mov r10d,dword ptr ds:[r15+r8*8+21C] | start of long resolution scaling calculation method within jump
|
||||
*/
|
||||
internal const string PATTERN_RESOLUTION_SCALING_FIX = "47 47 8B 94 C7 1C 02 00 00"; // 47 47 8B 94 C7 1C 02 00 00
|
||||
internal const string PATTERN_RESOLUTION_SCALING_FIX_MASK = "xxxxxxxxx";
|
||||
internal const int PATTERN_RESOLUTION_SCALING_FIX_OFFSET = -1;
|
||||
internal static byte[] PATCH_RESOLUTION_SCALING_FIX_ENABLE = new byte[1] { 0xEB }; // JMP
|
||||
internal static byte[] PATCH_RESOLUTION_SCALING_FIX_DISABLE = new byte[1] { 0x74 }; // JE
|
||||
|
||||
|
||||
/**
|
||||
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 <float>fFOV from table
|
||||
0000000140739548 | F3:0F1008 | movss xmm1,dword ptr ds:[rax] |
|
||||
000000014073954C | F3:0F590D 0CE79B02 | mulss xmm1,dword ptr ds:[1430F7C60] | pFovTableEntry->fFov
|
||||
*/
|
||||
// credits to 'jackfuste' for original offset
|
||||
internal const string PATTERN_FOVSETTING = "F3 0F 10 08 F3 0F 59 0D 00 00 9B 02"; // F3 0F 10 08 F3 0F 59 0D ?? ?? 9B 02
|
||||
internal const string PATTERN_FOVSETTING_MASK = "xxxxxxxx??xx";
|
||||
internal const int PATTERN_FOVSETTING_OFFSET = 8;
|
||||
/**
|
||||
|
||||
*/
|
||||
internal static Dictionary<byte[], string> PATCH_FOVSETTING_MATRIX = new Dictionary<byte[], string>
|
||||
{
|
||||
{ new byte[2] {0x00, 0xE7}, "- 50%" },
|
||||
{ new byte[2] {0x04, 0xE7}, "- 10%" },
|
||||
{ new byte[2] {0x10, 0xE7}, "+ 15%" },
|
||||
{ new byte[2] {0x14, 0xE7}, "+ 40%" },
|
||||
{ new byte[2] {0x18, 0xE7}, "+ 75%" },
|
||||
{ new byte[2] {0x1C, 0xE7}, "+ 90%" }
|
||||
};
|
||||
internal static byte[] PATCH_FOVSETTING_DISABLE = new byte[2] { 0x0C, 0xE7 }; // + 0%
|
||||
|
||||
|
||||
/**
|
||||
Reference pointer pTimeRelated to pTimescaleManager pointer, offset in struct to <float>fTimescale which acts as a global speed scale for almost all ingame calculations
|
||||
0000000141149E87 | 48:8B05 3A24B402 | mov rax,qword ptr ds:[143C8C2C8] | pTimeRelated->[pTimescaleManager+0x360]->fTimescale
|
||||
0000000141149E8E | F3:0F1088 60030000 | movss xmm1,dword ptr ds:[rax+360] | offset from TimescaleManager->fTimescale
|
||||
0000000141149E96 | F3:0F5988 68020000 | mulss xmm1,dword ptr ds:[rax+268] |
|
||||
*/
|
||||
// credits to 'Zullie the Witch' for original offset
|
||||
internal const string PATTERN_TIMESCALE = "48 8B 05 00 00 00 00 F3 0F 10 88 00 00 00 00 F3 0F"; // 48 8B 05 ?? ?? ?? ?? F3 0F 10 88 ?? ?? ?? ?? F3 0F
|
||||
internal const string PATTERN_TIMESCALE_MASK = "xxx????xxxx????xx";
|
||||
internal const int PATTERN_TIMESCALE_INSTRUCTION_LENGTH = 7;
|
||||
internal const int PATTERN_TIMESCALE_POINTER_OFFSET_OFFSET = 11;
|
||||
|
||||
/**
|
||||
Reference pointer pPlayerStructRelated1 to 4 more pointers up to player data class, offset in struct to <float>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] |
|
||||
*/
|
||||
// credits to 'Zullie the Witch' for original offset
|
||||
internal const string PATTERN_TIMESCALE_PLAYER = "48 8B 1D 00 00 00 00 48 85 DB 74 3C 8B 17"; // 48 8B 1D ?? ?? ?? ?? 48 85 DB 74 3C 8B 17
|
||||
internal const string PATTERN_TIMESCALE_PLAYER_MASK = "xxx????xxxxxxx";
|
||||
internal const int PATTERN_TIMESCALE_PLAYER_INSTRUCTION_LENGTH = 7;
|
||||
internal const int PATTERN_TIMESCALE_POINTER2_OFFSET = 0x88;
|
||||
internal const int PATTERN_TIMESCALE_POINTER3_OFFSET = 0x1FF8;
|
||||
internal const int PATTERN_TIMESCALE_POINTER4_OFFSET = 0x28;
|
||||
internal const int PATTERN_TIMESCALE_POINTER5_OFFSET = 0xD00;
|
||||
}
|
||||
}
|
||||
|
|
@ -5,25 +5,64 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SekiroFpsUnlockAndMore"
|
||||
mc:Ignorable="d"
|
||||
Title="Sekiro FPS Unlocker and more v1.0.2" Height="Auto" SizeToContent="WidthAndHeight" Width="Auto" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing">
|
||||
Title="Sekiro FPS Unlocker and more v1.1.0" Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing">
|
||||
|
||||
<Grid Background="#FFF9F9F9">
|
||||
<CheckBox x:Name="cbUnlockFps" Content="FPS lock (0= unlimited):" IsChecked="True" HorizontalAlignment="Left" Margin="10,12,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/>
|
||||
<TextBox x:Name="tbFps" Text="144" MaxLength="3" HorizontalAlignment="Left" Height="25" Margin="181,10,10,10" VerticalAlignment="Top" Width="106" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler"/>
|
||||
<CheckBox x:Name="cbAddWidescreen" Content="Add custom resolution:" HorizontalAlignment="Left" Margin="10,42,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/>
|
||||
<TextBox x:Name="tbWidth" Text="2560" MaxLength="4" HorizontalAlignment="Left" Height="25" Margin="181,40,0,0" VerticalAlignment="Top" Width="45" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
|
||||
<Label Content="x" HorizontalAlignment="Left" Margin="226,36,0,0" VerticalAlignment="Top" FontSize="14 px"/>
|
||||
<TextBox x:Name="tbHeight" Text="1080" MaxLength="4" HorizontalAlignment="Left" Height="25" Margin="242,40,0,0" VerticalAlignment="Top" Width="45" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
|
||||
<CheckBox x:Name="cbFov" Content="Increase FOV by:" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/>
|
||||
<ComboBox x:Name="cbSelectFov" HorizontalAlignment="Left" VerticalAlignment="Top" Width="106" Height="25" Margin="181,70,10,10" FontSize="14 px" SelectedValuePath="Key" DisplayMemberPath="Value"/>
|
||||
<CheckBox x:Name="cbBorderless" Content="Borderless window" HorizontalAlignment="Left" Margin="10,100,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CbBorderless_Checked" Unchecked="CbBorderless_Unchecked"/>
|
||||
<CheckBox x:Name="cbBorderlessStretch" Content="Fullscreen stretch" IsEnabled="False" HorizontalAlignment="Left" Margin="152,100,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/>
|
||||
<Button x:Name="bPatch" Content="Patch game (CTRL + P)" FontSize="14 px" HorizontalAlignment="Left" Margin="10,125,10,10" VerticalAlignment="Top" Width="277" Height="30"
|
||||
BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Focusable="False" Click="BPatch_Click" />
|
||||
<TextBox x:Name="tbStatus" Text="waiting for game..." TextAlignment="Center" HorizontalAlignment="Left" TextWrapping="NoWrap" Height="25" Margin="10,165,10,10" VerticalAlignment="Top" Width="277" FontSize="14 px" IsEnabled="False" FontWeight="Bold" />
|
||||
<StackPanel HorizontalAlignment="Left" Height="Auto" Margin="12,195,12,5" VerticalAlignment="Top" Width="275">
|
||||
<TextBlock HorizontalAlignment="Left" TextWrapping="WrapWithOverflow" VerticalAlignment="Top" FontSize="11 px" IsEnabled="False">
|
||||
<StackPanel Margin="10,10,10,0" Width="290" Height="Auto">
|
||||
<DockPanel LastChildFill="False">
|
||||
<CheckBox x:Name="cbFramelock" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Frame rate lock:" IsChecked="True" Checked="CbFramelock_Check_Handler" Unchecked="CbFramelock_Check_Handler" />
|
||||
<TextBox x:Name="tbFramelock" DockPanel.Dock="Right" Margin="0,0,0,0" Width="116" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Text="144" MaxLength="3" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
|
||||
</DockPanel>
|
||||
<DockPanel Margin="0,5,0,0" LastChildFill="False">
|
||||
<CheckBox x:Name="cbAddResolution" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Add custom resolution:" Checked="CbAddResolution_Check_Handler" Unchecked="CbAddResolution_Check_Handler" />
|
||||
<TextBox x:Name="tbHeight" DockPanel.Dock="Right" Margin="0,0,0,0" Width="50" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Text="1080" MaxLength="4" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
|
||||
<Label DockPanel.Dock="Right" Margin="0,0,0,0" Height="25" FontSize="14 px" Content="x" />
|
||||
<TextBox x:Name="tbWidth" DockPanel.Dock="Right" Margin="0,0,0,0" Width="50" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Text="2560" MaxLength="4" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
|
||||
</DockPanel>
|
||||
<DockPanel Margin="0,5,0,0" LastChildFill="False">
|
||||
<CheckBox x:Name="cbFov" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Increase FOV by:" Checked="CbFov_Check_Handler" Unchecked="CbFov_Check_Handler" />
|
||||
<ComboBox x:Name="cbSelectFov" DockPanel.Dock="Right" Margin="0,0,0,0" Width="116" Height="25" FontSize="14 px" SelectedValuePath="Key" DisplayMemberPath="Value" DropDownClosed="CbSelectFov_DropDownClosed"/>
|
||||
</DockPanel>
|
||||
<StackPanel Margin="0,5,0,0" Orientation="Horizontal">
|
||||
<CheckBox x:Name="cbBorderless" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Borderless window" IsEnabled="False" Checked="CbBorderless_Checked" Unchecked="CbBorderless_Unchecked"/>
|
||||
<CheckBox x:Name="cbBorderlessStretch" DockPanel.Dock="Right" Margin="10,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Fullscreen stretch" IsEnabled="False" Checked="CbBorderlessStretch_Check_Handler" Unchecked="CbBorderlessStretch_Check_Handler" />
|
||||
</StackPanel>
|
||||
<Expander x:Name="exGameMods" Margin="-3,4,0,0" Height="Auto" FontSize="14 px" Header="Game modifications" IsExpanded="False">
|
||||
<Grid Margin="3,0,0,0" Background="#FFF9F9F9">
|
||||
<StackPanel Width="Auto" Height="Auto">
|
||||
<DockPanel Margin="0,3,0,0" LastChildFill="False">
|
||||
<CheckBox x:Name="cbGameSpeed" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Game speed (%):" Checked="CbGameSpeed_Check_Handler" Unchecked="CbGameSpeed_Check_Handler" />
|
||||
<Button x:Name="bGs100" DockPanel.Dock="Right" Content="100" Margin="0,0,0,0" Width="30" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BGs100_Click" />
|
||||
<Button x:Name="bGsHigher" DockPanel.Dock="Right" Content=">" Margin="0,0,3,0" Width="25" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BGsHigher_Click" />
|
||||
<TextBox x:Name="tbGameSpeed" DockPanel.Dock="Right" Margin="0,0,3,0" Width="30" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Text="100" TextAlignment="Center" MaxLength="3" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
|
||||
<Button x:Name="bGsLower" DockPanel.Dock="Right" Content="<" Margin="0,0,3,0" Width="25" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BGsLower_Click" />
|
||||
<Button x:Name="bGs0" DockPanel.Dock="Right" Content="0" Margin="0,0,3,0" Width="30" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BGs0_Click" />
|
||||
</DockPanel>
|
||||
<DockPanel Margin="0,5,0,0" LastChildFill="False">
|
||||
<CheckBox x:Name="cbPlayerSpeed" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Player speed (%):" ToolTip="To enable this start the game and load a save, then start the patcher." Checked="CbPlayerSpeed_Check_Handler" Unchecked="CbPlayerSpeed_Check_Handler" />
|
||||
<Button x:Name="bPs100" DockPanel.Dock="Right" Content="100" Margin="0,0,0,0" Width="30" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BPs100_Click" />
|
||||
<Button x:Name="bPsHigher" DockPanel.Dock="Right" Content=">" Margin="0,0,3,0" Width="25" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BPsHigher_Click" />
|
||||
<TextBox x:Name="tbPlayerSpeed" DockPanel.Dock="Right" Margin="0,0,3,0" Width="30" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Text="100" TextAlignment="Center" MaxLength="3" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
|
||||
<Button x:Name="bPsLower" DockPanel.Dock="Right" Content="<" Margin="0,0,3,0" Width="25" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BPsLower_Click" />
|
||||
<Button x:Name="bPs0" DockPanel.Dock="Right" Content="0" Margin="0,0,3,0" Width="30" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BPs0_Click" />
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Expander>
|
||||
<Button x:Name="bPatch" Margin="0,7,0,0" Width="290" Height="30" FontSize="14 px" IsEnabled="False" Content="Patch game (CTRL + P)" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
|
||||
Focusable="False" Click="BPatch_Click" />
|
||||
<TextBox x:Name="tbStatus" Margin="0,5,0,0" Width="290" Height="25" FontSize="14 px" FontWeight="Bold" Text="waiting for game..." TextAlignment="Center" TextWrapping="NoWrap" IsEnabled="False" />
|
||||
<TextBlock HorizontalAlignment="Left" TextWrapping="WrapWithOverflow" Margin="2,5,2,0" VerticalAlignment="Top" FontSize="11 px" IsEnabled="False">
|
||||
<TextBlock.Inlines>
|
||||
<Run FontWeight="Bold" Foreground="#FF0046FF">This patcher does not modify game files, you have to start it every time.</Run>
|
||||
<Run FontWeight="Bold">If your monitor is 60 Hz you will have to use</Run>
|
||||
<Run FontWeight="Bold" Foreground="#FFF00000">fullscreen mode and force disable VSYNC</Run>
|
||||
<Run FontWeight="Bold">with Nvidia Control panel or AMD Radeon Settings to get frame rate unlock working.</Run>
|
||||
|
|
@ -31,18 +70,16 @@
|
|||
<Run FontWeight="Bold">If your monitor is >60 Hz you will have to use</Run>
|
||||
<Run FontWeight="Bold" Foreground="#FFF00000">borderless window mode or force the game to run on highest available refresh rate</Run>
|
||||
<Run FontWeight="Bold">using Nvidia Control panel or AMD Radeon Settings.</Run>
|
||||
<Run>Borderless window mode requires "Window mode" in game settings first.</Run>
|
||||
<Run FontWeight="Bold">Custom resolution adds 21/9 support and overwrites default 1920x1080 resolution, hud will be limited to 16/9 though.</Run>
|
||||
<Run>Borderless window mode requires "Windowed" in game settings first.</Run>
|
||||
<Run FontWeight="Bold">Custom resolution adds 21/9 support and overwrites a default resolution, hud will be limited to 16/9.</Run>
|
||||
<Run>Borderless window mode with custom resolution requires you to patch and set resolution first, then add borderless patch afterwards.</Run>
|
||||
<Run FontWeight="Bold">For FOV patch to work you need to be ingame.</Run>
|
||||
<Run>FOV patch resets after save game reload.</Run>
|
||||
<Run FontWeight="Bold" Foreground="#FFF00000">See the link below for detailed information, GSYNC support and an AMD fix.</Run>
|
||||
<Run FontWeight="Bold">To enable Player Speed modification you have to be ingame first.</Run>
|
||||
<Run FontWeight="Bold" Foreground="#FFF00000">See the link below for detailed information, guides, GSYNC support and an AMD fix.</Run>
|
||||
</TextBlock.Inlines>
|
||||
</TextBlock>
|
||||
|
||||
<Label HorizontalAlignment="Right" VerticalAlignment="Top" FontSize="12 px">
|
||||
<Label HorizontalAlignment="Right" FontSize="12 px">
|
||||
<Hyperlink NavigateUri="https://github.com/uberhalit/SekiroFpsUnlockAndMore" RequestNavigate="Hyperlink_RequestNavigate">
|
||||
v1.0.2 - by uberhalit
|
||||
v1.1.0 - by uberhalit
|
||||
</Hyperlink>
|
||||
</Label>
|
||||
</StackPanel>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,31 +0,0 @@
|
|||
|
||||
namespace SekiroFpsUnlockAndMore
|
||||
{
|
||||
internal class Offsets
|
||||
{
|
||||
internal const string PATTERN_FRAMELOCK = "00 88 88 3C 4C 89 AB 00"; // ?? 88 88 3C 4C 89 AB ?? // pattern/signature of frame rate limiter, first byte (last in mem) can can be 88/90 instead of 89 due to precision loss on floating point numbers
|
||||
internal const string PATTERN_FRAMELOCK_MASK = "?xxxxxx?"; // mask for frame rate limiter signature scanning
|
||||
internal const string PATTERN_FRAMELOCK_LONG = "44 88 6B 00 C7 43 00 89 88 88 3C 4C 89 AB 00 00 00 00"; // 44 88 6B ?? C7 43 ?? 89 88 88 3C 4C 89 AB ?? ?? ?? ??
|
||||
internal const string PATTERN_FRAMELOCK_LONG_MASK = "xxx?xx?xxxxxxx????";
|
||||
internal const int PATTERN_FRAMELOCK_LONG_OFFSET = 7;
|
||||
internal const string PATTERN_FRAMELOCK_FUZZY = "C7 43 00 00 00 00 00 4C 89 AB 00 00 00 00"; // C7 43 ?? ?? ?? ?? ?? 4C 89 AB ?? ?? ?? ??
|
||||
internal const string PATTERN_FRAMELOCK_FUZZY_MASK = "xx?????xxx????";
|
||||
internal const int PATTERN_FRAMELOCK_FUZZY_OFFSET = 3; // offset to byte array from found position
|
||||
internal const string PATTERN_FRAMELOCK_RUNNING_FIX = "F3 0F 59 05 00 30 92 02 0F 2F F8"; // F3 0F 59 05 ?? 30 92 02 0F 2F F8 | 0F 51 C2 F3 0F 59 05 ?? ?? ?? ?? 0F 2F F8
|
||||
internal const string PATTERN_FRAMELOCK_RUNNING_FIX_MASK = "xxxx?xxxxxx";
|
||||
internal const int PATTERN_FRAMELOCK_RUNNING_FIX_OFFSET = 4;
|
||||
internal const string PATTERN_RESOLUTION_POINTER = "0F 57 D2 89 0D 00 00 00 00 0F 57 C9 89 15 00 00 00 00"; // 0F 57 D2 89 0D ?? ?? ?? ?? 0F 57 C9 89 15 ?? ?? ?? ??
|
||||
internal const string PATTERN_RESOLUTION_POINTER_MASK = "xxxxx????xxxxx????";
|
||||
internal const int PATTERN_RESOLUTION_POINTER_OFFSET = 3;
|
||||
internal const int PATTERN_RESOLUTION_POINTER_INSTRUCTION_LENGTH = 6;
|
||||
internal const string PATTERN_RESOLUTION_DEFAULT = "80 07 00 00 38 04"; // 1920x1080
|
||||
internal const string PATTERN_RESOLUTION_DEFAULT_MASK = "xxxxxx";
|
||||
internal const string PATTERN_WIDESCREEN_219 = "00 47 47 8B 94 C7 1C 02 00 00"; // ?? 47 47 8B 94 C7 1C 02 00 00
|
||||
internal const string PATTERN_WIDESCREEN_219_MASK = "?xxxxxxxxx";
|
||||
|
||||
// credits to jackfuste for FOV findings
|
||||
internal const string PATTERN_FOVSETTING = "F3 0F 10 08 F3 0F 59 0D 00 00 9B 02"; // F3 0F 10 08 F3 0F 59 0D ?? ?? 9B 02
|
||||
internal const string PATTERN_FOVSETTING_MASK = "xxxxxxxx??xx";
|
||||
internal const int PATTERN_FOVSETTING_OFFSET = 8;
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,81 @@ namespace SekiroFpsUnlockAndMore
|
|||
{
|
||||
class PatternScan
|
||||
{
|
||||
private long dwStart = 0;
|
||||
private byte[] bData;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize PatternScanner and read all memory from process.
|
||||
/// </summary>
|
||||
/// <param name="hProcess">Handle to the process in whose memory pattern will be searched for.</param>
|
||||
/// <param name="pModule">Module which will be searched for the pattern.</param>
|
||||
public PatternScan(IntPtr hProcess, ProcessModule pModule)
|
||||
{
|
||||
if (IntPtr.Size == 4)
|
||||
dwStart = (uint)pModule.BaseAddress;
|
||||
else if (IntPtr.Size == 8)
|
||||
dwStart = (long)pModule.BaseAddress;
|
||||
int nSize = pModule.ModuleMemorySize;
|
||||
bData = new byte[nSize];
|
||||
|
||||
if (!ReadProcessMemory(hProcess, dwStart, bData, nSize, out IntPtr lpNumberOfBytesRead))
|
||||
throw new Exception("ReadProcessMemory error!");
|
||||
if (lpNumberOfBytesRead.ToInt64() != nSize)
|
||||
throw new Exception("ReadProcessMemory error!");
|
||||
if (bData == null || bData.Length == 0)
|
||||
throw new Exception("Could not read memory in FindPattern.");
|
||||
}
|
||||
|
||||
~PatternScan()
|
||||
{
|
||||
bData = null;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a pattern or signature inside another process's memory.
|
||||
/// </summary>
|
||||
|
||||
/// <param name="szPattern">A character-delimited string representing the pattern to be found.</param>
|
||||
/// <param name="szMask">A string of 'x' (match), '!' (not-match), or '?' (wildcard).</param>
|
||||
/// <param name="cDelimiter">Determines how the string will be split. If null, defaults to ' '.</param>
|
||||
/// <returns>The address of the beginning of the pattern if found, 0 if not found</returns>
|
||||
internal Int64 FindPatternInternal(string szPattern, string szMask, char cDelimiter = ' ')
|
||||
{
|
||||
string[] saPattern = szPattern.Split(cDelimiter);
|
||||
byte[] bPattern = new byte[saPattern.Length];
|
||||
for (int i = 0; i < saPattern.Length; i++)
|
||||
bPattern[i] = Convert.ToByte(saPattern[i], 0x10);
|
||||
|
||||
if (bPattern == null || bPattern.Length == 0)
|
||||
throw new ArgumentNullException("Pattern's length is zero!");
|
||||
if (bPattern.Length != szMask.Length)
|
||||
throw new ArgumentException("Pattern's bytes and szMask must be of the same size!");
|
||||
|
||||
long ix;
|
||||
int iy;
|
||||
bool bFound = false;
|
||||
int patternLength = bPattern.Length;
|
||||
int dataLength = bData.Length - patternLength;
|
||||
|
||||
for (ix = 0; ix < dataLength; ix++)
|
||||
{
|
||||
bFound = true;
|
||||
for (iy = 0; iy < patternLength; iy++)
|
||||
{
|
||||
if ((szMask[iy] == 'x' && bPattern[iy] != bData[ix + iy]) ||
|
||||
(szMask[iy] == '!' && bPattern[iy] == bData[ix + iy]))
|
||||
{
|
||||
bFound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bFound)
|
||||
return Convert.ToInt64((long)dwStart + ix);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a pattern or signature inside another process's memory.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -21,5 +21,5 @@ using System.Runtime.InteropServices;
|
|||
ResourceDictionaryLocation.SourceAssembly
|
||||
)]
|
||||
|
||||
[assembly: AssemblyVersion("1.0.2.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.2.0")]
|
||||
[assembly: AssemblyVersion("1.1.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.1.0.0")]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>SekiroFpsUnlockAndMore</RootNamespace>
|
||||
<AssemblyName>SekiroFpsUnlockAndMore</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
|
|
@ -62,6 +62,7 @@
|
|||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="SettingsService.cs" />
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
|
|
@ -76,7 +77,7 @@
|
|||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Offsets.cs" />
|
||||
<Compile Include="GameData.cs" />
|
||||
<Compile Include="PatternScan.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
|
|
|
|||
110
SekiroFpsUnlockAndMore/SettingsService.cs
Normal file
110
SekiroFpsUnlockAndMore/SettingsService.cs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Windows;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace SekiroFpsUnlockAndMore
|
||||
{
|
||||
[XmlRoot("SekiroFpsUnlockAndMore")]
|
||||
[Serializable]
|
||||
public class SettingsService
|
||||
{
|
||||
private readonly string sConfigurationPath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\config.xml";
|
||||
|
||||
/// <summary>
|
||||
/// Read and store settings here.
|
||||
/// </summary>
|
||||
public SettingsService settings;
|
||||
|
||||
|
||||
/**
|
||||
* Settings definition
|
||||
*/
|
||||
[XmlElement]
|
||||
public bool cbFramelock { get; set; }
|
||||
[XmlElement]
|
||||
public int tbFramelock { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbAddResolution { get; set; }
|
||||
[XmlElement]
|
||||
public int tbWidth { get; set; }
|
||||
[XmlElement]
|
||||
public int tbHeight { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbFov { get; set; }
|
||||
[XmlElement]
|
||||
public int cbSelectFov { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbBorderless { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbBorderlessStretch { get; set; }
|
||||
[XmlElement]
|
||||
public bool exGameMods { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbGameSpeed { get; set; }
|
||||
[XmlElement]
|
||||
public int tbGameSpeed { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbPlayerSpeed { get; set; }
|
||||
[XmlElement]
|
||||
public int tbPlayerSpeed { get; set; }
|
||||
|
||||
public SettingsService() { }
|
||||
|
||||
/// <summary>
|
||||
/// Create a settings provider to load and save settings.
|
||||
/// </summary>
|
||||
/// <param name="settingsFilePath">The file path to the settings file.</param>
|
||||
public SettingsService(string settingsFilePath = null)
|
||||
{
|
||||
if (settingsFilePath != null)
|
||||
{
|
||||
sConfigurationPath = settingsFilePath;
|
||||
settings = new SettingsService();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load settings from file into settings property.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal bool Load()
|
||||
{
|
||||
if (!File.Exists(sConfigurationPath)) return false;
|
||||
|
||||
XmlSerializer xmlSerializer = new XmlSerializer(typeof(SettingsService));
|
||||
using (StreamReader streamReader = new StreamReader(sConfigurationPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
settings = (SettingsService)xmlSerializer.Deserialize(streamReader);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Error while loading configuration file:\n" + ex.Message, "Sekiro FPS Unlocker and more");
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save settings from settings property to file.
|
||||
/// </summary>
|
||||
internal void Save()
|
||||
{
|
||||
XmlSerializer xmlSerializer = new XmlSerializer(typeof(SettingsService));
|
||||
using (StreamWriter streamReader = new StreamWriter(sConfigurationPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
xmlSerializer.Serialize(streamReader, settings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Error while writing configuration file:\n" + ex.Message, "Sekiro FPS Unlocker and more");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue