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

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>