mirror of
https://github.com/uberhalit/SekiroFpsUnlockAndMore.git
synced 2026-06-13 09:57:55 +00:00
added +25% FOV option
moved costy patterscans to external thread added check to game version fixed whitespaces/tabstops
This commit is contained in:
parent
af0e5a25da
commit
af5458ada6
6 changed files with 243 additions and 222 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
# Sekiro FPS Unlocker and more
|
# 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 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 and various game modifications for [Sekiro: Shadows Die Twice](https://www.sekirothegame.com/) written in C#.
|
||||||
Patches games memory while running, does not modify any game files. Wrks with every game version (legit steam & oh-not-so-legit), should work with all future updates. Also available [Nexus Mods](https://www.nexusmods.com/sekiro/mods/13/).
|
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 [Nexus Mods](https://www.nexusmods.com/sekiro/mods/13/).
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
|
|
@ -130,7 +130,7 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s
|
||||||
7. Select either `DeathCounter.txt` (only tracks true deaths, excluding revives) or `TotalKillsCounter.txt`
|
7. Select either `DeathCounter.txt` (only tracks true deaths, excluding revives) or `TotalKillsCounter.txt`
|
||||||
8. Customize font style, color and position
|
8. Customize font style, color and position
|
||||||
9. To add additional counters repeat steps 4-7
|
9. To add additional counters repeat steps 4-7
|
||||||
10. [[!On Stream Display with OBS](https://camo.githubusercontent.com/007910d42ace53ee0db0ea8b61d525751b9d48a6/68747470733a2f2f692e696d6775722e636f6d2f4c39546e6f34462e706e67)](#)
|
10. [](#)
|
||||||
|
|
||||||
### To use any of the game modifications
|
### To use any of the game modifications
|
||||||
1. Start the game
|
1. Start the game
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
internal const string PROCESS_NAME = "sekiro";
|
internal const string PROCESS_NAME = "sekiro";
|
||||||
internal const string PROCESS_TITLE = "Sekiro";
|
internal const string PROCESS_TITLE = "Sekiro";
|
||||||
internal const string PROCESS_DESCRIPTION = "Shadows Die Twice";
|
internal const string PROCESS_DESCRIPTION = "Shadows Die Twice";
|
||||||
|
internal const string PROCESS_EXE_VERSION = "1.2.0.0";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -142,7 +143,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
internal const int PATTERN_FOVSETTING_OFFSET = 8;
|
internal const int PATTERN_FOVSETTING_OFFSET = 8;
|
||||||
/**
|
/**
|
||||||
00000001430F7C60
|
00000001430F7C60
|
||||||
Key: Patch to pFovTableEntry last 2 bytes
|
Key: Patch to pFovTableEntry (last 2 bytes)
|
||||||
Value: Value resolve in float table from pFovTableEntry->fFov
|
Value: Value resolve in float table from pFovTableEntry->fFov
|
||||||
*/
|
*/
|
||||||
internal static Dictionary<byte[], string> PATCH_FOVSETTING_MATRIX = new Dictionary<byte[], string>
|
internal static Dictionary<byte[], string> PATCH_FOVSETTING_MATRIX = new Dictionary<byte[], string>
|
||||||
|
|
@ -150,6 +151,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
{ new byte[2] {0x00, 0xE7}, "- 50%" },
|
{ new byte[2] {0x00, 0xE7}, "- 50%" },
|
||||||
{ new byte[2] {0x04, 0xE7}, "- 10%" },
|
{ new byte[2] {0x04, 0xE7}, "- 10%" },
|
||||||
{ new byte[2] {0x10, 0xE7}, "+ 15%" },
|
{ new byte[2] {0x10, 0xE7}, "+ 15%" },
|
||||||
|
{ new byte[2] {0x42, 0x9B}, "+ 25%" },
|
||||||
{ new byte[2] {0x14, 0xE7}, "+ 40%" },
|
{ new byte[2] {0x14, 0xE7}, "+ 40%" },
|
||||||
{ new byte[2] {0x18, 0xE7}, "+ 75%" },
|
{ new byte[2] {0x18, 0xE7}, "+ 75%" },
|
||||||
{ new byte[2] {0x1C, 0xE7}, "+ 90%" }
|
{ new byte[2] {0x1C, 0xE7}, "+ 90%" }
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.Threading;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Windows.Interop;
|
using System.Windows.Interop;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
|
@ -36,9 +37,10 @@ namespace SekiroFpsUnlockAndMore
|
||||||
internal SettingsService _settingsService;
|
internal SettingsService _settingsService;
|
||||||
internal StatusViewModel _statusViewModel = new StatusViewModel();
|
internal StatusViewModel _statusViewModel = new StatusViewModel();
|
||||||
|
|
||||||
internal readonly System.Timers.Timer _timerStatsCheck = new System.Timers.Timer();
|
internal readonly DispatcherTimer _dispatcherTimerGameCheck = new DispatcherTimer();
|
||||||
internal readonly DispatcherTimer _dispatcherTimerFreezeMem = new DispatcherTimer();
|
internal readonly DispatcherTimer _dispatcherTimerFreezeMem = new DispatcherTimer();
|
||||||
internal readonly DispatcherTimer _dispatcherTimerCheck = new DispatcherTimer();
|
internal readonly BackgroundWorker _bgwScanGame = new BackgroundWorker();
|
||||||
|
internal readonly System.Timers.Timer _timerStatsCheck = new System.Timers.Timer();
|
||||||
internal bool _running = false;
|
internal bool _running = false;
|
||||||
internal bool _gameInitializing = false;
|
internal bool _gameInitializing = false;
|
||||||
internal string _logPath;
|
internal string _logPath;
|
||||||
|
|
@ -63,7 +65,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
var mutex = new Mutex(true, "sekiroFpsUnlockAndMore", out bool isNewInstance);
|
var mutex = new Mutex(true, "sekiroFpsUnlockAndMore", out bool isNewInstance);
|
||||||
if (!isNewInstance)
|
if (!isNewInstance)
|
||||||
{
|
{
|
||||||
MessageBox.Show("Another instance is already running!", "Sekiro FPS Unlocker and more");
|
MessageBox.Show("Another instance is already running!", "Sekiro FPS Unlocker and more", MessageBoxButton.OK, MessageBoxImage.Exclamation);
|
||||||
Environment.Exit(0);
|
Environment.Exit(0);
|
||||||
}
|
}
|
||||||
GC.KeepAlive(mutex);
|
GC.KeepAlive(mutex);
|
||||||
|
|
@ -79,17 +81,24 @@ namespace SekiroFpsUnlockAndMore
|
||||||
|
|
||||||
IntPtr hWnd = new WindowInteropHelper(this).Handle;
|
IntPtr hWnd = new WindowInteropHelper(this).Handle;
|
||||||
if (!RegisterHotKey(hWnd, 9009, MOD_CONTROL, VK_P))
|
if (!RegisterHotKey(hWnd, 9009, MOD_CONTROL, VK_P))
|
||||||
MessageBox.Show("Hotkey is already in use, it may not work.", "Sekiro FPS Unlocker and more");
|
MessageBox.Show("Hotkey is already in use, it may not work.", "Sekiro FPS Unlocker and more", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||||
|
|
||||||
ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
|
ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
|
||||||
|
|
||||||
_dispatcherTimerCheck.Tick += new EventHandler(async (object s, EventArgs a) =>
|
_bgwScanGame.DoWork += new DoWorkEventHandler(ReadGame);
|
||||||
|
_bgwScanGame.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnReadGameFinish);
|
||||||
|
|
||||||
|
_dispatcherTimerGameCheck.Tick += new EventHandler(async (object s, EventArgs a) =>
|
||||||
{
|
{
|
||||||
bool result = await CheckGame();
|
bool result = await CheckGame();
|
||||||
if (result) PatchGame();
|
if (result)
|
||||||
|
{
|
||||||
|
_bgwScanGame.RunWorkerAsync();
|
||||||
|
_dispatcherTimerGameCheck.Stop();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
_dispatcherTimerCheck.Interval = new TimeSpan(0, 0, 0, 0, 2000);
|
_dispatcherTimerGameCheck.Interval = new TimeSpan(0, 0, 0, 0, 2000);
|
||||||
_dispatcherTimerCheck.Start();
|
_dispatcherTimerGameCheck.Start();
|
||||||
|
|
||||||
_dispatcherTimerFreezeMem.Tick += new EventHandler(FreezeMemory);
|
_dispatcherTimerFreezeMem.Tick += new EventHandler(FreezeMemory);
|
||||||
_dispatcherTimerFreezeMem.Interval = new TimeSpan(0, 0, 0, 0, 2000);
|
_dispatcherTimerFreezeMem.Interval = new TimeSpan(0, 0, 0, 0, 2000);
|
||||||
|
|
@ -179,6 +188,9 @@ namespace SekiroFpsUnlockAndMore
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private Task<bool> CheckGame()
|
private Task<bool> CheckGame()
|
||||||
{
|
{
|
||||||
|
// game process have been found last check and can be read now, aborting
|
||||||
|
if (_gameInitializing) return Task.FromResult(true);
|
||||||
|
|
||||||
Process[] procList = Process.GetProcessesByName(GameData.PROCESS_NAME);
|
Process[] procList = Process.GetProcessesByName(GameData.PROCESS_NAME);
|
||||||
if (procList.Length < 1)
|
if (procList.Length < 1)
|
||||||
return Task.FromResult(false);
|
return Task.FromResult(false);
|
||||||
|
|
@ -220,7 +232,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
if (!_retryAccess)
|
if (!_retryAccess)
|
||||||
{
|
{
|
||||||
UpdateStatus("no access to game...", Brushes.Red);
|
UpdateStatus("no access to game...", Brushes.Red);
|
||||||
_dispatcherTimerCheck.Stop();
|
_dispatcherTimerGameCheck.Stop();
|
||||||
return Task.FromResult(false);
|
return Task.FromResult(false);
|
||||||
}
|
}
|
||||||
_gameHwnd = IntPtr.Zero;
|
_gameHwnd = IntPtr.Zero;
|
||||||
|
|
@ -235,14 +247,23 @@ namespace SekiroFpsUnlockAndMore
|
||||||
return Task.FromResult(false);
|
return Task.FromResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// give the game some time to initialize
|
string gameFileVersion = FileVersionInfo.GetVersionInfo(procList[0].MainModule.FileName).FileVersion;
|
||||||
if (!_gameInitializing)
|
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);
|
||||||
|
_settingsService.ApplicationSettings.gameVersionNotify = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// give the game some time to initialize
|
||||||
_gameInitializing = true;
|
_gameInitializing = true;
|
||||||
return Task.FromResult(false);
|
return Task.FromResult(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//string gameFileVersion = FileVersionInfo.GetVersionInfo(procList[0].MainModule.FileName).FileVersion;
|
/// <summary>
|
||||||
|
/// Read all game offsets and pointer (external).
|
||||||
|
/// </summary>
|
||||||
|
private void ReadGame(object sender, DoWorkEventArgs doWorkEventArgs)
|
||||||
|
{
|
||||||
PatternScan patternScan = new PatternScan(_gameAccessHwnd, _gameProc.MainModule);
|
PatternScan patternScan = new PatternScan(_gameAccessHwnd, _gameProc.MainModule);
|
||||||
|
|
||||||
_offset_framelock = patternScan.FindPatternInternal(GameData.PATTERN_FRAMELOCK, GameData.PATTERN_FRAMELOCK_MASK, ' ') + GameData.PATTERN_FRAMELOCK_OFFSET;
|
_offset_framelock = patternScan.FindPatternInternal(GameData.PATTERN_FRAMELOCK, GameData.PATTERN_FRAMELOCK_MASK, ' ') + GameData.PATTERN_FRAMELOCK_OFFSET;
|
||||||
|
|
@ -253,83 +274,41 @@ namespace SekiroFpsUnlockAndMore
|
||||||
Debug.WriteLine("2. fFrameTick found at: 0x" + _offset_framelock.ToString("X"));
|
Debug.WriteLine("2. fFrameTick found at: 0x" + _offset_framelock.ToString("X"));
|
||||||
}
|
}
|
||||||
if (!IsValidAddress(_offset_framelock))
|
if (!IsValidAddress(_offset_framelock))
|
||||||
{
|
|
||||||
UpdateStatus("fFrameTick not found...", Brushes.Red);
|
|
||||||
LogToFile("fFrameTick not found...");
|
|
||||||
_offset_framelock = 0x0;
|
_offset_framelock = 0x0;
|
||||||
this.cbFramelock.IsEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
_offset_framelock_speed_fix = patternScan.FindPatternInternal(GameData.PATTERN_FRAMELOCK_SPEED_FIX, GameData.PATTERN_FRAMELOCK_SPEED_FIX_MASK, ' ') + GameData.PATTERN_FRAMELOCK_SPEED_FIX_OFFSET;
|
_offset_framelock_speed_fix = patternScan.FindPatternInternal(GameData.PATTERN_FRAMELOCK_SPEED_FIX, GameData.PATTERN_FRAMELOCK_SPEED_FIX_MASK, ' ') + GameData.PATTERN_FRAMELOCK_SPEED_FIX_OFFSET;
|
||||||
Debug.WriteLine("pFrametimeRunningSpeed at: 0x" + _offset_framelock_speed_fix.ToString("X"));
|
Debug.WriteLine("pFrametimeRunningSpeed at: 0x" + _offset_framelock_speed_fix.ToString("X"));
|
||||||
if (!IsValidAddress(_offset_framelock_speed_fix))
|
if (!IsValidAddress(_offset_framelock_speed_fix))
|
||||||
{
|
|
||||||
UpdateStatus("pFrametimeRunningSpeed no found...", Brushes.Red);
|
|
||||||
LogToFile("pFrametimeRunningSpeed not found...");
|
|
||||||
_offset_framelock_speed_fix = 0x0;
|
_offset_framelock_speed_fix = 0x0;
|
||||||
this.cbFramelock.IsEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool enableResolutionPatch = true;
|
_offset_resolution_default = patternScan.FindPatternInternal((int)SystemParameters.PrimaryScreenWidth > 1280 ? GameData.PATTERN_RESOLUTION_DEFAULT : GameData.PATTERN_RESOLUTION_DEFAULT_720, GameData.PATTERN_RESOLUTION_DEFAULT_MASK, ' ');
|
||||||
if ((int) SystemParameters.PrimaryScreenWidth < 1281) _use_resolution_720 = true;
|
|
||||||
_offset_resolution_default = patternScan.FindPatternInternal(!_use_resolution_720 ? GameData.PATTERN_RESOLUTION_DEFAULT : GameData.PATTERN_RESOLUTION_DEFAULT_720, GameData.PATTERN_RESOLUTION_DEFAULT_MASK, ' ');
|
|
||||||
Debug.WriteLine("default resolution found at: 0x" + _offset_resolution_default.ToString("X"));
|
Debug.WriteLine("default resolution found at: 0x" + _offset_resolution_default.ToString("X"));
|
||||||
if (!IsValidAddress(_offset_resolution_default))
|
if (!IsValidAddress(_offset_resolution_default))
|
||||||
{
|
|
||||||
UpdateStatus("default resolution not found...", Brushes.Red);
|
|
||||||
LogToFile("default resolution not found...");
|
|
||||||
enableResolutionPatch = false;
|
|
||||||
_offset_resolution_default = 0x0;
|
_offset_resolution_default = 0x0;
|
||||||
}
|
|
||||||
_offset_resolution_scaling_fix = patternScan.FindPatternInternal(GameData.PATTERN_RESOLUTION_SCALING_FIX, GameData.PATTERN_RESOLUTION_SCALING_FIX_MASK, ' ') + GameData.PATTERN_RESOLUTION_SCALING_FIX_OFFSET;
|
_offset_resolution_scaling_fix = patternScan.FindPatternInternal(GameData.PATTERN_RESOLUTION_SCALING_FIX, GameData.PATTERN_RESOLUTION_SCALING_FIX_MASK, ' ') + GameData.PATTERN_RESOLUTION_SCALING_FIX_OFFSET;
|
||||||
Debug.WriteLine("scaling fix found at: 0x" + _offset_resolution_scaling_fix.ToString("X"));
|
Debug.WriteLine("scaling fix found at: 0x" + _offset_resolution_scaling_fix.ToString("X"));
|
||||||
if (!IsValidAddress(_offset_resolution_scaling_fix))
|
if (!IsValidAddress(_offset_resolution_scaling_fix))
|
||||||
{
|
|
||||||
UpdateStatus("scaling fix not found...", Brushes.Red);
|
|
||||||
LogToFile("scaling fix not found...");
|
|
||||||
enableResolutionPatch = false;
|
|
||||||
_offset_resolution_scaling_fix = 0x0;
|
_offset_resolution_scaling_fix = 0x0;
|
||||||
}
|
|
||||||
long ref_pCurrentResolutionWidth = patternScan.FindPatternInternal(GameData.PATTERN_RESOLUTION_POINTER, GameData.PATTERN_RESOLUTION_POINTER_MASK, ' ') + GameData.PATTERN_RESOLUTION_POINTER_OFFSET;
|
long ref_pCurrentResolutionWidth = patternScan.FindPatternInternal(GameData.PATTERN_RESOLUTION_POINTER, GameData.PATTERN_RESOLUTION_POINTER_MASK, ' ') + GameData.PATTERN_RESOLUTION_POINTER_OFFSET;
|
||||||
Debug.WriteLine("ref_pCurrentResolutionWidth found at: 0x" + ref_pCurrentResolutionWidth.ToString("X"));
|
Debug.WriteLine("ref_pCurrentResolutionWidth found at: 0x" + ref_pCurrentResolutionWidth.ToString("X"));
|
||||||
if (!IsValidAddress(ref_pCurrentResolutionWidth))
|
if (IsValidAddress(ref_pCurrentResolutionWidth))
|
||||||
{
|
|
||||||
UpdateStatus("re_pCurrentResolutionWidth not found...", Brushes.Red);
|
|
||||||
LogToFile("ref_pCurrentResolutionWidth not found...");
|
|
||||||
enableResolutionPatch = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
_offset_resolution = DereferenceStaticX64Pointer(_gameAccessHwnd, ref_pCurrentResolutionWidth, GameData.PATTERN_RESOLUTION_POINTER_INSTRUCTION_LENGTH);
|
_offset_resolution = DereferenceStaticX64Pointer(_gameAccessHwnd, ref_pCurrentResolutionWidth, GameData.PATTERN_RESOLUTION_POINTER_INSTRUCTION_LENGTH);
|
||||||
Debug.WriteLine("pCurrentResolutionWidth at: 0x" + _offset_resolution.ToString("X"));
|
Debug.WriteLine("pCurrentResolutionWidth at: 0x" + _offset_resolution.ToString("X"));
|
||||||
if (!IsValidAddress(_offset_resolution))
|
if (!IsValidAddress(_offset_resolution))
|
||||||
{
|
|
||||||
UpdateStatus("pCurrentResolutionWidth not valid...", Brushes.Red);
|
|
||||||
LogToFile("pCurrentResolutionWidth not valid...");
|
|
||||||
_offset_resolution = 0x0;
|
_offset_resolution = 0x0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
this.cbAddResolution.IsEnabled = enableResolutionPatch;
|
|
||||||
|
|
||||||
_offset_fovsetting = patternScan.FindPatternInternal(GameData.PATTERN_FOVSETTING, GameData.PATTERN_FOVSETTING_MASK, ' ') + GameData.PATTERN_FOVSETTING_OFFSET;
|
_offset_fovsetting = patternScan.FindPatternInternal(GameData.PATTERN_FOVSETTING, GameData.PATTERN_FOVSETTING_MASK, ' ') + GameData.PATTERN_FOVSETTING_OFFSET;
|
||||||
Debug.WriteLine("pFovTableEntry found at: 0x" + _offset_fovsetting.ToString("X"));
|
Debug.WriteLine("pFovTableEntry found at: 0x" + _offset_fovsetting.ToString("X"));
|
||||||
if (!IsValidAddress(_offset_fovsetting))
|
if (!IsValidAddress(_offset_fovsetting))
|
||||||
{
|
|
||||||
UpdateStatus("pFovTableEntry not found...", Brushes.Red);
|
|
||||||
LogToFile("pFovTableEntry not found...");
|
|
||||||
_offset_fovsetting = 0x0;
|
_offset_fovsetting = 0x0;
|
||||||
this.cbFov.IsEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long ref_pPlayerStatsRelated = patternScan.FindPatternInternal(GameData.PATTERN_PLAYER_DEATHS, GameData.PATTERN_PLAYER_DEATHS_MASK, ' ') + GameData.PATTERN_PLAYER_DEATHS_OFFSET;
|
long ref_pPlayerStatsRelated = patternScan.FindPatternInternal(GameData.PATTERN_PLAYER_DEATHS, GameData.PATTERN_PLAYER_DEATHS_MASK, ' ') + GameData.PATTERN_PLAYER_DEATHS_OFFSET;
|
||||||
Debug.WriteLine("ref_pPlayerStatsRelated found at: 0x" + ref_pPlayerStatsRelated.ToString("X"));
|
Debug.WriteLine("ref_pPlayerStatsRelated found at: 0x" + ref_pPlayerStatsRelated.ToString("X"));
|
||||||
if (!IsValidAddress(ref_pPlayerStatsRelated))
|
if (IsValidAddress(ref_pPlayerStatsRelated))
|
||||||
{
|
|
||||||
UpdateStatus("ref_pPlayerStatsRelated not found...", Brushes.Red);
|
|
||||||
LogToFile("ref_pPlayerStatsRelated not found...");
|
|
||||||
this.cbLogStats.IsEnabled = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
long pPlayerStatsRelated = DereferenceStaticX64Pointer(_gameAccessHwndStatic, ref_pPlayerStatsRelated, GameData.PATTERN_PLAYER_DEATHS_INSTRUCTION_LENGTH);
|
long pPlayerStatsRelated = DereferenceStaticX64Pointer(_gameAccessHwndStatic, ref_pPlayerStatsRelated, GameData.PATTERN_PLAYER_DEATHS_INSTRUCTION_LENGTH);
|
||||||
Debug.WriteLine("pPlayerStatsRelated found at: 0x" + pPlayerStatsRelated.ToString("X"));
|
Debug.WriteLine("pPlayerStatsRelated found at: 0x" + pPlayerStatsRelated.ToString("X"));
|
||||||
|
|
@ -338,40 +317,22 @@ namespace SekiroFpsUnlockAndMore
|
||||||
int playerStatsToDeathsOffset = Read<Int32>(_gameAccessHwndStatic, ref_pPlayerStatsRelated + GameData.PATTERN_PLAYER_DEATHS_POINTER_OFFSET_OFFSET);
|
int playerStatsToDeathsOffset = Read<Int32>(_gameAccessHwndStatic, ref_pPlayerStatsRelated + GameData.PATTERN_PLAYER_DEATHS_POINTER_OFFSET_OFFSET);
|
||||||
Debug.WriteLine("offset pPlayerStats->iPlayerDeaths found : 0x" + playerStatsToDeathsOffset.ToString("X"));
|
Debug.WriteLine("offset pPlayerStats->iPlayerDeaths found : 0x" + playerStatsToDeathsOffset.ToString("X"));
|
||||||
|
|
||||||
if (playerStatsToDeathsOffset > 0) _offset_player_deaths = Read<Int64>(_gameAccessHwndStatic, pPlayerStatsRelated) + playerStatsToDeathsOffset;
|
if (playerStatsToDeathsOffset > 0)
|
||||||
|
_offset_player_deaths = Read<Int64>(_gameAccessHwndStatic, pPlayerStatsRelated) + playerStatsToDeathsOffset;
|
||||||
Debug.WriteLine("iPlayerDeaths found at: 0x" + _offset_player_deaths.ToString("X"));
|
Debug.WriteLine("iPlayerDeaths found at: 0x" + _offset_player_deaths.ToString("X"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!IsValidAddress(_offset_player_deaths))
|
if (!IsValidAddress(_offset_player_deaths))
|
||||||
{
|
|
||||||
UpdateStatus("Player Deaths not found...", Brushes.Red);
|
|
||||||
LogToFile("Player Deaths not found...");
|
|
||||||
_offset_player_deaths = 0x0;
|
_offset_player_deaths = 0x0;
|
||||||
this.cbLogStats.IsEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long ref_pTotalKills = patternScan.FindPatternInternal(GameData.PATTERN_TOTAL_KILLS, GameData.PATTERN_TOTAL_KILLS_MASK, ' ');
|
long ref_pTotalKills = patternScan.FindPatternInternal(GameData.PATTERN_TOTAL_KILLS, GameData.PATTERN_TOTAL_KILLS_MASK, ' ');
|
||||||
Debug.WriteLine("ref_pTotalKills found at: 0x" + ref_pTotalKills.ToString("X"));
|
Debug.WriteLine("ref_pTotalKills found at: 0x" + ref_pTotalKills.ToString("X"));
|
||||||
if (!IsValidAddress(ref_pTotalKills))
|
if (IsValidAddress(ref_pTotalKills))
|
||||||
{
|
|
||||||
UpdateStatus("ref_pTotalKills not found...", Brushes.Red);
|
|
||||||
LogToFile("ref_pTotalKills not found...");
|
|
||||||
this.cbLogStats.IsEnabled = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
_offset_total_kills = DereferenceStaticX64Pointer(_gameAccessHwndStatic, ref_pTotalKills, GameData.PATTERN_TOTAL_KILLS_INSTRUCTION_LENGTH);
|
_offset_total_kills = DereferenceStaticX64Pointer(_gameAccessHwndStatic, ref_pTotalKills, GameData.PATTERN_TOTAL_KILLS_INSTRUCTION_LENGTH);
|
||||||
if (!IsValidAddress(_offset_total_kills))
|
if (!IsValidAddress(_offset_total_kills))
|
||||||
{
|
|
||||||
UpdateStatus("pTotalKills not valid...", Brushes.Red);
|
|
||||||
LogToFile("pTotalKills not valid...");
|
|
||||||
_offset_total_kills = 0x0;
|
_offset_total_kills = 0x0;
|
||||||
this.cbLogStats.IsEnabled = false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (_offset_player_deaths > 0x0 && _offset_total_kills > 0x0) _timerStatsCheck.Start();
|
|
||||||
|
|
||||||
this.cbBorderless.IsEnabled = true;
|
|
||||||
|
|
||||||
long ref_pTimeRelated = patternScan.FindPatternInternal(GameData.PATTERN_TIMESCALE, GameData.PATTERN_TIMESCALE_MASK, ' ');
|
long ref_pTimeRelated = patternScan.FindPatternInternal(GameData.PATTERN_TIMESCALE, GameData.PATTERN_TIMESCALE_MASK, ' ');
|
||||||
Debug.WriteLine("ref_pTimeRelated found at: 0x" + ref_pTimeRelated.ToString("X"));
|
Debug.WriteLine("ref_pTimeRelated found at: 0x" + ref_pTimeRelated.ToString("X"));
|
||||||
|
|
@ -384,17 +345,9 @@ namespace SekiroFpsUnlockAndMore
|
||||||
_offset_timescale = Read<Int64>(_gameAccessHwndStatic, pTimescaleManager) + Read<Int32>(_gameAccessHwndStatic, ref_pTimeRelated + GameData.PATTERN_TIMESCALE_POINTER_OFFSET_OFFSET);
|
_offset_timescale = Read<Int64>(_gameAccessHwndStatic, pTimescaleManager) + Read<Int32>(_gameAccessHwndStatic, ref_pTimeRelated + GameData.PATTERN_TIMESCALE_POINTER_OFFSET_OFFSET);
|
||||||
Debug.WriteLine("fTimescale found at: 0x" + _offset_timescale.ToString("X"));
|
Debug.WriteLine("fTimescale found at: 0x" + _offset_timescale.ToString("X"));
|
||||||
if (!IsValidAddress(_offset_timescale))
|
if (!IsValidAddress(_offset_timescale))
|
||||||
{
|
|
||||||
_offset_timescale = 0x0;
|
_offset_timescale = 0x0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (_offset_timescale == 0x0)
|
|
||||||
{
|
|
||||||
UpdateStatus("fTimescale not found...", Brushes.Red);
|
|
||||||
LogToFile("fTimescale not found...");
|
|
||||||
this.cbGameSpeed.IsEnabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
long pPlayerStructRelated1 = patternScan.FindPatternInternal(GameData.PATTERN_TIMESCALE_PLAYER, GameData.PATTERN_TIMESCALE_PLAYER_MASK, ' ');
|
long pPlayerStructRelated1 = patternScan.FindPatternInternal(GameData.PATTERN_TIMESCALE_PLAYER, GameData.PATTERN_TIMESCALE_PLAYER_MASK, ' ');
|
||||||
Debug.WriteLine("pPlayerStructRelated1 found at: 0x" + pPlayerStructRelated1.ToString("X"));
|
Debug.WriteLine("pPlayerStructRelated1 found at: 0x" + pPlayerStructRelated1.ToString("X"));
|
||||||
|
|
@ -420,7 +373,6 @@ namespace SekiroFpsUnlockAndMore
|
||||||
_offset_timescale_player = Read<Int64>(_gameAccessHwndStatic, pPlayerStructRelated5) + GameData.PATTERN_TIMESCALE_POINTER5_OFFSET;
|
_offset_timescale_player = Read<Int64>(_gameAccessHwndStatic, pPlayerStructRelated5) + GameData.PATTERN_TIMESCALE_POINTER5_OFFSET;
|
||||||
Debug.WriteLine("fTimescalePlayer found at: 0x" + _offset_timescale_player.ToString("X"));
|
Debug.WriteLine("fTimescalePlayer found at: 0x" + _offset_timescale_player.ToString("X"));
|
||||||
if (!IsValidAddress(_offset_timescale_player))
|
if (!IsValidAddress(_offset_timescale_player))
|
||||||
{
|
|
||||||
_offset_timescale_player = 0x0;
|
_offset_timescale_player = 0x0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -428,18 +380,86 @@ namespace SekiroFpsUnlockAndMore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// All game data has been read.
|
||||||
|
/// </summary>
|
||||||
|
private void OnReadGameFinish(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
|
||||||
|
{
|
||||||
|
if (_offset_framelock == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("frame tick not found...", Brushes.Red);
|
||||||
|
LogToFile("frame tick not found...");
|
||||||
|
this.cbFramelock.IsEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_offset_framelock_speed_fix == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("running speed fix no found...", Brushes.Red);
|
||||||
|
LogToFile("running speed fix not found...");
|
||||||
|
this.cbFramelock.IsEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)SystemParameters.PrimaryScreenWidth < 1281) _use_resolution_720 = true;
|
||||||
|
if (_offset_resolution_default == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("default resolution not found...", Brushes.Red);
|
||||||
|
LogToFile("default resolution not found...");
|
||||||
|
this.cbAddResolution.IsEnabled = false;
|
||||||
|
}
|
||||||
|
if (_offset_resolution_scaling_fix == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("scaling fix not found...", Brushes.Red);
|
||||||
|
LogToFile("scaling fix not found...");
|
||||||
|
this.cbAddResolution.IsEnabled = false;
|
||||||
|
}
|
||||||
|
if (_offset_resolution == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("current resolution not found...", Brushes.Red);
|
||||||
|
LogToFile("current resolution not found...");
|
||||||
|
this.cbAddResolution.IsEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_offset_fovsetting == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("fov table not found...", Brushes.Red);
|
||||||
|
LogToFile("fov table not found...");
|
||||||
|
this.cbFov.IsEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_offset_player_deaths == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("player deaths not found...", Brushes.Red);
|
||||||
|
LogToFile("player deaths not found...");
|
||||||
|
this.cbLogStats.IsEnabled = false;
|
||||||
|
}
|
||||||
|
if (_offset_total_kills == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("player kills not found...", Brushes.Red);
|
||||||
|
LogToFile("player kills not found...");
|
||||||
|
this.cbLogStats.IsEnabled = false;
|
||||||
|
}
|
||||||
|
if (_offset_player_deaths > 0x0 && _offset_total_kills > 0x0)
|
||||||
|
_timerStatsCheck.Start();
|
||||||
|
|
||||||
|
this.cbBorderless.IsEnabled = true;
|
||||||
|
|
||||||
|
if (_offset_timescale == 0x0)
|
||||||
|
{
|
||||||
|
UpdateStatus("timescale not found...", Brushes.Red);
|
||||||
|
LogToFile("timescale not found...");
|
||||||
|
this.cbGameSpeed.IsEnabled = false;
|
||||||
|
}
|
||||||
if (_offset_timescale_player_pointer_start == 0x0)
|
if (_offset_timescale_player_pointer_start == 0x0)
|
||||||
{
|
{
|
||||||
UpdateStatus("Playerscale not found...", Brushes.Red);
|
UpdateStatus("player timescale not found...", Brushes.Red);
|
||||||
LogToFile("Playerscale not found...");
|
//LogToFile("player timescale not found...");
|
||||||
this.cbPlayerSpeed.IsEnabled = false;
|
this.cbPlayerSpeed.IsEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bPatch.IsEnabled = true;
|
this.bPatch.IsEnabled = true;
|
||||||
|
|
||||||
_running = true;
|
_running = true;
|
||||||
_dispatcherTimerCheck.Stop();
|
PatchGame();
|
||||||
return Task.FromResult(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -461,13 +481,11 @@ namespace SekiroFpsUnlockAndMore
|
||||||
{
|
{
|
||||||
_offset_timescale_player = Read<Int64>(_gameAccessHwndStatic, pPlayerStructRelated5) + GameData.PATTERN_TIMESCALE_POINTER5_OFFSET;
|
_offset_timescale_player = Read<Int64>(_gameAccessHwndStatic, pPlayerStructRelated5) + GameData.PATTERN_TIMESCALE_POINTER5_OFFSET;
|
||||||
if (IsValidAddress(_offset_timescale_player))
|
if (IsValidAddress(_offset_timescale_player))
|
||||||
{
|
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!valid) _offset_timescale_player = 0x0;
|
if (!valid) _offset_timescale_player = 0x0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -509,7 +527,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
this.cbGameSpeed.IsEnabled = true;
|
this.cbGameSpeed.IsEnabled = true;
|
||||||
this.cbPlayerSpeed.IsEnabled = true;
|
this.cbPlayerSpeed.IsEnabled = true;
|
||||||
UpdateStatus("waiting for game...", Brushes.White);
|
UpdateStatus("waiting for game...", Brushes.White);
|
||||||
_dispatcherTimerCheck.Start();
|
_dispatcherTimerGameCheck.Start();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -821,7 +839,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void StatsReadTimer(object sender, EventArgs e)
|
private void StatsReadTimer(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (_gameAccessHwndStatic == IntPtr.Zero || _offset_player_deaths == 0x0 || _offset_total_kills == 0x0) return;
|
if (!_running || _gameAccessHwndStatic == IntPtr.Zero || _offset_player_deaths == 0x0 || _offset_total_kills == 0x0) return;
|
||||||
int playerDeaths = Read<Int32>(_gameAccessHwndStatic, _offset_player_deaths);
|
int playerDeaths = Read<Int32>(_gameAccessHwndStatic, _offset_player_deaths);
|
||||||
_statusViewModel.Deaths = playerDeaths;
|
_statusViewModel.Deaths = playerDeaths;
|
||||||
if (_statLoggingEnabled) LogStatsFile(_deathCounterPath, playerDeaths.ToString());
|
if (_statLoggingEnabled) LogStatsFile(_deathCounterPath, playerDeaths.ToString());
|
||||||
|
|
@ -990,7 +1008,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
/// <returns>The static offset from the process to the referenced object.</returns>
|
/// <returns>The static offset from the process to the referenced object.</returns>
|
||||||
private static Int64 DereferenceStaticX64Pointer(IntPtr hProcess, Int64 lpInstructionAddress, int instructionLength)
|
private static Int64 DereferenceStaticX64Pointer(IntPtr hProcess, Int64 lpInstructionAddress, int instructionLength)
|
||||||
{
|
{
|
||||||
return lpInstructionAddress + Read<Int32>(hProcess, lpInstructionAddress + (instructionLength -0x04)) + instructionLength;
|
return lpInstructionAddress + Read<Int32>(hProcess, lpInstructionAddress + (instructionLength - 0x04)) + instructionLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ namespace SekiroFpsUnlockAndMore
|
||||||
* Settings definition
|
* Settings definition
|
||||||
*/
|
*/
|
||||||
[XmlElement]
|
[XmlElement]
|
||||||
|
public bool gameVersionNotify { get; set; }
|
||||||
public bool cbFramelock { get; set; }
|
public bool cbFramelock { get; set; }
|
||||||
[XmlElement]
|
[XmlElement]
|
||||||
public int tbFramelock { get; set; }
|
public int tbFramelock { get; set; }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue