initial version

This commit is contained in:
uberhalit 2019-03-25 21:25:24 +01:00
parent 44263f2c72
commit e01a01822c
16 changed files with 1275 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.vs/
*bin/
*obj/
*.ico

121
README.md Normal file
View file

@ -0,0 +1,121 @@
# Sekiro FPS Unlocker and more
A small utility to remove frame rate limit, add custom resolutions with 21/9 widescreen support, increase field of view (FOV) (credits to jackfuste) and borderless window mode for [Sekiro: Shadows Die Twice](https://www.sekirothegame.com/) written in C#.
Patches games memory while running, does not modify any game files. works with every game version (legit steam & oh-not-so-legit), should work with all future updates.
![Sekiro FPS Unlocker and more]()
## Download
[Get the latest release here](https://github.com/uberhalit/SekiroFpsUnlockAndMore/releases)
## Features
* does not modify any game files, RAM patches only
* works with legit, unmodified steam version as well as with unpacked, not-so-legit versions
* 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
* 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)
* 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
* requires "Windowed" in ingame settings first
* automatically patch game on startup
## Usage
The game enforces VSYNC and forces 60 Hz in fullscreen even on 144 Hz monitors so we have to override these.
### Follow these steps (Nvidia):
1. Open Nvidia Control Panel
2. Navigate to `Configurate 3D Settings -> Program settings`
3. Select Sekiro from the dropdown or add it manually if it's missing: `Add -> Select Sekiro`
4. **Set `Vertical sync` to `Off`**
5. **Set `Preferred refresh rate` to `Highest available`**
6. Start `Sekiro FPS Unlocker and more` and set FPS lock to your desired framerate
7. Start the game and use fullscreen or borderless window mode
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
### Or these (AMD):
1. Open Radeon Settings
2. Navigate to `Gaming -> Sekiro` or add it manually if it's missing: `Add -> Browse -> Sekiro`
3. **Set `Wait for Vertical Refresh` to `Enhanced Sync`**
4. Start `Sekiro FPS Unlocker and more` and set FPS lock to your desired frame rate
5. **Launch the game in windowed mode, then switch to fullscreen once in game**
6. The last step is important as AMD somehow does not correctly disable VSYNC otherwise
### To play the game with GSYNC do these additional steps (Nvidia):
1. Set `Monitor Technology` to `G-SYNC`
2. Make sure that `Preferred refresh rate` is still set to `Highest available`
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
4. Start `Sekiro FPS Unlocker and more` and set FPS lock to your monitors refresh rate
5. Start the game and set it to Fullscreen
6. 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.
### To add a custom resolution
1. Start the game
2. Start `Sekiro FPS Unlocker and more`, set you desired resolution and enable it by ticking the check box
3. Set your custom resolution in the graphical settings, be aware that the ingame HUD will be limited to 16/9
### To use the FOV changer
1. Start the game
2. Load up your save game
3. Start `Sekiro FPS Unlocker and more`, set you desired FOV value and enable it by ticking the check box
4. If you reload a save FOV will reset so patch game manually again
### To use borderless window mode:
1. Start the game
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
## Preview
### Unlocking frame rate:
![unlocked frame rate]()
### Increasing FOV:
![FOV increase on the fly and borderless window]()
### See it in action:
![preview]()
## Prerequisites
* .NET Framework 4.0
* administrative privileges (for patching)
* 64 bit OS
## Building
Use Visual Studio 2017 to build
## Contributing
Feel free to open an issue or create a pull request at any time
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
## Credits
* jackfuste for FOV findings and running speed fix
* TyChii93 for AMD and widescreen testing
* [Darius Dan](www.dariusdan.com) for the icon
## Limitations
* the game has forced VSYNC so unlocking the frame rate when your monitor has 60Hz will do nothing. You'll have to disable VSYNC in Nvidia Control Panel or AMD Driver first
* your monitor has to support your custom resolution otherwise it show up correctly
* due to how the game renders altering FOV will not move the HUD
* unlocking framerate and custom resolutions only work in borderless window mode or with VSYNC force disabled
## Version History
* v1.0.0 (2019-03-25)
* Initial release

View file

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.168
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SekiroFpsUnlockAndMore", "SekiroFpsUnlockAndMore\SekiroFpsUnlockAndMore.csproj", "{DDB24669-982C-44D6-8375-6176CD97B7E2}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DDB24669-982C-44D6-8375-6176CD97B7E2}.Debug|x64.ActiveCfg = Debug|x64
{DDB24669-982C-44D6-8375-6176CD97B7E2}.Debug|x64.Build.0 = Debug|x64
{DDB24669-982C-44D6-8375-6176CD97B7E2}.Release|x64.ActiveCfg = Release|x64
{DDB24669-982C-44D6-8375-6176CD97B7E2}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7EBF1A6D-0BBD-4A3E-895E-001A3A9DCD6B}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>

View file

@ -0,0 +1,9 @@
<Application x:Class="SekiroFpsUnlockAndMore.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SekiroFpsUnlockAndMore"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View file

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
namespace SekiroFpsUnlockAndMore
{
/// <summary>
/// Interaktionslogik für "App.xaml"
/// </summary>
public partial class App : Application
{
}
}

View file

@ -0,0 +1,49 @@
<Window x:Class="SekiroFpsUnlockAndMore.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SekiroFpsUnlockAndMore"
mc:Ignorable="d"
Title="Sekiro FPS Unlocker and more v1.0.0" Height="530" Width="306" ResizeMode="CanMinimize" Loaded="Window_Loaded" Closing="Window_Closing">
<Grid>
<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"/>
<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" />
<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" />
<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"/>
<CheckBox x:Name="cbBorderless" Content="Borderless window mode" HorizontalAlignment="Left" Margin="10,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"
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" />
<StackPanel HorizontalAlignment="Left" Height="305" Margin="13,195,0,0" VerticalAlignment="Top" Width="275">
<TextBlock HorizontalAlignment="Left" TextWrapping="WrapWithOverflow" VerticalAlignment="Top" FontSize="11 px" IsEnabled="False">
<TextBlock.Inlines>
<Run FontWeight="Bold">If your monitor is 60 Hz you will have to use</Run>
<Run FontWeight="Bold" Foreground="#FFF00000">fullscreen mode and force disable VSYNC</Run>
<Run FontWeight="Bold">with Nvidia Control panel or AMD Radeon Settings to get frame rate unlock working.</Run>
<Run>To avoid stuttering it's recommended to disable VSYNC even with a 144 Hz monitor.</Run>
<Run FontWeight="Bold">If your monitor is >60 Hz you will have to use</Run>
<Run FontWeight="Bold" Foreground="#FFF00000">borderless window mode or force the game to run on highest available refresh rate</Run>
<Run FontWeight="Bold">using Nvidia Control panel or AMD Radeon Settings.</Run>
<Run>Borderless window mode requires "Window mode" in game settings first.</Run>
<Run FontWeight="Bold">Custom resolution adds 21/9 support and overwrites default 1920x1080 resolution, hud will be limited to 16/9 though.</Run>
<Run>Borderless window mode with custom resolution requires you to patch and set resolution first, then add borderless patch afterwards.</Run>
<Run FontWeight="Bold">For FOV patch to work you need to be ingame.</Run>
<Run>FOV patch resets after save game reload.</Run>
<Run FontWeight="Bold" Foreground="#FFF00000">See the link below for detailed information, GSYNC support and an AMD fix.</Run>
</TextBlock.Inlines>
</TextBlock>
<Label HorizontalAlignment="Right" VerticalAlignment="Top" FontSize="12 px">
<Hyperlink NavigateUri="https://github.com/uberhalit/SekiroFpsUnlockAndMore" RequestNavigate="Hyperlink_RequestNavigate">
v1.0.0 - by uberhalit
</Hyperlink>
</Label>
</StackPanel>
</Grid>
</Window>

View file

@ -0,0 +1,600 @@
using System;
using System.IO;
using System.Windows;
using System.Diagnostics;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Interop;
using System.Windows.Threading;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace SekiroFpsUnlockAndMore
{
public partial class MainWindow : Window
{
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<byte, string> _fovMatrix = new Dictionary<byte, string>
{
{ 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 readonly DispatcherTimer _dispatcherTimerCheck = new DispatcherTimer();
internal string logPath;
internal bool retryAccess = true;
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// On window loaded.
/// </summary>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
logPath = Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + @"\SekiroFpsUnlockAndMore.log";
this.cbSelectFov.ItemsSource = _fovMatrix;
this.cbSelectFov.SelectedIndex = 0;
IntPtr hwnd = new WindowInteropHelper(this).Handle;
if (!RegisterHotKey(hwnd, 9009, MOD_CONTROL, VK_P))
MessageBox.Show("Hotkey is already in use, it may not work.", "Sekiro FPS Unlocker and more");
// add a hook for WindowsMessageQueue to recognize hotkey-press
ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcherThreadFilterMessage);
_dispatcherTimerCheck.Tick += new EventHandler(CheckGame);
_dispatcherTimerCheck.Interval = new TimeSpan(0, 0, 0, 3);
_dispatcherTimerCheck.Start();
}
/// <summary>
/// On window closing.
/// </summary>
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
ComponentDispatcher.ThreadFilterMessage -= ComponentDispatcherThreadFilterMessage;
IntPtr hwnd = new WindowInteropHelper(this).Handle;
UnregisterHotKey(hwnd, 9009);
if (_gameProc != IntPtr.Zero)
CloseHandle(_gameProc);
}
/// <summary>
/// Windows Message queue (Wndproc) to catch HotKeyPressed
/// </summary>
private void ComponentDispatcherThreadFilterMessage(ref MSG msg, ref bool handled)
{
if (!handled)
{
if (msg.message == WM_HOTKEY_MSG_ID) // hotkeyevent
{
if (msg.wParam.ToInt32() == 9009) // patch game
{
handled = true;
PatchGame();
}
}
}
}
/// <summary>
/// Checks if game is running and initializes further functionality.
/// </summary>
private void CheckGame(object sender, EventArgs e)
{
Process[] procList = Process.GetProcessesByName(PROCESS_NAME);
if (procList.Length < 1)
return;
if (_running || _offset_framelock != 0x0)
return;
int gameIndex = -1;
for (int i = 0; i < procList.Length; i++)
{
if (procList[i].MainWindowTitle == PROCESS_TITLE && procList[i].MainModule.FileVersionInfo.FileDescription.Contains(PROCESS_DESCRIPTION))
{
gameIndex = i;
break;
}
}
if (gameIndex < 0)
{
UpdateStatus("no valid game process found...", Brushes.Red);
LogToFile("no valid game process found...");
for (int j = 0; j < procList.Length; j++)
{
LogToFile(string.Format("\tProcess #{0}: '{1}' | ({2})", j, procList[j].MainModule.FileName, procList[j].MainModule.FileVersionInfo.FileName));
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));
}
return;
}
_game = procList[gameIndex];
_gameHwnd = procList[gameIndex].MainWindowHandle;
_gameProc = OpenProcess(PROCESS_ALL_ACCESS, false, (uint)procList[gameIndex].Id);
_gameProcStatic = _gameProc;
if (_gameHwnd == IntPtr.Zero || _gameProc == IntPtr.Zero || procList[gameIndex].MainModule.BaseAddress == IntPtr.Zero)
{
LogToFile("no access to game...");
LogToFile("Hwnd: " + _gameHwnd.ToString("X"));
LogToFile("Proc: " + _gameProc.ToString("X"));
LogToFile("Base: " + procList[gameIndex].MainModule.BaseAddress.ToString("X"));
if (!retryAccess)
{
UpdateStatus("no access to game...", Brushes.Red);
_dispatcherTimerCheck.Stop();
return;
}
_gameHwnd = IntPtr.Zero;
if (_gameProc != IntPtr.Zero)
{
CloseHandle(_gameProc);
_gameProc = IntPtr.Zero;
_gameProcStatic = IntPtr.Zero;
}
LogToFile("retrying...");
retryAccess = false;
return;
}
//string gameFileVersion = FileVersionInfo.GetVersionInfo(procList[0].MainModule.FileName).FileVersion;
_offset_framelock = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, PATTERN_FRAMELOCK, 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;
Debug.WriteLine("2. Framelock found at: 0x" + _offset_framelock.ToString("X"));
}
if (!IsValid(_offset_framelock))
{
UpdateStatus("framelock not found...", Brushes.Red);
LogToFile("framelock not found...");
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;
Debug.WriteLine("Running fix found at: 0x" + _offset_framelock_running_fix.ToString("X"));
if (!IsValid(_offset_framelock_running_fix))
{
UpdateStatus("running fix not found...", Brushes.Red);
LogToFile("running fix not found...");
this.cbAddWidescreen.IsEnabled = false;
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))
{
UpdateStatus("resolution not found...", Brushes.Red);
LogToFile("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, ' ');
Debug.WriteLine("Widescreen 21/9 found at: 0x" + _offset_widescreen_219.ToString("X"));
if (!IsValid(_offset_widescreen_219))
{
UpdateStatus("widescreen 21/9 not found...", Brushes.Red);
LogToFile("Widescreen 21/9 not found...");
this.cbAddWidescreen.IsEnabled = false;
this.cbAddWidescreen.IsChecked = false;
}
_offset_fovsetting = PatternScan.FindPattern(_gameProc, procList[gameIndex].MainModule, PATTERN_FOVSETTING, PATTERN_FOVSETTING_MASK, ' ') + PATTERN_FOVSETTING_OFFSET;
Debug.WriteLine("FOV found at: 0x" + _offset_fovsetting.ToString("X"));
if (!IsValid(_offset_fovsetting))
{
UpdateStatus("FOV not found...", Brushes.Red);
LogToFile("FOV not found...");
this.cbFov.IsEnabled = false;
this.cbFov.IsChecked = false;
}
_running = true;
_dispatcherTimerCheck.Stop();
PatchGame();
}
/// <summary>
/// Patch up this broken port
/// </summary>
private void PatchGame()
{
if (!_running)
return;
if (_game.HasExited)
{
_running = false;
_gameHwnd = IntPtr.Zero;
_gameProc = IntPtr.Zero;
_gameProcStatic = IntPtr.Zero;
_offset_framelock = 0x0;
_offset_framelock_running_fix = 0x0;
_offset_resolution = 0x0;
_offset_widescreen_219 = 0x0;
_offset_fovsetting = 0x0;
UpdateStatus("waiting for game...", Brushes.White);
_dispatcherTimerCheck.Start();
return;
}
if (this.cbUnlockFps.IsChecked == true)
{
int fps = -1;
bool isNumber = Int32.TryParse(this.tbFps.Text, out fps);
if (fps < 0 || !isNumber)
{
this.tbFps.Text = "60";
fps = 60;
}
else if (fps > 0 && fps < 30)
{
this.tbFps.Text = "30";
fps = 30;
}
else if (fps > 300)
{
this.tbFps.Text = "300";
fps = 300;
}
if (fps == 0)
{
WriteBytes(_gameProcStatic, _offset_framelock, PATCH_FRAMERATE_UNLIMITED);
WriteBytes(_gameProcStatic, _offset_framelock_running_fix, new byte[1] { 0xF8 }); // F8 is maximum
}
else
{
int speed = 144 + (int)Math.Ceiling((fps - 60) / 16f) * 8; // calculation from game functions
if (speed > 248)
speed = 248;
float deltaTime = (1000f / fps) / 1000f;
Debug.WriteLine("Deltatime hex: 0x" + getHexRepresentationFromFloat(deltaTime));
Debug.WriteLine("Speed hex: 0x" + speed.ToString("X"));
WriteBytes(_gameProcStatic, _offset_framelock, BitConverter.GetBytes(deltaTime));
WriteBytes(_gameProcStatic, _offset_framelock_running_fix, new byte[] { (byte)Convert.ToInt16(speed) });
}
}
else if (this.cbUnlockFps.IsChecked == false)
{
float deltaTime = (1000f / 60) / 1000f;
WriteBytes(_gameProcStatic, _offset_framelock, BitConverter.GetBytes(deltaTime));
WriteBytes(_gameProcStatic, _offset_framelock_running_fix, PATCH_FRAMERATE_RUNNING_FIX_DISABLE);
}
if (this.cbAddWidescreen.IsChecked == true)
{
int width = -1;
bool isNumber = Int32.TryParse(this.tbWidth.Text, out width);
if (width < 800 || !isNumber)
{
this.tbWidth.Text = "2560";
width = 2560;
}
else if (width > 5760)
{
this.tbWidth.Text = "5760";
width = 5760;
}
int height = -1;
isNumber = Int32.TryParse(this.tbHeight.Text, out height);
if (height < 450 || !isNumber)
{
this.tbHeight.Text = "1080";
height = 1080;
}
else if (height > 2160)
{
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);
}
else if (this.cbAddWidescreen.IsChecked == false)
{
WriteBytes(_gameProcStatic, _offset_resolution, BitConverter.GetBytes(1920));
WriteBytes(_gameProcStatic, _offset_resolution + 4, BitConverter.GetBytes(1080));
WriteBytes(_gameProcStatic, _offset_widescreen_219, PATCH_WIDESCREEN_219_DISABLE);
}
if (this.cbFov.IsChecked == true)
{
byte[] fovByte = new byte[1];
fovByte[0] = ((KeyValuePair<byte, string>) this.cbSelectFov.SelectedItem).Key;
WriteBytes(_gameProcStatic, _offset_fovsetting, fovByte);
}
else if (this.cbFov.IsChecked == false)
{
WriteBytes(_gameProcStatic, _offset_fovsetting, PATCH_FOV_DISABLE);
}
if (this.cbBorderless.IsChecked == true)
{
if (!IsFullscreen(_gameHwnd))
SetWindowBorderless(_gameHwnd);
else
{
MessageBox.Show("Please exit fullscreen first before activating borderless window mode.", "Sekiro FPS Unlocker and more");
this.cbBorderless.IsChecked = false;
}
}
else if (this.cbBorderless.IsChecked == false && !IsFullscreen(_gameHwnd))
{
SetWindowWindowed(_gameHwnd);
}
if (this.cbUnlockFps.IsChecked == true || this.cbAddWidescreen.IsChecked == true || this.cbFov.IsChecked == true)
UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game patched!", Brushes.Green);
else
UpdateStatus(DateTime.Now.ToString("HH:mm:ss") + " Game unpatched!", Brushes.White);
}
/// <summary>
/// Returns the hexadecimal representation of an IEEE-754 floating point number
/// </summary>
/// <param name="input">The floating point number</param>
/// <returns>The hexadecimal representation of the input</returns>
private string getHexRepresentationFromFloat(float input)
{
uint f = BitConverter.ToUInt32(BitConverter.GetBytes(input), 0);
return "0x" + f.ToString("X8");
}
/// <summary>
/// Checks if window is in fullscreen mode.
/// </summary>
/// <param name="hwnd">The main window handle of the window.</param>
/// <remarks>
/// Fullscreen windows have WS_EX_TOPMOST flag set.
/// </remarks>
/// <returns>True if window is run in fullscreen mode.</returns>
private bool IsFullscreen(IntPtr hwnd)
{
long wndStyle = GetWindowLongPtr(hwnd, GWL_STYLE).ToInt64();
long wndExStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE).ToInt64();
if (wndStyle == 0 || wndExStyle == 0)
return false;
if ((wndExStyle & WS_EX_TOPMOST) == 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;
}
/// <summary>
/// Sets a window to ordinary windowed mode
/// </summary>
/// <param name="hwnd">The handle to the window.</param>
private void SetWindowWindowed(IntPtr hwnd)
{
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | WS_CAPTION | WS_BORDER | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_SYSMENU | WS_GROUP | WS_MINIMIZEBOX);
}
/// <summary>
/// Sets a window to borderless windowed mode and moves it to position 0x0.
/// </summary>
/// <param name="hwnd">The handle to the window.</param>
private void SetWindowBorderless(IntPtr hwnd)
{
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
RECT rect;
GetWindowRect(hwnd, out rect);
SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, rect.Right - rect.Left, rect.Bottom - rect.Top, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}
/// <summary>
/// Checks if a pointer is valid.
/// </summary>
/// <param name="address">The address the pointer points to.</param>
/// <returns>True if pointer points to a valid address.</returns>
private static bool IsValid(Int64 address)
{
return (address >= 0x10000 && address < 0x000F000000000000);
}
/// <summary>
/// Writes a given type and value to processes memory using a generic method.
/// </summary>
/// <param name="gameProc">The process handle to read from.</param>
/// <param name="lpBaseAddress">The address to write from.</param>
/// <param name="bytes">The byte array to write.</param>
/// <returns>True if successful, false otherwise.</returns>
private static bool WriteBytes(IntPtr gameProc, Int64 lpBaseAddress, byte[] bytes)
{
IntPtr lpNumberOfBytesWritten;
return WriteProcessMemory(gameProc, lpBaseAddress, bytes, (ulong)bytes.Length, out lpNumberOfBytesWritten);
}
/// <summary>
/// Check whether input is numeric only.
/// </summary>
/// <param name="text">The text to check.</param>
/// <returns>True if inout is numeric only.</returns>
private bool IsNumericInput(string text)
{
return Regex.IsMatch(text, "[^0-9]+");
}
private void UpdateStatus(string text, Brush color)
{
this.tbStatus.Background = color;
this.tbStatus.Text = text;
}
private void Numeric_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = IsNumericInput(e.Text);
}
private void Numeric_PastingHandler(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(String)))
{
String text = (String)e.DataObject.GetData(typeof(String));
if (IsNumericInput(text)) e.CancelCommand();
}
else e.CancelCommand();
}
private void CheckBoxChanged_Handler(object sender, RoutedEventArgs e)
{
PatchGame();
}
private void BPatch_Click(object sender, RoutedEventArgs e)
{
PatchGame();
}
private void Hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
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
private const int WM_HOTKEY_MSG_ID = 0x0312;
private const int MOD_CONTROL = 0x0002;
private const uint VK_P = 0x0050;
private const uint PROCESS_ALL_ACCESS = 0x001F0FFF;
private const int GWL_EXSTYLE = -20;
private const int GWL_STYLE = -16;
private const uint WS_CLIPSIBLINGS = 0x04000000;
private const uint WS_DLGFRAME = 0x00400000;
private const uint WS_SYSMENU = 0x00080000;
private const uint WS_GROUP = 0x00020000;
private const uint WS_MINIMIZEBOX = 0x00020000;
private const uint WS_POPUP = 0x80000000;
private const uint WS_VISIBLE = 0x10000000;
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_NOTOPMOST = -2;
private const uint SWP_FRAMECHANGED = 0x0020;
private const uint SWP_SHOWWINDOW = 0x0040;
[DllImport("user32.dll")]
public static extern Boolean RegisterHotKey(IntPtr hWnd, Int32 id, UInt32 fsModifiers, UInt32 vlc);
[DllImport("user32.dll")]
public static extern Boolean UnregisterHotKey(IntPtr hWnd, Int32 id);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr OpenProcess(
UInt32 dwDesiredAccess,
Boolean bInheritHandle,
UInt32 dwProcessId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern Boolean CloseHandle(IntPtr hObject);
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr GetWindowLongPtr(IntPtr hWnd, Int32 nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, Int32 nIndex, Int64 dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
public static extern IntPtr SetWindowPos(IntPtr hWnd, Int32 hWndInsertAfter, Int32 X, Int32 Y, Int32 cx, Int32 cy, UInt32 uFlags);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern bool WriteProcessMemory(
IntPtr hProcess,
Int64 lpBaseAddress,
[In, Out] Byte[] lpBuffer,
UInt64 dwSize,
out IntPtr lpNumberOfBytesWritten);
#endregion
}
}

View file

@ -0,0 +1,79 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace SekiroFpsUnlockAndMore
{
class PatternScan
{
/// <summary>
/// Finds a pattern or signature inside another process's memory.
/// </summary>
/// <param name="hProcess">Handle to the process in whose memory pattern will be searched for.</param>
/// <param name="pModule">Module which will be searched for the pattern.</param>
/// <param name="szPattern">A character-delimited string representing the pattern to be found.</param>
/// <param name="szMask">A string of 'x' (match), '!' (not-match), or '?' (wildcard).</param>
/// <param name="cDelimiter">Determines how the string will be split. If null, defaults to ' '.</param>
/// <returns>The address of the beginning of the pattern if found, 0 if not found</returns>
internal static Int64 FindPattern(IntPtr hProcess, ProcessModule pModule, string szPattern, string szMask, char cDelimiter = ' ')
{
string[] saPattern = szPattern.Split(cDelimiter);
byte[] bPattern = new byte[saPattern.Length];
for (int i = 0; i < saPattern.Length; i++)
bPattern[i] = Convert.ToByte(saPattern[i], 0x10);
if (bPattern == null || bPattern.Length == 0)
throw new ArgumentNullException("Pattern's length is zero!");
if (bPattern.Length != szMask.Length)
throw new ArgumentException("Pattern's bytes and szMask must be of the same size!");
long dwStart = 0;
if (IntPtr.Size == 4)
dwStart = (uint)pModule.BaseAddress;
else if (IntPtr.Size == 8)
dwStart = (long)pModule.BaseAddress;
int nSize = pModule.ModuleMemorySize;
IntPtr lpNumberOfBytesRead;
byte[] bData = new byte[nSize];
if (!ReadProcessMemory(hProcess, dwStart, bData, nSize, out lpNumberOfBytesRead))
throw new Exception("ReadProcessMemory error!");
if (lpNumberOfBytesRead.ToInt64() != nSize)
throw new Exception("ReadProcessMemory error!");
if (bData == null || bData.Length == 0)
throw new Exception("Could not read memory in FindPattern.");
long ix;
int iy;
bool bFound = false;
int patternLength = bPattern.Length;
int dataLength = bData.Length - patternLength;
for (ix = 0; ix < dataLength; ix++)
{
bFound = true;
for (iy = 0; iy < patternLength; iy++)
{
if ((szMask[iy] == 'x' && bPattern[iy] != bData[ix + iy]) ||
(szMask[iy] == '!' && bPattern[iy] == bData[ix + iy]))
{
bFound = false;
break;
}
}
if (bFound)
return Convert.ToInt64((long)dwStart + ix);
}
return 0;
}
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadProcessMemory(
IntPtr hProcess,
Int64 lpBaseAddress,
[Out] Byte[] lpBuffer,
Int64 dwSize,
out IntPtr lpNumberOfBytesRead);
}
}

View file

@ -0,0 +1,25 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
[assembly: AssemblyTitle("SekiroFpsUnlockAndMore")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SekiroFpsUnlockAndMore")]
[assembly: AssemblyCopyright("Copyright © uberhalit 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None,
ResourceDictionaryLocation.SourceAssembly
)]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SekiroFpsUnlockAndMore.Properties {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SekiroFpsUnlockAndMore.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View file

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View file

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SekiroFpsUnlockAndMore.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View file

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View file

@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DDB24669-982C-44D6-8375-6176CD97B7E2}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>SekiroFpsUnlockAndMore</RootNamespace>
<AssemblyName>SekiroFpsUnlockAndMore</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="PatternScan.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="app.manifest" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Resource Include="icon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
</application>
</compatibility>
</assembly>