updated guide

cleanup
This commit is contained in:
uberhalit 2019-03-27 15:57:23 +01:00
parent 9df5b8832b
commit 35dd34c9c5
6 changed files with 107 additions and 84 deletions

View file

@ -5,7 +5,7 @@ Patches games memory while running, does not modify any game files. works with e
## Download ## Download
[Get the latest release here](https://github.com/uberhalit/SekiroFpsUnlockAndMore/releases) **[Get the latest release here](https://github.com/uberhalit/SekiroFpsUnlockAndMore/releases)**
### See it in action: ### See it in action:
[![Video preview](https://camo.githubusercontent.com/99b882828d8bb814a126282d67f0394460259df0/68747470733a2f2f692e696d6775722e636f6d2f4b4e4674454d772e706e67)](https://giant.gfycat.com/DevotedArtisticKingsnake.webm) [![Video preview](https://camo.githubusercontent.com/99b882828d8bb814a126282d67f0394460259df0/68747470733a2f2f692e696d6775722e636f6d2f4b4e4674454d772e706e67)](https://giant.gfycat.com/DevotedArtisticKingsnake.webm)
@ -16,13 +16,9 @@ Patches games memory while running, does not modify any game files. works with e
* works with legit, unmodified steam version as well as with unpacked, not-so-legit versions * works with legit, unmodified steam version as well as with unpacked, not-so-legit versions
* GSYNC and FreeSync support even in borderless window mode * GSYNC and FreeSync support even in borderless window mode
* unlock frame rate (remove FPS limit) by setting a new custom limit or setting lock to unlimited * unlock frame rate (remove FPS limit) by setting a new custom limit or setting lock to unlimited
* 60 Hz monitors: disable VSYNC via driver (use 'Enhanced Sync' on AMD) and use fullscreen
* high refresh rate monitors: use borderless or force monitor to always use highest available refresh rate and then use fullscreen
* add a custom resolution, 21/9 widescreen supported (will overwrite the default 1920x1080 resolution, HUD limited to 16/9) * add a custom resolution, 21/9 widescreen supported (will overwrite the default 1920x1080 resolution, HUD limited to 16/9)
* increase field of view (FOV) (credits to jackfuste) * increase field of view (FOV) (credits to jackfuste)
* you have to be ingame with a loaded save game, FOV will reset after every time a save game loads
* set the game to borderless window mode * set the game to borderless window mode
* requires "Windowed" in ingame settings first
* automatically patch game on startup * automatically patch game on startup
* seamlessly switch between windowed, borderless and borderless fullscreen * seamlessly switch between windowed, borderless and borderless fullscreen
* hotkey for patching while in (borderless) window mode * hotkey for patching while in (borderless) window mode
@ -30,34 +26,61 @@ Patches games memory while running, does not modify any game files. works with e
## Usage ## Usage
The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors so we have to override these. The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors so we have to override these.
#### 60 Hz monitors: disable VSYNC via driver (use 'Enhanced Sync' on AMD) and use fullscreen, see guide below
#### high refresh rate monitors: use borderless or force monitor to always use highest available refresh rate and then use fullscreen, see guide below
### Follow these steps (Nvidia): ### Follow these steps on Nvidia:
1. Open Nvidia Control Panel 1. Open Nvidia Control Panel
2. Navigate to `Configurate 3D Settings -> Program settings` 2. Navigate to `Display -> Change resolution`
3. Select Sekiro from the dropdown or add it manually if it's missing: `Add -> Select Sekiro` 3. **Make sure your monitor is set to the highest Refresh rate possible:**
4. **Set `Vertical sync` to `Off`** 4. [![Make sure your monitor is set to the highest Refresh rate possible](https://camo.githubusercontent.com/331eb420bee67f4e57d7e46601bfd51f462de68f/68747470733a2f2f692e696d6775722e636f6d2f625667767155372e706e67)](#)
5. **Set `Preferred refresh rate` to `Highest available`** 5. Navigate to `3D Settings -> Manage 3D settings -> Program Settings`
6. Start `Sekiro FPS Unlocker and more` and set FPS lock to your desired framerate 6. Select Sekiro from the dropdown or add it manually if it's missing: `Add -> Select Sekiro -> Add Selected Program`
7. Start the game and use fullscreen or borderless window mode 7. **Set `Vertical sync` to `Off`**
8. These steps will force disable vsync so it won't limit your fps to monitor refresh rate and also force the monitor to ignore the games request to run at 60 Hz if in fullscreen 8. **Set `Preferred refresh rate` to `Highest available`**
9. [![Vertical sync Off and Preferred refresh rate Highest available](https://camo.githubusercontent.com/bae53a6199d5a6fc2b8e0c4f0bfab322ebecd648/68747470733a2f2f692e696d6775722e636f6d2f35446f526d55452e706e67)](#)
10. Hit apply and close Nvidia Control Panel
11. Start `Sekiro FPS Unlocker and more` and set FPS lock to your desired framerate
12. Start the game and use fullscreen or borderless window mode
13. These steps will force disable vsync so it won't limit your fps to monitor refresh rate and also force the monitor to ignore the games request to run at 60 Hz if in fullscreen
#### If you do not have 'Preferred refresh rate' or 'Vertical sync' follow these steps (Nvidia):
1. Download and extract the [Nvidia Inspector](https://www.techpowerup.com/download/nvidia-inspector/)
2. Start the Nvidia Profile Inspector
3. Under `2 - Sync and Refresh` set `Prefered Refreshrate` to `Highest available` and `Vertical Sync` to `Force off`
4. [![Vertical sync Off and Preferred refresh rate Highest available](https://camo.githubusercontent.com/560355d19113ad3e6782c75cae992e7c91a4e0fd/68747470733a2f2f692e696d6775722e636f6d2f4657424b57536e2e706e67)](#)
5. Hit `Apply changes` and you are good to go
### Or these (AMD): ### Follow these steps on AMD:
1. Open Radeon Settings 1. Right click on Desktop -> `Display settings`
2. Navigate to `Gaming -> Sekiro` or add it manually if it's missing: `Add -> Browse -> Sekiro` 2. Scroll down an click `Advanced Display Settings -> Display Adapter Properties`
3. **Set `Wait for Vertical Refresh` to `Enhanced Sync`** 3. **Switch to `Monitor` tab and make sure your monitor is set to the highest Refresh rate possible:**
4. Start `Sekiro FPS Unlocker and more` and set FPS lock to your desired frame rate 4. [![Make sure your monitor is set to the highest Refresh rate possible](https://camo.githubusercontent.com/8ba71a0b512eb68509f7e7506a92a78f3cd47537/68747470733a2f2f692e696d6775722e636f6d2f61774b4862774d2e706e67)](#)
5. **Launch the game in windowed mode, then switch to fullscreen once in game** 5. Open Radeon Settings
6. The last step is important as AMD somehow does not correctly disable VSYNC otherwise 6. Navigate to `Gaming -> Sekiro` or add it manually if it's missing: `Add -> Browse -> Sekiro`
7. **Set `Wait for Vertical Refresh` to `Enhanced Sync`**:
8. [![Wait for Vertical Refresh Enhanced Sync](https://camo.githubusercontent.com/7c00daebb59c7e46c455e30b6caa055c63185dcb/68747470733a2f2f692e696d6775722e636f6d2f456e77595146322e706e67)](#)
9. Apply and close Radeon Settings
10. Start `Sekiro FPS Unlocker and more` and set FPS lock to your desired frame rate
11. **Launch the game in windowed mode, then switch to fullscreen once in game**
12. The last step is important as AMD somehow does not correctly disable VSYNC otherwise
#### If you do not have 'Enhanced Sync' follow these steps (AMD):
1. Try setting `Wait for Vertical Refresh` to `Off` instead:
2. [![Wait for Vertical Refresh Off](https://camo.githubusercontent.com/c06be2d7a7be65e379996eee66685209b276dcea/68747470733a2f2f692e696d6775722e636f6d2f417a7a716545332e706e67)](#)
3. Be aware however that it seems like AMDs latest drivers are buggy in that regard
### To play the game with GSYNC do these additional steps (Nvidia): ### To play the game with GSYNC do these additional steps (Nvidia):
1. Set `Monitor Technology` to `G-SYNC` 1. Under Nvidia Control Panel navigate to `3D Settings -> Manage 3D settings -> Program Settings -> Sekiro`
2. Make sure that `Preferred refresh rate` is still set to `Highest available` 2. Set `Monitor Technology` to `G-SYNC`
3. Use a 3rd party frame rate limiter like [RTSS](https://www.guru3d.com/files-details/rtss-rivatuner-statistics-server-download.html) and set a frame rate limit just a few fps below your monitor refresh rate, on a 144Hz Monitor use 138 3. Make sure that `Preferred refresh rate` is still set to `Highest available`
4. Start `Sekiro FPS Unlocker and more` and set FPS lock to your monitors refresh rate 4. Make sure that `Vertical sync` is still set to `Off`
5. Start the game and set it to Fullscreen 5. [![Control Panel](https://camo.githubusercontent.com/b7b491c24020fd3eca41d857bd58b1c0c2ee037f/68747470733a2f2f692e696d6775722e636f6d2f614a41744444632e706e67)](#)
6. Enjoy perfectly tearing free variable high refresh rates without VSYNC 6. Don't forget to Apply and close Nvidia Control Panel
7. Use a 3rd party frame rate limiter like [RTSS](https://www.guru3d.com/files-details/rtss-rivatuner-statistics-server-download.html) and set a frame rate limit just a few fps below your monitor refresh rate, on a 144Hz Monitor use 138
8. Start `Sekiro FPS Unlocker and more` and set FPS lock to your monitors refresh rate
9. Start the game and set it to Fullscreen
10. Enjoy perfectly tearing free variable high refresh rates without VSYNC
The graphic setup has to be done only once but as the patcher hot-patches the memory you have to start the patcher every time you want to unlock frame rate etc. The graphic setup has to be done only once but as the patcher hot-patches the memory **you have to start the patcher every time you want to unlock frame rate etc**.
### To add a custom resolution ### To add a custom resolution
1. Start the game 1. Start the game

View file

@ -5,23 +5,23 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SekiroFpsUnlockAndMore" xmlns:local="clr-namespace:SekiroFpsUnlockAndMore"
mc:Ignorable="d" mc:Ignorable="d"
Title="Sekiro FPS Unlocker and more v1.0.0" Height="530" Width="306" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing"> Title="Sekiro FPS Unlocker and more v1.0.2" Height="Auto" SizeToContent="WidthAndHeight" Width="Auto" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing">
<Grid> <Grid Background="#FFF9F9F9">
<CheckBox x:Name="cbUnlockFps" Content="FPS lock (0= unlimited):" IsChecked="True" HorizontalAlignment="Left" Margin="10,12,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/> <CheckBox x:Name="cbUnlockFps" Content="FPS lock (0= unlimited):" IsChecked="True" HorizontalAlignment="Left" Margin="10,12,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/>
<TextBox x:Name="tbFps" Text="144" MaxLength="3" HorizontalAlignment="Left" Height="25" Margin="181,10,0,0" VerticalAlignment="Top" Width="106" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler"/> <TextBox x:Name="tbFps" Text="144" MaxLength="3" HorizontalAlignment="Left" Height="25" Margin="181,10,10,10" VerticalAlignment="Top" Width="106" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler"/>
<CheckBox x:Name="cbAddWidescreen" Content="Add custom resolution:" HorizontalAlignment="Left" Margin="10,42,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/> <CheckBox x:Name="cbAddWidescreen" Content="Add custom resolution:" HorizontalAlignment="Left" Margin="10,42,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/>
<TextBox x:Name="tbWidth" Text="2560" MaxLength="4" HorizontalAlignment="Left" Height="25" Margin="181,40,0,0" VerticalAlignment="Top" Width="45" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" /> <TextBox x:Name="tbWidth" Text="2560" MaxLength="4" HorizontalAlignment="Left" Height="25" Margin="181,40,0,0" VerticalAlignment="Top" Width="45" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
<Label Content="x" HorizontalAlignment="Left" Margin="226,36,0,0" VerticalAlignment="Top" FontSize="14 px"/> <Label Content="x" HorizontalAlignment="Left" Margin="226,36,0,0" VerticalAlignment="Top" FontSize="14 px"/>
<TextBox x:Name="tbHeight" Text="1080" MaxLength="4" HorizontalAlignment="Left" Height="25" Margin="242,40,0,0" VerticalAlignment="Top" Width="45" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" /> <TextBox x:Name="tbHeight" Text="1080" MaxLength="4" HorizontalAlignment="Left" Height="25" Margin="242,40,0,0" VerticalAlignment="Top" Width="45" FontSize="14 px" PreviewTextInput="Numeric_PreviewTextInput" DataObject.Pasting="Numeric_PastingHandler" />
<CheckBox x:Name="cbFov" Content="Increase FOV by:" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/> <CheckBox x:Name="cbFov" Content="Increase FOV by:" HorizontalAlignment="Left" Margin="10,72,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/>
<ComboBox x:Name="cbSelectFov" HorizontalAlignment="Left" VerticalAlignment="Top" Width="106" Height="25" Margin="181,70,0,0" FontSize="14 px" SelectedValuePath="Key" DisplayMemberPath="Value"/> <ComboBox x:Name="cbSelectFov" HorizontalAlignment="Left" VerticalAlignment="Top" Width="106" Height="25" Margin="181,70,10,10" FontSize="14 px" SelectedValuePath="Key" DisplayMemberPath="Value"/>
<CheckBox x:Name="cbBorderless" Content="Borderless window" HorizontalAlignment="Left" Margin="10,100,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CbBorderless_Checked" Unchecked="CbBorderless_Unchecked"/> <CheckBox x:Name="cbBorderless" Content="Borderless window" HorizontalAlignment="Left" Margin="10,100,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CbBorderless_Checked" Unchecked="CbBorderless_Unchecked"/>
<CheckBox x:Name="cbBorderlessStretch" Content="Fullscreen stretch" IsEnabled="False" HorizontalAlignment="Left" Margin="152,100,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/> <CheckBox x:Name="cbBorderlessStretch" Content="Fullscreen stretch" IsEnabled="False" HorizontalAlignment="Left" Margin="152,100,0,0" VerticalAlignment="Top" FontSize="14 px" Checked="CheckBoxChanged_Handler" Unchecked="CheckBoxChanged_Handler"/>
<Button x:Name="bPatch" Content="Patch game (CTRL + P)" FontSize="14 px" HorizontalAlignment="Left" Margin="10,125,0,0" VerticalAlignment="Top" Width="277" Height="30" <Button x:Name="bPatch" Content="Patch game (CTRL + P)" FontSize="14 px" HorizontalAlignment="Left" Margin="10,125,10,10" VerticalAlignment="Top" Width="277" Height="30"
BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Focusable="False" Click="BPatch_Click" /> BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Focusable="False" Click="BPatch_Click" />
<TextBox x:Name="tbStatus" Text="waiting for game..." TextAlignment="Center" HorizontalAlignment="Left" TextWrapping="NoWrap" Height="25" Margin="10,165,0,0" VerticalAlignment="Top" Width="277" FontSize="14 px" IsEnabled="False" FontWeight="Bold" /> <TextBox x:Name="tbStatus" Text="waiting for game..." TextAlignment="Center" HorizontalAlignment="Left" TextWrapping="NoWrap" Height="25" Margin="10,165,10,10" VerticalAlignment="Top" Width="277" FontSize="14 px" IsEnabled="False" FontWeight="Bold" />
<StackPanel HorizontalAlignment="Left" Height="305" Margin="13,195,0,0" VerticalAlignment="Top" Width="275"> <StackPanel HorizontalAlignment="Left" Height="Auto" Margin="12,195,12,5" VerticalAlignment="Top" Width="275">
<TextBlock HorizontalAlignment="Left" TextWrapping="WrapWithOverflow" VerticalAlignment="Top" FontSize="11 px" IsEnabled="False"> <TextBlock HorizontalAlignment="Left" TextWrapping="WrapWithOverflow" VerticalAlignment="Top" FontSize="11 px" IsEnabled="False">
<TextBlock.Inlines> <TextBlock.Inlines>
<Run FontWeight="Bold">If your monitor is 60 Hz you will have to use</Run> <Run FontWeight="Bold">If your monitor is 60 Hz you will have to use</Run>

View file

@ -21,15 +21,15 @@ namespace SekiroFpsUnlockAndMore
internal byte[] PATCH_FRAMERATE_UNLIMITED = new byte[4] { 0x00, 0x00, 0x00, 0x00 }; internal byte[] PATCH_FRAMERATE_UNLIMITED = new byte[4] { 0x00, 0x00, 0x00, 0x00 };
internal byte[] PATCH_WIDESCREEN_219_DISABLE = new byte[1] { 0x74 }; internal byte[] PATCH_WIDESCREEN_219_DISABLE = new byte[1] { 0x74 };
internal byte[] PATCH_WIDESCREEN_219_ENABLE = new byte[1] { 0xEB }; internal byte[] PATCH_WIDESCREEN_219_ENABLE = new byte[1] { 0xEB };
internal byte[] PATCH_FOV_DISABLE = new byte[1] { 0x0C }; internal byte[] PATCH_FOV_DISABLE = new byte[2] { 0x0C, 0xE7};
internal Dictionary<byte, string> PATCH_FOVMATRIX = new Dictionary<byte, string> internal Dictionary<byte[], string> PATCH_FOVMATRIX = new Dictionary<byte[], string>
{ {
{ 0x00, "- 50%" }, { new byte[2] {0x00, 0xE7}, "- 50%" },
{ 0x04, "- 10%" }, { new byte[2] {0x04, 0xE7}, "- 10%" },
{ 0x10, "+ 15%" }, { new byte[2] {0x10, 0xE7}, "+ 15%" },
{ 0x14, "+ 40%" }, { new byte[2] {0x14, 0xE7}, "+ 40%" },
{ 0x18, "+ 75%" }, { new byte[2] {0x18, 0xE7}, "+ 75%" },
{ 0x1C, "+ 90%" }, { new byte[2] {0x1C, 0xE7}, "+ 90%" },
}; };
internal Process _game; internal Process _game;
@ -261,12 +261,16 @@ namespace SekiroFpsUnlockAndMore
if (_game.HasExited) if (_game.HasExited)
{ {
_running = false; _running = false;
if (_gameProc != IntPtr.Zero)
CloseHandle(_gameProc);
_game = null;
_gameHwnd = IntPtr.Zero; _gameHwnd = IntPtr.Zero;
_gameProc = IntPtr.Zero; _gameProc = IntPtr.Zero;
_gameProcStatic = IntPtr.Zero; _gameProcStatic = IntPtr.Zero;
_offset_framelock = 0x0; _offset_framelock = 0x0;
_offset_framelock_running_fix = 0x0; _offset_framelock_running_fix = 0x0;
_offset_resolution = 0x0; _offset_resolution = 0x0;
_offset_resolution_default = 0x0;
_offset_widescreen_219 = 0x0; _offset_widescreen_219 = 0x0;
_offset_fovsetting = 0x0; _offset_fovsetting = 0x0;
UpdateStatus("waiting for game...", Brushes.White); UpdateStatus("waiting for game...", Brushes.White);
@ -320,8 +324,7 @@ namespace SekiroFpsUnlockAndMore
if (this.cbAddWidescreen.IsChecked == true) if (this.cbAddWidescreen.IsChecked == true)
{ {
int width = -1; bool isNumber = Int32.TryParse(this.tbWidth.Text, out int width);
bool isNumber = Int32.TryParse(this.tbWidth.Text, out width);
if (width < 800 || !isNumber) if (width < 800 || !isNumber)
{ {
this.tbWidth.Text = "2560"; this.tbWidth.Text = "2560";
@ -332,8 +335,7 @@ namespace SekiroFpsUnlockAndMore
this.tbWidth.Text = "5760"; this.tbWidth.Text = "5760";
width = 5760; width = 5760;
} }
int height = -1; isNumber = Int32.TryParse(this.tbHeight.Text, out int height);
isNumber = Int32.TryParse(this.tbHeight.Text, out height);
if (height < 450 || !isNumber) if (height < 450 || !isNumber)
{ {
this.tbHeight.Text = "1080"; this.tbHeight.Text = "1080";
@ -357,8 +359,7 @@ namespace SekiroFpsUnlockAndMore
if (this.cbFov.IsChecked == true) if (this.cbFov.IsChecked == true)
{ {
byte[] fovByte = new byte[1]; byte[] fovByte = ((KeyValuePair<byte[], string>) this.cbSelectFov.SelectedItem).Key;
fovByte[0] = ((KeyValuePair<byte, string>) this.cbSelectFov.SelectedItem).Key;
WriteBytes(_gameProcStatic, _offset_fovsetting, fovByte); WriteBytes(_gameProcStatic, _offset_fovsetting, fovByte);
} }
else if (this.cbFov.IsChecked == false) else if (this.cbFov.IsChecked == false)
@ -406,8 +407,8 @@ namespace SekiroFpsUnlockAndMore
/// <summary> /// <summary>
/// Returns the hexadecimal representation of an IEEE-754 floating point number /// Returns the hexadecimal representation of an IEEE-754 floating point number
/// </summary> /// </summary>
/// <param name="input">The floating point number</param> /// <param name="input">The floating point number.</param>
/// <returns>The hexadecimal representation of the input</returns> /// <returns>The hexadecimal representation of the input.</returns>
private string getHexRepresentationFromFloat(float input) private string getHexRepresentationFromFloat(float input)
{ {
uint f = BitConverter.ToUInt32(BitConverter.GetBytes(input), 0); uint f = BitConverter.ToUInt32(BitConverter.GetBytes(input), 0);
@ -514,8 +515,7 @@ namespace SekiroFpsUnlockAndMore
private static T Read<T>(IntPtr gameProc, Int64 lpBaseAddress) private static T Read<T>(IntPtr gameProc, Int64 lpBaseAddress)
{ {
byte[] lpBuffer = new byte[Marshal.SizeOf(typeof(T))]; byte[] lpBuffer = new byte[Marshal.SizeOf(typeof(T))];
IntPtr lpNumberOfBytesRead; ReadProcessMemory(gameProc, lpBaseAddress, lpBuffer, (ulong)lpBuffer.Length, out _);
ReadProcessMemory(gameProc, lpBaseAddress, lpBuffer, (ulong)lpBuffer.Length, out lpNumberOfBytesRead);
GCHandle gcHandle = GCHandle.Alloc(lpBuffer, GCHandleType.Pinned); GCHandle gcHandle = GCHandle.Alloc(lpBuffer, GCHandleType.Pinned);
T structure = (T)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(T)); T structure = (T)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(T));
gcHandle.Free(); gcHandle.Free();
@ -531,8 +531,7 @@ namespace SekiroFpsUnlockAndMore
/// <returns>True if successful, false otherwise.</returns> /// <returns>True if successful, false otherwise.</returns>
private static bool WriteBytes(IntPtr gameProc, Int64 lpBaseAddress, byte[] bytes) private static bool WriteBytes(IntPtr gameProc, Int64 lpBaseAddress, byte[] bytes)
{ {
IntPtr lpNumberOfBytesWritten; return WriteProcessMemory(gameProc, lpBaseAddress, bytes, (ulong)bytes.Length, out _);
return WriteProcessMemory(gameProc, lpBaseAddress, bytes, (ulong)bytes.Length, out lpNumberOfBytesWritten);
} }
/// <summary> /// <summary>
@ -540,8 +539,8 @@ namespace SekiroFpsUnlockAndMore
/// </summary> /// </summary>
/// <param name="hProcess">Handle to the process in whose memory the pattern has been found.</param> /// <param name="hProcess">Handle to the process in whose memory the pattern has been found.</param>
/// <param name="lpPatternAddress">The address where the pattern has been found.</param> /// <param name="lpPatternAddress">The address where the pattern has been found.</param>
/// <param name="instructionLength">The length of the instruction including the 4 bytes pointer</param> /// <param name="instructionLength">The length of the instruction including the 4 bytes pointer.</param>
/// <remarks>Static pointers in x86-64 are relative offsets from the instruction address. </remarks> /// <remarks>Static pointers in x86-64 are relative offsets from the instruction address.</remarks>
/// <returns>The static offset from the process to desired object).</returns> /// <returns>The static offset from the process to desired object).</returns>
internal static Int64 FindOffsetToStaticPointer(IntPtr hProcess, Int64 lpPatternAddress, int instructionLength) internal static Int64 FindOffsetToStaticPointer(IntPtr hProcess, Int64 lpPatternAddress, int instructionLength)
{ {
@ -558,6 +557,27 @@ namespace SekiroFpsUnlockAndMore
return Regex.IsMatch(text, "[^0-9]+"); return Regex.IsMatch(text, "[^0-9]+");
} }
/// <summary>
/// Logs messages to log file
/// </summary>
/// <param name="msg">The message to write to file.</param>
private void LogToFile(string msg)
{
string timedMsg = "[" + DateTime.Now + "] " + msg;
Debug.WriteLine(timedMsg);
try
{
using (StreamWriter writer = new StreamWriter(_logPath, true))
{
writer.WriteLine(timedMsg);
}
}
catch (Exception ex)
{
MessageBox.Show("Writing to log file failed: " + ex.Message, "Sekiro Fps Unlock And More");
}
}
private void UpdateStatus(string text, Brush color) private void UpdateStatus(string text, Brush color)
{ {
this.tbStatus.Background = color; this.tbStatus.Background = color;
@ -571,9 +591,9 @@ namespace SekiroFpsUnlockAndMore
private void Numeric_PastingHandler(object sender, DataObjectPastingEventArgs e) private void Numeric_PastingHandler(object sender, DataObjectPastingEventArgs e)
{ {
if (e.DataObject.GetDataPresent(typeof(String))) if (e.DataObject.GetDataPresent(typeof(string)))
{ {
String text = (String)e.DataObject.GetData(typeof(String)); string text = (string)e.DataObject.GetData(typeof(string));
if (IsNumericInput(text)) e.CancelCommand(); if (IsNumericInput(text)) e.CancelCommand();
} }
else e.CancelCommand(); else e.CancelCommand();
@ -608,24 +628,6 @@ namespace SekiroFpsUnlockAndMore
e.Handled = true; e.Handled = true;
} }
// log messages to file
private void LogToFile(string msg)
{
string timedMsg = "[" + DateTime.Now + "] " + msg;
Debug.WriteLine(timedMsg);
try
{
using (StreamWriter writer = new StreamWriter(_logPath, true))
{
writer.WriteLine(timedMsg);
}
}
catch (Exception ex)
{
MessageBox.Show("Writing to log file failed: " + ex.Message, "Sekiro Fps Unlock And More");
}
}
#region WINAPI #region WINAPI
private const int WM_HOTKEY_MSG_ID = 0x0312; private const int WM_HOTKEY_MSG_ID = 0x0312;
private const int MOD_CONTROL = 0x0002; private const int MOD_CONTROL = 0x0002;

View file

@ -24,8 +24,8 @@ namespace SekiroFpsUnlockAndMore
internal const string PATTERN_WIDESCREEN_219_MASK = "?xxxxxxxxx"; internal const string PATTERN_WIDESCREEN_219_MASK = "?xxxxxxxxx";
// credits to jackfuste for FOV findings // credits to jackfuste for FOV findings
internal const string PATTERN_FOVSETTING = "F3 0F 10 08 F3 0F 59 0D 00 E7 9B 02"; // F3 0F 10 08 F3 0F 59 0D ?? E7 9B 02 internal const string PATTERN_FOVSETTING = "F3 0F 10 08 F3 0F 59 0D 00 00 9B 02"; // F3 0F 10 08 F3 0F 59 0D ?? ?? 9B 02
internal const string PATTERN_FOVSETTING_MASK = "xxxxxxxx?xxx"; internal const string PATTERN_FOVSETTING_MASK = "xxxxxxxx??xx";
internal const int PATTERN_FOVSETTING_OFFSET = 8; internal const int PATTERN_FOVSETTING_OFFSET = 8;
} }
} }

View file

@ -33,11 +33,9 @@ namespace SekiroFpsUnlockAndMore
else if (IntPtr.Size == 8) else if (IntPtr.Size == 8)
dwStart = (long)pModule.BaseAddress; dwStart = (long)pModule.BaseAddress;
int nSize = pModule.ModuleMemorySize; int nSize = pModule.ModuleMemorySize;
IntPtr lpNumberOfBytesRead;
byte[] bData = new byte[nSize]; byte[] bData = new byte[nSize];
if (!ReadProcessMemory(hProcess, dwStart, bData, nSize, out lpNumberOfBytesRead)) if (!ReadProcessMemory(hProcess, dwStart, bData, nSize, out IntPtr lpNumberOfBytesRead))
throw new Exception("ReadProcessMemory error!"); throw new Exception("ReadProcessMemory error!");
if (lpNumberOfBytesRead.ToInt64() != nSize) if (lpNumberOfBytesRead.ToInt64() != nSize)
throw new Exception("ReadProcessMemory error!"); throw new Exception("ReadProcessMemory error!");

View file

@ -1,6 +1,6 @@
using System.Reflection; using System.Windows;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Windows;
[assembly: AssemblyTitle("SekiroFpsUnlockAndMore")] [assembly: AssemblyTitle("SekiroFpsUnlockAndMore")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]