diff --git a/README.md b/README.md index 54318d8..8eab315 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s 4. Start `Sekiro FPS Unlocker and more` and enable borderless window mode 5. If you want fullscreen borderless enable `Fullscreen stretch` -### To display death/kill counters in OBS +### To display total death/kill counters in OBS 1. Start the game 2. Load up your save game 3. Start `Sekiro FPS Unlocker and more` and enable `Log stats` check box @@ -126,6 +126,7 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s 7. Select either `DeathCouner.txt` (only tracks true deaths, excluding revives) or `TotalKillsCounter.txt` 9. Customize font style and color 10. To add additional counters repeat steps 4-7 +11. [[!On Stream Display with OBS](https://camo.githubusercontent.com/007910d42ace53ee0db0ea8b61d525751b9d48a6/68747470733a2f2f692e696d6775722e636f6d2f4c39546e6f34462e706e67)](#) ### To use any of the game modifications 1. Start the game @@ -135,7 +136,7 @@ The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors s ## Preview -[![Sekiro FPS Unlocker and more](https://camo.githubusercontent.com/275b23b532ec7dcfc18a83d0ba9e8ae1f20b9e20/68747470733a2f2f692e696d6775722e636f6d2f615179334869392e706e67)](#) +[![Sekiro FPS Unlocker and more](https://camo.githubusercontent.com/53468e92a923083b0fa8d19350dffdfde3b1d480/68747470733a2f2f692e696d6775722e636f6d2f435656497555312e706e67)](#) ### Unlocked framerate [![Sekiro FPS Unlocker and more](https://camo.githubusercontent.com/2c22eea5a618066716cdd1d45274720814592172/68747470733a2f2f692e696d6775722e636f6d2f534e636b6445732e706e67)](#) @@ -163,6 +164,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Credits +* Me_TheCat for his contribution to log stats and display them in OBS * Zullie the Witch#7202 for game speed and player speed modifier offsets * jackfuste for FOV offset and basic running speed fix * TyChii93#2376 for AMD and widescreen testing @@ -174,10 +176,14 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file * in fullscreen the game forces the monitor to 60 Hz so you'll have to handle this with driver override too, see Usage * your monitor has to support your custom resolution otherwise it won't show up correctly * due to how the game renders altering HUD is limited to 16/9 even on 21/9 resolutions +* Player speed modification needs a loaded save before it can be activated * the hotkey won't work if the game runs in exclusive, true fullscreen mode ## Version History +* v1.2.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) diff --git a/SekiroFpsUnlockAndMore/GameData.cs b/SekiroFpsUnlockAndMore/GameData.cs index b683109..2ae222d 100644 --- a/SekiroFpsUnlockAndMore/GameData.cs +++ b/SekiroFpsUnlockAndMore/GameData.cs @@ -29,7 +29,7 @@ namespace SekiroFpsUnlockAndMore fFrametimeCriticalRunningSpeed should be roughly half the frame rate: 30 @ 60FPS limit, 50 @ 100FPS limit... 00000001407D4E08 | F3:0F5905 90309202 | mulss xmm0,dword ptr ds:[1430F7EA0] | pFrametimeRunningSpeed->fFrametimeCriticalRunningSpeed */ - internal const string PATTERN_FRAMELOCK_SPEED_FIX = "F3 0F 59 05 00 30 92 02"; // F3 0F 59 05 ?? 30 92 02 | 0F 51 C2 F3 0F 59 05 ?? ?? ?? ?? 0F 2F F8 + internal const string PATTERN_FRAMELOCK_SPEED_FIX = "F3 0F 59 05 00 30 92 02"; // F3 0F 59 05 ?? 30 92 02 internal const string PATTERN_FRAMELOCK_SPEED_FIX_MASK = "xxxx?xxx"; internal const int PATTERN_FRAMELOCK_SPEED_FIX_OFFSET = 4; /** diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml b/SekiroFpsUnlockAndMore/MainWindow.xaml index 1bfd603..e338429 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml @@ -5,7 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SekiroFpsUnlockAndMore" mc:Ignorable="d" - Title="Sekiro FPS Unlocker and more v1.1.1" Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing"> + Title="Sekiro FPS Unlocker and more v1.2.0" Width="Auto" Height="Auto" SizeToContent="WidthAndHeight" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing"> @@ -28,7 +28,7 @@ - + @@ -81,7 +81,7 @@ diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs index 5158e08..0b0553e 100644 --- a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs +++ b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs @@ -40,6 +40,7 @@ namespace SekiroFpsUnlockAndMore internal readonly DispatcherTimer _dispatcherTimerFreezeMem = new DispatcherTimer(); internal readonly DispatcherTimer _dispatcherTimerCheck = new DispatcherTimer(); internal bool _running = false; + internal bool _gameInitializing = false; internal string _logPath; internal string _deathCounterPath; internal string _killCounterPath; @@ -87,13 +88,13 @@ namespace SekiroFpsUnlockAndMore bool result = await CheckGame(); if (result) PatchGame(); }); - _dispatcherTimerCheck.Interval = new TimeSpan(0, 0, 0, 2); + _dispatcherTimerCheck.Interval = new TimeSpan(0, 0, 0, 0, 2000); _dispatcherTimerCheck.Start(); _dispatcherTimerFreezeMem.Tick += new EventHandler(FreezeMemory); _dispatcherTimerFreezeMem.Interval = new TimeSpan(0, 0, 0, 0, 2000); - _timerStatsCheck.Elapsed += new ElapsedEventHandler(StatReadTimer); + _timerStatsCheck.Elapsed += new ElapsedEventHandler(StatsReadTimer); _timerStatsCheck.Interval = 2000; } @@ -142,12 +143,12 @@ namespace SekiroFpsUnlockAndMore this.cbSelectFov.SelectedIndex = _settingsService.ApplicationSettings.cbSelectFov; this.cbBorderless.IsChecked = _settingsService.ApplicationSettings.cbBorderless; this.cbBorderlessStretch.IsChecked = _settingsService.ApplicationSettings.cbBorderlessStretch; + this.cbLogStats.IsChecked = _settingsService.ApplicationSettings.cbLogStats; this.exGameMods.IsExpanded = _settingsService.ApplicationSettings.exGameMods; 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.cbLogStats.IsChecked = _settingsService.ApplicationSettings.cbLogStats; } /// @@ -164,12 +165,12 @@ namespace SekiroFpsUnlockAndMore _settingsService.ApplicationSettings.cbSelectFov = this.cbSelectFov.SelectedIndex; _settingsService.ApplicationSettings.cbBorderless = this.cbBorderless.IsChecked == true; _settingsService.ApplicationSettings.cbBorderlessStretch = this.cbBorderlessStretch.IsChecked == true; + _settingsService.ApplicationSettings.cbLogStats = this.cbLogStats.IsChecked == true; _settingsService.ApplicationSettings.exGameMods = this.exGameMods.IsExpanded; _settingsService.ApplicationSettings.cbGameSpeed = this.cbGameSpeed.IsChecked == true; _settingsService.ApplicationSettings.tbGameSpeed = Convert.ToInt32(this.tbGameSpeed.Text); _settingsService.ApplicationSettings.cbPlayerSpeed = this.cbPlayerSpeed.IsChecked == true; _settingsService.ApplicationSettings.tbPlayerSpeed = Convert.ToInt32(this.tbPlayerSpeed.Text); - _settingsService.ApplicationSettings.cbLogStats = this.cbLogStats.IsChecked == true; _settingsService.Save(); } @@ -203,7 +204,7 @@ namespace SekiroFpsUnlockAndMore LogToFile(string.Format("\tDescription #{0}: {1} | {2} | {3}", j, procList[j].MainWindowTitle, procList[j].MainModule.FileVersionInfo.CompanyName, procList[j].MainModule.FileVersionInfo.FileDescription)); LogToFile(string.Format("\tData #{0}: {1} | {2} | {3} | {4} | {5}", j, procList[j].MainModule.FileVersionInfo.FileVersion, procList[j].MainModule.ModuleMemorySize, procList[j].StartTime, procList[j].Responding, procList[j].HasExited)); } - Task.FromResult(false); + return Task.FromResult(false); } _gameProc = procList[gameIndex]; @@ -220,7 +221,7 @@ namespace SekiroFpsUnlockAndMore { UpdateStatus("no access to game...", Brushes.Red); _dispatcherTimerCheck.Stop(); - Task.FromResult(false); + return Task.FromResult(false); } _gameHwnd = IntPtr.Zero; if (_gameAccessHwnd != IntPtr.Zero) @@ -231,7 +232,14 @@ namespace SekiroFpsUnlockAndMore } LogToFile("retrying..."); _retryAccess = false; - Task.FromResult(false); + return Task.FromResult(false); + } + + // give the game some time to initialize + if (!_gameInitializing) + { + _gameInitializing = true; + return Task.FromResult(false); } //string gameFileVersion = FileVersionInfo.GetVersionInfo(procList[0].MainModule.FileName).FileVersion; @@ -329,6 +337,7 @@ namespace SekiroFpsUnlockAndMore { int playerStatsToDeathsOffset = Read(_gameAccessHwndStatic, ref_pPlayerStatsRelated + GameData.PATTERN_PLAYER_DEATHS_POINTER_OFFSET_OFFSET); Debug.WriteLine("offset pPlayerStats->iPlayerDeaths found : 0x" + playerStatsToDeathsOffset.ToString("X")); + if (playerStatsToDeathsOffset > 0) _offset_player_deaths = Read(_gameAccessHwndStatic, pPlayerStatsRelated) + playerStatsToDeathsOffset; Debug.WriteLine("iPlayerDeaths found at: 0x" + _offset_player_deaths.ToString("X")); } @@ -434,9 +443,9 @@ namespace SekiroFpsUnlockAndMore } /// - /// Read and refresh all offsets that can change on quick travel or save game loading. + /// Read and refresh the player speed offset that can change on quick travel or save game loading. /// - private void ReadIngameOffsets() + private void ReadPlayerTimescaleOffsets() { bool valid = false; if (_offset_timescale_player_pointer_start > 0) @@ -474,10 +483,13 @@ namespace SekiroFpsUnlockAndMore _running = false; if (_gameAccessHwnd != IntPtr.Zero) CloseHandle(_gameAccessHwnd); + _dispatcherTimerFreezeMem.Stop(); + _timerStatsCheck.Stop(); _gameProc = null; _gameHwnd = IntPtr.Zero; _gameAccessHwnd = IntPtr.Zero; _gameAccessHwndStatic = IntPtr.Zero; + _gameInitializing = false; _offset_framelock = 0x0; _offset_framelock_speed_fix = 0x0; _offset_resolution = 0x0; @@ -488,6 +500,7 @@ namespace SekiroFpsUnlockAndMore _offset_total_kills = 0x0; _offset_timescale = 0x0; _offset_timescale_player = 0x0; + _offset_timescale_player_pointer_start = 0x0; this.cbFramelock.IsEnabled = true; this.cbAddResolution.IsEnabled = true; this.cbFov.IsEnabled = true; @@ -712,7 +725,7 @@ namespace SekiroFpsUnlockAndMore if (!this.cbPlayerSpeed.IsEnabled || !CanPatchGame()) return false; if (this.cbPlayerSpeed.IsChecked == true) { - if (_offset_timescale_player_pointer_start > 0x0) ReadIngameOffsets(); + if (_offset_timescale_player_pointer_start > 0x0) ReadPlayerTimescaleOffsets(); if (_offset_timescale_player == 0x0) { this.cbPlayerSpeed.IsChecked = false; @@ -784,7 +797,7 @@ namespace SekiroFpsUnlockAndMore return; } if (_offset_timescale_player_pointer_start == 0x0 || !CanPatchGame()) return; - if (_offset_timescale_player_pointer_start > 0x0) ReadIngameOffsets(); + if (_offset_timescale_player_pointer_start > 0x0) ReadPlayerTimescaleOffsets(); if (_offset_timescale_player == 0x0) return; bool isNumber = Int32.TryParse(this.tbPlayerSpeed.Text, out int playerSpeed); @@ -806,7 +819,7 @@ namespace SekiroFpsUnlockAndMore /// /// Reads some hidden stats and outputs them to text files and status bar. Use to display counters on Twitch stream or just look at them and get disappointed. /// - private void StatReadTimer(object sender, EventArgs e) + private void StatsReadTimer(object sender, EventArgs e) { if (_gameAccessHwndStatic == IntPtr.Zero || _offset_player_deaths == 0x0 || _offset_total_kills == 0x0) return; int playerDeaths = Read(_gameAccessHwndStatic, _offset_player_deaths); diff --git a/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs b/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs index cb8b897..5ff7f80 100644 --- a/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs +++ b/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs @@ -21,5 +21,5 @@ using System.Runtime.InteropServices; ResourceDictionaryLocation.SourceAssembly )] -[assembly: AssemblyVersion("1.1.1.0")] -[assembly: AssemblyFileVersion("1.1.1.0")] +[assembly: AssemblyVersion("1.2.0.0")] +[assembly: AssemblyFileVersion("1.2.0.0")]