mirror of
https://github.com/uberhalit/SekiroFpsUnlockAndMore.git
synced 2026-06-13 01:47:54 +00:00
Added option to preven dragonrot increase
Added option to disable death penalties Increased maximum custom resolution width Logfiles will be deleted when option gets disabled Added indicator on game processing Added status indicator for memes and dreams Fixes and minor GUI changes
This commit is contained in:
parent
7d6ba33c93
commit
7b91934caf
11 changed files with 827 additions and 368 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,3 +2,4 @@
|
|||
*bin/
|
||||
*obj/
|
||||
*.ico
|
||||
*.user
|
||||
|
|
|
|||
84
README.md
84
README.md
|
|
@ -1,6 +1,6 @@
|
|||
# Sekiro FPS Unlocker and more
|
||||
|
||||
A small utility to remove frame rate limit, add custom resolutions with 21:9 widescreen support, change field of view (FOV), borderless window mode, display and log stats (OBS), disable automatic camera adjustments and various game modifications for [Sekiro: Shadows Die Twice](https://www.sekirothegame.com/) written in C#.
|
||||
A small utility to remove frame rate limit, add custom resolutions with 21:9 widescreen support, change field of view (FOV), borderless window mode, display kills/deaths and log them (OBS), disable automatic camera adjustments 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. Works with every game version (legit steam & oh-not-so-legit), should work with all future updates. Also available on [Nexus Mods](https://www.nexusmods.com/sekiro/mods/13/).
|
||||
|
||||
## Download
|
||||
|
|
@ -8,7 +8,7 @@ Patches games memory while running, does not modify any game files. Works with e
|
|||
**[Get the latest release here](https://github.com/uberhalit/SekiroFpsUnlockAndMore/releases)**
|
||||
|
||||
### See it in action:
|
||||
[](https://giant.gfycat.com/GraciousMadeupJavalina.webm)
|
||||
[](https://giant.gfycat.com/WanDisgustingAlpinegoat.webm)
|
||||
|
||||
## Features
|
||||
|
||||
|
|
@ -17,12 +17,14 @@ Patches games memory while running, does not modify any game files. Works with e
|
|||
* G-SYNC and FreeSync support even in borderless window mode
|
||||
* 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)
|
||||
* increase or decrease field of view (FOV)
|
||||
* set the game to borderless window mode
|
||||
* disable camera auto rotate adjustment on movement (intended for mouse users)
|
||||
* disable centering of camera (cam reset) on lock-on if there is no target
|
||||
* display hidden counters such as death/kill count and optionally log them to file to display in OBS
|
||||
* 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
|
||||
* global game speed modifier (increase or decrease)
|
||||
* player speed modifier (increase or decrease)
|
||||
* automatically patch game on startup
|
||||
|
|
@ -107,8 +109,8 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s
|
|||
### 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. Select 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
|
||||
3. Select your custom resolution in the graphical settings (a default resolution like 1920x1080 or 1280x720 will be replaced with the new one)
|
||||
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
|
||||
|
|
@ -124,12 +126,6 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s
|
|||
6. Enable borderless window mode
|
||||
7. If you want fullscreen borderless enable `Fullscreen stretch`
|
||||
|
||||
### 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.
|
||||
|
||||
### On 'Disable camera reset on lock-on':
|
||||
You you press your target lok-on key and no target is in sight the game will reset and center your camera position and disable your input while its doing so. Ticking this checkbox will remove this behavior of the game.
|
||||
|
||||
### To display total death/kill counters in OBS:
|
||||
1. Start the game
|
||||
2. Load up your save game
|
||||
|
|
@ -142,14 +138,28 @@ You you press your target lok-on key and no target is in sight the game will res
|
|||
9. To add additional counters repeat steps 4-7
|
||||
10. [](#)
|
||||
|
||||
### 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
|
||||
5. Be aware that player and game speed modifications can potentially crash the game in certain cutscenes and NPC interactions
|
||||
### 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.
|
||||
|
||||
### 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.
|
||||
|
||||
### On 'Prevent dragonrot increase on death':
|
||||
This option will remove the effect dragonrot has on NPCs, if an NPC already got dragonrot then it will ensure that their condition won't worsen when you die. The internal dragonrot counter will however keep increasing, nobody will be affected by it though. Keep in mind that there are certain thresholds regarding amount of deaths between dragonrot levels, if you enable this feature and die a level might get skipped so even when you disable it afterwards the dragonrot level for all NPCs will only increase after you have hit the **next** threshold.
|
||||
|
||||
### 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 '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.
|
||||
|
||||
### 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.
|
||||
Be aware that both speed modifications can potentially crash the game in certain cutscenes and NPC interactions so use them with caution.
|
||||
|
||||
## Troubleshooting:
|
||||
* 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'`
|
||||
* Try adding the whole game folder and `Sekiro FPS Unlocker and more` to your antivirus's exclusion list
|
||||
|
|
@ -170,13 +180,13 @@ You you press your target lok-on key and no target is in sight the game will res
|
|||
|
||||
## Preview
|
||||
|
||||
[](#)
|
||||
[](#)
|
||||
|
||||
### Unlocked framerate
|
||||
[](#)
|
||||
[](#)
|
||||
|
||||
### Increased FOV, borderless window and 90% game speed
|
||||
[](#)
|
||||
### Increased FOV, disabled mouse adjustments and 90% game speed
|
||||
[](#)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
|
@ -210,31 +220,45 @@ 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
|
||||
* 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
|
||||
* disabling automatic camera rotation adjustment on movement is intended for mouse users only, using it on a non-native windows controller will disable slow-tolting on sticks
|
||||
* disabling automatic camera rotation adjustment on movement is intended for mouse users, using it on a non-native windows controller will disable slow-tilting on sticks until the game is restarted
|
||||
* Player speed modification needs a loaded save before it can be activated
|
||||
* Player and game speed modification can potentially crash the game in certain cutscenes and NPC interactions, use with caution
|
||||
* the hotkey won't work if the game runs in exclusive, true fullscreen mode
|
||||
|
||||
## Version History
|
||||
|
||||
* v1.2.3.0 (2019-04-15)
|
||||
* 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
|
||||
* Log files for game stats will be deleted now if option gets disabled
|
||||
* Added indicator to notify about game scanning process
|
||||
* Added a status indicator depending on active settings ;)
|
||||
* Readme inside utility can be collapsed now
|
||||
* Fixed an issue with borderless mode on high-dpi screens that used Windows scaling > 100%
|
||||
* Fixed an issue with borderless checkboxes upon start
|
||||
* Fixed a potential issue with 0 game speed (time freeze)
|
||||
* Fixed a minor GUI issue
|
||||
* Changed some internal methods
|
||||
* v1.2.2.0 (2019-04-13)
|
||||
* FOV can be set to any value between -95% and +95% now
|
||||
* Adden option to disable camera reset on lock-on if there is no target to lock-on
|
||||
* Added option to disable camera reset on lock-on if there is no target to lock-on
|
||||
* Fixed an issue with custom resolutions on certain system configurations
|
||||
* v1.2.1.1 (2019-04-09)
|
||||
* Added prompt to let user decide between mouse or controller input
|
||||
* This selection will fix locked up-down controls (pitch) on controllers if 'disable camera auto rotation" is used
|
||||
* v1.2.1 (2019-04-07)
|
||||
* v1.2.1.0 (2019-04-07)
|
||||
* Added an option to disable automatic camera rotation adjust on movement (thanks to Cielos for some offsets)
|
||||
* Added +25% FOV option
|
||||
* Improved initial load time and patching speed
|
||||
* v1.2.0 (2019-04-02)
|
||||
* v1.2.0.0 (2019-04-02)
|
||||
* Added stats (kills & deaths for now) with an option to log them to file for display in OBS (thanks to Me_TheCat for his contribution)
|
||||
* Player speed modifier will stick between quicktravel now
|
||||
* v1.1.0.1 (2019-03-31)
|
||||
* Fixed topmost for borderless
|
||||
* v1.1.0 (2019-03-30)
|
||||
* v1.1.0.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)
|
||||
* Custom resolution now support displays down to 1280x720
|
||||
|
|
@ -243,12 +267,12 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|||
* 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)
|
||||
* 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
|
||||
* Fixed borderless Z-order issue where task bar could be infront of window (thanks to [Forkinator](https://github.com/Forkinator) for reporting)
|
||||
* Fixed resolution issues in borderless (thanks to King Henry V#6946 for reporting)
|
||||
* v1.0.1 (2019-03-26)
|
||||
* v1.0.1.0 (2019-03-26)
|
||||
* Fixed scaling issue in borderless window mode (thanks to Spacecop42#0947 for reporting)
|
||||
* v1.0.0 (2019-03-25)
|
||||
* v1.0.0.0 (2019-03-25)
|
||||
* Initial release
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
xmlns:local="clr-namespace:SekiroFpsUnlockAndMore"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
<LinearGradientBrush x:Key="resStatusBarModeColorMock">
|
||||
<GradientStop Color="Purple" Offset="0.0" />
|
||||
<GradientStop Color="LimeGreen" Offset="0.25" />
|
||||
<GradientStop Color="Red" Offset="0.5" />
|
||||
<GradientStop Color="Blue" Offset="0.75" />
|
||||
</LinearGradientBrush>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows;
|
||||
|
||||
namespace SekiroFpsUnlockAndMore
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaktionslogik für "App.xaml"
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SekiroFpsUnlockAndMore
|
||||
{
|
||||
|
|
@ -13,88 +11,92 @@ namespace SekiroFpsUnlockAndMore
|
|||
|
||||
|
||||
/**
|
||||
<float>fFrameTick determines default frame rate limit in seconds
|
||||
<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"; // 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 = "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
|
||||
internal const string PATTERN_FRAMELOCK_FUZZY = "C7 43 ?? ?? ?? ?? ?? 4C 89 AB";
|
||||
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
|
||||
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
|
||||
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 |
|
||||
*/
|
||||
internal const string PATTERN_FRAMELOCK_SPEED_FIX = "F3 0F 59 05 ?? 30 92 02";
|
||||
internal const int PATTERN_FRAMELOCK_SPEED_FIX_OFFSET = 4;
|
||||
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;
|
||||
/**
|
||||
00000001430F7E10
|
||||
Key: Patch to pFrametimeRunningSpeed last byte
|
||||
Value: Value resolve in float table from pFrametimeRunningSpeed->fFrametimeCriticalRunningSpeed
|
||||
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 readonly Dictionary<byte[], float> PATCH_FRAMELOCK_SPEED_FIX_MATRIX = new Dictionary<byte[], float>
|
||||
private static readonly float[] PATCH_FRAMELOCK_SPEED_FIX_MATRIX = new 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 }
|
||||
15f,
|
||||
16f,
|
||||
16.6667f,
|
||||
18f,
|
||||
18.6875f,
|
||||
18.8516f,
|
||||
20f,
|
||||
24f,
|
||||
25f,
|
||||
27.5f,
|
||||
30f,
|
||||
32f,
|
||||
38.5f,
|
||||
40f,
|
||||
48f,
|
||||
49.5f,
|
||||
50f,
|
||||
57.2958f,
|
||||
60f,
|
||||
64f,
|
||||
66.75f,
|
||||
67f,
|
||||
78.8438f,
|
||||
80f,
|
||||
84f,
|
||||
90f,
|
||||
93.8f,
|
||||
100f,
|
||||
120f,
|
||||
127f,
|
||||
128f,
|
||||
130f,
|
||||
140f,
|
||||
144f,
|
||||
150f
|
||||
};
|
||||
internal static readonly byte[] PATCH_FRAMELOCK_SPEED_FIX_DISABLE = new byte[1] { 0x90 }; // 30f
|
||||
internal const float PATCH_FRAMELOCK_SPEED_FIX_DEFAULT_VALUE = 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)
|
||||
/// <returns>The value of the closest speed fix.</returns>
|
||||
internal static float 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))
|
||||
float closestSpeedFix = PATCH_FRAMELOCK_SPEED_FIX_DEFAULT_VALUE;
|
||||
foreach (float speedFix in PATCH_FRAMELOCK_SPEED_FIX_MATRIX)
|
||||
{
|
||||
if (Math.Abs(idealSpeedFix - speedFix.Value) < Math.Abs(idealSpeedFix - closestSpeedFix.Value))
|
||||
if (Math.Abs(idealSpeedFix - speedFix) < Math.Abs(idealSpeedFix - closestSpeedFix))
|
||||
closestSpeedFix = speedFix;
|
||||
}
|
||||
return closestSpeedFix.Key;
|
||||
return closestSpeedFix;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Reference pointer pCurrentResolutionWidth to <int>iInternalGameWidth (and <int>iInternalGameHeight which is +4 bytes)
|
||||
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 |
|
||||
|
|
@ -107,28 +109,30 @@ namespace SekiroFpsUnlockAndMore
|
|||
|
||||
/**
|
||||
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
|
||||
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 00 08 00 00 80 04 00 00"; // 1920x1080
|
||||
internal const string PATTERN_RESOLUTION_DEFAULT_720 = "00 05 00 00 D0 02 00 00 A0 05 00 00 2A 03 00 00"; // 1280x720
|
||||
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] { 0x00, 0x05, 0x00, 0x00, 0xD0, 0x02, 0x00, 0x00 };
|
||||
internal static readonly byte[] PATCH_RESOLUTION_DEFAULT_DISABLE = new byte[8] { 0x80, 0x07, 0x00, 0x00, 0x38, 0x04, 0x00, 0x00 };
|
||||
internal static readonly byte[] PATCH_RESOLUTION_DEFAULT_DISABLE_720 = new byte[8] { 0x00, 0x05, 0x00, 0x00, 0xD0, 0x02, 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
|
||||
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 |
|
||||
*/
|
||||
internal const string PATTERN_RESOLUTION_SCALING_FIX = "47 47 8B 94 C7 1C 02 00 00";
|
||||
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
|
||||
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
|
||||
internal static readonly byte[] PATCH_RESOLUTION_SCALING_FIX_DISABLE = new byte[3] { 0x85, 0xC9, 0x74 }; // test ecx,ecx; 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
|
||||
FOV is in radians while default is 1.0deg (0.0174533rad), to increase by 25% you'd write 1.25deg (0.0218166rad) as fFov
|
||||
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.
|
||||
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] |
|
||||
|
|
@ -140,92 +144,15 @@ 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] |
|
||||
*/
|
||||
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;
|
||||
internal static readonly byte[] INJECT_CAMADJUST_PITCH_SHELLCODE = new byte[]
|
||||
{
|
||||
0x0F, 0x28, 0xA6, 0x70, 0x01, 0x00, 0x00, // movaps xmm4,xmmword ptr ds:[rsi+170]
|
||||
0x0F, 0x29, 0xA5, 0x70, 0x08, 0x00, 0x00 // movaps xmmword ptr ss:[rbp+870],xmm4
|
||||
};
|
||||
/**
|
||||
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 |
|
||||
*/
|
||||
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;
|
||||
internal const int INJECT_CAMADJUST_YAW_Z_OVERWRITE_LENGTH = 8;
|
||||
internal static readonly byte[] INJECT_CAMADJUST_YAW_Z_SHELLCODE = new byte[]
|
||||
{
|
||||
0xF3, 0x0F, 0x10, 0x86, 0x74, 0x01, 0x00, 0x00, // movss xmm0,dword ptr ds:[rsi+174]
|
||||
0xF3, 0x0F, 0x11, 0x86, 0x74, 0x01, 0x00, 0x00 // movss dword ptr ds:[rsi+174],xmm0
|
||||
};
|
||||
/**
|
||||
Controls automatic camera pitch adjust on move on XY-axis. Pointer in rax holds new pitch while rsi+170 holds current one prior movement so we overwrite xmm0 with the old pitch value and then overwrite [rax] with xmm0
|
||||
Breaks Pitch on emulated controllers...
|
||||
000000014073B476 | F3:0F1000 | movss xmm0,dword ptr ds:[rax] | newCamPitch | code inject overwrite from here
|
||||
000000014073B47A | F3:0F1186 70010000 | movss dword ptr ds:[rsi+170],xmm0 | camPitch
|
||||
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 |
|
||||
*/
|
||||
// thanks to 'Cielos' for original offset
|
||||
internal const string PATTERN_CAMADJUST_PITCH_XY = "F3 ?? ?? ?? F3 ?? ?? ?? ?? ?? 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[]
|
||||
{
|
||||
0xF3, 0x0F, 0x10, 0x86, 0x70, 0x01, 0x00, 0x00, // movss xmm0,dword ptr ds:[rsi+170]
|
||||
0xF3, 0x0F, 0x11, 0x00, // movss dword ptr ds:[rax],xmm0
|
||||
0xF3, 0x0F, 0x10, 0x00, // movss xmm0,dword ptr ds:[rax]
|
||||
0xF3, 0x0F, 0x11, 0x86, 0x70, 0x01, 0x00, 0x00 // movss dword ptr ds:[rsi+170],xmm0
|
||||
};
|
||||
/**
|
||||
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
|
||||
*/
|
||||
// thanks to 'Cielos' for original offset
|
||||
internal const string PATTERN_CAMADJUST_YAW_XY = "E8 ?? ?? ?? ?? F3 0F 11 86 74 01 00 00 E9";
|
||||
internal const int PATTERN_CAMADJUST_YAW_XY_OFFSET = 5;
|
||||
internal const int INJECT_CAMADJUST_YAW_XY_OVERWRITE_LENGTH = 8;
|
||||
internal static readonly byte[] INJECT_CAMADJUST_YAW_XY_SHELLCODE = new byte[]
|
||||
{
|
||||
0xF3, 0x0F, 0x10, 0x86, 0x74, 0x01, 0x00, 0x00, // movss xmm0,dword ptr ds:[rsi+174]
|
||||
0xF3, 0x0F, 0x11, 0x86, 0x74, 0x01, 0x00, 0x00 // movss dword ptr ds:[rsi+174],xmm0
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
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] |
|
||||
*/
|
||||
internal const string PATTERN_CAMRESET_LOCKON = "C6 86 ?? ?? 00 00 ?? F3 0F 10 8E ?? ?? 00 00";
|
||||
internal const int PATTERN_CAMRESET_LOCKON_OFFSET = 6;
|
||||
internal static byte[] PATCH_CAMRESET_LOCKON_DISABLE = new byte[1] { 0x00 }; // FALSE
|
||||
internal static byte[] PATCH_CAMRESET_LOCKON_ENABLE = new byte[1] { 0x01 }; // TRUE
|
||||
|
||||
|
||||
/**
|
||||
Reference pointer pPlayerStatsRelated to PlayerStats pointer, offset in struct to <int>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
|
||||
*/
|
||||
Reference pointer pPlayerStatsRelated to PlayerStats pointer, offset in struct to <int>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
|
||||
*/
|
||||
// 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";
|
||||
internal const int PATTERN_PLAYER_DEATHS_OFFSET = 29;
|
||||
|
|
@ -245,7 +172,164 @@ namespace SekiroFpsUnlockAndMore
|
|||
|
||||
|
||||
/**
|
||||
Reference pointer pTimeRelated to TimescaleManager pointer, offset in struct to <float>fTimescale which acts as a global speed scale for almost all ingame calculations
|
||||
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] |
|
||||
*/
|
||||
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;
|
||||
internal static readonly byte[] INJECT_CAMADJUST_PITCH_SHELLCODE = new byte[]
|
||||
{
|
||||
0x0F, 0x28, 0xA6, 0x70, 0x01, 0x00, 0x00, // movaps xmm4,xmmword ptr ds:[rsi+170]
|
||||
0x0F, 0x29, 0xA5, 0x70, 0x08, 0x00, 0x00 // movaps xmmword ptr ss:[rbp+870],xmm4
|
||||
};
|
||||
/**
|
||||
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 |
|
||||
*/
|
||||
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;
|
||||
internal const int INJECT_CAMADJUST_YAW_Z_OVERWRITE_LENGTH = 8;
|
||||
internal static readonly byte[] INJECT_CAMADJUST_YAW_Z_SHELLCODE = new byte[]
|
||||
{
|
||||
0xF3, 0x0F, 0x10, 0x86, 0x74, 0x01, 0x00, 0x00, // movss xmm0,dword ptr ds:[rsi+174]
|
||||
0xF3, 0x0F, 0x11, 0x86, 0x74, 0x01, 0x00, 0x00 // movss dword ptr ds:[rsi+174],xmm0
|
||||
};
|
||||
/**
|
||||
Controls automatic camera pitch adjust on move on XY-axis.
|
||||
Pointer in rax holds new pitch while rsi+170 holds current one prior movement so we overwrite xmm0 with the old pitch value and then overwrite [rax] with xmm0.
|
||||
Breaks Pitch on emulated controllers...
|
||||
000000014073B476 | F3:0F1000 | movss xmm0,dword ptr ds:[rax] | newCamPitch | code inject overwrite from here
|
||||
000000014073B47A | F3:0F1186 70010000 | movss dword ptr ds:[rsi+170],xmm0 | camPitch
|
||||
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 |
|
||||
*/
|
||||
// thanks to 'Cielos' for original offset
|
||||
internal const string PATTERN_CAMADJUST_PITCH_XY = "F3 ?? ?? ?? F3 ?? ?? ?? ?? ?? 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[]
|
||||
{
|
||||
0xF3, 0x0F, 0x10, 0x86, 0x70, 0x01, 0x00, 0x00, // movss xmm0,dword ptr ds:[rsi+170]
|
||||
0xF3, 0x0F, 0x11, 0x00, // movss dword ptr ds:[rax],xmm0
|
||||
0xF3, 0x0F, 0x10, 0x00, // movss xmm0,dword ptr ds:[rax]
|
||||
0xF3, 0x0F, 0x11, 0x86, 0x70, 0x01, 0x00, 0x00 // movss dword ptr ds:[rsi+170],xmm0
|
||||
};
|
||||
/**
|
||||
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
|
||||
*/
|
||||
// thanks to 'Cielos' for original offset
|
||||
internal const string PATTERN_CAMADJUST_YAW_XY = "E8 ?? ?? ?? ?? F3 0F 11 86 ?? ?? 00 00 E9";
|
||||
internal const int PATTERN_CAMADJUST_YAW_XY_OFFSET = 5;
|
||||
internal const int INJECT_CAMADJUST_YAW_XY_OVERWRITE_LENGTH = 8;
|
||||
internal static readonly byte[] INJECT_CAMADJUST_YAW_XY_SHELLCODE = new byte[]
|
||||
{
|
||||
0xF3, 0x0F, 0x10, 0x86, 0x74, 0x01, 0x00, 0x00, // movss xmm0,dword ptr ds:[rsi+174]
|
||||
0xF3, 0x0F, 0x11, 0x86, 0x74, 0x01, 0x00, 0x00 // movss dword ptr ds:[rsi+174],xmm0
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
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] |
|
||||
*/
|
||||
internal const string PATTERN_CAMRESET_LOCKON = "C6 86 ?? ?? 00 00 ?? F3 0F 10 8E ?? ?? 00 00";
|
||||
internal const int PATTERN_CAMRESET_LOCKON_OFFSET = 6;
|
||||
internal static readonly byte[] PATCH_CAMRESET_LOCKON_DISABLE = new byte[1] { 0x00 }; // false
|
||||
internal static readonly byte[] PATCH_CAMRESET_LOCKON_ENABLE = new byte[1] { 0x01 }; // true
|
||||
|
||||
|
||||
/**
|
||||
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.
|
||||
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...
|
||||
*/
|
||||
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
|
||||
|
||||
|
||||
/**
|
||||
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] |
|
||||
*/
|
||||
internal const string PATTERN_DEATHPENALTIES1 = "F3 ?? 0F 2C ?? 41 ?? ?? 48 ?? ?? E8 ?? ?? ?? ?? 8B";
|
||||
internal const int PATTERN_DEATHPENALTIES1_OFFSET = 11;
|
||||
internal const int PATCH_DEATHPENALTIES1_INSTRUCTION_LENGTH = 5;
|
||||
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 |
|
||||
*/
|
||||
internal const string PATTERN_DEATHPENALTIES2 = "8B ?? 89 83 ?? ?? ?? ?? 45 ?? ?? 44 89 ?? 24 ?? ?? 00 00 2B ?? 89 ?? 24 ?? ?? 00 00 E8";
|
||||
internal const int PATTERN_DEATHPENALTIES2_OFFSET = 2;
|
||||
internal const int PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH = 26;
|
||||
internal static readonly byte[] PATCH_DEATHPENALTIES2_DISABLE = new byte[26] // nop
|
||||
{
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
|
||||
0x90, 0x90
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
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()
|
||||
*/
|
||||
internal const string PATTERN_DEATHSCOUNTER = "0F 84 ?? ?? ?? ?? 84 DB 0F 85 ?? ?? ?? ?? 48 8B ?? E8";
|
||||
internal const int PATTERN_DEATHSCOUNTER_OFFSET = 6;
|
||||
internal static readonly byte[] PATCH_DEATHSCOUNTER_DISABLE = new byte[4] { 0x90, 0x90, 0x90, 0xE9 }; // nop; jmp
|
||||
internal static readonly byte[] PATCH_DEATHSCOUNTER_ENABLE = new byte[4] { 0x84, 0xDB, 0x0F, 0x85 }; // test bl,bl; jne
|
||||
|
||||
|
||||
/**
|
||||
Reference pointer pTimeRelated to TimescaleManager 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->[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] |
|
||||
|
|
@ -257,14 +341,15 @@ namespace SekiroFpsUnlockAndMore
|
|||
|
||||
|
||||
/**
|
||||
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] |
|
||||
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] |
|
||||
00000001406BF1E5 | 81FA 10270000 | cmp edx,2710 |
|
||||
*/
|
||||
// credits to 'Zullie the Witch' for original offset
|
||||
internal const string PATTERN_TIMESCALE_PLAYER = "48 8B 1D ?? ?? ?? ?? 48 85 DB 74 3C 8B 17";
|
||||
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_POINTER3_OFFSET = 0x1FF8;
|
||||
|
|
|
|||
|
|
@ -5,81 +5,85 @@
|
|||
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.2" Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing">
|
||||
Title="Sekiro FPS Unlocker and more v1.2.3" Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing">
|
||||
|
||||
<Grid Background="#FFF9F9F9">
|
||||
<DockPanel>
|
||||
<StackPanel DockPanel.Dock="Top" Margin="10,10,10,0" Width="290" Height="Auto">
|
||||
<StackPanel DockPanel.Dock="Top" Margin="10,10,10,0" Width="300" 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" />
|
||||
<CheckBox x:Name="cbFramelock" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Frame rate lock:" ToolTip="Make sure to read the guide" IsChecked="True" Checked="CbFramelock_Check_Handler" Unchecked="CbFramelock_Check_Handler" TabIndex="1" />
|
||||
<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" TabIndex="2" />
|
||||
</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" />
|
||||
<CheckBox x:Name="cbAddResolution" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Add custom resolution:" ToolTip="Your monitor has to natively support this resolution" Checked="CbAddResolution_Check_Handler" Unchecked="CbAddResolution_Check_Handler" TabIndex="3" />
|
||||
<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" TabIndex="5" />
|
||||
<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" />
|
||||
<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" TabIndex="4" />
|
||||
</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="Change FOV by (%):" Checked="CbFov_Check_Handler" Unchecked="CbFov_Check_Handler" />
|
||||
<CheckBox x:Name="cbFov" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Change FOV by (%):" ToolTip="Increase or decrease" Checked="CbFov_Check_Handler" Unchecked="CbFov_Check_Handler" TabIndex="6" />
|
||||
<Button x:Name="bFovHigher" DockPanel.Dock="Right" Content=">" Margin="0,0,0,0" Width="25" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Focusable="False" Click="BFovHigher_Click" />
|
||||
<TextBox x:Name="tbFov" DockPanel.Dock="Right" Margin="0,0,3,0" Width="30" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Text="25" TextAlignment="Center" MaxLength="3" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
|
||||
<TextBox x:Name="tbFov" DockPanel.Dock="Right" Margin="0,0,3,0" Width="30" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Text="25" TextAlignment="Center" MaxLength="3" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" TabIndex="7" />
|
||||
<Button x:Name="bFovLower" 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="BFovLower_Click" />
|
||||
<Button x:Name="bFov0" DockPanel.Dock="Right" Content="0" Margin="0,0,3,0" Width="27" Height="25" FontSize="14 px" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Focusable="False" Click="BFov0_Click" />
|
||||
</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" ToolTip="To enable this set 'Windowed' mode in game options first." 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" />
|
||||
<CheckBox x:Name="cbBorderless" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Borderless window" ToolTip="To enable this set 'Windowed' mode in game options first" IsEnabled="False" Checked="CbBorderless_Checked" Unchecked="CbBorderless_Unchecked" TabIndex="8"/>
|
||||
<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" TabIndex="9" />
|
||||
</StackPanel>
|
||||
<CheckBox x:Name="cbLogStats" Margin="0,5,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Log stats (Deaths, Kills) to file for OBS" ToolTip="Check the guide on how to display these on stream with OBS." Checked="CbStatChanged" Unchecked="CbStatChanged" />
|
||||
<Expander x:Name="exGameMods" Margin="-3,5,0,0" Height="Auto" FontSize="14 px" Header="Modifications" IsExpanded="True">
|
||||
<CheckBox x:Name="cbLogStats" Margin="0,5,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Log stats (Deaths, Kills) to file for OBS" ToolTip="Check the guide on how to display these on stream with OBS" Checked="CbStatChanged" Unchecked="CbStatChanged" TabIndex="10" />
|
||||
<Expander x:Name="exGameMods" Margin="-3,5,0,0" Height="Auto" FontSize="14 px" Header="Modifications" IsExpanded="True" TabIndex="11">
|
||||
<Grid Margin="3,1,0,0" Background="#FFF9F9F9">
|
||||
<StackPanel Width="Auto" Height="Auto">
|
||||
<CheckBox x:Name="cbCamAdjust" Margin="0,5,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Disable camera auto rotate on movement" ToolTip="Disables the annoying automatic camera adjustment on movement. Intended for mouse users." Checked="CbCamAdjust_Check_Handler" Unchecked="CbCamAdjust_Check_Handler" />
|
||||
<CheckBox x:Name="cbCamReset" Margin="0,3,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Disable camera reset on lock-on" ToolTip="Disables the annoying camera centering on lock-on when there is no target." Checked="CbCamReset_Check_Handler" Unchecked="CbCamReset_Check_Handler" />
|
||||
<CheckBox x:Name="cbCamAdjust" Margin="0,5,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Disable camera auto rotate on movement" ToolTip="Disables the annoying automatic camera adjustment on movement. Intended for mouse users" Checked="CbCamAdjust_Check_Handler" Unchecked="CbCamAdjust_Check_Handler" TabIndex="12" />
|
||||
<CheckBox x:Name="cbCamReset" Margin="0,3,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Disable camera reset on lock-on" ToolTip="Disables the annoying camera centering on lock-on when there is no target" Checked="CbCamReset_Check_Handler" Unchecked="CbCamReset_Check_Handler" TabIndex="13" />
|
||||
<CheckBox x:Name="cbDragonrot" Margin="0,3,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Prevent dragonrot increase on death" ToolTip="NPCs won't get the disease and/or their condition won't get worse" Checked="CbDragonrot_Check_Handler" Unchecked="CbDragonrot_Check_Handler" TabIndex="14" />
|
||||
<CheckBox x:Name="cbDeathPenalty" Margin="0,3,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Disable death penalties (except dragonrot)" ToolTip="Disables Sen and Experience loss upon death" Checked="CbDeathPenalty_Check_Handler" Unchecked="CbDeathPenalty_Check_Handler" TabIndex="15" />
|
||||
<CheckBox x:Name="cbDeathPenaltyHidden" Margin="0,3,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="(DEBUG) Disable hidden death penalties" ToolTip="DEBUG ONLY" Checked="CbDeathPenaltyHidden_Check_Handler" Unchecked="CbDeathPenaltyHidden_Check_Handler" IsTabStop="False" Visibility="Collapsed" />
|
||||
<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 (%):" ToolTip="Increase or decrease. Can potentially crash the game in cutscenes, use with caution." Checked="CbGameSpeed_Check_Handler" Unchecked="CbGameSpeed_Check_Handler" />
|
||||
<CheckBox x:Name="cbGameSpeed" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Game speed (%):" ToolTip="Increase or decrease. Can potentially crash the game in cutscenes, use with caution" Checked="CbGameSpeed_Check_Handler" Unchecked="CbGameSpeed_Check_Handler" TabIndex="16" />
|
||||
<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" />
|
||||
<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" TabIndex="17" />
|
||||
<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="Increase or decrease. To enable this start the game and load a save, then tick the checkbox. Can potentially crash the game in cutscenes, use with caution." Checked="CbPlayerSpeed_Check_Handler" Unchecked="CbPlayerSpeed_Check_Handler" />
|
||||
<CheckBox x:Name="cbPlayerSpeed" DockPanel.Dock="Left" Margin="0,0,0,0" Height="25" FontSize="14 px" VerticalContentAlignment="Center" Content="Player speed (%):" ToolTip="Increase or decrease. To enable this start the game and load a save, then tick the checkbox. Can potentially crash the game in cutscenes, use with caution" Checked="CbPlayerSpeed_Check_Handler" Unchecked="CbPlayerSpeed_Check_Handler" TabIndex="18" />
|
||||
<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" />
|
||||
<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" TabIndex="19" />
|
||||
<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 Margin="2,5,2,0" FontSize="11 px" TextWrapping="WrapWithOverflow" 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>
|
||||
<Run>To avoid stuttering it's recommended to always disable VSYNC (except when you have GSYNC).</Run>
|
||||
<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 "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 activate borderless afterwards.</Run>
|
||||
<Run FontWeight="Bold">Disabling camera auto rotate is mostly intended for mouse users.</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" FontSize="12 px">
|
||||
<Button x:Name="bPatch" Margin="0,7,0,0" Width="300" 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" TabIndex="20" IsTabStop="False" />
|
||||
<TextBox x:Name="tbStatus" Margin="0,5,0,0" Width="300" Height="25" FontSize="14 px" FontWeight="Bold" Text="waiting for game..." TextAlignment="Center" TextWrapping="NoWrap" IsEnabled="False" />
|
||||
<Expander x:Name="exGuide" Margin="0,8,0,0" Height="Auto" FontSize="14 px" Header="ReadMe" IsExpanded="True" TabIndex="21">
|
||||
<TextBlock Margin="2,6,2,0" FontSize="11 px" TextWrapping="WrapWithOverflow" 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>
|
||||
<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 "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 activate borderless afterwards.</Run>
|
||||
<Run FontWeight="Bold">Disabling camera auto rotate is mostly intended for mouse users.</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>
|
||||
</Expander>
|
||||
<Label HorizontalAlignment="Right" FontSize="12 px" TabIndex="22">
|
||||
<Hyperlink NavigateUri="https://github.com/uberhalit/SekiroFpsUnlockAndMore" RequestNavigate="Hyperlink_RequestNavigate">
|
||||
v1.2.2 - by uberhalit
|
||||
v1.2.3 - by uberhalit
|
||||
</Hyperlink>
|
||||
</Label>
|
||||
</StackPanel>
|
||||
|
|
@ -98,8 +102,13 @@
|
|||
</TextBlock>
|
||||
</StatusBarItem>
|
||||
<Separator Margin="5,4,5,4" Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}"/>
|
||||
<StatusBarItem DockPanel.Dock="Left" HorizontalAlignment="Left">
|
||||
<TextBlock>
|
||||
<Run x:Name="sbMode" FontWeight="SemiBold" FontStyle="Italic" />
|
||||
</TextBlock>
|
||||
</StatusBarItem>
|
||||
<StatusBarItem DockPanel.Dock="Right" HorizontalAlignment="Right">
|
||||
<TextBlock Name="sbStatus" />
|
||||
<TextBlock Name="sbInput" />
|
||||
</StatusBarItem>
|
||||
</StatusBar>
|
||||
</DockPanel>
|
||||
|
|
|
|||
|
|
@ -23,17 +23,23 @@ namespace SekiroFpsUnlockAndMore
|
|||
internal IntPtr _gameAccessHwnd = IntPtr.Zero;
|
||||
internal static IntPtr _gameAccessHwndStatic;
|
||||
internal long _offset_framelock = 0x0;
|
||||
internal long _offset_framelock_speed_fix = 0x0;
|
||||
internal long _offset_resolution = 0x0;
|
||||
internal long _offset_resolution_default = 0x0;
|
||||
internal long _offset_resolution_scaling_fix = 0x0;
|
||||
internal long _offset_camera_reset = 0x0;
|
||||
internal long _offset_total_kills = 0x0;
|
||||
internal long _offset_player_deaths = 0x0;
|
||||
internal long _offset_camera_reset = 0x0;
|
||||
internal long _offset_dragonrot_routine = 0x0;
|
||||
internal long _offset_deathpenalties1 = 0x0;
|
||||
internal long _offset_deathpenalties2 = 0x0;
|
||||
internal long _offset_deathscounter_routine = 0x0;
|
||||
internal long _offset_timescale = 0x0;
|
||||
internal long _offset_timescale_player = 0x0;
|
||||
internal long _offset_timescale_player_pointer_start = 0x0;
|
||||
|
||||
internal byte[] _patch_deathpenalties1_enable;
|
||||
internal byte[] _patch_deathpenalties2_enable;
|
||||
|
||||
internal MemoryCaveGenerator _memoryCaveGenerator;
|
||||
internal SettingsService _settingsService;
|
||||
internal StatusViewModel _statusViewModel = new StatusViewModel();
|
||||
|
|
@ -44,16 +50,21 @@ namespace SekiroFpsUnlockAndMore
|
|||
internal readonly System.Timers.Timer _timerStatsCheck = new System.Timers.Timer();
|
||||
internal bool _running = false;
|
||||
internal bool _gameInitializing = false;
|
||||
internal static string _logPath;
|
||||
internal string _deathCounterPath;
|
||||
internal string _killCounterPath;
|
||||
internal bool _retryAccess = true;
|
||||
internal bool _use_resolution_720 = false;
|
||||
internal bool _codeCave_camadjust = false;
|
||||
internal bool _dataCave_speedfix = false;
|
||||
internal bool _dataCave_fovsetting = false;
|
||||
internal bool _codeCave_camadjust = false;
|
||||
internal bool _retryAccess = true;
|
||||
internal bool _statLoggingEnabled = false;
|
||||
internal bool _initialStartup = true;
|
||||
internal bool _debugMode = false;
|
||||
internal static string _path_logs;
|
||||
internal string _path_deathsLog;
|
||||
internal string _path_killsLog;
|
||||
internal RECT _windowRect;
|
||||
internal Size _screenSize;
|
||||
|
||||
internal const string _DATACAVE_SPEEDFIX_POINTER = "speedfixPointer";
|
||||
internal const string _DATACAVE_FOV_POINTER = "fovPointer";
|
||||
internal const string _CODECAVE_CAMADJUST_PITCH = "camAdjustPitch";
|
||||
internal const string _CODECAVE_CAMADJUST_YAW_Z = "camAdjustYawZ";
|
||||
|
|
@ -79,19 +90,14 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
GC.KeepAlive(mutex);
|
||||
|
||||
_logPath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\SekiroFpsUnlockAndMore.log";
|
||||
_deathCounterPath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\DeathCounter.txt";
|
||||
_killCounterPath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\TotalKillsCounter.txt";
|
||||
_path_logs = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\SekiroFpsUnlockAndMore.log";
|
||||
_path_deathsLog = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\DeathCounter.txt";
|
||||
_path_killsLog = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\TotalKillsCounter.txt";
|
||||
|
||||
LoadConfiguration();
|
||||
|
||||
if (_settingsService.ApplicationSettings.cameraAdjustNotify)
|
||||
{
|
||||
if (_settingsService.ApplicationSettings.peasantInput)
|
||||
this.sbStatus.Text = "Controller Input";
|
||||
else
|
||||
this.sbStatus.Text = "Mouse Input";
|
||||
}
|
||||
this.sbInput.Text = _settingsService.ApplicationSettings.peasantInput ? "Controller" : "Mouse";
|
||||
|
||||
IntPtr hWnd = new WindowInteropHelper(this).Handle;
|
||||
if (!RegisterHotKey(hWnd, 9009, MOD_CONTROL, VK_P))
|
||||
|
|
@ -99,6 +105,9 @@ namespace SekiroFpsUnlockAndMore
|
|||
|
||||
ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
|
||||
|
||||
_screenSize = GetDpiSafeResolution();
|
||||
if ((int)_screenSize.Width < 1920) _use_resolution_720 = true;
|
||||
|
||||
_bgwScanGame.DoWork += new DoWorkEventHandler(ReadGame);
|
||||
_bgwScanGame.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnReadGameFinish);
|
||||
|
||||
|
|
@ -107,6 +116,7 @@ namespace SekiroFpsUnlockAndMore
|
|||
bool result = await CheckGame();
|
||||
if (result)
|
||||
{
|
||||
UpdateStatus("scanning game...", Brushes.Orange);
|
||||
_bgwScanGame.RunWorkerAsync();
|
||||
_dispatcherTimerGameCheck.Stop();
|
||||
}
|
||||
|
|
@ -124,7 +134,7 @@ namespace SekiroFpsUnlockAndMore
|
|||
/// <summary>
|
||||
/// On window closing.
|
||||
/// </summary>
|
||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
private void Window_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
_timerStatsCheck.Stop();
|
||||
SaveConfiguration();
|
||||
|
|
@ -166,14 +176,19 @@ namespace SekiroFpsUnlockAndMore
|
|||
this.tbFov.Text = _settingsService.ApplicationSettings.tbFov.ToString();
|
||||
this.cbBorderless.IsChecked = _settingsService.ApplicationSettings.cbBorderless;
|
||||
this.cbBorderlessStretch.IsChecked = _settingsService.ApplicationSettings.cbBorderlessStretch;
|
||||
this.cbCamAdjust.IsChecked = _settingsService.ApplicationSettings.cbCamAdjust;
|
||||
this.cbCamReset.IsChecked = _settingsService.ApplicationSettings.cbCamReset;
|
||||
this.cbLogStats.IsChecked = _settingsService.ApplicationSettings.cbLogStats;
|
||||
this.exGameMods.IsExpanded = _settingsService.ApplicationSettings.exGameMods;
|
||||
this.cbCamAdjust.IsChecked = _settingsService.ApplicationSettings.cbCamAdjust;
|
||||
this.cbCamReset.IsChecked = _settingsService.ApplicationSettings.cbCamReset;
|
||||
this.cbDragonrot.IsChecked = _settingsService.ApplicationSettings.cbDragonrot;
|
||||
this.cbDeathPenalty.IsChecked = _settingsService.ApplicationSettings.cbDeathPenalty;
|
||||
this.cbDeathPenaltyHidden.Visibility = _settingsService.ApplicationSettings.hiddenDPs == ZUH_HIDDEN_DP ? Visibility.Visible : Visibility.Collapsed;
|
||||
if (_settingsService.ApplicationSettings.hiddenDPs == ZUH_HIDDEN_DP) { _debugMode = true; sbMode.Text = "DEBUG"; }
|
||||
this.cbGameSpeed.IsChecked = _settingsService.ApplicationSettings.cbGameSpeed;
|
||||
this.tbGameSpeed.Text = _settingsService.ApplicationSettings.tbGameSpeed.ToString();
|
||||
this.cbPlayerSpeed.IsChecked = _settingsService.ApplicationSettings.cbPlayerSpeed;
|
||||
this.tbPlayerSpeed.Text = _settingsService.ApplicationSettings.tbPlayerSpeed.ToString();
|
||||
this.exGuide.IsExpanded = _settingsService.ApplicationSettings.exGuide;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -190,24 +205,57 @@ namespace SekiroFpsUnlockAndMore
|
|||
_settingsService.ApplicationSettings.tbFov = this.tbFov.Text != "" && !this.tbFov.Text.Contains(" ") ? Convert.ToInt32(this.tbFov.Text) : 25;
|
||||
_settingsService.ApplicationSettings.cbBorderless = this.cbBorderless.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.cbBorderlessStretch = this.cbBorderlessStretch.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.cbCamAdjust = this.cbCamAdjust.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.cbCamReset = this.cbCamReset.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.cbLogStats = this.cbLogStats.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.exGameMods = this.exGameMods.IsExpanded;
|
||||
_settingsService.ApplicationSettings.cbCamAdjust = this.cbCamAdjust.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.cbCamReset = this.cbCamReset.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.cbDragonrot = this.cbDragonrot.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.cbDeathPenalty = this.cbDeathPenalty.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.cbGameSpeed = this.cbGameSpeed.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.tbGameSpeed = this.tbGameSpeed.Text != "" && !this.tbGameSpeed.Text.Contains(" ") ? Convert.ToInt32(this.tbGameSpeed.Text) : 100;
|
||||
_settingsService.ApplicationSettings.cbPlayerSpeed = this.cbPlayerSpeed.IsChecked == true;
|
||||
_settingsService.ApplicationSettings.tbPlayerSpeed = this.tbPlayerSpeed.Text != "" && !this.tbPlayerSpeed.Text.Contains(" ") ? Convert.ToInt32(this.tbPlayerSpeed.Text) : 100;
|
||||
_settingsService.ApplicationSettings.exGuide = this.exGuide.IsExpanded;
|
||||
_settingsService.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets GUI and clears configuration file.
|
||||
/// </summary>
|
||||
private void ClearConfiguration()
|
||||
{
|
||||
this.cbFramelock.IsChecked = false;
|
||||
this.tbFramelock.Text = "144";
|
||||
this.cbAddResolution.IsChecked = false;
|
||||
this.tbWidth.Text = "2560";
|
||||
this.tbHeight.Text = "1080";
|
||||
this.cbFov.IsChecked = false;
|
||||
this.tbFov.Text = "25";
|
||||
this.cbBorderless.IsChecked = false;
|
||||
this.cbBorderlessStretch.IsChecked = false;
|
||||
this.cbLogStats.IsChecked = false;
|
||||
this.exGameMods.IsExpanded = true;
|
||||
this.cbCamAdjust.IsChecked = false;
|
||||
this.cbCamReset.IsChecked = false;
|
||||
this.cbDragonrot.IsChecked = false;
|
||||
this.cbDeathPenalty.IsChecked = false;
|
||||
this.cbDeathPenaltyHidden.Visibility = Visibility.Collapsed;
|
||||
this.cbGameSpeed.IsChecked = false;
|
||||
this.tbGameSpeed.Text = "100";
|
||||
this.cbPlayerSpeed.IsChecked = false;
|
||||
this.tbPlayerSpeed.Text = "100";
|
||||
this.sbMode.Text = "";
|
||||
_settingsService.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if game is running and initializes further functionality.
|
||||
/// </summary>
|
||||
private Task<bool> CheckGame()
|
||||
{
|
||||
// game process have been found last check and can be read now, aborting
|
||||
if (_gameInitializing) return Task.FromResult(true);
|
||||
if (_gameInitializing)
|
||||
return Task.FromResult(true);
|
||||
|
||||
Process[] procList = Process.GetProcessesByName(GameData.PROCESS_NAME);
|
||||
if (procList.Length < 1)
|
||||
|
|
@ -268,17 +316,17 @@ namespace SekiroFpsUnlockAndMore
|
|||
string gameFileVersion = FileVersionInfo.GetVersionInfo(procList[0].MainModule.FileName).FileVersion;
|
||||
if (gameFileVersion != GameData.PROCESS_EXE_VERSION && !_settingsService.ApplicationSettings.gameVersionNotify)
|
||||
{
|
||||
MessageBox.Show("Unknown game version.\nSome functions might not work properly or even crash the game. " +
|
||||
"Check for updates on this utility regularly following the link at the bottom.", "Sekiro FPS Unlocker and more", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
MessageBox.Show(string.Format("Unknown game version '{0}'.\nSome functions might not work properly or even crash the game. " +
|
||||
"Check for updates on this utility regularly following the link at the bottom.", gameFileVersion), "Sekiro FPS Unlocker and more", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
ClearConfiguration();
|
||||
_settingsService.ApplicationSettings.gameVersionNotify = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_settingsService.ApplicationSettings.gameVersionNotify = false;
|
||||
}
|
||||
|
||||
// give the game some time to initialize
|
||||
_gameInitializing = true;
|
||||
UpdateStatus("game initializing...", Brushes.Orange);
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
|
|
@ -300,17 +348,21 @@ namespace SekiroFpsUnlockAndMore
|
|||
if (!IsValidAddress(_offset_framelock))
|
||||
_offset_framelock = 0x0;
|
||||
|
||||
_offset_framelock_speed_fix = patternScan.FindPattern(GameData.PATTERN_FRAMELOCK_SPEED_FIX) + GameData.PATTERN_FRAMELOCK_SPEED_FIX_OFFSET;
|
||||
Debug.WriteLine("pFrametimeRunningSpeed at: 0x" + _offset_framelock_speed_fix.ToString("X"));
|
||||
if (!IsValidAddress(_offset_framelock_speed_fix))
|
||||
_offset_framelock_speed_fix = 0x0;
|
||||
long lpSpeedFixPointer = patternScan.FindPattern(GameData.PATTERN_FRAMELOCK_SPEED_FIX) + GameData.PATTERN_FRAMELOCK_SPEED_FIX_OFFSET;
|
||||
Debug.WriteLine("lpSpeedFixPointer at: 0x" + lpSpeedFixPointer.ToString("X"));
|
||||
if (IsValidAddress(lpSpeedFixPointer))
|
||||
{
|
||||
if (_memoryCaveGenerator.CreateNewDataCave(_DATACAVE_SPEEDFIX_POINTER, lpSpeedFixPointer, BitConverter.GetBytes(GameData.PATCH_FRAMELOCK_SPEED_FIX_DEFAULT_VALUE), PointerStyle.dwRelative))
|
||||
_dataCave_speedfix = true;
|
||||
Debug.WriteLine("lpSpeedFixPointer data cave at: 0x" + _memoryCaveGenerator.GetDataCaveAddressByName(_DATACAVE_SPEEDFIX_POINTER).ToString("X"));
|
||||
}
|
||||
|
||||
_offset_resolution_default = patternScan.FindPattern((int)SystemParameters.PrimaryScreenWidth > 1280 ? GameData.PATTERN_RESOLUTION_DEFAULT : GameData.PATTERN_RESOLUTION_DEFAULT_720);
|
||||
_offset_resolution_default = patternScan.FindPattern(_use_resolution_720 ? GameData.PATTERN_RESOLUTION_DEFAULT_720 : GameData.PATTERN_RESOLUTION_DEFAULT);
|
||||
Debug.WriteLine("default resolution found at: 0x" + _offset_resolution_default.ToString("X"));
|
||||
if (!IsValidAddress(_offset_resolution_default))
|
||||
_offset_resolution_default = 0x0;
|
||||
|
||||
_offset_resolution_scaling_fix = patternScan.FindPattern(GameData.PATTERN_RESOLUTION_SCALING_FIX) + GameData.PATTERN_RESOLUTION_SCALING_FIX_OFFSET;
|
||||
_offset_resolution_scaling_fix = patternScan.FindPattern(GameData.PATTERN_RESOLUTION_SCALING_FIX);
|
||||
Debug.WriteLine("scaling fix found at: 0x" + _offset_resolution_scaling_fix.ToString("X"));
|
||||
if (!IsValidAddress(_offset_resolution_scaling_fix))
|
||||
_offset_resolution_scaling_fix = 0x0;
|
||||
|
|
@ -334,11 +386,6 @@ namespace SekiroFpsUnlockAndMore
|
|||
Debug.WriteLine("lpFovPointer data cave at: 0x" + _memoryCaveGenerator.GetDataCaveAddressByName(_DATACAVE_FOV_POINTER).ToString("X"));
|
||||
}
|
||||
|
||||
_offset_camera_reset = patternScan.FindPattern(GameData.PATTERN_CAMRESET_LOCKON) + GameData.PATTERN_CAMRESET_LOCKON_OFFSET;
|
||||
Debug.WriteLine("lpCameraReset found at: 0x" + _offset_camera_reset.ToString("X"));
|
||||
if (!IsValidAddress(_offset_camera_reset))
|
||||
_offset_camera_reset = 0x0;
|
||||
|
||||
long ref_lpPlayerStatsRelated = patternScan.FindPattern(GameData.PATTERN_PLAYER_DEATHS) + GameData.PATTERN_PLAYER_DEATHS_OFFSET;
|
||||
Debug.WriteLine("ref_lpPlayerStatsRelated found at: 0x" + ref_lpPlayerStatsRelated.ToString("X"));
|
||||
if (IsValidAddress(ref_lpPlayerStatsRelated))
|
||||
|
|
@ -367,6 +414,82 @@ namespace SekiroFpsUnlockAndMore
|
|||
_offset_total_kills = 0x0;
|
||||
}
|
||||
|
||||
long lpCamAdjustPitch = patternScan.FindPattern(GameData.PATTERN_CAMADJUST_PITCH);
|
||||
long lpCamAdjustYawZ = patternScan.FindPattern(GameData.PATTERN_CAMADJUST_YAW_Z) + GameData.PATTERN_CAMADJUST_YAW_Z_OFFSET;
|
||||
long lpCamAdjustPitchXY = patternScan.FindPattern(GameData.PATTERN_CAMADJUST_PITCH_XY);
|
||||
long lpCamAdjustYawXY = patternScan.FindPattern(GameData.PATTERN_CAMADJUST_YAW_XY) + GameData.PATTERN_CAMADJUST_YAW_XY_OFFSET;
|
||||
Debug.WriteLine("lpCamAdjustPitch found at: 0x" + lpCamAdjustPitch.ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustYawZ found at: 0x" + lpCamAdjustYawZ.ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustPitchXY found at: 0x" + lpCamAdjustPitchXY.ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustYawXY found at: 0x" + lpCamAdjustYawXY.ToString("X"));
|
||||
if (IsValidAddress(lpCamAdjustPitch) && IsValidAddress(lpCamAdjustYawZ) && IsValidAddress(lpCamAdjustPitchXY) && IsValidAddress(lpCamAdjustYawXY))
|
||||
{
|
||||
List<bool> results = new List<bool>
|
||||
{
|
||||
_memoryCaveGenerator.CreateNewCodeCave(_CODECAVE_CAMADJUST_PITCH, lpCamAdjustPitch, GameData.INJECT_CAMADJUST_PITCH_OVERWRITE_LENGTH, GameData.INJECT_CAMADJUST_PITCH_SHELLCODE),
|
||||
_memoryCaveGenerator.CreateNewCodeCave(_CODECAVE_CAMADJUST_YAW_Z, lpCamAdjustYawZ, GameData.INJECT_CAMADJUST_YAW_Z_OVERWRITE_LENGTH, GameData.INJECT_CAMADJUST_YAW_Z_SHELLCODE),
|
||||
_memoryCaveGenerator.CreateNewCodeCave(_CODECAVE_CAMADJUST_PITCH_XY, lpCamAdjustPitchXY, GameData.INJECT_CAMADJUST_PITCH_XY_OVERWRITE_LENGTH, GameData.INJECT_CAMADJUST_PITCH_XY_SHELLCODE),
|
||||
_memoryCaveGenerator.CreateNewCodeCave(_CODECAVE_CAMADJUST_YAW_XY, lpCamAdjustYawXY, GameData.INJECT_CAMADJUST_YAW_XY_OVERWRITE_LENGTH, GameData.INJECT_CAMADJUST_YAW_XY_SHELLCODE)
|
||||
};
|
||||
Debug.WriteLine("lpCamAdjustPitch code cave at: 0x" + _memoryCaveGenerator.GetCodeCaveAddressByName(_CODECAVE_CAMADJUST_PITCH).ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustYawZ code cave at: 0x" + _memoryCaveGenerator.GetCodeCaveAddressByName(_CODECAVE_CAMADJUST_YAW_Z).ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustPitchXY code cave at: 0x" + _memoryCaveGenerator.GetCodeCaveAddressByName(_CODECAVE_CAMADJUST_PITCH_XY).ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustYawXY code cave at: 0x" + _memoryCaveGenerator.GetCodeCaveAddressByName(_CODECAVE_CAMADJUST_YAW_XY).ToString("X"));
|
||||
if (results.IndexOf(false) < 0)
|
||||
_codeCave_camadjust = true;
|
||||
}
|
||||
|
||||
_offset_camera_reset = patternScan.FindPattern(GameData.PATTERN_CAMRESET_LOCKON) + GameData.PATTERN_CAMRESET_LOCKON_OFFSET;
|
||||
Debug.WriteLine("lpCameraReset found at: 0x" + _offset_camera_reset.ToString("X"));
|
||||
if (!IsValidAddress(_offset_camera_reset))
|
||||
_offset_camera_reset = 0x0;
|
||||
|
||||
_offset_dragonrot_routine = patternScan.FindPattern(GameData.PATTERN_DRAGONROT_EFFECT) + GameData.PATTERN_DRAGONROT_EFFECT_OFFSET;
|
||||
Debug.WriteLine("lpDragonRot found at: 0x" + _offset_dragonrot_routine.ToString("X"));
|
||||
if (!IsValidAddress(_offset_dragonrot_routine))
|
||||
_offset_dragonrot_routine = 0x0;
|
||||
|
||||
_offset_deathpenalties1 = patternScan.FindPattern(GameData.PATTERN_DEATHPENALTIES1) + GameData.PATTERN_DEATHPENALTIES1_OFFSET;
|
||||
Debug.WriteLine("lpDeathPenalties1 found at: 0x" + _offset_deathpenalties1.ToString("X"));
|
||||
if (IsValidAddress(_offset_deathpenalties1))
|
||||
{
|
||||
_patch_deathpenalties1_enable = new byte[GameData.PATCH_DEATHPENALTIES1_INSTRUCTION_LENGTH];
|
||||
if (!ReadProcessMemory(_gameAccessHwnd, _offset_deathpenalties1, _patch_deathpenalties1_enable, (ulong)GameData.PATCH_DEATHPENALTIES1_INSTRUCTION_LENGTH, out IntPtr lpNumberOfBytesRead) || lpNumberOfBytesRead.ToInt32() != GameData.PATCH_DEATHPENALTIES1_INSTRUCTION_LENGTH)
|
||||
_patch_deathpenalties1_enable = null;
|
||||
else
|
||||
Debug.WriteLine("deathPenalties1 original instruction set: " + BitConverter.ToString(_patch_deathpenalties1_enable).Replace('-', ' '));
|
||||
if (_patch_deathpenalties1_enable != null)
|
||||
{
|
||||
_offset_deathpenalties2 = patternScan.FindPattern(GameData.PATTERN_DEATHPENALTIES2) + GameData.PATTERN_DEATHPENALTIES2_OFFSET;
|
||||
Debug.WriteLine("lpDeathPenalties2 found at: 0x" + _offset_deathpenalties2.ToString("X"));
|
||||
if (IsValidAddress(_offset_deathpenalties2))
|
||||
{
|
||||
_patch_deathpenalties2_enable = new byte[GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH];
|
||||
if (!ReadProcessMemory(_gameAccessHwnd, _offset_deathpenalties2, _patch_deathpenalties2_enable, (ulong) GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH, out lpNumberOfBytesRead) || lpNumberOfBytesRead.ToInt32() != GameData.PATCH_DEATHPENALTIES2_INSTRUCTION_LENGTH)
|
||||
_patch_deathpenalties2_enable = null;
|
||||
else
|
||||
Debug.WriteLine("deathPenalties2 original instruction set: " + BitConverter.ToString(_patch_deathpenalties2_enable).Replace('-', ' '));
|
||||
}
|
||||
else
|
||||
_offset_deathpenalties2 = 0x0;
|
||||
}
|
||||
}
|
||||
if (_offset_deathpenalties2 == 0x0 || _patch_deathpenalties2_enable == null)
|
||||
{
|
||||
_offset_deathpenalties1 = 0x0;
|
||||
_offset_deathpenalties2 = 0x0;
|
||||
_patch_deathpenalties1_enable = null;
|
||||
_patch_deathpenalties2_enable = null;
|
||||
}
|
||||
|
||||
if (_settingsService.ApplicationSettings.hiddenDPs == ZUH_HIDDEN_DP)
|
||||
{
|
||||
_offset_deathscounter_routine = patternScan.FindPattern(GameData.PATTERN_DEATHSCOUNTER) + GameData.PATTERN_DEATHSCOUNTER_OFFSET;
|
||||
Debug.WriteLine("lpDeathsCounter found at: 0x" + _offset_deathscounter_routine.ToString("X"));
|
||||
if (!IsValidAddress(_offset_deathscounter_routine))
|
||||
_offset_deathscounter_routine = 0x0;
|
||||
}
|
||||
|
||||
long ref_lpTimeRelated = patternScan.FindPattern(GameData.PATTERN_TIMESCALE);
|
||||
Debug.WriteLine("ref_lpTimeRelated found at: 0x" + ref_lpTimeRelated.ToString("X"));
|
||||
if (IsValidAddress(ref_lpTimeRelated))
|
||||
|
|
@ -412,31 +535,6 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
long lpCamAdjustPitch = patternScan.FindPattern(GameData.PATTERN_CAMADJUST_PITCH);
|
||||
long lpCamAdjustYawZ = patternScan.FindPattern(GameData.PATTERN_CAMADJUST_YAW_Z) + GameData.PATTERN_CAMADJUST_YAW_Z_OFFSET;
|
||||
long lpCamAdjustPitchXY = patternScan.FindPattern(GameData.PATTERN_CAMADJUST_PITCH_XY);
|
||||
long lpCamAdjustYawXY = patternScan.FindPattern(GameData.PATTERN_CAMADJUST_YAW_XY) + GameData.PATTERN_CAMADJUST_YAW_XY_OFFSET;
|
||||
Debug.WriteLine("lpCamAdjustPitch found at: 0x" + lpCamAdjustPitch.ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustYawZ found at: 0x" + lpCamAdjustYawZ.ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustPitchXY found at: 0x" + lpCamAdjustPitchXY.ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustYawXY found at: 0x" + lpCamAdjustYawXY.ToString("X"));
|
||||
if (IsValidAddress(lpCamAdjustPitch) && IsValidAddress(lpCamAdjustYawZ) && IsValidAddress(lpCamAdjustPitchXY) && IsValidAddress(lpCamAdjustYawXY))
|
||||
{
|
||||
List<bool> results = new List<bool>
|
||||
{
|
||||
_memoryCaveGenerator.CreateNewCodeCave(_CODECAVE_CAMADJUST_PITCH, lpCamAdjustPitch, GameData.INJECT_CAMADJUST_PITCH_OVERWRITE_LENGTH, GameData.INJECT_CAMADJUST_PITCH_SHELLCODE),
|
||||
_memoryCaveGenerator.CreateNewCodeCave(_CODECAVE_CAMADJUST_YAW_Z, lpCamAdjustYawZ, GameData.INJECT_CAMADJUST_YAW_Z_OVERWRITE_LENGTH, GameData.INJECT_CAMADJUST_YAW_Z_SHELLCODE),
|
||||
_memoryCaveGenerator.CreateNewCodeCave(_CODECAVE_CAMADJUST_PITCH_XY, lpCamAdjustPitchXY, GameData.INJECT_CAMADJUST_PITCH_XY_OVERWRITE_LENGTH, GameData.INJECT_CAMADJUST_PITCH_XY_SHELLCODE),
|
||||
_memoryCaveGenerator.CreateNewCodeCave(_CODECAVE_CAMADJUST_YAW_XY, lpCamAdjustYawXY, GameData.INJECT_CAMADJUST_YAW_XY_OVERWRITE_LENGTH, GameData.INJECT_CAMADJUST_YAW_XY_SHELLCODE)
|
||||
};
|
||||
Debug.WriteLine("lpCamAdjustPitch code cave at: 0x" + _memoryCaveGenerator.GetCodeCaveAddressByName(_CODECAVE_CAMADJUST_PITCH).ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustYawZ code cave at: 0x" + _memoryCaveGenerator.GetCodeCaveAddressByName(_CODECAVE_CAMADJUST_YAW_Z).ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustPitchXY code cave at: 0x" + _memoryCaveGenerator.GetCodeCaveAddressByName(_CODECAVE_CAMADJUST_PITCH_XY).ToString("X"));
|
||||
Debug.WriteLine("lpCamAdjustYawXY code cave at: 0x" + _memoryCaveGenerator.GetCodeCaveAddressByName(_CODECAVE_CAMADJUST_YAW_XY).ToString("X"));
|
||||
if (results.IndexOf(false) < 0)
|
||||
_codeCave_camadjust = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -451,14 +549,13 @@ namespace SekiroFpsUnlockAndMore
|
|||
this.cbFramelock.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (_offset_framelock_speed_fix == 0x0)
|
||||
if (!_dataCave_speedfix)
|
||||
{
|
||||
UpdateStatus("running speed fix no found...", Brushes.Red);
|
||||
LogToFile("running speed fix not found...");
|
||||
UpdateStatus("could not create speed fix table...", Brushes.Red);
|
||||
LogToFile("could not create speed fix table...");
|
||||
this.cbFramelock.IsEnabled = false;
|
||||
}
|
||||
|
||||
if ((int)SystemParameters.PrimaryScreenWidth < 1920) _use_resolution_720 = true;
|
||||
if (_offset_resolution_default == 0x0)
|
||||
{
|
||||
UpdateStatus("default resolution not found...", Brushes.Red);
|
||||
|
|
@ -485,12 +582,7 @@ namespace SekiroFpsUnlockAndMore
|
|||
this.cbFov.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (_offset_camera_reset == 0x0)
|
||||
{
|
||||
UpdateStatus("camera reset not found...", Brushes.Red);
|
||||
LogToFile("camera reset not found...");
|
||||
this.cbCamReset.IsEnabled = false;
|
||||
}
|
||||
this.cbBorderless.IsEnabled = true;
|
||||
|
||||
if (_offset_player_deaths == 0x0)
|
||||
{
|
||||
|
|
@ -507,8 +599,6 @@ namespace SekiroFpsUnlockAndMore
|
|||
if (_offset_player_deaths > 0x0 && _offset_total_kills > 0x0)
|
||||
_timerStatsCheck.Start();
|
||||
|
||||
this.cbBorderless.IsEnabled = true;
|
||||
|
||||
if (!_codeCave_camadjust)
|
||||
{
|
||||
UpdateStatus("cam adjust not found...", Brushes.Red);
|
||||
|
|
@ -516,6 +606,30 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
this.cbCamAdjust.IsEnabled = _codeCave_camadjust;
|
||||
|
||||
if (_offset_camera_reset == 0x0)
|
||||
{
|
||||
UpdateStatus("camera reset not found...", Brushes.Red);
|
||||
LogToFile("camera reset not found...");
|
||||
this.cbCamReset.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (_offset_dragonrot_routine == 0x0)
|
||||
{
|
||||
UpdateStatus("dragonrot not found...", Brushes.Red);
|
||||
LogToFile("dragonrot not found...");
|
||||
this.cbDragonrot.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (_offset_deathpenalties2 == 0x0)
|
||||
{
|
||||
UpdateStatus("death penalties not found...", Brushes.Red);
|
||||
LogToFile("death penalties not found...");
|
||||
this.cbDeathPenalty.IsEnabled = false;
|
||||
}
|
||||
|
||||
if (_offset_deathscounter_routine == 0x0)
|
||||
this.cbDeathPenaltyHidden.IsEnabled = false;
|
||||
|
||||
if (_offset_timescale == 0x0)
|
||||
{
|
||||
UpdateStatus("timescale not found...", Brushes.Red);
|
||||
|
|
@ -581,19 +695,26 @@ namespace SekiroFpsUnlockAndMore
|
|||
_gameAccessHwnd = IntPtr.Zero;
|
||||
_gameAccessHwndStatic = IntPtr.Zero;
|
||||
_gameInitializing = false;
|
||||
_initialStartup = true;
|
||||
_offset_framelock = 0x0;
|
||||
_offset_framelock_speed_fix = 0x0;
|
||||
_dataCave_speedfix = false;
|
||||
_offset_resolution = 0x0;
|
||||
_offset_resolution_default = 0x0;
|
||||
_offset_resolution_scaling_fix = 0x0;
|
||||
_offset_camera_reset = 0x0;
|
||||
_dataCave_fovsetting = false;
|
||||
_offset_player_deaths = 0x0;
|
||||
_offset_total_kills = 0x0;
|
||||
_codeCave_camadjust = false;
|
||||
_offset_camera_reset = 0x0;
|
||||
_offset_dragonrot_routine = 0x0;
|
||||
_offset_deathpenalties1 = 0x0;
|
||||
_offset_deathpenalties2 = 0x0;
|
||||
_offset_deathscounter_routine = 0x0;
|
||||
_offset_timescale = 0x0;
|
||||
_offset_timescale_player = 0x0;
|
||||
_offset_timescale_player_pointer_start = 0x0;
|
||||
_dataCave_fovsetting = false;
|
||||
_codeCave_camadjust = false;
|
||||
_patch_deathpenalties1_enable = null;
|
||||
_patch_deathpenalties2_enable = null;
|
||||
_memoryCaveGenerator.ClearCaves();
|
||||
_memoryCaveGenerator = null;
|
||||
this.cbFramelock.IsEnabled = true;
|
||||
|
|
@ -616,7 +737,7 @@ namespace SekiroFpsUnlockAndMore
|
|||
/// <param name="showStatus">Determines if status should be updated from within method, default is true.</param>
|
||||
private bool PatchFramelock(bool showStatus = true)
|
||||
{
|
||||
if (!this.cbFramelock.IsEnabled || _offset_framelock == 0x0 || !CanPatchGame()) return false;
|
||||
if (!this.cbFramelock.IsEnabled || _offset_framelock == 0x0 || !_dataCave_speedfix || !CanPatchGame()) return false;
|
||||
if (this.cbFramelock.IsChecked == true)
|
||||
{
|
||||
int fps = -1;
|
||||
|
|
@ -637,18 +758,22 @@ namespace SekiroFpsUnlockAndMore
|
|||
fps = 300;
|
||||
}
|
||||
|
||||
byte[] speedFix = GameData.FindSpeedFixForRefreshRate(fps);
|
||||
float deltaTime = (1000f / fps) / 1000f;
|
||||
Debug.WriteLine("Deltatime hex: 0x" + GetHexRepresentationFromFloat(deltaTime));
|
||||
Debug.WriteLine("Speed hex: 0x" + speedFix[0].ToString("X"));
|
||||
float speedFix = GameData.FindSpeedFixForRefreshRate(fps);
|
||||
Debug.WriteLine("Deltatime hex: " + GetHexRepresentationFromFloat(deltaTime));
|
||||
Debug.WriteLine("Speed hex: " + GetHexRepresentationFromFloat(speedFix));
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_framelock, BitConverter.GetBytes(deltaTime));
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_framelock_speed_fix, speedFix);
|
||||
_memoryCaveGenerator.UpdateDataCaveValueByName(_DATACAVE_SPEEDFIX_POINTER, BitConverter.GetBytes(speedFix));
|
||||
_memoryCaveGenerator.ActivateDataCaveByName(_DATACAVE_SPEEDFIX_POINTER);
|
||||
}
|
||||
else if (this.cbFramelock.IsChecked == false)
|
||||
{
|
||||
float deltaTime = (1000f / 60) / 1000f;
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_framelock, BitConverter.GetBytes(deltaTime));
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_framelock_speed_fix, GameData.PATCH_FRAMELOCK_SPEED_FIX_DISABLE);
|
||||
if (!_initialStartup)
|
||||
{
|
||||
float deltaTime = (1000f / 60) / 1000f;
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_framelock, BitConverter.GetBytes(deltaTime));
|
||||
_memoryCaveGenerator.DeactivateDataCaveByName(_DATACAVE_SPEEDFIX_POINTER);
|
||||
}
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -673,10 +798,10 @@ namespace SekiroFpsUnlockAndMore
|
|||
this.tbWidth.Text = "800";
|
||||
width = 800;
|
||||
}
|
||||
else if (width > 5760)
|
||||
else if (width > 7680)
|
||||
{
|
||||
this.tbWidth.Text = "5760";
|
||||
width = 5760;
|
||||
this.tbWidth.Text = "7680";
|
||||
width = 7680;
|
||||
}
|
||||
isNumber = Int32.TryParse(this.tbHeight.Text, out int height);
|
||||
if (height < 450 || !isNumber)
|
||||
|
|
@ -695,9 +820,12 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
else if (this.cbAddResolution.IsChecked == false)
|
||||
{
|
||||
this.cbBorderless.IsChecked = false;
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_resolution_default, !_use_resolution_720 ? GameData.PATCH_RESOLUTION_DEFAULT_DISABLE : GameData.PATCH_RESOLUTION_DEFAULT_DISABLE_720);
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_resolution_scaling_fix, GameData.PATCH_RESOLUTION_SCALING_FIX_DISABLE);
|
||||
if (!_initialStartup)
|
||||
{
|
||||
this.cbBorderless.IsChecked = false;
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_resolution_default, !_use_resolution_720 ? GameData.PATCH_RESOLUTION_DEFAULT_DISABLE : GameData.PATCH_RESOLUTION_DEFAULT_DISABLE_720);
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_resolution_scaling_fix, GameData.PATCH_RESOLUTION_SCALING_FIX_DISABLE);
|
||||
}
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -733,7 +861,8 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
else if (this.cbFov.IsChecked == false)
|
||||
{
|
||||
_memoryCaveGenerator.DeactivateDataCaveByName(_DATACAVE_FOV_POINTER);
|
||||
if (!_initialStartup)
|
||||
_memoryCaveGenerator.DeactivateDataCaveByName(_DATACAVE_FOV_POINTER);
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -763,7 +892,7 @@ namespace SekiroFpsUnlockAndMore
|
|||
int height = Read<Int32>(_gameAccessHwnd, _offset_resolution + 4);
|
||||
Debug.WriteLine(string.Format("Client Resolution: {0}x{1}", width, height));
|
||||
if (this.cbBorderlessStretch.IsChecked == true)
|
||||
SetWindowBorderless(_gameHwnd, (int)SystemParameters.PrimaryScreenWidth, (int)SystemParameters.PrimaryScreenHeight, 0, 0);
|
||||
SetWindowBorderless(_gameHwnd, (int)_screenSize.Width, (int)_screenSize.Height, 0, 0);
|
||||
else
|
||||
SetWindowBorderless(_gameHwnd, width, height, _windowRect.Left, _windowRect.Top);
|
||||
}
|
||||
|
|
@ -794,14 +923,89 @@ namespace SekiroFpsUnlockAndMore
|
|||
/// <param name="showStatus">Determines if status should be updated from within method, default is true.</param>
|
||||
private bool PatchCamReset(bool showStatus = true)
|
||||
{
|
||||
if (!this.cbCamReset.IsEnabled || !CanPatchGame()) return false;
|
||||
if (!this.cbCamReset.IsEnabled || _offset_camera_reset == 0x0 || !CanPatchGame()) return false;
|
||||
if (this.cbCamReset.IsChecked == true)
|
||||
{
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_camera_reset, GameData.PATCH_CAMRESET_LOCKON_DISABLE);
|
||||
}
|
||||
else if (this.cbCamReset.IsChecked == false)
|
||||
{
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_camera_reset, GameData.PATCH_CAMRESET_LOCKON_ENABLE);
|
||||
if (!_initialStartup)
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_camera_reset, GameData.PATCH_CAMRESET_LOCKON_ENABLE);
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game patched!", Brushes.Green);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Patches the game's dragonrot effect on NPCs.
|
||||
/// </summary>
|
||||
/// <param name="showStatus">Determines if status should be updated from within method, default is true.</param>
|
||||
private bool PatchDragonrot(bool showStatus = true)
|
||||
{
|
||||
if (!this.cbDragonrot.IsEnabled || _offset_dragonrot_routine == 0x0 || !CanPatchGame()) return false;
|
||||
if (this.cbDragonrot.IsChecked == true)
|
||||
{
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_dragonrot_routine, GameData.PATCH_DRAGONROT_EFFECT_DISABLE);
|
||||
}
|
||||
else if (this.cbDragonrot.IsChecked == false)
|
||||
{
|
||||
if (!_initialStartup)
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_dragonrot_routine, GameData.PATCH_DRAGONROT_EFFECT_ENABLE);
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game patched!", Brushes.Green);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Patches the game's death penalties.
|
||||
/// </summary>
|
||||
/// <param name="showStatus">Determines if status should be updated from within method, default is true.</param>
|
||||
private bool PatchDeathPenalty(bool showStatus = true)
|
||||
{
|
||||
if (!this.cbDeathPenalty.IsEnabled || _offset_deathpenalties2 == 0x0 || !CanPatchGame()) return false;
|
||||
SetModeTag();
|
||||
if (this.cbDeathPenalty.IsChecked == true)
|
||||
{
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties1, GameData.PATCH_DEATHPENALTIES1_DISABLE);
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties2, GameData.PATCH_DEATHPENALTIES2_DISABLE);
|
||||
}
|
||||
else if (this.cbDeathPenalty.IsChecked == false)
|
||||
{
|
||||
if (_initialStartup)
|
||||
{
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties1, _patch_deathpenalties1_enable);
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_deathpenalties2, _patch_deathpenalties2_enable);
|
||||
}
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game patched!", Brushes.Green);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Patches the game's hidden death penalties.
|
||||
/// </summary>
|
||||
/// <param name="showStatus">Determines if status should be updated from within method, default is true.</param>
|
||||
private bool PatchDeathPenaltyHidden(bool showStatus = true)
|
||||
{
|
||||
if (!this.cbDeathPenaltyHidden.IsEnabled || _offset_deathscounter_routine == 0x0 || !CanPatchGame()) return false;
|
||||
if (this.cbDeathPenaltyHidden.IsChecked == true)
|
||||
{
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_deathscounter_routine, GameData.PATCH_DEATHSCOUNTER_DISABLE);
|
||||
}
|
||||
else if (this.cbDeathPenaltyHidden.IsChecked == false)
|
||||
{
|
||||
if (!_initialStartup)
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_deathscounter_routine, GameData.PATCH_DEATHSCOUNTER_ENABLE);
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -832,13 +1036,16 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
float timeScale = gameSpeed / 100f;
|
||||
if (timeScale < 0.01f)
|
||||
timeScale = 0.00001f;
|
||||
timeScale = 0.0001f;
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_timescale, BitConverter.GetBytes(timeScale));
|
||||
SetModeTag();
|
||||
}
|
||||
else if (this.cbGameSpeed.IsChecked == false)
|
||||
{
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_timescale, BitConverter.GetBytes(1.0f));
|
||||
if (!_initialStartup)
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_timescale, BitConverter.GetBytes(1.0f));
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
SetModeTag();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -878,15 +1085,18 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
float timeScalePlayer = playerSpeed / 100f;
|
||||
if (timeScalePlayer < 0.01f)
|
||||
timeScalePlayer = 0.00001f;
|
||||
timeScalePlayer = 0.0001f;
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_timescale_player, BitConverter.GetBytes(timeScalePlayer));
|
||||
if (!_dispatcherTimerFreezeMem.IsEnabled) _dispatcherTimerFreezeMem.Start();
|
||||
SetModeTag();
|
||||
}
|
||||
else if (this.cbPlayerSpeed.IsChecked == false)
|
||||
{
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_timescale_player, BitConverter.GetBytes(1.0f));
|
||||
if (!_initialStartup)
|
||||
WriteBytes(_gameAccessHwndStatic, _offset_timescale_player, BitConverter.GetBytes(1.0f));
|
||||
if (showStatus) UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
_dispatcherTimerFreezeMem.Stop();
|
||||
SetModeTag();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -908,6 +1118,8 @@ namespace SekiroFpsUnlockAndMore
|
|||
PatchFov(false),
|
||||
PatchWindow(false),
|
||||
PatchCamReset(false),
|
||||
PatchDragonrot(false),
|
||||
PatchDeathPenalty(false),
|
||||
PatchGameSpeed(false),
|
||||
PatchPlayerSpeed(false)
|
||||
};
|
||||
|
|
@ -915,6 +1127,7 @@ namespace SekiroFpsUnlockAndMore
|
|||
UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game patched!", Brushes.Green);
|
||||
else
|
||||
UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
|
||||
_initialStartup = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -943,9 +1156,9 @@ namespace SekiroFpsUnlockAndMore
|
|||
if (result == MessageBoxResult.No)
|
||||
{
|
||||
_settingsService.ApplicationSettings.peasantInput = true;
|
||||
this.sbStatus.Text = "Controller Input";
|
||||
this.sbInput.Text = "Controller";
|
||||
}
|
||||
else this.sbStatus.Text = "Mouse Input";
|
||||
else this.sbInput.Text = "Mouse";
|
||||
_settingsService.ApplicationSettings.cameraAdjustNotify = true;
|
||||
}
|
||||
|
||||
|
|
@ -959,12 +1172,15 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
else
|
||||
{
|
||||
this.cbCamAdjust.IsEnabled = false;
|
||||
_memoryCaveGenerator.DeactivateCodeCaveByName(_CODECAVE_CAMADJUST_PITCH);
|
||||
_memoryCaveGenerator.DeactivateCodeCaveByName(_CODECAVE_CAMADJUST_YAW_Z);
|
||||
_memoryCaveGenerator.DeactivateCodeCaveByName(_CODECAVE_CAMADJUST_PITCH_XY);
|
||||
_memoryCaveGenerator.DeactivateCodeCaveByName(_CODECAVE_CAMADJUST_YAW_XY);
|
||||
this.cbCamAdjust.IsEnabled = true;
|
||||
if (!_initialStartup)
|
||||
{
|
||||
this.cbCamAdjust.IsEnabled = false;
|
||||
_memoryCaveGenerator.DeactivateCodeCaveByName(_CODECAVE_CAMADJUST_PITCH);
|
||||
_memoryCaveGenerator.DeactivateCodeCaveByName(_CODECAVE_CAMADJUST_YAW_Z);
|
||||
_memoryCaveGenerator.DeactivateCodeCaveByName(_CODECAVE_CAMADJUST_PITCH_XY);
|
||||
_memoryCaveGenerator.DeactivateCodeCaveByName(_CODECAVE_CAMADJUST_YAW_XY);
|
||||
this.cbCamAdjust.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1006,11 +1222,64 @@ namespace SekiroFpsUnlockAndMore
|
|||
if (!_running || _gameAccessHwndStatic == IntPtr.Zero || _offset_player_deaths == 0x0 || _offset_total_kills == 0x0) return;
|
||||
int playerDeaths = Read<Int32>(_gameAccessHwndStatic, _offset_player_deaths);
|
||||
_statusViewModel.Deaths = playerDeaths;
|
||||
if (_statLoggingEnabled) LogStatsFile(_deathCounterPath, playerDeaths.ToString());
|
||||
if (_statLoggingEnabled) LogStatsFile(_path_deathsLog, playerDeaths.ToString());
|
||||
int totalKills = Read<Int32>(_gameAccessHwndStatic, _offset_total_kills);
|
||||
totalKills -= playerDeaths; // Since this value seems to track every death, including the player
|
||||
_statusViewModel.Kills = totalKills;
|
||||
if (_statLoggingEnabled) LogStatsFile(_killCounterPath, totalKills.ToString());
|
||||
if (_statLoggingEnabled) LogStatsFile(_path_killsLog, totalKills.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets mode according to user settings.
|
||||
/// </summary>
|
||||
private void SetModeTag()
|
||||
{
|
||||
if (_debugMode) return;
|
||||
string mode = "";
|
||||
bool isGameSpeed = this.cbGameSpeed.IsChecked == true;
|
||||
bool isPlayerSpeed = this.cbPlayerSpeed.IsChecked == true;
|
||||
if (!Int32.TryParse(this.tbGameSpeed.Text, out int gameSpeed)) gameSpeed = 100;
|
||||
if (!Int32.TryParse(this.tbPlayerSpeed.Text, out int playerSpeed)) playerSpeed = 100;
|
||||
if (!isGameSpeed) gameSpeed = 100;
|
||||
if (!isPlayerSpeed) playerSpeed = 100;
|
||||
int speedDifference = playerSpeed - gameSpeed;
|
||||
bool gitGudLmao = false;
|
||||
if (isGameSpeed || isPlayerSpeed)
|
||||
{
|
||||
if (speedDifference > 5 || (isGameSpeed && gameSpeed < 90))
|
||||
mode = "Easy mode";
|
||||
if (speedDifference > 20 || (isGameSpeed && gameSpeed <= 80))
|
||||
{
|
||||
gitGudLmao = true;
|
||||
mode = "Journalist mode";
|
||||
}
|
||||
if (speedDifference > 35 || (isGameSpeed && gameSpeed <= 65))
|
||||
{
|
||||
gitGudLmao = true;
|
||||
mode = "you've cheated yourself";
|
||||
}
|
||||
if (speedDifference <= -10 && (!isGameSpeed || gameSpeed >= 100))
|
||||
mode = "Getting gud";
|
||||
if (isGameSpeed && gameSpeed == 0)
|
||||
mode = "Time freeze";
|
||||
if (isGameSpeed && gameSpeed >= 200)
|
||||
mode = "Super speed";
|
||||
}
|
||||
if (this.cbDeathPenalty.IsChecked == true)
|
||||
{
|
||||
mode = "Cheater mode";
|
||||
this.sbMode.Foreground = Brushes.Red;
|
||||
}
|
||||
else if (gitGudLmao)
|
||||
{
|
||||
ResourceDictionary resourceDictionary = Application.Current.Resources;
|
||||
LinearGradientBrush statusBarModeColor = resourceDictionary["resStatusBarModeColorMock"] as LinearGradientBrush;
|
||||
this.sbMode.Foreground = statusBarModeColor;
|
||||
}
|
||||
else
|
||||
this.sbMode.Foreground = Brushes.Black;
|
||||
|
||||
this.sbMode.Text = mode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1024,6 +1293,19 @@ namespace SekiroFpsUnlockAndMore
|
|||
return "0x" + f.ToString("X8");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates DPI-clean resolution of the primary screen. Requires dpiAware in manifest.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private Size GetDpiSafeResolution()
|
||||
{
|
||||
PresentationSource presentationSource = PresentationSource.FromVisual(this);
|
||||
if (presentationSource == null)
|
||||
return new Size(SystemParameters.PrimaryScreenWidth, SystemParameters.PrimaryScreenHeight);
|
||||
Matrix matrix = presentationSource.CompositionTarget.TransformToDevice;
|
||||
return new Size(SystemParameters.PrimaryScreenWidth * matrix.M22, SystemParameters.PrimaryScreenHeight * matrix.M11);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if window is minimized.
|
||||
/// </summary>
|
||||
|
|
@ -1195,7 +1477,7 @@ namespace SekiroFpsUnlockAndMore
|
|||
Debug.WriteLine(timedMsg);
|
||||
try
|
||||
{
|
||||
using (StreamWriter writer = new StreamWriter(_logPath, true))
|
||||
using (StreamWriter writer = new StreamWriter(_path_logs, true))
|
||||
{
|
||||
writer.WriteLine(timedMsg);
|
||||
}
|
||||
|
|
@ -1307,6 +1589,25 @@ namespace SekiroFpsUnlockAndMore
|
|||
PatchWindow();
|
||||
}
|
||||
|
||||
private void CbStatChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_statLoggingEnabled = cbLogStats.IsChecked == true;
|
||||
if (!_statLoggingEnabled)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (File.Exists(_path_deathsLog))
|
||||
File.Delete(_path_deathsLog);
|
||||
if (File.Exists(_path_killsLog))
|
||||
File.Delete(_path_killsLog);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Failed to delete stats files: " + ex.Message, "Sekiro Fps Unlock And More");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CbCamAdjust_Check_Handler(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (this.cbCamAdjust.IsEnabled)
|
||||
|
|
@ -1319,9 +1620,22 @@ namespace SekiroFpsUnlockAndMore
|
|||
PatchCamReset();
|
||||
}
|
||||
|
||||
private void CbStatChanged(object sender, RoutedEventArgs e)
|
||||
private void CbDragonrot_Check_Handler(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_statLoggingEnabled = cbLogStats.IsChecked == true;
|
||||
if (this.cbDragonrot.IsEnabled)
|
||||
PatchDragonrot();
|
||||
}
|
||||
|
||||
private void CbDeathPenalty_Check_Handler(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (this.cbDeathPenalty.IsEnabled)
|
||||
PatchDeathPenalty();
|
||||
}
|
||||
|
||||
private void CbDeathPenaltyHidden_Check_Handler(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (this.cbDeathPenaltyHidden.IsEnabled && this.cbDeathPenaltyHidden.Visibility == Visibility.Visible)
|
||||
PatchDeathPenaltyHidden();
|
||||
}
|
||||
|
||||
private void CbGameSpeed_Check_Handler(object sender, RoutedEventArgs e)
|
||||
|
|
@ -1430,6 +1744,7 @@ namespace SekiroFpsUnlockAndMore
|
|||
private const uint SWP_NOACTIVATE = 0x0010;
|
||||
private const uint SWP_FRAMECHANGED = 0x0020;
|
||||
private const uint SWP_SHOWWINDOW = 0x0040;
|
||||
private const int ZUH_HIDDEN_DP = 0x7;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
public static extern Boolean RegisterHotKey(IntPtr hWnd, Int32 id, UInt32 fsModifiers, UInt32 vlc);
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ namespace SekiroFpsUnlockAndMore
|
|||
bFound = true;
|
||||
for (iy = 0; iy < patternLength; iy++)
|
||||
{
|
||||
if (szMask[iy] != 'x' || bPattern[iy] == bData[ix + iy]) continue;
|
||||
if (szMask[iy] != 'x' || bPattern[iy] == bData[ix + iy])
|
||||
continue;
|
||||
bFound = false;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,13 +13,10 @@ using System.Runtime.InteropServices;
|
|||
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None,
|
||||
ResourceDictionaryLocation.SourceAssembly
|
||||
)]
|
||||
|
||||
[assembly: AssemblyVersion("1.2.2.0")]
|
||||
[assembly: AssemblyFileVersion("1.2.2.0")]
|
||||
[assembly: AssemblyVersion("1.2.3.0")]
|
||||
[assembly: AssemblyFileVersion("1.2.3.0")]
|
||||
|
|
@ -37,13 +37,19 @@ namespace SekiroFpsUnlockAndMore
|
|||
[XmlElement]
|
||||
public bool cbBorderlessStretch { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbLogStats { get; set; }
|
||||
[XmlElement]
|
||||
public bool exGameMods { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbCamAdjust { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbCamReset { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbLogStats { get; set; }
|
||||
public bool cbDragonrot { get; set; }
|
||||
[XmlElement]
|
||||
public bool exGameMods { get; set; }
|
||||
public bool cbDeathPenalty { get; set; }
|
||||
[XmlElement]
|
||||
public int hiddenDPs { get; set; }
|
||||
[XmlElement]
|
||||
public bool cbGameSpeed { get; set; }
|
||||
[XmlElement]
|
||||
|
|
@ -52,6 +58,8 @@ namespace SekiroFpsUnlockAndMore
|
|||
public bool cbPlayerSpeed { get; set; }
|
||||
[XmlElement]
|
||||
public int tbPlayerSpeed { get; set; }
|
||||
[XmlElement]
|
||||
public bool exGuide { get; set; }
|
||||
}
|
||||
|
||||
public class SettingsService
|
||||
|
|
@ -103,11 +111,11 @@ namespace SekiroFpsUnlockAndMore
|
|||
internal void Save()
|
||||
{
|
||||
XmlSerializer xmlSerializer = new XmlSerializer(typeof(ApplicationSettings));
|
||||
using (StreamWriter streamReader = new StreamWriter(_sConfigurationPath))
|
||||
using (StreamWriter streamWriter = new StreamWriter(_sConfigurationPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
xmlSerializer.Serialize(streamReader, ApplicationSettings);
|
||||
xmlSerializer.Serialize(streamWriter, ApplicationSettings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -115,5 +123,22 @@ namespace SekiroFpsUnlockAndMore
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all settings and deletes the settings file.
|
||||
/// </summary>
|
||||
internal void Clear()
|
||||
{
|
||||
ApplicationSettings = new ApplicationSettings();
|
||||
try
|
||||
{
|
||||
if (File.Exists(_sConfigurationPath))
|
||||
File.Delete(_sConfigurationPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
MessageBox.Show("Error while trying to delete configuration file:\n" + ex.Message, "Sekiro FPS Unlocker and more");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,4 +14,10 @@
|
|||
|
||||
</application>
|
||||
</compatibility>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue