diff --git a/README.md b/README.md
index 830c11e..1e1026f 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,8 @@ Patches games memory while running, does not modify any game files. works with e
* set the game to borderless window mode
* requires "Windowed" in ingame settings first
* automatically patch game on startup
+* seamlessly switch between windowed, borderless and borderless fullscreen
+* hotkey for patching while in (borderless) window mode
## Usage
@@ -73,6 +75,7 @@ The graphic setup has to be done only once but as the patcher hot-patches the me
2. Go to `Settings -> Graphical settings -> Monitor Mode` and set it to `Windowed`
3. Set your resolution
4. Start `Sekiro FPS Unlocker and more` and enable borderless window mode
+5. If you want fullscreen borderless enable `Fullscreen stretch`
## Preview
@@ -106,7 +109,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
* jackfuste for FOV findings and running speed fix
* TyChii93#2376 for AMD and widescreen testing
-* [Darius Dan](https://www.dariusdan.com) for the icon
+* [Darius Dan](http://www.dariusdan.com) for the icon
## Limitations
@@ -115,9 +118,15 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
* your monitor has to support your custom resolution otherwise it won't show up correctly
* due to how the game renders altering FOV will not move the HUD
* the HUD is limited to 16/9 even on 21/9 resolutions
+* the hotkey won't work if the game runs in exclusive, true fullscreen mode
## Version History
+* v1.0.2 (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)
* Fixed scaling issue in borderless window mode (thanks to Spacecop42#0947 for reporting)
* v1.0.0 (2019-03-25)
diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml b/SekiroFpsUnlockAndMore/MainWindow.xaml
index 5255a8a..0fed42e 100644
--- a/SekiroFpsUnlockAndMore/MainWindow.xaml
+++ b/SekiroFpsUnlockAndMore/MainWindow.xaml
@@ -16,7 +16,8 @@
-
+
+
@@ -41,7 +42,7 @@
diff --git a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs
index 0c45d22..f3d6466 100644
--- a/SekiroFpsUnlockAndMore/MainWindow.xaml.cs
+++ b/SekiroFpsUnlockAndMore/MainWindow.xaml.cs
@@ -17,55 +17,37 @@ namespace SekiroFpsUnlockAndMore
internal const string PROCESS_NAME = "sekiro";
internal const string PROCESS_TITLE = "Sekiro";
internal const string PROCESS_DESCRIPTION = "Shadows Die Twice";
-
- internal const string PATTERN_FRAMELOCK = "00 88 88 3C 4C 89 AB 00"; // ?? 88 88 3C 4C 89 AB ?? // pattern/signature of frame rate limiter, first byte (last in mem) can can be 88/90 instead of 89 due to precision loss on floating point numbers
- internal const string PATTERN_FRAMELOCK_MASK = "?xxxxxx?"; // mask for frame rate limiter signature scanning
- internal const string PATTERN_FRAMELOCK_LONG = "44 88 6B 00 C7 43 00 89 88 88 3C 4C 89 AB 00 00 00 00"; // 44 88 6B ?? C7 43 ?? 89 88 88 3C 4C 89 AB ?? ?? ?? ??
- internal const string PATTERN_FRAMELOCK_LONG_MASK = "xxx?xx?xxxxxxx????";
- internal const int PATTERN_FRAMELOCK_LONG_OFFSET = 7;
- internal const string PATTERN_FRAMELOCK_FUZZY = "C7 43 00 00 00 00 00 4C 89 AB 00 00 00 00"; // C7 43 ?? ?? ?? ?? ?? 4C 89 AB ?? ?? ?? ??
- internal const string PATTERN_FRAMELOCK_FUZZY_MASK = "xx?????xxx????";
- internal const int PATTERN_FRAMELOCK_FUZZY_OFFSET = 3; // offset to byte array from found position
- internal const string PATTERN_FRAMELOCK_RUNNING_FIX = "F3 0F 59 05 00 30 92 02 0F 2F F8"; // F3 0F 59 05 ?? 30 92 02 0F 2F F8 | 0F 51 C2 F3 0F 59 05 ?? ?? ?? ?? 0F 2F F8
- internal const string PATTERN_FRAMELOCK_RUNNING_FIX_MASK = "xxxx?xxxxxx";
- internal const int PATTERN_FRAMELOCK_RUNNING_FIX_OFFSET = 4;
- internal const string PATTERN_RESOLUTION = "80 07 00 00 38 04"; // 1920x1080
- internal const string PATTERN_RESOLUTION_MASK = "xxxxxx";
- internal const string PATTERN_WIDESCREEN_219 = "00 47 47 8B 94 C7 1C 02 00 00"; // ?? 47 47 8B 94 C7 1C 02 00 00
- internal const string PATTERN_WIDESCREEN_219_MASK = "?xxxxxxxxx";
internal byte[] PATCH_FRAMERATE_RUNNING_FIX_DISABLE = new byte[1] { 0x90 };
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_ENABLE = new byte[1] { 0xEB };
internal byte[] PATCH_FOV_DISABLE = new byte[1] { 0x0C };
-
- // 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_MASK = "xxxxxxxx?xxx";
- internal const int PATTERN_FOVSETTING_OFFSET = 8;
- internal Dictionary _fovMatrix = new Dictionary
+ internal Dictionary PATCH_FOVMATRIX = new Dictionary
{
+ { 0x00, "- 50%" },
+ { 0x04, "- 10%" },
{ 0x10, "+ 15%" },
{ 0x14, "+ 40%" },
{ 0x18, "+ 75%" },
{ 0x1C, "+ 90%" },
};
- internal long _offset_framelock = 0x0;
- internal long _offset_framelock_running_fix = 0x0;
- internal long _offset_resolution = 0x0;
- internal long _offset_widescreen_219 = 0x0;
- internal long _offset_fovsetting = 0x0;
- internal bool _running = false;
internal Process _game;
internal IntPtr _gameHwnd = IntPtr.Zero;
internal IntPtr _gameProc = IntPtr.Zero;
internal static IntPtr _gameProcStatic;
+ internal long _offset_framelock = 0x0;
+ internal long _offset_framelock_running_fix = 0x0;
+ internal long _offset_resolution = 0x0;
+ internal long _offset_resolution_default = 0x0;
+ internal long _offset_widescreen_219 = 0x0;
+ internal long _offset_fovsetting = 0x0;
+
internal readonly DispatcherTimer _dispatcherTimerCheck = new DispatcherTimer();
+ internal bool _running = false;
internal string _logPath;
internal bool _retryAccess = true;
internal RECT _windowRect;
- internal RECT _clientRect;
public MainWindow()
{
@@ -79,8 +61,8 @@ namespace SekiroFpsUnlockAndMore
{
_logPath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\SekiroFpsUnlockAndMore.log";
- this.cbSelectFov.ItemsSource = _fovMatrix;
- this.cbSelectFov.SelectedIndex = 0;
+ this.cbSelectFov.ItemsSource = PATCH_FOVMATRIX;
+ this.cbSelectFov.SelectedIndex = 2;
IntPtr hwnd = new WindowInteropHelper(this).Handle;
if (!RegisterHotKey(hwnd, 9009, MOD_CONTROL, VK_P))
@@ -90,7 +72,7 @@ namespace SekiroFpsUnlockAndMore
ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
_dispatcherTimerCheck.Tick += new EventHandler(CheckGame);
- _dispatcherTimerCheck.Interval = new TimeSpan(0, 0, 0, 3);
+ _dispatcherTimerCheck.Interval = new TimeSpan(0, 0, 0, 2);
_dispatcherTimerCheck.Start();
}
@@ -188,11 +170,11 @@ namespace SekiroFpsUnlockAndMore
//string gameFileVersion = FileVersionInfo.GetVersionInfo(procList[0].MainModule.FileName).FileVersion;
- _offset_framelock = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, PATTERN_FRAMELOCK, PATTERN_FRAMELOCK_MASK, ' ');
+ _offset_framelock = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_FRAMELOCK, Offsets.PATTERN_FRAMELOCK_MASK, ' ');
Debug.WriteLine("1. Framelock found at: 0x" + _offset_framelock.ToString("X"));
if (!IsValid(_offset_framelock))
{
- _offset_framelock = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, PATTERN_FRAMELOCK_FUZZY, PATTERN_FRAMELOCK_FUZZY_MASK, ' ') + PATTERN_FRAMELOCK_FUZZY_OFFSET;
+ _offset_framelock = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_FRAMELOCK_FUZZY, Offsets.PATTERN_FRAMELOCK_FUZZY_MASK, ' ') + Offsets.PATTERN_FRAMELOCK_FUZZY_OFFSET;
Debug.WriteLine("2. Framelock found at: 0x" + _offset_framelock.ToString("X"));
}
if (!IsValid(_offset_framelock))
@@ -202,7 +184,7 @@ namespace SekiroFpsUnlockAndMore
this.cbUnlockFps.IsEnabled = false;
this.cbUnlockFps.IsChecked = false;
}
- _offset_framelock_running_fix = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, PATTERN_FRAMELOCK_RUNNING_FIX, PATTERN_FRAMELOCK_RUNNING_FIX_MASK, ' ') + PATTERN_FRAMELOCK_RUNNING_FIX_OFFSET;
+ _offset_framelock_running_fix = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_FRAMELOCK_RUNNING_FIX, Offsets.PATTERN_FRAMELOCK_RUNNING_FIX_MASK, ' ') + Offsets.PATTERN_FRAMELOCK_RUNNING_FIX_OFFSET;
Debug.WriteLine("Running fix found at: 0x" + _offset_framelock_running_fix.ToString("X"));
if (!IsValid(_offset_framelock_running_fix))
{
@@ -212,16 +194,16 @@ namespace SekiroFpsUnlockAndMore
this.cbAddWidescreen.IsChecked = false;
}
- _offset_resolution = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, PATTERN_RESOLUTION, PATTERN_RESOLUTION_MASK, ' ');
- Debug.WriteLine("Resolution found at: 0x" + _offset_resolution.ToString("X"));
- if (!IsValid(_offset_resolution))
+ _offset_resolution_default = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_RESOLUTION_DEFAULT, Offsets.PATTERN_RESOLUTION_DEFAULT_MASK, ' ');
+ Debug.WriteLine("Default resolution found at: 0x" + _offset_resolution_default.ToString("X"));
+ if (!IsValid(_offset_resolution_default))
{
- UpdateStatus("resolution not found...", Brushes.Red);
- LogToFile("resolution not found...");
+ UpdateStatus("default resolution not found...", Brushes.Red);
+ LogToFile("default resolution not found...");
this.cbAddWidescreen.IsEnabled = false;
this.cbAddWidescreen.IsChecked = false;
}
- _offset_widescreen_219 = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, PATTERN_WIDESCREEN_219, PATTERN_WIDESCREEN_219_MASK, ' ');
+ _offset_widescreen_219 = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_WIDESCREEN_219, Offsets.PATTERN_WIDESCREEN_219_MASK, ' ');
Debug.WriteLine("Widescreen 21/9 found at: 0x" + _offset_widescreen_219.ToString("X"));
if (!IsValid(_offset_widescreen_219))
{
@@ -231,7 +213,29 @@ namespace SekiroFpsUnlockAndMore
this.cbAddWidescreen.IsChecked = false;
}
- _offset_fovsetting = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, PATTERN_FOVSETTING, PATTERN_FOVSETTING_MASK, ' ') + PATTERN_FOVSETTING_OFFSET;
+ long offset_resolution_pointer = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_RESOLUTION_POINTER, Offsets.PATTERN_RESOLUTION_POINTER_MASK, ' ') + Offsets.PATTERN_RESOLUTION_POINTER_OFFSET;
+ Debug.WriteLine("Resolution pointer found at: 0x" + offset_resolution_pointer.ToString("X"));
+ if (!IsValid(offset_resolution_pointer))
+ {
+ UpdateStatus("Resolution pointer not found...", Brushes.Red);
+ LogToFile("Resolution pointer not found...");
+ this.cbBorderless.IsEnabled = false;
+ this.cbBorderless.IsChecked = false;
+ }
+ else
+ {
+ _offset_resolution = FindOffsetToStaticPointer(_gameProc, offset_resolution_pointer, Offsets.PATTERN_RESOLUTION_POINTER_INSTRUCTION_LENGTH);
+ Debug.WriteLine("Resolution found at: 0x" + _offset_resolution.ToString("X"));
+ if (!IsValid(_offset_resolution))
+ {
+ UpdateStatus("Resolution not valid...", Brushes.Red);
+ LogToFile("Resolution not valid...");
+ this.cbBorderless.IsEnabled = false;
+ this.cbBorderless.IsChecked = false;
+ }
+ }
+
+ _offset_fovsetting = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, Offsets.PATTERN_FOVSETTING, Offsets.PATTERN_FOVSETTING_MASK, ' ') + Offsets.PATTERN_FOVSETTING_OFFSET;
Debug.WriteLine("FOV found at: 0x" + _offset_fovsetting.ToString("X"));
if (!IsValid(_offset_fovsetting))
{
@@ -241,8 +245,6 @@ namespace SekiroFpsUnlockAndMore
this.cbFov.IsChecked = false;
}
- GetWindowRect(_gameHwnd, out _windowRect);
- GetClientRect(_gameHwnd, out _clientRect);
_running = true;
_dispatcherTimerCheck.Stop();
PatchGame();
@@ -342,14 +344,14 @@ namespace SekiroFpsUnlockAndMore
this.tbHeight.Text = "2160";
height = 2160;
}
- WriteBytes(_gameProcStatic, _offset_resolution, BitConverter.GetBytes(width));
- WriteBytes(_gameProcStatic, _offset_resolution + 4, BitConverter.GetBytes(height));
- WriteBytes(_gameProcStatic, _offset_widescreen_219, (float) width / (float) height > 1.9f ? PATCH_WIDESCREEN_219_ENABLE : PATCH_WIDESCREEN_219_DISABLE);
+ WriteBytes(_gameProcStatic, _offset_resolution_default, BitConverter.GetBytes(width));
+ WriteBytes(_gameProcStatic, _offset_resolution_default + 4, BitConverter.GetBytes(height));
+ WriteBytes(_gameProcStatic, _offset_widescreen_219, PATCH_WIDESCREEN_219_ENABLE);
}
else if (this.cbAddWidescreen.IsChecked == false)
{
- WriteBytes(_gameProcStatic, _offset_resolution, BitConverter.GetBytes(1920));
- WriteBytes(_gameProcStatic, _offset_resolution + 4, BitConverter.GetBytes(1080));
+ WriteBytes(_gameProcStatic, _offset_resolution_default, BitConverter.GetBytes(1920));
+ WriteBytes(_gameProcStatic, _offset_resolution_default + 4, BitConverter.GetBytes(1080));
WriteBytes(_gameProcStatic, _offset_widescreen_219, PATCH_WIDESCREEN_219_DISABLE);
}
@@ -366,17 +368,33 @@ namespace SekiroFpsUnlockAndMore
if (this.cbBorderless.IsChecked == true)
{
- if (!IsFullscreen(_gameHwnd))
- SetWindowBorderless(_gameHwnd);
- else
+ if (IsFullscreen(_gameHwnd))
{
MessageBox.Show("Please exit fullscreen first before activating borderless window mode.", "Sekiro FPS Unlocker and more");
this.cbBorderless.IsChecked = false;
}
+ else
+ {
+ if (!IsBorderless(_gameHwnd))
+ GetWindowRect(_gameHwnd, out _windowRect);
+ int width = Read(_gameProc, _offset_resolution);
+ int height = Read(_gameProc, _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);
+ else
+ SetWindowBorderless(_gameHwnd, width, height, _windowRect.Left, _windowRect.Top);
+ }
}
- else if (this.cbBorderless.IsChecked == false && !IsFullscreen(_gameHwnd))
+ else if (this.cbBorderless.IsChecked == false && IsBorderless(_gameHwnd))
{
- SetWindowWindowed(_gameHwnd);
+ if (_windowRect.Bottom > 0)
+ {
+ int width = _windowRect.Right - _windowRect.Left;
+ int height = _windowRect.Bottom - _windowRect.Top;
+ Debug.WriteLine(string.Format("Window Resolution: {0}x{1}", width, height));
+ SetWindowWindowed(_gameHwnd, width, height, _windowRect.Left, _windowRect.Top);
+ }
}
if (this.cbUnlockFps.IsChecked == true || this.cbAddWidescreen.IsChecked == true || this.cbFov.IsChecked == true)
@@ -408,7 +426,6 @@ namespace SekiroFpsUnlockAndMore
{
long wndStyle = GetWindowLongPtr(hwnd, GWL_STYLE).ToInt64();
long wndExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE).ToInt64();
-
if (wndStyle == 0 || wndExStyle == 0)
return false;
@@ -424,30 +441,56 @@ namespace SekiroFpsUnlockAndMore
return true;
}
+ ///
+ /// Checks if window is in borderless window mode.
+ ///
+ /// The main window handle of the window.
+ ///
+ /// Borderless windows have WS_POPUP flag set.
+ ///
+ /// True if window is run in borderless window mode.
+ private bool IsBorderless(IntPtr hwnd)
+ {
+ long wndStyle = GetWindowLongPtr(hwnd, GWL_STYLE).ToInt64();
+ if (wndStyle == 0)
+ return false;
+
+ if ((wndStyle & WS_POPUP) == 0)
+ return false;
+ if ((wndStyle & WS_CAPTION) != 0)
+ return false;
+ if ((wndStyle & WS_BORDER) != 0)
+ return false;
+
+ return true;
+ }
+
///
/// Sets a window to ordinary windowed mode
///
/// The handle to the window.
- private void SetWindowWindowed(IntPtr hwnd)
+ /// The desired window width.
+ /// The desired window height.
+ /// The desired X position of the window.
+ /// The desired Y position of the window.
+ private void SetWindowWindowed(IntPtr hwnd, int width, int height, int posX, int posY)
{
- var width = _windowRect.Right - _windowRect.Left;
- var height = _windowRect.Bottom - _windowRect.Top;
- Debug.WriteLine(string.Format("Window Resolution: {0}x{1}", width, height));
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | WS_CAPTION | WS_BORDER | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_SYSMENU | WS_GROUP | WS_MINIMIZEBOX);
- SetWindowPos(hwnd, HWND_NOTOPMOST, 40, 40, width, height, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
+ SetWindowPos(hwnd, HWND_NOTOPMOST, posX, posY, width, height, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}
///
/// Sets a window to borderless windowed mode and moves it to position 0x0.
///
/// The handle to the window.
- private void SetWindowBorderless(IntPtr hwnd)
+ /// The desired window width.
+ /// The desired window height.
+ /// The desired X position of the window.
+ /// The desired Y position of the window.
+ private void SetWindowBorderless(IntPtr hwnd, int width, int height, int posX, int posY)
{
- var width = _clientRect.Right - _clientRect.Left;
- var height = _clientRect.Bottom - _clientRect.Top;
- Debug.WriteLine(string.Format("Client Resolution: {0}x{1}", width, height));
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
- SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, width, height, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
+ SetWindowPos(hwnd, HWND_TOP, posX, posY, width, height, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}
///
@@ -460,6 +503,25 @@ namespace SekiroFpsUnlockAndMore
return (address >= 0x10000 && address < 0x000F000000000000);
}
+ ///
+ /// Reads a given type from processes memory using a generic method.
+ ///
+ /// The base type to read.
+ /// The process handle to read from.
+ /// The address to read from.
+ /// The given base type read from memory.
+ /// GCHandle and Marshal are costy.
+ private static T Read(IntPtr gameProc, Int64 lpBaseAddress)
+ {
+ byte[] lpBuffer = new byte[Marshal.SizeOf(typeof(T))];
+ IntPtr lpNumberOfBytesRead;
+ ReadProcessMemory(gameProc, lpBaseAddress, lpBuffer, (ulong)lpBuffer.Length, out lpNumberOfBytesRead);
+ GCHandle gcHandle = GCHandle.Alloc(lpBuffer, GCHandleType.Pinned);
+ T structure = (T)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(T));
+ gcHandle.Free();
+ return structure;
+ }
+
///
/// Writes a given type and value to processes memory using a generic method.
///
@@ -473,6 +535,19 @@ namespace SekiroFpsUnlockAndMore
return WriteProcessMemory(gameProc, lpBaseAddress, bytes, (ulong)bytes.Length, out lpNumberOfBytesWritten);
}
+ ///
+ /// Gets the static offset to a desired object instead of an offset to a pointer.
+ ///
+ /// Handle to the process in whose memory the pattern has been found.
+ /// The address where the pattern has been found.
+ /// The length of the instruction including the 4 bytes pointer
+ /// Static pointers in x86-64 are relative offsets from the instruction address.
+ /// The static offset from the process to desired object).
+ internal static Int64 FindOffsetToStaticPointer(IntPtr hProcess, Int64 lpPatternAddress, int instructionLength)
+ {
+ return lpPatternAddress + Read(hProcess, lpPatternAddress + (instructionLength -0x04)) + instructionLength;
+ }
+
///
/// Check whether input is numeric only.
///
@@ -509,6 +584,19 @@ namespace SekiroFpsUnlockAndMore
PatchGame();
}
+ private void CbBorderless_Checked(object sender, RoutedEventArgs e)
+ {
+ this.cbBorderlessStretch.IsEnabled = true;
+ PatchGame();
+ }
+
+ private void CbBorderless_Unchecked(object sender, RoutedEventArgs e)
+ {
+ this.cbBorderlessStretch.IsEnabled = false;
+ this.cbBorderlessStretch.IsChecked = false;
+ PatchGame();
+ }
+
private void BPatch_Click(object sender, RoutedEventArgs e)
{
PatchGame();
@@ -555,7 +643,8 @@ namespace SekiroFpsUnlockAndMore
private const uint WS_CAPTION = 0x00C00000;
private const uint WS_BORDER = 0x00800000;
private const uint WS_EX_TOPMOST = 0x00000008;
- private const uint WS_EX_WINDOWEDGE = 0x00000100;
+ private const int HWND_TOP = 0;
+ private const int HWND_TOPMOST = -1;
private const int HWND_NOTOPMOST = -2;
private const uint SWP_FRAMECHANGED = 0x0020;
private const uint SWP_SHOWWINDOW = 0x0040;
@@ -587,9 +676,6 @@ namespace SekiroFpsUnlockAndMore
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
- [DllImport("user32.dll")]
- public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
-
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
@@ -599,6 +685,14 @@ namespace SekiroFpsUnlockAndMore
public int Bottom; // y position of lower-right corner
}
+ [DllImport("kernel32.dll", SetLastError = true)]
+ private static extern Boolean ReadProcessMemory(
+ IntPtr hProcess,
+ Int64 lpBaseAddress,
+ [Out] Byte[] lpBuffer,
+ UInt64 dwSize,
+ out IntPtr lpNumberOfBytesRead);
+
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool WriteProcessMemory(
IntPtr hProcess,
diff --git a/SekiroFpsUnlockAndMore/Offsets.cs b/SekiroFpsUnlockAndMore/Offsets.cs
new file mode 100644
index 0000000..9e9d2b4
--- /dev/null
+++ b/SekiroFpsUnlockAndMore/Offsets.cs
@@ -0,0 +1,31 @@
+
+namespace SekiroFpsUnlockAndMore
+{
+ internal class Offsets
+ {
+ internal const string PATTERN_FRAMELOCK = "00 88 88 3C 4C 89 AB 00"; // ?? 88 88 3C 4C 89 AB ?? // pattern/signature of frame rate limiter, first byte (last in mem) can can be 88/90 instead of 89 due to precision loss on floating point numbers
+ internal const string PATTERN_FRAMELOCK_MASK = "?xxxxxx?"; // mask for frame rate limiter signature scanning
+ internal const string PATTERN_FRAMELOCK_LONG = "44 88 6B 00 C7 43 00 89 88 88 3C 4C 89 AB 00 00 00 00"; // 44 88 6B ?? C7 43 ?? 89 88 88 3C 4C 89 AB ?? ?? ?? ??
+ internal const string PATTERN_FRAMELOCK_LONG_MASK = "xxx?xx?xxxxxxx????";
+ internal const int PATTERN_FRAMELOCK_LONG_OFFSET = 7;
+ internal const string PATTERN_FRAMELOCK_FUZZY = "C7 43 00 00 00 00 00 4C 89 AB 00 00 00 00"; // C7 43 ?? ?? ?? ?? ?? 4C 89 AB ?? ?? ?? ??
+ internal const string PATTERN_FRAMELOCK_FUZZY_MASK = "xx?????xxx????";
+ internal const int PATTERN_FRAMELOCK_FUZZY_OFFSET = 3; // offset to byte array from found position
+ internal const string PATTERN_FRAMELOCK_RUNNING_FIX = "F3 0F 59 05 00 30 92 02 0F 2F F8"; // F3 0F 59 05 ?? 30 92 02 0F 2F F8 | 0F 51 C2 F3 0F 59 05 ?? ?? ?? ?? 0F 2F F8
+ internal const string PATTERN_FRAMELOCK_RUNNING_FIX_MASK = "xxxx?xxxxxx";
+ internal const int PATTERN_FRAMELOCK_RUNNING_FIX_OFFSET = 4;
+ internal const string PATTERN_RESOLUTION_POINTER = "0F 57 D2 89 0D 00 00 00 00 0F 57 C9 89 15 00 00 00 00"; // 0F 57 D2 89 0D ?? ?? ?? ?? 0F 57 C9 89 15 ?? ?? ?? ??
+ internal const string PATTERN_RESOLUTION_POINTER_MASK = "xxxxx????xxxxx????";
+ internal const int PATTERN_RESOLUTION_POINTER_OFFSET = 3;
+ internal const int PATTERN_RESOLUTION_POINTER_INSTRUCTION_LENGTH = 6;
+ internal const string PATTERN_RESOLUTION_DEFAULT = "80 07 00 00 38 04"; // 1920x1080
+ internal const string PATTERN_RESOLUTION_DEFAULT_MASK = "xxxxxx";
+ internal const string PATTERN_WIDESCREEN_219 = "00 47 47 8B 94 C7 1C 02 00 00"; // ?? 47 47 8B 94 C7 1C 02 00 00
+ internal const string PATTERN_WIDESCREEN_219_MASK = "?xxxxxxxxx";
+
+ // credits to jackfuste for FOV findings
+ internal const string PATTERN_FOVSETTING = "F3 0F 10 08 F3 0F 59 0D 00 E7 9B 02"; // F3 0F 10 08 F3 0F 59 0D ?? E7 9B 02
+ internal const string PATTERN_FOVSETTING_MASK = "xxxxxxxx?xxx";
+ internal const int PATTERN_FOVSETTING_OFFSET = 8;
+ }
+}
diff --git a/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs b/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs
index 8baa266..7ccf95c 100644
--- a/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs
+++ b/SekiroFpsUnlockAndMore/Properties/AssemblyInfo.cs
@@ -21,5 +21,5 @@ using System.Windows;
ResourceDictionaryLocation.SourceAssembly
)]
-[assembly: AssemblyVersion("1.0.1.0")]
-[assembly: AssemblyFileVersion("1.0.1.0")]
+[assembly: AssemblyVersion("1.0.2.0")]
+[assembly: AssemblyFileVersion("1.0.2.0")]
diff --git a/SekiroFpsUnlockAndMore/SekiroFpsUnlockAndMore.csproj b/SekiroFpsUnlockAndMore/SekiroFpsUnlockAndMore.csproj
index 074ec2a..8a3e127 100644
--- a/SekiroFpsUnlockAndMore/SekiroFpsUnlockAndMore.csproj
+++ b/SekiroFpsUnlockAndMore/SekiroFpsUnlockAndMore.csproj
@@ -76,6 +76,7 @@
+
Code