Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gui #413

Closed
wants to merge 1 commit into from
Closed

Gui #413

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Cpp2IL.Core/Utils/MiscUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ bool F2(T t)
"install.exe",
"launch.exe",
"MelonLoader.Installer.exe",
"crashpad_handler.exe"
"crashpad_handler.exe",
"EOSBootstrapper.exe",
"start_protected_game.exe"
];

public static string AnalyzeStackTracePointers(ulong[] pointers)
Expand Down
486 changes: 486 additions & 0 deletions Cpp2IL.Core/Utils/PathUtils.cs

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions Cpp2IL.Gui/App.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Cpp2IL.Gui.App"
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->

<Application.Styles>
<FluentTheme />
</Application.Styles>
</Application>
23 changes: 23 additions & 0 deletions Cpp2IL.Gui/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;

namespace Cpp2IL.Gui;

public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}

public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow();
}

base.OnFrameworkInitializationCompleted();
}
}
30 changes: 30 additions & 0 deletions Cpp2IL.Gui/Cpp2IL.Gui.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Avalonia" Version="11.0.10"/>
<PackageReference Include="Avalonia.Desktop" Version="11.0.10"/>
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.10"/>
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.0.10"/>
<!--Condition below is needed to remove Avalonia.Diagnostics package from build output in Release configuration.-->
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.10"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Cpp2IL.Core\Cpp2IL.Core.csproj" />
</ItemGroup>

<ItemGroup>
<Compile Update="Views\MainWindow.axaml.cs">
<DependentUpon>MainWindow.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
</Project>
21 changes: 21 additions & 0 deletions Cpp2IL.Gui/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Avalonia;
using System;

namespace Cpp2IL.Gui;

class Program
{
// Initialization code. Don't use any Avalonia, third-party APIs or any
// SynchronizationContext-reliant code before AppMain is called: things aren't initialized
// yet and stuff might break.
[STAThread]
public static void Main(string[] args) => BuildAvaloniaApp()
.StartWithClassicDesktopLifetime(args);

// Avalonia configuration, don't remove; also used by visual designer.
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>()
.UsePlatformDetect()
.WithInterFont()
.LogToTrace();
}
43 changes: 43 additions & 0 deletions Cpp2IL.Gui/Views/MainWindow.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<Window xmlns="https://github.com/avaloniaui"
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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Cpp2IL.Gui.MainWindow"
Title="Cpp2IL">
<Panel>
<TabControl x:Name="Tabs" Margin="2">
<TabItem Header="Game" TabIndex="0">
<Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="*">
<TextBlock Padding="50" Grid.Row="0" HorizontalAlignment="Center" FontSize="50">Cpp2IL</TextBlock>
<TextBlock Padding="10" HorizontalAlignment="Center" Grid.Row="1" FontSize="20">Select game</TextBlock>
<Grid HorizontalAlignment="Center" Grid.Row="2" ColumnDefinitions="*,*">
<Button Padding="10" Margin="10" HorizontalAlignment="Center" VerticalAlignment="Stretch"
Grid.Column="0"
Click="ShowFileBrowser">
Browse (file)
</Button>
<Button Padding="10" Margin="10" HorizontalAlignment="Center" VerticalAlignment="Stretch"
Grid.Column="1"
Click="ShowFolderBrowser">
Browse (folder)
</Button>
</Grid>
</Grid>
</TabItem>
<TabItem Header="Settings" TabIndex="1">
<Grid RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="*">
<Grid Grid.Row="0" VerticalAlignment="Center" HorizontalAlignment="Center"
ColumnDefinitions="Auto,Auto" RowDefinitions="*" Width="200">
<TextBlock VerticalAlignment="Center" Margin="10" Grid.Column="0">Output format</TextBlock>
<ComboBox x:Name="OutputFormat" Margin="10" Grid.Column="1" Width="200" MaxWidth="200"
PropertyChanged="SetOutputFormat">
</ComboBox>
</Grid>
<Button HorizontalAlignment="Center" Grid.Row="1" Click="ShowOutputFolderBrowser">Select output directory</Button>
<Button HorizontalAlignment="Center" Grid.Row="2" Click="Run">Run (this takes some time)</Button>
</Grid>
</TabItem>
</TabControl>
</Panel>
</Window>
186 changes: 186 additions & 0 deletions Cpp2IL.Gui/Views/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Platform.Storage;
using Cpp2IL.Core;
using Cpp2IL.Core.Api;
using Cpp2IL.Core.Extensions;
using Cpp2IL.Core.Logging;
using Cpp2IL.Core.Utils;

namespace Cpp2IL.Gui;

public partial class MainWindow : Window
{
private Cpp2IlRuntimeArgs _runtimeArgs;

public MainWindow()
{
InitializeComponent();

_runtimeArgs = new Cpp2IlRuntimeArgs();

Cpp2IlApi.Init();

foreach (var outputFormat in OutputFormatRegistry.AllOutputFormats)
{
var comboBoxItem = new ComboBoxItem { Content = outputFormat.OutputFormatName };
OutputFormat.Items.Add(comboBoxItem);
}

OutputFormat.SelectedIndex = 0;
}

private void Run(object? sender, RoutedEventArgs e)
{
Cpp2IlApi.ConfigureLib(false);
Cpp2IlApi.RuntimeOptions = _runtimeArgs;
_runtimeArgs.OutputFormat?.OnOutputFormatSelected();
GCSettings.LatencyMode =
_runtimeArgs.LowMemoryMode ? GCLatencyMode.Interactive : GCLatencyMode.SustainedLowLatency;
Cpp2IlApi.InitializeLibCpp2Il(_runtimeArgs.PathToAssembly, _runtimeArgs.PathToMetadata,
_runtimeArgs.UnityVersion);

if (_runtimeArgs.LowMemoryMode)
GC.Collect();

foreach (var (key, value) in _runtimeArgs.ProcessingLayerConfigurationOptions)
Cpp2IlApi.CurrentAppContext.PutExtraData(key, value);

var layers = _runtimeArgs.ProcessingLayersToRun.Clone();
RunProcessingLayers(_runtimeArgs,
processingLayer => processingLayer.PreProcess(Cpp2IlApi.CurrentAppContext, layers));
_runtimeArgs.ProcessingLayersToRun = layers;

RunProcessingLayers(_runtimeArgs, processingLayer => processingLayer.Process(Cpp2IlApi.CurrentAppContext));

if (_runtimeArgs.LowMemoryMode)
GC.Collect();

_runtimeArgs.OutputFormat.DoOutput(Cpp2IlApi.CurrentAppContext, _runtimeArgs.OutputRootDirectory);

PathUtils.CleanupExtractedFiles();
Cpp2IlPluginManager.CallOnFinish();
}

private static void RunProcessingLayers(Cpp2IlRuntimeArgs runtimeArgs, Action<Cpp2IlProcessingLayer> run)
{
foreach (var processingLayer in runtimeArgs.ProcessingLayersToRun)
{
#if !DEBUG
try
{
#endif
run(processingLayer);
#if !DEBUG
}
catch (Exception e)
{
Logger.ErrorNewline($"Processing layer {processingLayer.Id} threw an exception: {e}");
Environment.Exit(1);
}
#endif

if (runtimeArgs.LowMemoryMode)
GC.Collect();
}
}

private async void ShowOutputFolderBrowser(object? sender, RoutedEventArgs e)
{
var path = await ShowFileOrFolderPicker(true, "Select output folder");

if (string.IsNullOrEmpty(path))
return;

_runtimeArgs.OutputRootDirectory = path;
}

private void SetOutputFormat(object? sender, AvaloniaPropertyChangedEventArgs avaloniaPropertyChangedEventArgs)
{
if (OutputFormat == null || OutputFormat.SelectedIndex < 0)
return;

_runtimeArgs.OutputFormat = OutputFormatRegistry.AllOutputFormats[OutputFormat.SelectedIndex];
}

private async void ShowFileBrowser(object? sender, RoutedEventArgs e)
{
var path = await ShowFileOrFolderPicker(false, "Select game");
if (string.IsNullOrEmpty(path))
return;

try
{
PathUtils.ResolvePathsFromCommandLine(Path.GetDirectoryName(path), Path.GetFileNameWithoutExtension(path),
ref _runtimeArgs);
}
catch (Exception exception)
{
Logger.ErrorNewline(exception.ToString());
ShowPathResolveError(exception);
return;
}

ShowSettingsTab();
}

private async void ShowFolderBrowser(object? sender, RoutedEventArgs e)
{
var path = await ShowFileOrFolderPicker(true, "Select game");
if (string.IsNullOrEmpty(path))
return;
try
{
PathUtils.ResolvePathsFromCommandLine(path, null, ref _runtimeArgs);
}
catch (Exception exception)
{
Logger.ErrorNewline(exception.ToString());
ShowPathResolveError(exception);
return;
}

ShowSettingsTab();
}

private void ShowSettingsTab() => Tabs.SelectedIndex = 1;

private void ShowPathResolveError(Exception exception)
{
new MessageBox("Failed to load game! Try selecting exe instead of folder.", exception.ToString())
.ShowDialog(this);
}

private async Task<string> ShowFileOrFolderPicker(bool folderPicker, string name)
{
var topLevel = GetTopLevel(this);
if (topLevel == null)
throw new Exception("GetTopLevel(this) returned null");

IReadOnlyList<IStorageItem> item;

if (folderPicker)
{
item = await topLevel.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions()
{
AllowMultiple = false, Title = name
});
}
else
{
item = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions()
{
AllowMultiple = false, Title = name
});
}

return item.Count == 1 ? item[0].Path.LocalPath : string.Empty;
}
}
18 changes: 18 additions & 0 deletions Cpp2IL.Gui/Views/MessageBox.axaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Window xmlns="https://github.com/avaloniaui"
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"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Cpp2IL.Gui.MessageBox"
Title="Cpp2IL Error"
Width="570"
Height="350">
<Grid Margin="20" RowDefinitions="Auto,Auto,Auto" ColumnDefinitions="*">
<TextBlock x:Name="ErrorText" Grid.Row="0" HorizontalAlignment="Center" FontSize="20">Error</TextBlock>
<ScrollViewer Margin="20" Padding="20" Grid.Row="1" HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Visible" MaxHeight="200" Height="200" MaxWidth="400" Width="400">
<TextBlock x:Name="ExceptionText" Text="Exception" />
</ScrollViewer>
<Button Padding="10" Grid.Row="2" Click="Close" HorizontalAlignment="Center">OK</Button>
</Grid>
</Window>
16 changes: 16 additions & 0 deletions Cpp2IL.Gui/Views/MessageBox.axaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Avalonia.Controls;
using Avalonia.Interactivity;

namespace Cpp2IL.Gui;

public partial class MessageBox : Window
{
public MessageBox(string error, string exception)
{
InitializeComponent();
ErrorText.Text = error;
ExceptionText.Text = exception;
}

private void Close(object? sender, RoutedEventArgs e) => Close();
}
18 changes: 18 additions & 0 deletions Cpp2IL.Gui/app.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- This manifest is used on Windows only.
Don't remove it as it might cause problems with window transparency and embedded controls.
For more details visit https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests -->
<assemblyIdentity version="1.0.0.0" name="Cpp2IL.Gui.Desktop"/>

<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on
and is designed to work with. Uncomment the appropriate elements
and Windows will automatically select the most compatible environment. -->

<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
</assembly>
Loading
Loading