diff --git a/Ryujinx.Ava/AppHost.cs b/Ryujinx.Ava/AppHost.cs
index 2cf53ef691..5a0910e870 100644
--- a/Ryujinx.Ava/AppHost.cs
+++ b/Ryujinx.Ava/AppHost.cs
@@ -1,4 +1,6 @@
 using ARMeilleure.Translation;
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Input;
 using Avalonia.Threading;
 using LibHac.Tools.FsSystem;
@@ -13,6 +15,7 @@ using Ryujinx.Ava.Input;
 using Ryujinx.Ava.UI.Controls;
 using Ryujinx.Ava.UI.Helpers;
 using Ryujinx.Ava.UI.Models;
+using Ryujinx.Ava.UI.ViewModels;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common;
 using Ryujinx.Common.Configuration;
@@ -42,7 +45,7 @@ using System.Diagnostics;
 using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
-
+using Image = SixLabors.ImageSharp.Image;
 using InputManager = Ryujinx.Input.HLE.InputManager;
 using Key = Ryujinx.Input.Key;
 using MouseButton = Ryujinx.Input.MouseButton;
@@ -67,7 +70,7 @@ namespace Ryujinx.Ava
         private readonly AccountManager _accountManager;
         private readonly UserChannelPersistence _userChannelPersistence;
         private readonly InputManager _inputManager;
-        private readonly MainWindow _parent;
+        private readonly MainWindowViewModel _viewModel;
         private readonly IKeyboard _keyboardInterface;
         private readonly GraphicsDebugLevel _glLogLevel;
 
@@ -110,6 +113,7 @@ namespace Ryujinx.Ava
         public bool ScreenshotRequested { get; set; }
 
         private object _lockObject = new();
+        private TopLevel _topLevel;
 
         public AppHost(
             RendererHost renderer,
@@ -119,9 +123,10 @@ namespace Ryujinx.Ava
             ContentManager contentManager,
             AccountManager accountManager,
             UserChannelPersistence userChannelPersistence,
-            MainWindow parent)
+            MainWindowViewModel viewmodel,
+            TopLevel topLevel)
         {
-            _parent = parent;
+            _viewModel = viewmodel;
             _inputManager = inputManager;
             _accountManager = accountManager;
             _userChannelPersistence = userChannelPersistence;
@@ -129,7 +134,8 @@ namespace Ryujinx.Ava
             _hideCursorOnIdle = ConfigurationState.Instance.HideCursorOnIdle;
             _lastCursorMoveTime = Stopwatch.GetTimestamp();
             _glLogLevel = ConfigurationState.Instance.Logger.GraphicsDebugLevel;
-            _inputManager.SetMouseDriver(new AvaloniaMouseDriver(_parent, renderer));
+            _topLevel = topLevel;
+            _inputManager.SetMouseDriver(new AvaloniaMouseDriver(_topLevel, renderer));
             _keyboardInterface = (IKeyboard)_inputManager.KeyboardDriver.GetGamepad("0");
 
             NpadManager = _inputManager.CreateNpadManager();
@@ -144,15 +150,15 @@ namespace Ryujinx.Ava
 
             if (ApplicationPath.StartsWith("@SystemContent"))
             {
-                ApplicationPath = _parent.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
+                ApplicationPath = _viewModel.VirtualFileSystem.SwitchPathToSystemPath(ApplicationPath);
 
                 _isFirmwareTitle = true;
             }
 
             ConfigurationState.Instance.HideCursorOnIdle.Event += HideCursorState_Changed;
 
-            _parent.PointerLeave += Parent_PointerLeft;
-            _parent.PointerMoved += Parent_PointerMoved;
+            _topLevel.PointerLeave += TopLevel_PointerLeave;
+            _topLevel.PointerMoved += TopLevel_PointerMoved;
 
             ConfigurationState.Instance.System.IgnoreMissingServices.Event += UpdateIgnoreMissingServicesState;
             ConfigurationState.Instance.Graphics.AspectRatio.Event += UpdateAspectRatioState;
@@ -162,25 +168,27 @@ namespace Ryujinx.Ava
             _gpuCancellationTokenSource = new CancellationTokenSource();
         }
 
-        private void Parent_PointerMoved(object sender, PointerEventArgs e)
+        private void TopLevel_PointerMoved(object sender, PointerEventArgs e)
         {
-            _lastCursorMoveTime = Stopwatch.GetTimestamp();
-            var p = e.GetCurrentPoint(_parent).Position;
-            var r = _parent.InputHitTest(p);
-            _isMouseInRenderer = r == Renderer;
+            if (sender is Control visual)
+            {
+                _lastCursorMoveTime = Stopwatch.GetTimestamp();
+                var point = e.GetCurrentPoint(visual).Position;
+                _isMouseInRenderer = Equals(visual.InputHitTest(point), Renderer);
+            }
         }
 
-        private void Parent_PointerLeft(object sender, PointerEventArgs e)
+        private void TopLevel_PointerLeave(object sender, PointerEventArgs e)
         {
             _isMouseInRenderer = false;
-            _parent.Cursor = Cursor.Default;
+            _viewModel.Cursor = Cursor.Default;
         }
 
         private void SetRendererWindowSize(Size size)
         {
             if (_renderer != null)
             {
-                double scale = _parent.PlatformImpl.RenderScaling;
+                double scale = _topLevel.PlatformImpl.RenderScaling;
                 _renderer.Window?.SetSize((int)(size.Width * scale), (int)(size.Height * scale));
             }
         }
@@ -256,7 +264,7 @@ namespace Ryujinx.Ava
             NpadManager.Initialize(Device, ConfigurationState.Instance.Hid.InputConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
             TouchScreenManager.Initialize(Device);
 
-            _parent.ViewModel.IsGameRunning = true;
+            _viewModel.IsGameRunning = true;
 
             string titleNameSection = string.IsNullOrWhiteSpace(Device.Application.TitleName)
                 ? string.Empty
@@ -276,10 +284,10 @@ namespace Ryujinx.Ava
 
             Dispatcher.UIThread.InvokeAsync(() =>
             {
-                _parent.Title = $"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
+                _viewModel.Title = $"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}";
             });
 
-            _parent.ViewModel.SetUiProgressHandlers(Device);
+            _viewModel.SetUIProgressHandlers(Device);
 
             Renderer.SizeChanged += Window_SizeChanged;
 
@@ -287,7 +295,7 @@ namespace Ryujinx.Ava
 
             _renderingThread.Start();
 
-            _parent.ViewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
+            _viewModel.Volume = ConfigurationState.Instance.System.AudioVolume.Value;
 
             MainLoop();
 
@@ -321,7 +329,7 @@ namespace Ryujinx.Ava
             Dispatcher.UIThread.Post(() =>
             {
                 var value = e.NewValue;
-                _parent.ViewModel.Volume = e.NewValue;
+                _viewModel.Volume = e.NewValue;
             });
         }
 
@@ -369,7 +377,7 @@ namespace Ryujinx.Ava
         {
             if (Device.Application != null)
             {
-                _parent.UpdateGameMetadata(Device.Application.TitleIdText);
+                _viewModel.UpdateGameMetadata(Device.Application.TitleIdText);
             }
 
             ConfigurationState.Instance.System.IgnoreMissingServices.Event -= UpdateIgnoreMissingServicesState;
@@ -377,6 +385,9 @@ namespace Ryujinx.Ava
             ConfigurationState.Instance.System.EnableDockedMode.Event -= UpdateDockedModeState;
             ConfigurationState.Instance.System.AudioVolume.Event -= UpdateAudioVolumeState;
 
+            _topLevel.PointerLeave -= TopLevel_PointerLeave;
+            _topLevel.PointerMoved -= TopLevel_PointerMoved;
+
             _gpuCancellationTokenSource.Cancel();
             _gpuCancellationTokenSource.Dispose();
 
@@ -410,7 +421,7 @@ namespace Ryujinx.Ava
                 }
                 else
                 {
-                    _parent.Cursor = Cursor.Default;
+                    _viewModel.Cursor = Cursor.Default;
                 }
             });
         }
@@ -422,57 +433,65 @@ namespace Ryujinx.Ava
 
             SystemVersion firmwareVersion = ContentManager.GetCurrentFirmwareVersion();
 
-            if (!SetupValidator.CanStartApplication(ContentManager, ApplicationPath, out UserError userError))
+            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
-                if (SetupValidator.CanFixStartApplication(ContentManager, ApplicationPath, userError, out firmwareVersion))
+                if (!SetupValidator.CanStartApplication(ContentManager, ApplicationPath, out UserError userError))
                 {
-                    if (userError == UserError.NoFirmware)
                     {
-                        UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
-                            LocaleManager.Instance[LocaleKeys.DialogFirmwareNoFirmwareInstalledMessage],
-                            string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallEmbeddedMessage], firmwareVersion.VersionString),
-                            LocaleManager.Instance[LocaleKeys.InputDialogYes],
-                            LocaleManager.Instance[LocaleKeys.InputDialogNo],
-                            "");
-
-                        if (result != UserResult.Yes)
+                        if (SetupValidator.CanFixStartApplication(ContentManager, ApplicationPath, userError, out firmwareVersion))
                         {
-                            await UserErrorDialog.ShowUserErrorDialog(userError, _parent);
+                            if (userError == UserError.NoFirmware)
+                            {
+                                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
+                                    LocaleManager.Instance[LocaleKeys.DialogFirmwareNoFirmwareInstalledMessage],
+                                    string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallEmbeddedMessage],
+                                    firmwareVersion.VersionString),
+                                    LocaleManager.Instance[LocaleKeys.InputDialogYes],
+                                    LocaleManager.Instance[LocaleKeys.InputDialogNo],
+                                    "");
+
+                                if (result != UserResult.Yes)
+                                {
+                                    await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow));
+                                    Device.Dispose();
+
+                                    return false;
+                                }
+                            }
+
+                            if (!SetupValidator.TryFixStartApplication(ContentManager, ApplicationPath, userError, out _))
+                            {
+                                await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow));
+                                Device.Dispose();
+
+                                return false;
+                            }
+
+                            // Tell the user that we installed a firmware for them.
+                            if (userError == UserError.NoFirmware)
+                            {
+                                firmwareVersion = ContentManager.GetCurrentFirmwareVersion();
+
+                                _viewModel.RefreshFirmwareStatus();
+
+                                await ContentDialogHelper.CreateInfoDialog(
+                                    string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstalledMessage],
+                                    firmwareVersion.VersionString),
+                                    string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallEmbeddedSuccessMessage],
+                                    firmwareVersion.VersionString),
+                                    LocaleManager.Instance[LocaleKeys.InputDialogOk],
+                                    "",
+                                    LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
+                            }
+                        }
+                        else
+                        {
+                            await UserErrorDialog.ShowUserErrorDialog(userError, (desktop.MainWindow as MainWindow));
                             Device.Dispose();
 
                             return false;
                         }
                     }
-
-                    if (!SetupValidator.TryFixStartApplication(ContentManager, ApplicationPath, userError, out _))
-                    {
-                        await UserErrorDialog.ShowUserErrorDialog(userError, _parent);
-                        Device.Dispose();
-
-                        return false;
-                    }
-
-                    // Tell the user that we installed a firmware for them.
-                    if (userError == UserError.NoFirmware)
-                    {
-                        firmwareVersion = ContentManager.GetCurrentFirmwareVersion();
-
-                        _parent.RefreshFirmwareStatus();
-
-                        await ContentDialogHelper.CreateInfoDialog(
-                            string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstalledMessage], firmwareVersion.VersionString),
-                            string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallEmbeddedSuccessMessage], firmwareVersion.VersionString),
-                            LocaleManager.Instance[LocaleKeys.InputDialogOk],
-                            "",
-                            LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
-                    }
-                }
-                else
-                {
-                    await UserErrorDialog.ShowUserErrorDialog(userError, _parent);
-                    Device.Dispose();
-
-                    return false;
                 }
             }
 
@@ -567,7 +586,7 @@ namespace Ryujinx.Ava
 
             DiscordIntegrationModule.SwitchToPlayingState(Device.Application.TitleIdText, Device.Application.TitleName);
 
-            _parent.ApplicationLibrary.LoadAndSaveMetaData(Device.Application.TitleIdText, appMetadata =>
+            _viewModel.ApplicationLibrary.LoadAndSaveMetaData(Device.Application.TitleIdText, appMetadata =>
             {
                 appMetadata.LastPlayed = DateTime.UtcNow.ToString();
             });
@@ -578,13 +597,13 @@ namespace Ryujinx.Ava
         internal void Resume()
         {
             Device?.System.TogglePauseEmulation(false);
-            _parent.ViewModel.IsPaused = false;
+            _viewModel.IsPaused = false;
         }
 
         internal void Pause()
         {
             Device?.System.TogglePauseEmulation(true);
-            _parent.ViewModel.IsPaused = true;
+            _viewModel.IsPaused = true;
         }
 
         private void InitializeSwitchInstance()
@@ -632,7 +651,7 @@ namespace Ryujinx.Ava
                         Logger.Warning?.Print(LogClass.Audio, "Found OpenAL, changing configuration.");
 
                         ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.OpenAl;
-                        MainWindow.SaveConfig();
+                        MainWindowViewModel.SaveConfig();
 
                         deviceDriver = new OpenALHardwareDeviceDriver();
                     }
@@ -645,7 +664,7 @@ namespace Ryujinx.Ava
                             Logger.Warning?.Print(LogClass.Audio, "Found SoundIO, changing configuration.");
 
                             ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SoundIo;
-                            MainWindow.SaveConfig();
+                            MainWindowViewModel.SaveConfig();
 
                             deviceDriver = new SoundIoHardwareDeviceDriver();
                         }
@@ -671,7 +690,7 @@ namespace Ryujinx.Ava
                         Logger.Warning?.Print(LogClass.Audio, "Found SDL2, changing configuration.");
 
                         ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SDL2;
-                        MainWindow.SaveConfig();
+                        MainWindowViewModel.SaveConfig();
 
                         deviceDriver = new SDL2HardwareDeviceDriver();
                     }
@@ -684,7 +703,7 @@ namespace Ryujinx.Ava
                             Logger.Warning?.Print(LogClass.Audio, "Found OpenAL, changing configuration.");
 
                             ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.OpenAl;
-                            MainWindow.SaveConfig();
+                            MainWindowViewModel.SaveConfig();
 
                             deviceDriver = new OpenALHardwareDeviceDriver();
                         }
@@ -710,7 +729,7 @@ namespace Ryujinx.Ava
                         Logger.Warning?.Print(LogClass.Audio, "Found SDL2, changing configuration.");
 
                         ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SDL2;
-                        MainWindow.SaveConfig();
+                        MainWindowViewModel.SaveConfig();
 
                         deviceDriver = new SDL2HardwareDeviceDriver();
                     }
@@ -723,7 +742,7 @@ namespace Ryujinx.Ava
                             Logger.Warning?.Print(LogClass.Audio, "Found SoundIO, changing configuration.");
 
                             ConfigurationState.Instance.System.AudioBackend.Value = AudioBackend.SoundIo;
-                            MainWindow.SaveConfig();
+                            MainWindowViewModel.SaveConfig();
 
                             deviceDriver = new SoundIoHardwareDeviceDriver();
                         }
@@ -740,14 +759,14 @@ namespace Ryujinx.Ava
             IntegrityCheckLevel fsIntegrityCheckLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None;
 
             HLE.HLEConfiguration configuration = new HLE.HLEConfiguration(VirtualFileSystem,
-                                                                          _parent.LibHacHorizonManager,
+                                                                          _viewModel.LibHacHorizonManager,
                                                                           ContentManager,
                                                                           _accountManager,
                                                                           _userChannelPersistence,
                                                                           renderer,
                                                                           deviceDriver,
                                                                           memoryConfiguration,
-                                                                          _parent.UiHandler,
+                                                                          _viewModel.UiHandler,
                                                                           (SystemLanguage)ConfigurationState.Instance.System.Language.Value,
                                                                           (RegionCode)ConfigurationState.Instance.System.Region.Value,
                                                                           ConfigurationState.Instance.Graphics.EnableVsync,
@@ -788,14 +807,14 @@ namespace Ryujinx.Ava
         {
             Dispatcher.UIThread.InvokeAsync(() =>
             {
-                if (_parent.ViewModel.StartGamesInFullscreen)
+                if (_viewModel.StartGamesInFullscreen)
                 {
-                    _parent.WindowState = WindowState.FullScreen;
+                    _viewModel.WindowState = WindowState.FullScreen;
                 }
 
-                if (_parent.WindowState == WindowState.FullScreen)
+                if (_viewModel.WindowState == WindowState.FullScreen)
                 {
-                    _parent.ViewModel.ShowMenuAndStatusBar = false;
+                    _viewModel.ShowMenuAndStatusBar = false;
                 }
             });
 
@@ -819,7 +838,7 @@ namespace Ryujinx.Ava
             Width = (int)Renderer.Bounds.Width;
             Height = (int)Renderer.Bounds.Height;
 
-            _renderer.Window.SetSize((int)(Width * _parent.PlatformImpl.RenderScaling), (int)(Height * _parent.PlatformImpl.RenderScaling));
+            _renderer.Window.SetSize((int)(Width * _topLevel.PlatformImpl.RenderScaling), (int)(Height * _topLevel.PlatformImpl.RenderScaling));
 
             _chrono.Start();
 
@@ -847,7 +866,7 @@ namespace Ryujinx.Ava
                         if (!_renderingStarted)
                         {
                             _renderingStarted = true;
-                            _parent.SwitchToGameControl();
+                            _viewModel.SwitchToRenderer(false);
                         }
 
                         Device.PresentFrame(() => Renderer?.SwapBuffers());
@@ -914,7 +933,7 @@ namespace Ryujinx.Ava
             {
                 Dispatcher.UIThread.Post(() =>
                 {
-                    _parent.Cursor = _isMouseInRenderer ? InvisibleCursor : Cursor.Default;
+                    _viewModel.Cursor = _isMouseInRenderer ? InvisibleCursor : Cursor.Default;
                 });
             }
             else
@@ -925,7 +944,7 @@ namespace Ryujinx.Ava
 
                     Dispatcher.UIThread.Post(() =>
                     {
-                        _parent.Cursor = cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency ? InvisibleCursor : Cursor.Default;
+                        _viewModel.Cursor = cursorMoveDelta >= CursorHideIdleTime * Stopwatch.Frequency ? InvisibleCursor : Cursor.Default;
                     });
                 }
             }
@@ -938,13 +957,13 @@ namespace Ryujinx.Ava
                 return false;
             }
 
-            if (_parent.IsActive)
+            if (_viewModel.IsActive)
             {
                 Dispatcher.UIThread.Post(() =>
                 {
                     HandleScreenState();
 
-                    if (_keyboardInterface.GetKeyboardStateSnapshot().IsPressed(Key.Delete) && _parent.WindowState != WindowState.FullScreen)
+                    if (_keyboardInterface.GetKeyboardStateSnapshot().IsPressed(Key.Delete) && _viewModel.WindowState != WindowState.FullScreen)
                     {
                         Device.Application.DiskCacheLoadState?.Cancel();
                     }
@@ -953,7 +972,7 @@ namespace Ryujinx.Ava
 
             NpadManager.Update(ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
 
-            if (_parent.IsActive)
+            if (_viewModel.IsActive)
             {
                 KeyboardHotkeyState currentHotkeyState = GetHotkeyState();
 
@@ -969,10 +988,10 @@ namespace Ryujinx.Ava
                             ScreenshotRequested = true;
                             break;
                         case KeyboardHotkeyState.ShowUi:
-                            _parent.ViewModel.ShowMenuAndStatusBar = true;
+                            _viewModel.ShowMenuAndStatusBar = true;
                             break;
                         case KeyboardHotkeyState.Pause:
-                            if (_parent.ViewModel.IsPaused)
+                            if (_viewModel.IsPaused)
                             {
                                 Resume();
                             }
@@ -991,7 +1010,7 @@ namespace Ryujinx.Ava
                                 Device.SetVolume(0);
                             }
 
-                            _parent.ViewModel.Volume = Device.GetVolume();
+                            _viewModel.Volume = Device.GetVolume();
                             break;
                         case KeyboardHotkeyState.ResScaleUp:
                             GraphicsConfig.ResScale = GraphicsConfig.ResScale % MaxResolutionScale + 1;
@@ -1004,13 +1023,13 @@ namespace Ryujinx.Ava
                             _newVolume = MathF.Round((Device.GetVolume() + VolumeDelta), 2);
                             Device.SetVolume(_newVolume);
 
-                            _parent.ViewModel.Volume = Device.GetVolume();
+                            _viewModel.Volume = Device.GetVolume();
                             break;
                         case KeyboardHotkeyState.VolumeDown:
                             _newVolume = MathF.Round((Device.GetVolume() - VolumeDelta), 2);
                             Device.SetVolume(_newVolume);
 
-                            _parent.ViewModel.Volume = Device.GetVolume();
+                            _viewModel.Volume = Device.GetVolume();
                             break;
                         case KeyboardHotkeyState.None:
                             (_keyboardInterface as AvaloniaKeyboard).Clear();
@@ -1030,7 +1049,7 @@ namespace Ryujinx.Ava
             // Touchscreen
             bool hasTouch = false;
 
-            if (_parent.IsActive && !ConfigurationState.Instance.Hid.EnableMouse)
+            if (_viewModel.IsActive && !ConfigurationState.Instance.Hid.EnableMouse)
             {
                 hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as AvaloniaMouseDriver).IsButtonPressed(MouseButton.Button1), ConfigurationState.Instance.Graphics.AspectRatio.Value.ToFloat());
             }
diff --git a/Ryujinx.Ava/Assets/Styles/Styles.xaml b/Ryujinx.Ava/Assets/Styles/Styles.xaml
index de965a2a0b..c5e760e81d 100644
--- a/Ryujinx.Ava/Assets/Styles/Styles.xaml
+++ b/Ryujinx.Ava/Assets/Styles/Styles.xaml
@@ -269,6 +269,8 @@
         <Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
         <Color x:Key="ThemeContentBackgroundColor">#FF2D2D2D</Color>
         <Color x:Key="ThemeControlBorderColor">#FF505050</Color>
+        <Color x:Key="VsyncEnabled">#FF2EEAC9</Color>
+        <Color x:Key="VsyncDisabled">#FFFF4554</Color>
         <x:Double x:Key="ScrollBarThickness">15</x:Double>
         <x:Double x:Key="FontSizeSmall">8</x:Double>
         <x:Double x:Key="FontSizeNormal">10</x:Double>
diff --git a/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs b/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
index eb58752cee..b0b6cdf05a 100644
--- a/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
+++ b/Ryujinx.Ava/Input/AvaloniaMouseDriver.cs
@@ -11,10 +11,10 @@ namespace Ryujinx.Ava.Input
 {
     internal class AvaloniaMouseDriver : IGamepadDriver
     {
-        private Control         _widget;
-        private bool            _isDisposed;
-        private Size            _size;
-        private readonly Window _window;
+        private Control           _widget;
+        private bool              _isDisposed;
+        private Size              _size;
+        private readonly TopLevel _window;
 
         public bool[]  PressedButtons  { get; }
         public Vector2 CurrentPosition { get; private set; }
@@ -23,7 +23,7 @@ namespace Ryujinx.Ava.Input
         public string               DriverName  => "AvaloniaMouseDriver";
         public ReadOnlySpan<string> GamepadsIds => new[] { "0" };
 
-        public AvaloniaMouseDriver(Window window, Control parent)
+        public AvaloniaMouseDriver(TopLevel window, Control parent)
         {
             _widget = parent;
             _window = window;
diff --git a/Ryujinx.Ava/Modules/Updater/Updater.cs b/Ryujinx.Ava/Modules/Updater/Updater.cs
index bc4760bae8..a7399407fa 100644
--- a/Ryujinx.Ava/Modules/Updater/Updater.cs
+++ b/Ryujinx.Ava/Modules/Updater/Updater.cs
@@ -56,7 +56,7 @@ namespace Ryujinx.Modules
             }
 
             Running = true;
-            mainWindow.CanUpdate = false;
+            mainWindow.ViewModel.CanUpdate = false;
 
             // Detect current platform
             if (OperatingSystem.IsMacOS())
@@ -182,7 +182,7 @@ namespace Ryujinx.Modules
                 }
 
                 Running = false;
-                mainWindow.CanUpdate = true;
+                mainWindow.ViewModel.CanUpdate = true;
 
                 return;
             }
diff --git a/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs b/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
index f4d9bc8066..0809cb4f8d 100644
--- a/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
+++ b/Ryujinx.Ava/UI/Applet/AvaHostUiHandler.cs
@@ -144,9 +144,9 @@ namespace Ryujinx.Ava.UI.Applet
         public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
         {
             device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
-            if (_parent.AppHost != null)
+            if (_parent.ViewModel.AppHost != null)
             {
-                _parent.AppHost.Stop();
+                _parent.ViewModel.AppHost.Stop();
             }
         }
 
diff --git a/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs b/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs
index 314746e76e..bae4762ebe 100644
--- a/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs
+++ b/Ryujinx.Ava/UI/Applet/AvaloniaDynamicTextInputHandler.cs
@@ -136,7 +136,7 @@ namespace Ryujinx.Ava.UI.Applet
             Dispatcher.UIThread.Post(() =>
             {
                 _hiddenTextBox.Clear();
-                _parent.RendererControl.Focus();
+                _parent.ViewModel.RendererControl.Focus();
 
                 _parent = null;
             });
diff --git a/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs b/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs
index fe5e272101..77c7a2d2cc 100644
--- a/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs
+++ b/Ryujinx.Ava/UI/Applet/AvaloniaHostUiTheme.cs
@@ -13,8 +13,8 @@ namespace Ryujinx.Ava.UI.Applet
             DefaultBackgroundColor = BrushToThemeColor(parent.Background);
             DefaultForegroundColor = BrushToThemeColor(parent.Foreground);
             DefaultBorderColor = BrushToThemeColor(parent.BorderBrush);
-            SelectionBackgroundColor = BrushToThemeColor(parent.SearchBox.SelectionBrush);
-            SelectionForegroundColor = BrushToThemeColor(parent.SearchBox.SelectionForegroundBrush);
+            SelectionBackgroundColor = BrushToThemeColor(parent.ViewControls.SearchBox.SelectionBrush);
+            SelectionForegroundColor = BrushToThemeColor(parent.ViewControls.SearchBox.SelectionForegroundBrush);
         }
 
         public string FontFamily { get; }
diff --git a/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs b/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs
index 6a2afad1fc..82a75788de 100644
--- a/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs
+++ b/Ryujinx.Ava/UI/ViewModels/ControllerSettingsViewModel.cs
@@ -244,9 +244,9 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
                 _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
-                if (_mainWindow.AppHost != null)
+                if (_mainWindow.ViewModel.AppHost != null)
                 {
-                    _mainWindow.AppHost.NpadManager.BlockInputUpdates();
+                    _mainWindow.ViewModel.AppHost.NpadManager.BlockInputUpdates();
                 }
 
                 _isLoaded = false;
@@ -862,7 +862,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                 }
             }
 
-            _mainWindow.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
+            _mainWindow.ViewModel.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
 
             // Atomically replace and signal input change.
             // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
@@ -891,7 +891,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             _mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
             _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
 
-            _mainWindow.AppHost?.NpadManager.UnblockInputUpdates();
+            _mainWindow.ViewModel.AppHost?.NpadManager.UnblockInputUpdates();
 
             SelectedGamepad?.Dispose();
 
diff --git a/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
index 514a8bb358..9571af477b 100644
--- a/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
+++ b/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs
@@ -1,5 +1,5 @@
-using Avalonia;
 using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
 using Avalonia.Input;
 using Avalonia.Media;
 using Avalonia.Threading;
@@ -7,12 +7,12 @@ using DynamicData;
 using DynamicData.Binding;
 using LibHac.Fs;
 using LibHac.FsSystem;
-using LibHac.Ncm;
 using Ryujinx.Ava.Common;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.Input;
 using Ryujinx.Ava.UI.Controls;
 using Ryujinx.Ava.UI.Helpers;
+using Ryujinx.Ava.UI.Models;
 using Ryujinx.Ava.UI.Windows;
 using Ryujinx.Common;
 using Ryujinx.Common.Configuration;
@@ -21,11 +21,13 @@ using Ryujinx.Cpu;
 using Ryujinx.HLE;
 using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS;
-using Ryujinx.Modules;
+using Ryujinx.HLE.HOS.Services.Account.Acc;
+using Ryujinx.HLE.Ui;
 using Ryujinx.Ui.App.Common;
 using Ryujinx.Ui.Common;
 using Ryujinx.Ui.Common.Configuration;
 using Ryujinx.Ui.Common.Helper;
+using SixLabors.ImageSharp.PixelFormats;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -35,14 +37,14 @@ using System.Threading;
 using System.Threading.Tasks;
 using Path = System.IO.Path;
 using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
+using UserId = LibHac.Fs.UserId;
 
 namespace Ryujinx.Ava.UI.ViewModels
 {
-    internal class MainWindowViewModel : BaseModel
+    public class MainWindowViewModel : BaseModel
     {
         private const int HotKeyPressDelayMs = 500;
 
-        private readonly MainWindow _owner;
         private ObservableCollection<ApplicationData> _applications;
         private string _aspectStatusText;
 
@@ -57,7 +59,7 @@ namespace Ryujinx.Ava.UI.ViewModels
         private string _gpuStatusText;
         private bool _isAmiiboRequested;
         private bool _isGameRunning;
-        private bool _isLoading;
+        private bool _isFullScreen;
         private int _progressMaximum;
         private int _progressValue;
         private long _lastFullscreenToggle = Environment.TickCount64;
@@ -76,15 +78,29 @@ namespace Ryujinx.Ava.UI.ViewModels
         private bool _isLoadingIndeterminate = true;
         private bool _showAll;
         private string _lastScannedAmiiboId;
+        private bool _statusBarVisible;
         private ReadOnlyObservableCollection<ApplicationData> _appsObservableList;
-        public ApplicationLibrary ApplicationLibrary => _owner.ApplicationLibrary;
 
-        public string TitleName { get; internal set; }
+        private string _showUiKey = "F4";
+        private string _pauseKey = "F5";
+        private string _screenshotKey = "F8";
+        private float _volume;
+        private string _backendText;
 
-        public MainWindowViewModel(MainWindow owner) : this()
-        {
-            _owner = owner;
-        }
+        public ApplicationData ListSelectedApplication;
+        public ApplicationData GridSelectedApplication;
+        private bool _canUpdate;
+        private Cursor _cursor;
+        private string _title;
+        private string _currentEmulatedGamePath;
+        private AutoResetEvent _rendererWaitEvent;
+        private WindowState _windowState;
+        private bool _isActive;
+
+        public event Action ReloadGameList;
+
+        private string TitleName { get; set; }
+        internal AppHost AppHost { get; set; }
 
         public MainWindowViewModel()
         {
@@ -95,6 +111,8 @@ namespace Ryujinx.Ava.UI.ViewModels
                 .Sort(GetComparer())
                 .Bind(out _appsObservableList).AsObservableList();
 
+            _rendererWaitEvent = new AutoResetEvent(false);
+
             if (Program.PreviewerDetached)
             {
                 LoadConfigurableHotKeys();
@@ -103,12 +121,37 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public void Initialize()
+        public void Initialize(
+            ContentManager contentManager,
+            ApplicationLibrary applicationLibrary,
+            VirtualFileSystem virtualFileSystem,
+            AccountManager accountManager,
+            Ryujinx.Input.HLE.InputManager inputManager,
+            UserChannelPersistence userChannelPersistence,
+            LibHacHorizonManager libHacHorizonManager,
+            IHostUiHandler uiHandler,
+            Action<bool> showLoading,
+            Action<bool> switchToGameControl,
+            Action<Control> setMainContent,
+            TopLevel topLevel)
         {
-            ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
-            ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
+            ContentManager = contentManager;
+            ApplicationLibrary = applicationLibrary;
+            VirtualFileSystem = virtualFileSystem;
+            AccountManager = accountManager;
+            InputManager = inputManager;
+            UserChannelPersistence = userChannelPersistence;
+            LibHacHorizonManager = libHacHorizonManager;
+            UiHandler = uiHandler;
+
+            ShowLoading = showLoading;
+            SwitchToGameControl = switchToGameControl;
+            SetMainContent = setMainContent;
+            TopLevel = topLevel;
         }
 
+#region Properties
+
         public string SearchText
         {
             get => _searchText;
@@ -130,6 +173,27 @@ namespace Ryujinx.Ava.UI.ViewModels
             _searchTimer = null;
         }
 
+        public bool CanUpdate
+        {
+            get => _canUpdate;
+            set
+            {
+                _canUpdate = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public Cursor Cursor
+        {
+            get => _cursor;
+            set
+            {
+                _cursor = value;
+                OnPropertyChanged();
+            }
+        }
+
         public ReadOnlyObservableCollection<ApplicationData> AppsObservableList
         {
             get => _appsObservableList;
@@ -152,6 +216,28 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
+        public long LastFullscreenToggle
+        {
+            get => _lastFullscreenToggle;
+            set
+            {
+                _lastFullscreenToggle = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public bool StatusBarVisible
+        {
+            get => _statusBarVisible && EnableNonGameRunningControls;
+            set
+            {
+                _statusBarVisible = value;
+
+                OnPropertyChanged();
+            }
+        }
+
         public bool EnableNonGameRunningControls => !IsGameRunning;
 
         public bool ShowFirmwareStatus => !ShowLoadProgress;
@@ -170,6 +256,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 OnPropertyChanged();
                 OnPropertyChanged(nameof(EnableNonGameRunningControls));
+                OnPropertyChanged(nameof(StatusBarVisible));
                 OnPropertyChanged(nameof(ShowFirmwareStatus));
             }
         }
@@ -208,11 +295,38 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        private string _showUikey = "F4";
-        private string _pauseKey = "F5";
-        private string _screenshotkey = "F8";
-        private float  _volume;
-        private string _backendText;
+        public bool IsFullScreen
+        {
+            get => _isFullScreen;
+            set
+            {
+                _isFullScreen = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public bool ShowAll
+        {
+            get => _showAll;
+            set
+            {
+                _showAll = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+        public string LastScannedAmiiboId
+        {
+            get => _lastScannedAmiiboId;
+            set
+            {
+                _lastScannedAmiiboId = value;
+
+                OnPropertyChanged();
+            }
+        }
 
         public ApplicationData SelectedApplication
         {
@@ -220,9 +334,9 @@ namespace Ryujinx.Ava.UI.ViewModels
             {
                 return Glyph switch
                 {
-                    Glyph.List => _owner.GameList.SelectedApplication,
-                    Glyph.Grid => _owner.GameGrid.SelectedApplication,
-                    _          => null,
+                    Glyph.List => ListSelectedApplication,
+                    Glyph.Grid => GridSelectedApplication,
+                    _ => null,
                 };
             }
         }
@@ -414,7 +528,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 if (_isGameRunning)
                 {
-                    _owner.AppHost.Device.SetVolume(_volume);
+                    AppHost.Device.SetVolume(_volume);
                 }
 
                 OnPropertyChanged(nameof(VolumeStatusText));
@@ -456,6 +570,18 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
+        public bool IsActive
+        {
+            get => _isActive;
+            set
+            {
+                _isActive = value;
+
+                OnPropertyChanged();
+            }
+        }
+
+
         public bool ShowContent
         {
             get => _showContent;
@@ -478,6 +604,17 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
+        public WindowState WindowState
+        {
+            get => _windowState;
+            internal set
+            {
+                _windowState = value;
+
+                OnPropertyChanged();
+            }
+        }
+
         public bool IsGrid => Glyph == Glyph.Grid;
         public bool IsList => Glyph == Glyph.List;
 
@@ -495,44 +632,6 @@ namespace Ryujinx.Ava.UI.ViewModels
             RefreshView();
         }
 
-        private IComparer<ApplicationData> GetComparer()
-        {
-            return SortMode switch
-            {
-                ApplicationSort.LastPlayed      => new Models.Generic.LastPlayedSortComparer(IsAscending),
-                ApplicationSort.FileSize        => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app  => app.FileSizeBytes)
-                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.FileSizeBytes),
-                ApplicationSort.TotalTimePlayed => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app  => app.TimePlayedNum)
-                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.TimePlayedNum),
-                ApplicationSort.Title           => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app  => app.TitleName)
-                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.TitleName),
-                ApplicationSort.Favorite        => !IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app  => app.Favorite)
-                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.Favorite),
-                ApplicationSort.Developer       => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app  => app.Developer)
-                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.Developer),
-                ApplicationSort.FileType        => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app  => app.FileExtension)
-                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.FileExtension),
-                ApplicationSort.Path            => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app  => app.Path)
-                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.Path),
-                _                               => null,
-            };
-        }
-
-        private void RefreshView()
-        {
-            RefreshGrid();
-        }
-
-        private void RefreshGrid()
-        {
-            Applications.ToObservableChangeSet()
-                .Filter(Filter)
-                .Sort(GetComparer())
-                .Bind(out _appsObservableList).AsObservableList();
-
-            OnPropertyChanged(nameof(AppsObservableList));
-        }
-
         public bool StartGamesInFullscreen
         {
             get => ConfigurationState.Instance.Ui.StartFullscreen;
@@ -559,6 +658,17 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
+        public string Title
+        {
+            get => _title;
+            set
+            {
+                _title = value;
+
+                OnPropertyChanged();
+            }
+        }
+
         public bool ShowConsoleVisible
         {
             get => ConsoleHelper.SetConsoleWindowStateSupported;
@@ -598,6 +708,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
                 OnPropertyChanged();
                 OnPropertyChanged(nameof(GridSizeScale));
+                OnPropertyChanged(nameof(GridItemSelectorSize));
 
                 ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
             }
@@ -617,14 +728,70 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public bool IsSortedByFavorite   => SortMode == ApplicationSort.Favorite;
-        public bool IsSortedByTitle      => SortMode == ApplicationSort.Title;
-        public bool IsSortedByDeveloper  => SortMode == ApplicationSort.Developer;
-        public bool IsSortedByLastPlayed => SortMode == ApplicationSort.LastPlayed;
-        public bool IsSortedByTimePlayed => SortMode == ApplicationSort.TotalTimePlayed;
-        public bool IsSortedByType       => SortMode == ApplicationSort.FileType;
-        public bool IsSortedBySize       => SortMode == ApplicationSort.FileSize;
-        public bool IsSortedByPath       => SortMode == ApplicationSort.Path;
+        public int ListItemSelectorSize
+        {
+            get
+            {
+                switch (ConfigurationState.Instance.Ui.GridSize)
+                {
+                    case 1:
+                        return 78;
+                    case 2:
+                        return 100;
+                    case 3:
+                        return 120;
+                    case 4:
+                        return 140;
+                    default:
+                        return 16;
+                }
+            }
+        }
+
+        public int GridItemSelectorSize
+        {
+            get
+            {
+                switch (ConfigurationState.Instance.Ui.GridSize)
+                {
+                    case 1:
+                        return 120;
+                    case 2:
+                        return ShowNames ? 210 : 150;
+                    case 3:
+                        return ShowNames ? 240 : 180;
+                    case 4:
+                        return ShowNames ? 280 : 220;
+                    default:
+                        return 16;
+                }
+            }
+        }
+
+        public int GridSizeScale
+        {
+            get => ConfigurationState.Instance.Ui.GridSize;
+            set
+            {
+                ConfigurationState.Instance.Ui.GridSize.Value = value;
+
+                if (value < 2)
+                {
+                    ShowNames = false;
+                }
+
+                OnPropertyChanged();
+                OnPropertyChanged(nameof(IsGridSmall));
+                OnPropertyChanged(nameof(IsGridMedium));
+                OnPropertyChanged(nameof(IsGridLarge));
+                OnPropertyChanged(nameof(IsGridHuge));
+                OnPropertyChanged(nameof(ListItemSelectorSize));
+                OnPropertyChanged(nameof(GridItemSelectorSize));
+                OnPropertyChanged(nameof(ShowNames));
+
+                ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
+            }
+        }
 
         public string SortName
         {
@@ -632,15 +799,15 @@ namespace Ryujinx.Ava.UI.ViewModels
             {
                 return SortMode switch
                 {
-                    ApplicationSort.Title           => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication],
-                    ApplicationSort.Developer       => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper],
-                    ApplicationSort.LastPlayed      => LocaleManager.Instance[LocaleKeys.GameListHeaderLastPlayed],
+                    ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication],
+                    ApplicationSort.Developer => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper],
+                    ApplicationSort.LastPlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderLastPlayed],
                     ApplicationSort.TotalTimePlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderTimePlayed],
-                    ApplicationSort.FileType        => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension],
-                    ApplicationSort.FileSize        => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize],
-                    ApplicationSort.Path            => LocaleManager.Instance[LocaleKeys.GameListHeaderPath],
-                    ApplicationSort.Favorite        => LocaleManager.Instance[LocaleKeys.CommonFavorite],
-                    _                               => string.Empty,
+                    ApplicationSort.FileType => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension],
+                    ApplicationSort.FileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize],
+                    ApplicationSort.Path => LocaleManager.Instance[LocaleKeys.GameListHeaderPath],
+                    ApplicationSort.Favorite => LocaleManager.Instance[LocaleKeys.CommonFavorite],
+                    _ => string.Empty,
                 };
             }
         }
@@ -662,9 +829,10 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public KeyGesture ShowUiKey
         {
-            get => KeyGesture.Parse(_showUikey); set
+            get => KeyGesture.Parse(_showUiKey);
+            set
             {
-                _showUikey = value.ToString();
+                _showUiKey = value.ToString();
 
                 OnPropertyChanged();
             }
@@ -672,9 +840,10 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public KeyGesture ScreenshotKey
         {
-            get => KeyGesture.Parse(_screenshotkey); set
+            get => KeyGesture.Parse(_screenshotKey);
+            set
             {
-                _screenshotkey = value.ToString();
+                _screenshotKey = value.ToString();
 
                 OnPropertyChanged();
             }
@@ -690,68 +859,73 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public bool IsGridSmall  => ConfigurationState.Instance.Ui.GridSize == 1;
+        public ContentManager ContentManager { get; private set; }
+        public ApplicationLibrary ApplicationLibrary { get; private set; }
+        public VirtualFileSystem VirtualFileSystem { get; private set; }
+        public AccountManager AccountManager { get; private set; }
+        public Ryujinx.Input.HLE.InputManager InputManager { get; private set; }
+        public UserChannelPersistence UserChannelPersistence { get; private set; }
+        public Action<bool> ShowLoading { get; private set; }
+        public Action<bool> SwitchToGameControl { get; private set; }
+        public Action<Control> SetMainContent { get; private set; }
+        public TopLevel TopLevel { get; private set; }
+        public RendererHost RendererControl { get; private set; }
+        public bool IsClosing { get; set; }
+        public LibHacHorizonManager LibHacHorizonManager { get; internal set; }
+        public IHostUiHandler UiHandler { get; internal set; }
+        public bool IsSortedByFavorite => SortMode == ApplicationSort.Favorite;
+        public bool IsSortedByTitle => SortMode == ApplicationSort.Title;
+        public bool IsSortedByDeveloper => SortMode == ApplicationSort.Developer;
+        public bool IsSortedByLastPlayed => SortMode == ApplicationSort.LastPlayed;
+        public bool IsSortedByTimePlayed => SortMode == ApplicationSort.TotalTimePlayed;
+        public bool IsSortedByType => SortMode == ApplicationSort.FileType;
+        public bool IsSortedBySize => SortMode == ApplicationSort.FileSize;
+        public bool IsSortedByPath => SortMode == ApplicationSort.Path;
+        public bool IsGridSmall => ConfigurationState.Instance.Ui.GridSize == 1;
         public bool IsGridMedium => ConfigurationState.Instance.Ui.GridSize == 2;
-        public bool IsGridLarge  => ConfigurationState.Instance.Ui.GridSize == 3;
-        public bool IsGridHuge   => ConfigurationState.Instance.Ui.GridSize == 4;
+        public bool IsGridLarge => ConfigurationState.Instance.Ui.GridSize == 3;
+        public bool IsGridHuge => ConfigurationState.Instance.Ui.GridSize == 4;
 
-        public int GridSizeScale
+#endregion
+
+#region PrivateMethods
+
+        private IComparer<ApplicationData> GetComparer()
         {
-            get => ConfigurationState.Instance.Ui.GridSize;
-            set
+            return SortMode switch
             {
-                ConfigurationState.Instance.Ui.GridSize.Value = value;
-
-                if (value < 2)
-                {
-                    ShowNames = false;
-                }
-
-                OnPropertyChanged();
-                OnPropertyChanged(nameof(IsGridSmall));
-                OnPropertyChanged(nameof(IsGridMedium));
-                OnPropertyChanged(nameof(IsGridLarge));
-                OnPropertyChanged(nameof(IsGridHuge));
-                OnPropertyChanged(nameof(ShowNames));
-
-                ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-            }
+                ApplicationSort.LastPlayed      => new Models.Generic.LastPlayedSortComparer(IsAscending),
+                ApplicationSort.FileSize        => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.FileSizeBytes)
+                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.FileSizeBytes),
+                ApplicationSort.TotalTimePlayed => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.TimePlayedNum)
+                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.TimePlayedNum),
+                ApplicationSort.Title           => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.TitleName)
+                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.TitleName),
+                ApplicationSort.Favorite        => !IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Favorite)
+                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.Favorite),
+                ApplicationSort.Developer       => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Developer)
+                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.Developer),
+                ApplicationSort.FileType        => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.FileExtension)
+                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.FileExtension),
+                ApplicationSort.Path            => IsAscending  ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Path)
+                                                                : SortExpressionComparer<ApplicationData>.Descending(app => app.Path),
+                _ => null,
+            };
         }
 
-        public async void OpenAmiiboWindow()
+        private void RefreshView()
         {
-            if (!_isAmiiboRequested)
-            {
-                return;
-            }
-
-            if (_owner.AppHost.Device.System.SearchingForAmiibo(out int deviceId))
-            {
-                string      titleId = _owner.AppHost.Device.Application.TitleIdText.ToUpper();
-                AmiiboWindow window = new(_showAll, _lastScannedAmiiboId, titleId);
-
-                await window.ShowDialog(_owner);
-
-                if (window.IsScanned)
-                {
-                    _showAll             = window.ViewModel.ShowAllAmiibo;
-                    _lastScannedAmiiboId = window.ScannedAmiibo.GetId();
-
-                    _owner.AppHost.Device.System.ScanAmiibo(deviceId, _lastScannedAmiiboId, window.ViewModel.UseRandomUuid);
-                }
-            }
+            RefreshGrid();
         }
 
-        public void SetUiProgressHandlers(Switch emulationContext)
+        private void RefreshGrid()
         {
-            if (emulationContext.Application.DiskCacheLoadState != null)
-            {
-                emulationContext.Application.DiskCacheLoadState.StateChanged -= ProgressHandler;
-                emulationContext.Application.DiskCacheLoadState.StateChanged += ProgressHandler;
-            }
+            Applications.ToObservableChangeSet()
+                .Filter(Filter)
+                .Sort(GetComparer())
+                .Bind(out _appsObservableList).AsObservableList();
 
-            emulationContext.Gpu.ShaderCacheStateChanged -= ProgressHandler;
-            emulationContext.Gpu.ShaderCacheStateChanged += ProgressHandler;
+            OnPropertyChanged(nameof(AppsObservableList));
         }
 
         private bool Filter(object arg)
@@ -764,148 +938,314 @@ namespace Ryujinx.Ava.UI.ViewModels
             return false;
         }
 
-        private void ApplicationLibrary_ApplicationAdded(object sender, ApplicationAddedEventArgs e)
+        private async Task HandleFirmwareInstallation(string filename)
         {
-            AddApplication(e.AppData);
-        }
-
-        private void ApplicationLibrary_ApplicationCountUpdated(object sender, ApplicationCountUpdatedEventArgs e)
-        {
-            StatusBarProgressValue   = e.NumAppsLoaded;
-            StatusBarProgressMaximum = e.NumAppsFound;
-
-            LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarGamesLoaded, StatusBarProgressValue, StatusBarProgressMaximum);
-
-            Dispatcher.UIThread.Post(() =>
+            try
             {
-                if (e.NumAppsFound == 0)
+                SystemVersion firmwareVersion = ContentManager.VerifyFirmwarePackage(filename);
+
+                if (firmwareVersion == null)
                 {
-                    _owner.LoadProgressBar.IsVisible = false;
+                    await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareNotFoundErrorMessage], filename));
+
+                    return;
                 }
 
-                if (e.NumAppsLoaded == e.NumAppsFound)
+                string dialogTitle = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallTitle], firmwareVersion.VersionString);
+
+                SystemVersion currentVersion = ContentManager.GetCurrentFirmwareVersion();
+
+                string dialogMessage = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallMessage], firmwareVersion.VersionString);
+
+                if (currentVersion != null)
                 {
-                    _owner.LoadProgressBar.IsVisible = false;
+                    dialogMessage += string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallSubMessage], currentVersion.VersionString);
                 }
-            });
-        }
 
-        public void AddApplication(ApplicationData applicationData)
-        {
-            Dispatcher.UIThread.InvokeAsync(() =>
-            {
-                Applications.Add(applicationData);
-            });
-        }
+                dialogMessage += LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallConfirmMessage];
 
-        public async void LoadApplications()
-        {
-            await Dispatcher.UIThread.InvokeAsync(() =>
-            {
-                Applications.Clear();
+                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
+                    dialogTitle,
+                    dialogMessage,
+                    LocaleManager.Instance[LocaleKeys.InputDialogYes],
+                    LocaleManager.Instance[LocaleKeys.InputDialogNo],
+                    LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
 
-                _owner.LoadProgressBar.IsVisible = true;
-                StatusBarProgressMaximum         = 0;
-                StatusBarProgressValue           = 0;
+                UpdateWaitWindow waitingDialog = ContentDialogHelper.CreateWaitingDialog(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallWaitMessage]);
 
-                LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0);
-            });
+                if (result == UserResult.Yes)
+                {
+                    Logger.Info?.Print(LogClass.Application, $"Installing firmware {firmwareVersion.VersionString}");
 
-            ReloadGameList();
-        }
+                    Thread thread = new(() =>
+                    {
+                        Dispatcher.UIThread.InvokeAsync(delegate
+                        {
+                            waitingDialog.Show();
+                        });
 
-        private void ReloadGameList()
-        {
-            if (_isLoading)
-            {
-                return;
+                        try
+                        {
+                            ContentManager.InstallFirmware(filename);
+
+                            Dispatcher.UIThread.InvokeAsync(async delegate
+                            {
+                                waitingDialog.Close();
+
+                                string message = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage], firmwareVersion.VersionString);
+
+                                await ContentDialogHelper.CreateInfoDialog(dialogTitle, message, LocaleManager.Instance[LocaleKeys.InputDialogOk], "", LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
+
+                                Logger.Info?.Print(LogClass.Application, message);
+
+                                // Purge Applet Cache.
+
+                                DirectoryInfo miiEditorCacheFolder = new DirectoryInfo(Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
+
+                                if (miiEditorCacheFolder.Exists)
+                                {
+                                    miiEditorCacheFolder.Delete(true);
+                                }
+                            });
+                        }
+                        catch (Exception ex)
+                        {
+                            Dispatcher.UIThread.InvokeAsync(async () =>
+                            {
+                                waitingDialog.Close();
+
+                                await ContentDialogHelper.CreateErrorDialog(ex.Message);
+                            });
+                        }
+                        finally
+                        {
+                            RefreshFirmwareStatus();
+                        }
+                    }) { Name = "GUI.FirmwareInstallerThread" };
+
+                    thread.Start();
+                }
             }
-
-            _isLoading = true;
-
-            Thread thread = new(() =>
+            catch (LibHac.Common.Keys.MissingKeyException ex)
             {
-                ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs.Value, ConfigurationState.Instance.System.Language);
-
-                _isLoading = false;
-            })
-            { Name = "GUI.AppListLoadThread", Priority = ThreadPriority.AboveNormal };
-
-            thread.Start();
-        }
-
-        public async void OpenFile()
-        {
-            OpenFileDialog dialog = new()
-            {
-                Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle]
-            };
-
-            dialog.Filters.Add(new FileDialogFilter
-            {
-                Name = LocaleManager.Instance[LocaleKeys.AllSupportedFormats],
-                Extensions =
+                if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
                 {
-                    "nsp",
-                    "pfs0",
-                    "xci",
-                    "nca",
-                    "nro",
-                    "nso"
+                    Logger.Error?.Print(LogClass.Application, ex.ToString());
+
+                    async void Action() => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys, (desktop.MainWindow as MainWindow));
+
+                    Dispatcher.UIThread.Post(Action);
                 }
-            });
-
-            dialog.Filters.Add(new FileDialogFilter { Name = "NSP",  Extensions = { "nsp" } });
-            dialog.Filters.Add(new FileDialogFilter { Name = "PFS0", Extensions = { "pfs0" } });
-            dialog.Filters.Add(new FileDialogFilter { Name = "XCI",  Extensions = { "xci" } });
-            dialog.Filters.Add(new FileDialogFilter { Name = "NCA",  Extensions = { "nca" } });
-            dialog.Filters.Add(new FileDialogFilter { Name = "NRO",  Extensions = { "nro" } });
-            dialog.Filters.Add(new FileDialogFilter { Name = "NSO",  Extensions = { "nso" } });
-
-            string[] files = await dialog.ShowAsync(_owner);
-
-            if (files != null && files.Length > 0)
+            }
+            catch (Exception ex)
             {
-                _owner.LoadApplication(files[0]);
+                await ContentDialogHelper.CreateErrorDialog(ex.Message);
             }
         }
 
-        public async void OpenFolder()
+        private void ProgressHandler<T>(T state, int current, int total) where T : Enum
         {
-            OpenFolderDialog dialog = new()
+            Dispatcher.UIThread.Post((() =>
             {
-                Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle]
-            };
+                ProgressMaximum = total;
+                ProgressValue = current;
 
-            string folder = await dialog.ShowAsync(_owner);
+                switch (state)
+                {
+                    case LoadState ptcState:
+                        CacheLoadStatus = $"{current} / {total}";
+                        switch (ptcState)
+                        {
+                            case LoadState.Unloaded:
+                            case LoadState.Loading:
+                                LoadHeading = LocaleManager.Instance[LocaleKeys.CompilingPPTC];
+                                IsLoadingIndeterminate = false;
+                                break;
+                            case LoadState.Loaded:
+                                LoadHeading = string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], TitleName);
+                                IsLoadingIndeterminate = true;
+                                CacheLoadStatus = "";
+                                break;
+                        }
+                        break;
+                    case ShaderCacheLoadingState shaderCacheState:
+                        CacheLoadStatus = $"{current} / {total}";
+                        switch (shaderCacheState)
+                        {
+                            case ShaderCacheLoadingState.Start:
+                            case ShaderCacheLoadingState.Loading:
+                                LoadHeading = LocaleManager.Instance[LocaleKeys.CompilingShaders];
+                                IsLoadingIndeterminate = false;
+                                break;
+                            case ShaderCacheLoadingState.Loaded:
+                                LoadHeading = string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], TitleName);
+                                IsLoadingIndeterminate = true;
+                                CacheLoadStatus = "";
+                                break;
+                        }
+                        break;
+                    default:
+                        throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
+                }
+            }));
+        }
 
-            if (!string.IsNullOrWhiteSpace(folder) && Directory.Exists(folder))
+        private void OpenSaveDirectory(in SaveDataFilter filter, ApplicationData data, ulong titleId)
+        {
+            ApplicationHelper.OpenSaveDir(in filter, titleId, data.ControlHolder, data.TitleName);
+        }
+
+        private async void ExtractLogo()
+        {
+            var selection = SelectedApplication;
+            if (selection != null)
             {
-                _owner.LoadApplication(folder);
+                await ApplicationHelper.ExtractSection(NcaSectionType.Logo, selection.Path);
             }
         }
 
+        private async void ExtractRomFs()
+        {
+            var selection = SelectedApplication;
+            if (selection != null)
+            {
+                await ApplicationHelper.ExtractSection(NcaSectionType.Data, selection.Path);
+            }
+        }
+
+        private async void ExtractExeFs()
+        {
+            var selection = SelectedApplication;
+            if (selection != null)
+            {
+                await ApplicationHelper.ExtractSection(NcaSectionType.Code, selection.Path);
+            }
+        }
+
+        private void PrepareLoadScreen()
+        {
+            using MemoryStream stream = new(SelectedIcon);
+            using var gameIconBmp = SixLabors.ImageSharp.Image.Load<Bgra32>(stream);
+
+            var dominantColor = IconColorPicker.GetFilteredColor(gameIconBmp).ToPixel<Bgra32>();
+
+            const float colorMultiple = 0.5f;
+
+            Color progressFgColor = Color.FromRgb(dominantColor.R, dominantColor.G, dominantColor.B);
+            Color progressBgColor = Color.FromRgb(
+                (byte)(dominantColor.R * colorMultiple),
+                (byte)(dominantColor.G * colorMultiple),
+                (byte)(dominantColor.B * colorMultiple));
+
+            ProgressBarForegroundColor = new SolidColorBrush(progressFgColor);
+            ProgressBarBackgroundColor = new SolidColorBrush(progressBgColor);
+        }
+
+        private void InitializeGame()
+        {
+            RendererControl.RendererInitialized += GlRenderer_Created;
+
+            AppHost.StatusUpdatedEvent += Update_StatusBar;
+            AppHost.AppExit += AppHost_AppExit;
+
+            _rendererWaitEvent.WaitOne();
+
+            AppHost?.Start();
+
+            AppHost?.DisposeContext();
+        }
+
+        private void HandleRelaunch()
+        {
+            if (UserChannelPersistence.PreviousIndex != -1 && UserChannelPersistence.ShouldRestart)
+            {
+                UserChannelPersistence.ShouldRestart = false;
+
+                Dispatcher.UIThread.Post(() =>
+                {
+                    LoadApplication(_currentEmulatedGamePath);
+                });
+            }
+            else
+            {
+                // Otherwise, clear state.
+                UserChannelPersistence = new UserChannelPersistence();
+                _currentEmulatedGamePath = null;
+            }
+        }
+
+        private void Update_StatusBar(object sender, StatusUpdatedEventArgs args)
+        {
+            if (ShowMenuAndStatusBar && !ShowLoadProgress)
+            {
+                Dispatcher.UIThread.InvokeAsync(() =>
+                {
+                    Avalonia.Application.Current.Styles.TryGetResource(args.VSyncEnabled
+                        ? "VsyncEnabled"
+                        : "VsyncDisabled", out object color);
+
+                    if (color is not null)
+                    {
+                        VsyncColor = new SolidColorBrush((Color)color);
+                    }
+
+                    DockedStatusText = args.DockedMode;
+                    AspectRatioStatusText = args.AspectRatio;
+                    GameStatusText = args.GameStatus;
+                    VolumeStatusText = args.VolumeStatus;
+                    FifoStatusText = args.FifoStatus;
+                    GpuNameText = args.GpuName;
+                    BackendText = args.GpuBackend;
+
+                    ShowStatusSeparator = true;
+                });
+            }
+        }
+
+        private void GlRenderer_Created(object sender, EventArgs e)
+        {
+            ShowLoading(false);
+
+            _rendererWaitEvent.Set();
+        }
+
+#endregion
+
+#region PublicMethods
+
+        public void SetUIProgressHandlers(Switch emulationContext)
+        {
+            if (emulationContext.Application.DiskCacheLoadState != null)
+            {
+                emulationContext.Application.DiskCacheLoadState.StateChanged -= ProgressHandler;
+                emulationContext.Application.DiskCacheLoadState.StateChanged += ProgressHandler;
+            }
+
+            emulationContext.Gpu.ShaderCacheStateChanged -= ProgressHandler;
+            emulationContext.Gpu.ShaderCacheStateChanged += ProgressHandler;
+        }
+
         public void LoadConfigurableHotKeys()
         {
             if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
             {
-                ShowUiKey = new KeyGesture(showUiKey, KeyModifiers.None);
+                ShowUiKey = new KeyGesture(showUiKey);
             }
 
             if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
             {
-                ScreenshotKey = new KeyGesture(screenshotKey, KeyModifiers.None);
+                ScreenshotKey = new KeyGesture(screenshotKey);
             }
 
             if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
             {
-                PauseKey = new KeyGesture(pauseKey, KeyModifiers.None);
+                PauseKey = new KeyGesture(pauseKey);
             }
         }
 
         public void TakeScreenshot()
         {
-            _owner.AppHost.ScreenshotRequested = true;
+            AppHost.ScreenshotRequested = true;
         }
 
         public void HideUi()
@@ -923,13 +1263,36 @@ namespace Ryujinx.Ava.UI.ViewModels
             Glyph = Glyph.Grid;
         }
 
-        public void OpenMiiApplet()
+        public async void InstallFirmwareFromFile()
         {
-            string contentPath = _owner.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
-
-            if (!string.IsNullOrWhiteSpace(contentPath))
+            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
             {
-                _owner.LoadApplication(contentPath, false, "Mii Applet");
+                OpenFileDialog dialog = new() { AllowMultiple = false };
+                dialog.Filters.Add(new FileDialogFilter { Name = LocaleManager.Instance[LocaleKeys.FileDialogAllTypes], Extensions = { "xci", "zip" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "XCI",                                                 Extensions = { "xci" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "ZIP",                                                 Extensions = { "zip" } });
+
+                string[] file = await dialog.ShowAsync(desktop.MainWindow);
+
+                if (file != null && file.Length > 0)
+                {
+                    await HandleFirmwareInstallation(file[0]);
+                }
+            }
+        }
+
+        public async void InstallFirmwareFromFolder()
+        {
+            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            {
+                OpenFolderDialog dialog = new();
+
+                string folder = await dialog.ShowAsync(desktop.MainWindow);
+
+                if (!string.IsNullOrEmpty(folder))
+                {
+                    await HandleFirmwareInstallation(folder);
+                }
             }
         }
 
@@ -947,39 +1310,6 @@ namespace Ryujinx.Ava.UI.ViewModels
             OpenHelper.OpenFolder(logPath);
         }
 
-        public void ToggleFullscreen()
-        {
-            if (Environment.TickCount64 - _lastFullscreenToggle < HotKeyPressDelayMs)
-            {
-                return;
-            }
-
-            _lastFullscreenToggle = Environment.TickCount64;
-
-            if (_owner.WindowState == WindowState.FullScreen)
-            {
-                _owner.WindowState = WindowState.Normal;
-
-                if (IsGameRunning)
-                {
-                    ShowMenuAndStatusBar = true;
-                }
-            }
-            else
-            {
-                _owner.WindowState = WindowState.FullScreen;
-
-                if (IsGameRunning)
-                {
-                    ShowMenuAndStatusBar = false;
-                }
-            }
-
-            OnPropertyChanged(nameof(IsFullScreen));
-        }
-
-        public bool IsFullScreen => _owner.WindowState == WindowState.FullScreen;
-
         public void ToggleDockMode()
         {
             if (IsGameRunning)
@@ -990,7 +1320,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public async void ExitCurrentState()
         {
-            if (_owner.WindowState == WindowState.FullScreen)
+            if (WindowState == WindowState.FullScreen)
             {
                 ToggleFullscreen();
             }
@@ -998,146 +1328,19 @@ namespace Ryujinx.Ava.UI.ViewModels
             {
                 await Task.Delay(100);
 
-                _owner.AppHost?.ShowExitPrompt();
+                AppHost?.ShowExitPrompt();
             }
         }
 
-        public async void OpenSettings()
-        {
-            _owner.SettingsWindow = new(_owner.VirtualFileSystem, _owner.ContentManager);
-
-            await _owner.SettingsWindow.ShowDialog(_owner);
-
-            LoadConfigurableHotKeys();
-        }
-
-        public async void ManageProfiles()
-        {
-            await NavigationDialogHost.Show(_owner.AccountManager, _owner.ContentManager, _owner.VirtualFileSystem, _owner.LibHacHorizonManager.RyujinxClient);
-        }
-
-        public async void OpenAboutWindow()
-        {
-            await AboutWindow.Show();
-        }
-
         public void ChangeLanguage(object obj)
         {
             LocaleManager.Instance.LoadDefaultLanguage();
             LocaleManager.Instance.LoadLanguage((string)obj);
         }
 
-        private void ProgressHandler<T>(T state, int current, int total) where T : Enum
+        public async void ManageProfiles()
         {
-            try
-            {
-                ProgressMaximum = total;
-                ProgressValue   = current;
-
-                switch (state)
-                {
-                    case LoadState ptcState:
-                        CacheLoadStatus = $"{current} / {total}";
-                        switch (ptcState)
-                        {
-                            case LoadState.Unloaded:
-                            case LoadState.Loading:
-                                LoadHeading            = LocaleManager.Instance[LocaleKeys.CompilingPPTC];
-                                IsLoadingIndeterminate = false;
-                                break;
-                            case LoadState.Loaded:
-                                LoadHeading            = string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], TitleName);
-                                IsLoadingIndeterminate = true;
-                                CacheLoadStatus        = "";
-                                break;
-                        }
-                        break;
-                    case ShaderCacheLoadingState shaderCacheState:
-                        CacheLoadStatus = $"{current} / {total}";
-                        switch (shaderCacheState)
-                        {
-                            case ShaderCacheLoadingState.Start:
-                            case ShaderCacheLoadingState.Loading:
-                                LoadHeading            = LocaleManager.Instance[LocaleKeys.CompilingShaders];
-                                IsLoadingIndeterminate = false;
-                                break;
-                            case ShaderCacheLoadingState.Loaded:
-                                LoadHeading            = string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], TitleName);
-                                IsLoadingIndeterminate = true;
-                                CacheLoadStatus        = "";
-                                break;
-                        }
-                        break;
-                    default:
-                        throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
-                }
-            }
-            catch (Exception) { }
-        }
-
-        public void OpenUserSaveDirectory()
-        {
-            ApplicationData selection = SelectedApplication;
-            if (selection != null)
-            {
-                Task.Run(() =>
-                {
-                    if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
-                    {
-                        Dispatcher.UIThread.Post(async () =>
-                        {
-                            await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogRyujinxErrorMessage], LocaleManager.Instance[LocaleKeys.DialogInvalidTitleIdErrorMessage]);
-                        });
-
-                        return;
-                    }
-
-                    UserId         userId         = new((ulong)_owner.AccountManager.LastOpenedUser.UserId.High, (ulong)_owner.AccountManager.LastOpenedUser.UserId.Low);
-                    SaveDataFilter saveDataFilter = SaveDataFilter.Make(titleIdNumber, saveType: default, userId, saveDataId: default, index: default);
-                    OpenSaveDirectory(in saveDataFilter, selection, titleIdNumber);
-                });
-            }
-        }
-
-        public void ToggleFavorite()
-        {
-            ApplicationData selection = SelectedApplication;
-            if (selection != null)
-            {
-                selection.Favorite = !selection.Favorite;
-
-                ApplicationLibrary.LoadAndSaveMetaData(selection.TitleId, appMetadata =>
-                {
-                    appMetadata.Favorite = selection.Favorite;
-                });
-
-                RefreshView();
-            }
-        }
-
-        public void OpenModsDirectory()
-        {
-            ApplicationData selection = SelectedApplication;
-            if (selection != null)
-            {
-                string modsBasePath  = _owner.VirtualFileSystem.ModLoader.GetModsBasePath();
-                string titleModsPath = _owner.VirtualFileSystem.ModLoader.GetTitleDir(modsBasePath, selection.TitleId);
-
-                OpenHelper.OpenFolder(titleModsPath);
-            }
-        }
-
-        public void OpenSdModsDirectory()
-        {
-            ApplicationData selection = SelectedApplication;
-
-            if (selection != null)
-            {
-                string sdModsBasePath = _owner.VirtualFileSystem.ModLoader.GetSdModsBasePath();
-                string titleModsPath  = _owner.VirtualFileSystem.ModLoader.GetTitleDir(sdModsBasePath, selection.TitleId);
-
-                OpenHelper.OpenFolder(titleModsPath);
-            }
+            await NavigationDialogHost.Show(AccountManager, ContentManager, VirtualFileSystem, LibHacHorizonManager.RyujinxClient);
         }
 
         public void OpenPtcDirectory()
@@ -1145,8 +1348,8 @@ namespace Ryujinx.Ava.UI.ViewModels
             ApplicationData selection = SelectedApplication;
             if (selection != null)
             {
-                string ptcDir     = Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu");
-                string mainPath   = Path.Combine(ptcDir, "0");
+                string ptcDir = Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu");
+                string mainPath = Path.Combine(ptcDir, "0");
                 string backupPath = Path.Combine(ptcDir, "1");
 
                 if (!Directory.Exists(ptcDir))
@@ -1165,7 +1368,7 @@ namespace Ryujinx.Ava.UI.ViewModels
             ApplicationData selection = SelectedApplication;
             if (selection != null)
             {
-                DirectoryInfo mainDir   = new(Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu", "0"));
+                DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu", "0"));
                 DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu", "1"));
 
                 // FIXME: Found a way to reproduce the bold effect on the title name (fork?).
@@ -1222,7 +1425,7 @@ namespace Ryujinx.Ava.UI.ViewModels
 
         public void SimulateWakeUpMessage()
         {
-            _owner.AppHost.Device.System.SimulateWakeUpMessage();
+            AppHost.Device.System.SimulateWakeUpMessage();
         }
 
         public async void PurgeShaderCache()
@@ -1240,7 +1443,7 @@ namespace Ryujinx.Ava.UI.ViewModels
                                                                                        LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
 
                 List<DirectoryInfo> oldCacheDirectories = new();
-                List<FileInfo>      newCacheFiles       = new();
+                List<FileInfo> newCacheFiles = new();
 
                 if (shaderCacheDir.Exists)
                 {
@@ -1278,57 +1481,6 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        public async void CheckForUpdates()
-        {
-            if (Updater.CanUpdate(true, _owner))
-            {
-                await Updater.BeginParse(_owner, true);
-            }
-        }
-
-        public async void OpenTitleUpdateManager()
-        {
-            ApplicationData selection = SelectedApplication;
-            if (selection != null)
-            {
-                await new TitleUpdateWindow(_owner.VirtualFileSystem, ulong.Parse(selection.TitleId, NumberStyles.HexNumber), selection.TitleName).ShowDialog(_owner);
-            }
-        }
-
-        public async void OpenDownloadableContentManager()
-        {
-            ApplicationData selection = SelectedApplication;
-            if (selection != null)
-            {
-                await new DownloadableContentManagerWindow(_owner.VirtualFileSystem, ulong.Parse(selection.TitleId, NumberStyles.HexNumber), selection.TitleName).ShowDialog(_owner);
-            }
-        }
-
-        public async void OpenCheatManager()
-        {
-            ApplicationData selection = SelectedApplication;
-            if (selection != null)
-            {
-                await new CheatWindow(_owner.VirtualFileSystem, selection.TitleId, selection.TitleName).ShowDialog(_owner);
-            }
-        }
-
-        public async void OpenCheatManagerForCurrentApp()
-        {
-            if (!IsGameRunning)
-            {
-                return;
-            }
-
-            ApplicationLoader application = _owner.AppHost.Device.Application;
-            if (application != null)
-            {
-                await new CheatWindow(_owner.VirtualFileSystem, application.TitleIdText, application.TitleName).ShowDialog(_owner);
-
-                _owner.AppHost.Device.EnableCheats();
-            }
-        }
-
         public void OpenDeviceSaveDirectory()
         {
             ApplicationData selection = SelectedApplication;
@@ -1338,10 +1490,12 @@ namespace Ryujinx.Ava.UI.ViewModels
                 {
                     if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
                     {
-                        Dispatcher.UIThread.Post(async () =>
+                        async void Action()
                         {
                             await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogRyujinxErrorMessage], LocaleManager.Instance[LocaleKeys.DialogInvalidTitleIdErrorMessage]);
-                        });
+                        }
+
+                        Dispatcher.UIThread.Post(Action);
 
                         return;
                     }
@@ -1361,10 +1515,12 @@ namespace Ryujinx.Ava.UI.ViewModels
                 {
                     if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
                     {
-                        Dispatcher.UIThread.Post(async () =>
+                        async void Action()
                         {
                             await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogRyujinxErrorMessage], LocaleManager.Instance[LocaleKeys.DialogInvalidTitleIdErrorMessage]);
-                        });
+                        }
+
+                        Dispatcher.UIThread.Post(Action);
 
                         return;
                     }
@@ -1375,169 +1531,421 @@ namespace Ryujinx.Ava.UI.ViewModels
             }
         }
 
-        private void OpenSaveDirectory(in SaveDataFilter filter, ApplicationData data, ulong titleId)
+        public void ToggleFavorite()
         {
-            ApplicationHelper.OpenSaveDir(in filter, titleId, data.ControlHolder, data.TitleName);
-        }
-
-        private async void ExtractLogo()
-        {
-            var selection = SelectedApplication;
+            ApplicationData selection = SelectedApplication;
             if (selection != null)
             {
-                await ApplicationHelper.ExtractSection(NcaSectionType.Logo, selection.Path);
-            }
-        }
+                selection.Favorite = !selection.Favorite;
 
-        private async void ExtractRomFs()
-        {
-            var selection = SelectedApplication;
-            if (selection != null)
-            {
-                await ApplicationHelper.ExtractSection(NcaSectionType.Data, selection.Path);
-            }
-        }
-
-        private async void ExtractExeFs()
-        {
-            var selection = SelectedApplication;
-            if (selection != null)
-            {
-                await ApplicationHelper.ExtractSection(NcaSectionType.Code, selection.Path);
-            }
-        }
-
-        public void CloseWindow()
-        {
-            _owner.Close();
-        }
-
-        private async Task HandleFirmwareInstallation(string filename)
-        {
-            try
-            {
-                SystemVersion firmwareVersion = _owner.ContentManager.VerifyFirmwarePackage(filename);
-
-                if (firmwareVersion == null)
+                ApplicationLibrary.LoadAndSaveMetaData(selection.TitleId, appMetadata =>
                 {
-                    await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareNotFoundErrorMessage], filename));
+                    appMetadata.Favorite = selection.Favorite;
+                });
+
+                RefreshView();
+            }
+        }
+
+        public void OpenUserSaveDirectory()
+        {
+            ApplicationData selection = SelectedApplication;
+            if (selection != null)
+            {
+                Task.Run(() =>
+                {
+                    if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
+                    {
+                        async void Action()
+                        {
+                            await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogRyujinxErrorMessage], LocaleManager.Instance[LocaleKeys.DialogInvalidTitleIdErrorMessage]);
+                        }
+
+                        Dispatcher.UIThread.Post(Action);
+
+                        return;
+                    }
+
+                    UserId         userId         = new((ulong)AccountManager.LastOpenedUser.UserId.High, (ulong)AccountManager.LastOpenedUser.UserId.Low);
+                    SaveDataFilter saveDataFilter = SaveDataFilter.Make(titleIdNumber, saveType: default, userId, saveDataId: default, index: default);
+                    OpenSaveDirectory(in saveDataFilter, selection, titleIdNumber);
+                });
+            }
+        }
+
+        public void OpenModsDirectory()
+        {
+            ApplicationData selection = SelectedApplication;
+            if (selection != null)
+            {
+                string modsBasePath  = VirtualFileSystem.ModLoader.GetModsBasePath();
+                string titleModsPath = VirtualFileSystem.ModLoader.GetTitleDir(modsBasePath, selection.TitleId);
+
+                OpenHelper.OpenFolder(titleModsPath);
+            }
+        }
+
+        public void OpenSdModsDirectory()
+        {
+            ApplicationData selection = SelectedApplication;
+
+            if (selection != null)
+            {
+                string sdModsBasePath = VirtualFileSystem.ModLoader.GetSdModsBasePath();
+                string titleModsPath  = VirtualFileSystem.ModLoader.GetTitleDir(sdModsBasePath, selection.TitleId);
+
+                OpenHelper.OpenFolder(titleModsPath);
+            }
+        }
+
+        public async void OpenTitleUpdateManager()
+        {
+            ApplicationData selection = SelectedApplication;
+            if (selection != null)
+            {
+                if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+                {
+                    await new TitleUpdateWindow(VirtualFileSystem, ulong.Parse(selection.TitleId, NumberStyles.HexNumber), selection.TitleName).ShowDialog(desktop.MainWindow);
+                }
+            }
+        }
+
+        public async void OpenDownloadableContentManager()
+        {
+            ApplicationData selection = SelectedApplication;
+            if (selection != null)
+            {
+                if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+                {
+                    await new DownloadableContentManagerWindow(VirtualFileSystem, ulong.Parse(selection.TitleId, NumberStyles.HexNumber), selection.TitleName).ShowDialog(desktop.MainWindow);
+                }
+            }
+        }
+
+        public async void OpenCheatManager()
+        {
+            ApplicationData selection = SelectedApplication;
+            if (selection != null)
+            {
+                if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+                {
+                    await new CheatWindow(VirtualFileSystem, selection.TitleId, selection.TitleName).ShowDialog(desktop.MainWindow);
+                }
+            }
+        }
+
+        public async void LoadApplications()
+        {
+            await Dispatcher.UIThread.InvokeAsync(() =>
+            {
+                Applications.Clear();
+
+                StatusBarVisible         = true;
+                StatusBarProgressMaximum = 0;
+                StatusBarProgressValue   = 0;
+
+                LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0);
+            });
+
+            ReloadGameList?.Invoke();
+        }
+
+        public async void OpenFile()
+        {
+            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            {
+                OpenFileDialog dialog = new()
+                {
+                    Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle]
+                };
+
+                dialog.Filters.Add(new FileDialogFilter
+                {
+                    Name = LocaleManager.Instance[LocaleKeys.AllSupportedFormats],
+                    Extensions =
+                    {
+                        "nsp",
+                        "pfs0",
+                        "xci",
+                        "nca",
+                        "nro",
+                        "nso"
+                    }
+                });
+
+                dialog.Filters.Add(new FileDialogFilter { Name = "NSP",  Extensions = { "nsp" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "PFS0", Extensions = { "pfs0" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "XCI",  Extensions = { "xci" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "NCA",  Extensions = { "nca" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "NRO",  Extensions = { "nro" } });
+                dialog.Filters.Add(new FileDialogFilter { Name = "NSO",  Extensions = { "nso" } });
+
+                string[] files = await dialog.ShowAsync(desktop.MainWindow);
+
+                if (files != null && files.Length > 0)
+                {
+                    LoadApplication(files[0]);
+                }
+            }
+        }
+
+        public async void OpenFolder()
+        {
+            if (Avalonia.Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+            {
+                OpenFolderDialog dialog = new()
+                {
+                    Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle]
+                };
+
+                string folder = await dialog.ShowAsync(desktop.MainWindow);
+
+                if (!string.IsNullOrWhiteSpace(folder) && Directory.Exists(folder))
+                {
+                    LoadApplication(folder);
+                }
+            }
+        }
+
+        public async void LoadApplication(string path, bool startFullscreen = false, string titleName = "")
+        {
+            if (AppHost != null)
+            {
+                await ContentDialogHelper.CreateInfoDialog(
+                    LocaleManager.Instance[LocaleKeys.DialogLoadAppGameAlreadyLoadedMessage],
+                    LocaleManager.Instance[LocaleKeys.DialogLoadAppGameAlreadyLoadedSubMessage],
+                    LocaleManager.Instance[LocaleKeys.InputDialogOk],
+                    "",
+                    LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
+
+                return;
+            }
+
+#if RELEASE
+            await PerformanceCheck();
+#endif
+
+            Logger.RestartTime();
+
+            if (SelectedIcon == null)
+            {
+                SelectedIcon = ApplicationLibrary.GetApplicationIcon(path);
+            }
+
+            PrepareLoadScreen();
+
+            RendererControl = new RendererHost(ConfigurationState.Instance.Logger.GraphicsDebugLevel);
+            if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.OpenGl)
+            {
+                RendererControl.CreateOpenGL();
+            }
+            else
+            {
+                RendererControl.CreateVulkan();
+            }
+
+            AppHost = new AppHost(
+                RendererControl,
+                InputManager,
+                path,
+                VirtualFileSystem,
+                ContentManager,
+                AccountManager,
+                UserChannelPersistence,
+                this,
+                TopLevel);
+
+            async void Action()
+            {
+                if (!await AppHost.LoadGuestApplication())
+                {
+                    AppHost.DisposeContext();
+                    AppHost = null;
 
                     return;
                 }
 
-                string dialogTitle = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallTitle], firmwareVersion.VersionString);
+                CanUpdate = false;
+                LoadHeading = string.IsNullOrWhiteSpace(titleName) ? string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], AppHost.Device.Application.TitleName) : titleName;
+                TitleName = string.IsNullOrWhiteSpace(titleName) ? AppHost.Device.Application.TitleName : titleName;
 
-                SystemVersion currentVersion = _owner.ContentManager.GetCurrentFirmwareVersion();
+                SwitchToRenderer(startFullscreen);
 
-                string dialogMessage = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallMessage], firmwareVersion.VersionString);
+                _currentEmulatedGamePath = path;
 
-                if (currentVersion != null)
+                Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
+                gameThread.Start();
+            }
+
+            Dispatcher.UIThread.Post(Action);
+        }
+
+        public void SwitchToRenderer(bool startFullscreen)
+        {
+            Dispatcher.UIThread.Post(() =>
+            {
+                SwitchToGameControl(startFullscreen);
+
+                SetMainContent(RendererControl);
+
+                RendererControl.Focus();
+            });
+        }
+
+        public void UpdateGameMetadata(string titleId)
+        {
+            ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
+            {
+                if (DateTime.TryParse(appMetadata.LastPlayed, out DateTime lastPlayedDateTime))
                 {
-                    dialogMessage += string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallSubMessage], currentVersion.VersionString);
-                }
+                    double sessionTimePlayed = DateTime.UtcNow.Subtract(lastPlayedDateTime).TotalSeconds;
 
-                dialogMessage += LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallConfirmMessage];
+                    appMetadata.TimePlayed += Math.Round(sessionTimePlayed, MidpointRounding.AwayFromZero);
+                }
+            });
+        }
+
+        public void RefreshFirmwareStatus()
+        {
+            SystemVersion version = null;
+            try
+            {
+                version = ContentManager.GetCurrentFirmwareVersion();
+            }
+            catch (Exception) { }
+
+            bool hasApplet = false;
+
+            if (version != null)
+            {
+                LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarSystemVersion,
+                    version.VersionString);
+
+                hasApplet = version.Major > 3;
+            }
+            else
+            {
+                LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarSystemVersion, "0.0");
+            }
+
+            IsAppletMenuActive = hasApplet;
+        }
+
+        public void AppHost_AppExit(object sender, EventArgs e)
+        {
+            if (IsClosing)
+            {
+                return;
+            }
+
+            IsGameRunning = false;
+
+            Dispatcher.UIThread.InvokeAsync(() =>
+            {
+                ShowMenuAndStatusBar = true;
+                ShowContent = true;
+                ShowLoadProgress = false;
+                IsLoadingIndeterminate = false;
+                CanUpdate = true;
+                Cursor = Cursor.Default;
+
+                SetMainContent(null);
+
+                AppHost = null;
+
+                HandleRelaunch();
+            });
+
+            RendererControl.RendererInitialized -= GlRenderer_Created;
+            RendererControl = null;
+
+            SelectedIcon = null;
+
+            Dispatcher.UIThread.InvokeAsync(() =>
+            {
+                Title = $"Ryujinx {Program.Version}";
+            });
+        }
+
+        public void ToggleFullscreen()
+        {
+            if (Environment.TickCount64 - LastFullscreenToggle < HotKeyPressDelayMs)
+            {
+                return;
+            }
+
+            LastFullscreenToggle = Environment.TickCount64;
+
+            if (WindowState == WindowState.FullScreen)
+            {
+                WindowState = WindowState.Normal;
+
+                if (IsGameRunning)
+                {
+                    ShowMenuAndStatusBar = true;
+                }
+            }
+            else
+            {
+                WindowState = WindowState.FullScreen;
+
+                if (IsGameRunning)
+                {
+                    ShowMenuAndStatusBar = false;
+                }
+            }
+
+            IsFullScreen = WindowState == WindowState.FullScreen;
+        }
+
+        public static void SaveConfig()
+        {
+            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
+        }
+
+        public static async Task PerformanceCheck()
+        {
+            if (ConfigurationState.Instance.Logger.EnableTrace.Value)
+            {
+                string mainMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckLoggingEnabledMessage];
+                string secondaryMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckLoggingEnabledConfirmMessage];
 
                 UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
-                    dialogTitle,
-                    dialogMessage,
+                    mainMessage,
+                    secondaryMessage,
                     LocaleManager.Instance[LocaleKeys.InputDialogYes],
                     LocaleManager.Instance[LocaleKeys.InputDialogNo],
                     LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
 
-                UpdateWaitWindow waitingDialog = ContentDialogHelper.CreateWaitingDialog(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallWaitMessage]);
-
-                if (result == UserResult.Yes)
+                if (result != UserResult.Yes)
                 {
-                    Logger.Info?.Print(LogClass.Application, $"Installing firmware {firmwareVersion.VersionString}");
+                    ConfigurationState.Instance.Logger.EnableTrace.Value = false;
 
-                    Thread thread = new(() =>
-                    {
-                        Dispatcher.UIThread.InvokeAsync(delegate
-                        {
-                            waitingDialog.Show();
-                        });
-
-                        try
-                        {
-                            _owner.ContentManager.InstallFirmware(filename);
-
-                            Dispatcher.UIThread.InvokeAsync(async delegate
-                            {
-                                waitingDialog.Close();
-
-                                string message = string.Format(LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage], firmwareVersion.VersionString);
-
-                                await ContentDialogHelper.CreateInfoDialog(dialogTitle, message, LocaleManager.Instance[LocaleKeys.InputDialogOk], "", LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
-
-                                Logger.Info?.Print(LogClass.Application, message);
-
-                                // Purge Applet Cache.
-
-                                DirectoryInfo miiEditorCacheFolder = new DirectoryInfo(Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
-
-                                if (miiEditorCacheFolder.Exists)
-                                {
-                                    miiEditorCacheFolder.Delete(true);
-                                }
-                            });
-                        }
-                        catch (Exception ex)
-                        {
-                            Dispatcher.UIThread.InvokeAsync(async () =>
-                            {
-                                waitingDialog.Close();
-
-                                await ContentDialogHelper.CreateErrorDialog(ex.Message);
-                            });
-                        }
-                        finally
-                        {
-                            _owner.RefreshFirmwareStatus();
-                        }
-                    });
-
-                    thread.Name = "GUI.FirmwareInstallerThread";
-                    thread.Start();
+                    SaveConfig();
                 }
             }
-            catch (LibHac.Common.Keys.MissingKeyException ex)
-            {
-                Logger.Error?.Print(LogClass.Application, ex.ToString());
 
-                Dispatcher.UIThread.Post(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys, _owner));
-            }
-            catch (Exception ex)
+            if (!string.IsNullOrWhiteSpace(ConfigurationState.Instance.Graphics.ShadersDumpPath.Value))
             {
-                await ContentDialogHelper.CreateErrorDialog(ex.Message);
+                string mainMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckShaderDumpEnabledMessage];
+                string secondaryMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckShaderDumpEnabledConfirmMessage];
+
+                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
+                    mainMessage,
+                    secondaryMessage,
+                    LocaleManager.Instance[LocaleKeys.InputDialogYes],
+                    LocaleManager.Instance[LocaleKeys.InputDialogNo],
+                    LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
+
+                if (result != UserResult.Yes)
+                {
+                    ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = "";
+
+                    SaveConfig();
+                }
             }
         }
 
-        public async void InstallFirmwareFromFile()
-        {
-            OpenFileDialog dialog = new() { AllowMultiple = false };
-            dialog.Filters.Add(new FileDialogFilter { Name = LocaleManager.Instance[LocaleKeys.FileDialogAllTypes], Extensions = { "xci", "zip" } });
-            dialog.Filters.Add(new FileDialogFilter { Name = "XCI",                                        Extensions = { "xci" } });
-            dialog.Filters.Add(new FileDialogFilter { Name = "ZIP",                                        Extensions = { "zip" } });
-
-            string[] file = await dialog.ShowAsync(_owner);
-
-            if (file != null && file.Length > 0)
-            {
-                await HandleFirmwareInstallation(file[0]);
-            }
-        }
-
-        public async void InstallFirmwareFromFolder()
-        {
-            OpenFolderDialog dialog = new();
-
-            string folder = await dialog.ShowAsync(_owner);
-
-            if (!string.IsNullOrWhiteSpace(folder))
-            {
-                await HandleFirmwareInstallation(folder);
-            }
-        }
+#endregion
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml b/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml
new file mode 100644
index 0000000000..0d0ae11937
--- /dev/null
+++ b/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml
@@ -0,0 +1,216 @@
+<UserControl
+    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"
+    xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
+    mc:Ignorable="d"
+    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
+    x:DataType="viewModels:MainWindowViewModel"
+    x:Class="Ryujinx.Ava.UI.Views.Main.MainMenuBarView"
+    x:CompileBindings="True">
+    <Design.DataContext>
+        <viewModels:MainWindowViewModel />
+    </Design.DataContext>
+    <DockPanel HorizontalAlignment="Stretch">
+        <Menu
+            Name="Menu"
+            Height="35"
+            Margin="0"
+            HorizontalAlignment="Left">
+            <Menu.ItemsPanel>
+                <ItemsPanelTemplate>
+                    <DockPanel Margin="0" HorizontalAlignment="Stretch" />
+                </ItemsPanelTemplate>
+            </Menu.ItemsPanel>
+            <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarFile}">
+                <MenuItem
+                    Command="{ReflectionBinding OpenFile}"
+                    Header="{locale:Locale MenuBarFileOpenFromFile}"
+                    IsEnabled="{Binding EnableNonGameRunningControls}"
+                    ToolTip.Tip="{locale:Locale LoadApplicationFileTooltip}" />
+                <MenuItem
+                    Command="{ReflectionBinding OpenFolder}"
+                    Header="{locale:Locale MenuBarFileOpenUnpacked}"
+                    IsEnabled="{Binding EnableNonGameRunningControls}"
+                    ToolTip.Tip="{locale:Locale LoadApplicationFolderTooltip}" />
+                <MenuItem Header="{locale:Locale MenuBarFileOpenApplet}" IsEnabled="{Binding IsAppletMenuActive}">
+                    <MenuItem
+                        Click="OpenMiiApplet"
+                        Header="Mii Edit Applet"
+                        ToolTip.Tip="{locale:Locale MenuBarFileOpenAppletOpenMiiAppletToolTip}" />
+                </MenuItem>
+                <Separator />
+                <MenuItem
+                    Command="{ReflectionBinding OpenRyujinxFolder}"
+                    Header="{locale:Locale MenuBarFileOpenEmuFolder}"
+                    ToolTip.Tip="{locale:Locale OpenRyujinxFolderTooltip}" />
+                <MenuItem
+                    Command="{ReflectionBinding OpenLogsFolder}"
+                    Header="{locale:Locale MenuBarFileOpenLogsFolder}"
+                    ToolTip.Tip="{locale:Locale OpenRyujinxLogsTooltip}" />
+                <Separator />
+                <MenuItem
+                    Click="CloseWindow"
+                    Header="{locale:Locale MenuBarFileExit}"
+                    ToolTip.Tip="{locale:Locale ExitTooltip}" />
+            </MenuItem>
+            <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarOptions}">
+                <MenuItem
+                    Command="{ReflectionBinding ToggleFullscreen}"
+                    Header="{locale:Locale MenuBarOptionsToggleFullscreen}"
+                    InputGesture="F11" />
+                <MenuItem>
+                    <MenuItem.Icon>
+                        <CheckBox IsChecked="{Binding StartGamesInFullscreen, Mode=TwoWay}"
+                                  MinWidth="250">
+                            <TextBlock Text="{locale:Locale MenuBarOptionsStartGamesInFullscreen}"/>
+                        </CheckBox>
+                    </MenuItem.Icon>
+                </MenuItem>
+                <MenuItem IsVisible="{Binding ShowConsoleVisible}">
+                    <MenuItem.Icon>
+                        <CheckBox IsChecked="{Binding ShowConsole, Mode=TwoWay}"
+                                  MinWidth="250">
+                            <TextBlock Text="{locale:Locale MenuBarOptionsShowConsole}"/>
+                        </CheckBox>
+                    </MenuItem.Icon>
+                </MenuItem>
+                <Separator />
+                <MenuItem Header="{locale:Locale MenuBarOptionsChangeLanguage}">
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="de_DE"
+                        Header="Deutsch" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="en_US"
+                        Header="English (US)" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="es_ES"
+                        Header="Español (ES)" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="fr_FR"
+                        Header="Français" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="it_IT"
+                        Header="Italiano" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="pt_BR"
+                        Header="Português (BR)" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="tr_TR"
+                        Header="Türkçe" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="el_GR"
+                        Header="Ελληνικά" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="pl_PL"
+                        Header="Polski" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="ru_RU"
+                        Header="Русский" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="zh_CN"
+                        Header="简体中文" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="zh_TW"
+                        Header="繁體中文" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="ja_JP"
+                        Header="日本語" />
+                    <MenuItem
+                        Command="{ReflectionBinding ChangeLanguage}"
+                        CommandParameter="ko_KR"
+                        Header="한국어" />
+                </MenuItem>
+                <Separator />
+                <MenuItem
+                    Click="OpenSettings"
+                    Header="{locale:Locale MenuBarOptionsSettings}"
+                    ToolTip.Tip="{locale:Locale OpenSettingsTooltip}" />
+                <MenuItem
+                    Command="{ReflectionBinding ManageProfiles}"
+                    Header="{locale:Locale MenuBarOptionsManageUserProfiles}"
+                    IsEnabled="{Binding EnableNonGameRunningControls}"
+                    ToolTip.Tip="{locale:Locale OpenProfileManagerTooltip}" />
+            </MenuItem>
+            <MenuItem
+                Name="ActionsMenuItem"
+                VerticalAlignment="Center"
+                Header="{locale:Locale MenuBarActions}"
+                IsEnabled="{Binding IsGameRunning}">
+                <MenuItem
+                    Click="PauseEmulation_Click"
+                    Header="{locale:Locale MenuBarOptionsPauseEmulation}"
+                    InputGesture="{Binding PauseKey}"
+                    IsEnabled="{Binding !IsPaused}"
+                    IsVisible="{Binding !IsPaused}" />
+                <MenuItem
+                    Click="ResumeEmulation_Click"
+                    Header="{locale:Locale MenuBarOptionsResumeEmulation}"
+                    InputGesture="{Binding PauseKey}"
+                    IsEnabled="{Binding IsPaused}"
+                    IsVisible="{Binding IsPaused}" />
+                <MenuItem
+                    Click="StopEmulation_Click"
+                    Header="{locale:Locale MenuBarOptionsStopEmulation}"
+                    InputGesture="Escape"
+                    IsEnabled="{Binding IsGameRunning}"
+                    ToolTip.Tip="{locale:Locale StopEmulationTooltip}" />
+                <MenuItem Command="{ReflectionBinding SimulateWakeUpMessage}" Header="{locale:Locale MenuBarOptionsSimulateWakeUpMessage}" />
+                <Separator />
+                <MenuItem
+                    Name="ScanAmiiboMenuItem"
+                    AttachedToVisualTree="ScanAmiiboMenuItem_AttachedToVisualTree"
+                    Click="OpenAmiiboWindow"
+                    Header="{locale:Locale MenuBarActionsScanAmiibo}"
+                    IsEnabled="{Binding IsAmiiboRequested}" />
+                <MenuItem
+                    Command="{ReflectionBinding TakeScreenshot}"
+                    Header="{locale:Locale MenuBarFileToolsTakeScreenshot}"
+                    InputGesture="{Binding ScreenshotKey}"
+                    IsEnabled="{Binding IsGameRunning}" />
+                <MenuItem
+                    Command="{ReflectionBinding HideUi}"
+                    Header="{locale:Locale MenuBarFileToolsHideUi}"
+                    InputGesture="{Binding ShowUiKey}"
+                    IsEnabled="{Binding IsGameRunning}" />
+                <MenuItem
+                    Click="OpenCheatManagerForCurrentApp"
+                    Header="{locale:Locale GameListContextMenuManageCheat}"
+                    IsEnabled="{Binding IsGameRunning}" />
+            </MenuItem>
+            <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarTools}">
+                <MenuItem Header="{locale:Locale MenuBarToolsInstallFirmware}" IsEnabled="{Binding EnableNonGameRunningControls}">
+                    <MenuItem Command="{ReflectionBinding InstallFirmwareFromFile}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromFile}" />
+                    <MenuItem Command="{ReflectionBinding InstallFirmwareFromFolder}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" />
+                </MenuItem>
+            </MenuItem>
+            <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarHelp}">
+                <MenuItem
+                    Name="UpdateMenuItem"
+                    IsEnabled="{Binding CanUpdate}"
+                    Click="CheckForUpdates"
+                    Header="{locale:Locale MenuBarHelpCheckForUpdates}"
+                    ToolTip.Tip="{locale:Locale CheckUpdatesTooltip}" />
+                <Separator />
+                <MenuItem
+                    Click="OpenAboutWindow"
+                    Header="{locale:Locale MenuBarHelpAbout}"
+                    ToolTip.Tip="{locale:Locale OpenAboutTooltip}" />
+            </MenuItem>
+        </Menu>
+    </DockPanel>
+</UserControl>
\ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs b/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
new file mode 100644
index 0000000000..8c28abffe6
--- /dev/null
+++ b/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml.cs
@@ -0,0 +1,146 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Ryujinx.Ava.UI.ViewModels;
+using Ryujinx.Ava.UI.Windows;
+using System.Threading.Tasks;
+using LibHac.FsSystem;
+using LibHac.Ncm;
+using Ryujinx.HLE.HOS;
+using Ryujinx.Modules;
+
+namespace Ryujinx.Ava.UI.Views.Main
+{
+    public partial class MainMenuBarView : UserControl
+    {
+        public MainWindow Window { get; private set; }
+        public MainWindowViewModel ViewModel { get; private set; }
+
+        public MainMenuBarView()
+        {
+            InitializeComponent();
+        }
+
+        protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+        {
+            base.OnAttachedToVisualTree(e);
+
+            if (this.VisualRoot is MainWindow window)
+            {
+                Window = window;
+            }
+
+            ViewModel = Window.ViewModel;
+            DataContext = ViewModel;
+        }
+
+        private async void StopEmulation_Click(object sender, RoutedEventArgs e)
+        {
+            await Task.Run(() =>
+            {
+                Window.ViewModel.AppHost?.ShowExitPrompt();
+            });
+        }
+
+        private async void PauseEmulation_Click(object sender, RoutedEventArgs e)
+        {
+            await Task.Run(() =>
+            {
+                Window.ViewModel.AppHost?.Pause();
+            });
+        }
+
+        private async void ResumeEmulation_Click(object sender, RoutedEventArgs e)
+        {
+            await Task.Run(() =>
+            {
+                Window.ViewModel.AppHost?.Resume();
+            });
+        }
+
+        public async void OpenSettings(object sender, RoutedEventArgs e)
+        {
+            Window.SettingsWindow = new(Window.VirtualFileSystem, Window.ContentManager);
+
+            await Window.SettingsWindow.ShowDialog(Window);
+
+            ViewModel.LoadConfigurableHotKeys();
+        }
+
+        public void OpenMiiApplet(object sender, RoutedEventArgs e)
+        {
+            string contentPath = ViewModel.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
+
+            if (!string.IsNullOrEmpty(contentPath))
+            {
+                ViewModel.LoadApplication(contentPath, false, "Mii Applet");
+            }
+        }
+
+        public async void OpenAmiiboWindow(object sender, RoutedEventArgs e)
+        {
+            if (!ViewModel.IsAmiiboRequested)
+            {
+                return;
+            }
+
+            if (ViewModel.AppHost.Device.System.SearchingForAmiibo(out int deviceId))
+            {
+                string titleId = ViewModel.AppHost.Device.Application.TitleIdText.ToUpper();
+                AmiiboWindow window = new(ViewModel.ShowAll, ViewModel.LastScannedAmiiboId, titleId);
+
+                await window.ShowDialog(Window);
+
+                if (window.IsScanned)
+                {
+                    ViewModel.ShowAll = window.ViewModel.ShowAllAmiibo;
+                    ViewModel.LastScannedAmiiboId = window.ScannedAmiibo.GetId();
+
+                    ViewModel.AppHost.Device.System.ScanAmiibo(deviceId, ViewModel.LastScannedAmiiboId, window.ViewModel.UseRandomUuid);
+                }
+            }
+        }
+
+        public async void OpenCheatManagerForCurrentApp(object sender, RoutedEventArgs e)
+        {
+            if (!ViewModel.IsGameRunning)
+            {
+                return;
+            }
+
+            ApplicationLoader application = ViewModel.AppHost.Device.Application;
+            if (application != null)
+            {
+                await new CheatWindow(Window.VirtualFileSystem, application.TitleIdText, application.TitleName).ShowDialog(Window);
+
+                ViewModel.AppHost.Device.EnableCheats();
+            }
+        }
+
+        private void ScanAmiiboMenuItem_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
+        {
+            if (sender is MenuItem)
+            {
+                ViewModel.IsAmiiboRequested = Window.ViewModel.AppHost.Device.System.SearchingForAmiibo(out _);
+            }
+        }
+
+        public async void CheckForUpdates(object sender, RoutedEventArgs e)
+        {
+            if (Updater.CanUpdate(true, Window))
+            {
+                await Updater.BeginParse(Window, true);
+            }
+        }
+
+        public async void OpenAboutWindow(object sender, RoutedEventArgs e)
+        {
+            await AboutWindow.Show();
+        }
+
+        public void CloseWindow(object sender, RoutedEventArgs e)
+        {
+            Window.Close();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml b/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml
new file mode 100644
index 0000000000..1670569542
--- /dev/null
+++ b/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml
@@ -0,0 +1,232 @@
+<UserControl
+    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"
+    xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
+    xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
+    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
+    mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+    x:Class="Ryujinx.Ava.UI.Views.Main.MainStatusBarView"
+    x:CompileBindings="True"
+    x:DataType="viewModels:MainWindowViewModel">
+    <Design.DataContext>
+        <viewModels:MainWindowViewModel />
+    </Design.DataContext>
+    <Grid
+        Name="StatusBar"
+        Margin="0"
+        MinHeight="22"
+        HorizontalAlignment="Stretch"
+        VerticalAlignment="Bottom"
+        Background="{DynamicResource ThemeContentBackgroundColor}"
+        DockPanel.Dock="Bottom"
+        IsVisible="{Binding ShowMenuAndStatusBar}">
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="Auto" />
+            <ColumnDefinition Width="Auto" />
+            <ColumnDefinition Width="*" />
+            <ColumnDefinition Width="Auto" />
+        </Grid.ColumnDefinitions>
+        <StackPanel
+            Grid.Column="0"
+            Margin="5"
+            VerticalAlignment="Center"
+            IsVisible="{Binding EnableNonGameRunningControls}">
+            <Grid Margin="0">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="Auto" />
+                    <ColumnDefinition Width="Auto" />
+                    <ColumnDefinition />
+                </Grid.ColumnDefinitions>
+                <Button
+                    Width="25"
+                    Height="25"
+                    MinWidth="0"
+                    Margin="0,0,5,0"
+                    VerticalAlignment="Center"
+                    Background="Transparent"
+                    Command="{ReflectionBinding LoadApplications}">
+                    <ui:SymbolIcon
+                        Width="50"
+                        Height="100"
+                        Symbol="Refresh" />
+                </Button>
+                <TextBlock
+                    Name="LoadStatus"
+                    Grid.Column="1"
+                    Margin="0,0,5,0"
+                    VerticalAlignment="Center"
+                    IsVisible="{Binding EnableNonGameRunningControls}"
+                    Text="{locale:Locale StatusBarGamesLoaded}" />
+                <ProgressBar
+                    Name="LoadProgressBar"
+                    Grid.Column="2"
+                    Height="6"
+                    VerticalAlignment="Center"
+                    Foreground="{DynamicResource HighlightColor}"
+                    IsVisible="{Binding StatusBarVisible}"
+                    Maximum="{Binding StatusBarProgressMaximum}"
+                    Value="{Binding StatusBarProgressValue}" />
+            </Grid>
+        </StackPanel>
+        <StackPanel
+            Grid.Column="1"
+            Margin="0,2"
+            HorizontalAlignment="Left"
+            VerticalAlignment="Center"
+            IsVisible="{Binding IsGameRunning}"
+            MaxHeight="18"
+            Orientation="Horizontal">
+            <TextBlock
+                Name="VsyncStatus"
+                Margin="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                Foreground="{Binding VsyncColor}"
+                IsVisible="{Binding !ShowLoadProgress}"
+                PointerReleased="VsyncStatus_PointerReleased"
+                Text="VSync"
+                TextAlignment="Left" />
+            <Border
+                Width="2"
+                Height="12"
+                Margin="0"
+                BorderBrush="Gray"
+                BorderThickness="1"
+                IsVisible="{Binding !ShowLoadProgress}" />
+            <TextBlock
+                Name="DockedStatus"
+                Margin="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                IsVisible="{Binding !ShowLoadProgress}"
+                PointerReleased="DockedStatus_PointerReleased"
+                Text="{Binding DockedStatusText}"
+                TextAlignment="Left" />
+            <Border
+                Width="2"
+                Height="12"
+                Margin="0"
+                BorderBrush="Gray"
+                BorderThickness="1"
+                IsVisible="{Binding !ShowLoadProgress}" />
+            <TextBlock
+                Name="AspectRatioStatus"
+                Margin="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                IsVisible="{Binding !ShowLoadProgress}"
+                PointerReleased="AspectRatioStatus_PointerReleased"
+                Text="{Binding AspectRatioStatusText}"
+                TextAlignment="Left" />
+            <Border
+                Width="2"
+                Height="12"
+                Margin="0"
+                BorderBrush="Gray"
+                BorderThickness="1"
+                IsVisible="{Binding !ShowLoadProgress}" />
+            <ui:ToggleSplitButton
+                Name="VolumeStatus"
+                Padding="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                VerticalContentAlignment="Center"
+                Background="{DynamicResource ThemeContentBackgroundColor}"
+                BorderThickness="0"
+                Content="{Binding VolumeStatusText}"
+                IsChecked="{Binding VolumeMuted}"
+                IsVisible="{Binding !ShowLoadProgress}">
+                <ui:ToggleSplitButton.Flyout>
+                    <Flyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway">
+                        <Grid Margin="0">
+                            <Slider
+                                MaxHeight="40"
+                                Width="150"
+                                Margin="0"
+                                Padding="0"
+                                IsSnapToTickEnabled="True"
+                                LargeChange="0.05"
+                                Maximum="1"
+                                Minimum="0"
+                                SmallChange="0.01"
+                                TickFrequency="0.05"
+                                ToolTip.Tip="{locale:Locale AudioVolumeTooltip}"
+                                Value="{Binding Volume}" />
+                        </Grid>
+                    </Flyout>
+                </ui:ToggleSplitButton.Flyout>
+            </ui:ToggleSplitButton>
+            <Border
+                Width="2"
+                Height="12"
+                Margin="0"
+                BorderBrush="Gray"
+                BorderThickness="1"
+                IsVisible="{Binding !ShowLoadProgress}" />
+            <TextBlock
+                Margin="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                IsVisible="{Binding !ShowLoadProgress}"
+                Text="{Binding GameStatusText}"
+                TextAlignment="Left" />
+            <Border
+                Width="2"
+                Height="12"
+                Margin="0"
+                BorderBrush="Gray"
+                BorderThickness="1"
+                IsVisible="{Binding !ShowLoadProgress}" />
+            <TextBlock
+                Margin="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                IsVisible="{Binding !ShowLoadProgress}"
+                Text="{Binding FifoStatusText}"
+                TextAlignment="Left" />
+            <Border
+                Width="2"
+                Height="12"
+                Margin="0"
+                BorderBrush="Gray"
+                BorderThickness="1"
+                IsVisible="{Binding !ShowLoadProgress}" />
+            <TextBlock
+                Margin="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                IsVisible="{Binding !ShowLoadProgress}"
+                Text="{Binding BackendText}"
+                TextAlignment="Left" />
+            <Border
+                Width="2"
+                Height="12"
+                Margin="0"
+                BorderBrush="Gray"
+                BorderThickness="1"
+                IsVisible="{Binding !ShowLoadProgress}" />
+            <TextBlock
+                Margin="5,0,5,0"
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                IsVisible="{Binding !ShowLoadProgress}"
+                Text="{Binding GpuNameText}"
+                TextAlignment="Left" />
+        </StackPanel>
+        <StackPanel
+            Grid.Column="3"
+            Margin="0,0,5,0"
+            VerticalAlignment="Center"
+            IsVisible="{Binding ShowFirmwareStatus}"
+            Orientation="Horizontal">
+            <TextBlock
+                Name="FirmwareStatus"
+                Margin="0"
+                HorizontalAlignment="Right"
+                VerticalAlignment="Center"
+                Text="{locale:Locale StatusBarSystemVersion}" />
+        </StackPanel>
+    </Grid>
+</UserControl>
\ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs b/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs
new file mode 100644
index 0000000000..d1050dddf7
--- /dev/null
+++ b/Ryujinx.Ava/UI/Views/Main/MainStatusBarView.axaml.cs
@@ -0,0 +1,52 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Ryujinx.Ava.UI.Windows;
+using Ryujinx.Common.Configuration;
+using Ryujinx.Common.Logging;
+using Ryujinx.Ui.Common.Configuration;
+using System;
+
+namespace Ryujinx.Ava.UI.Views.Main
+{
+    public partial class MainStatusBarView : UserControl
+    {
+        public MainWindow Window;
+
+        public MainStatusBarView()
+        {
+            InitializeComponent();
+        }
+
+        protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+        {
+            base.OnAttachedToVisualTree(e);
+
+            if (this.VisualRoot is MainWindow window)
+            {
+                Window = window;
+            }
+
+            DataContext = Window.ViewModel;
+        }
+
+        private void VsyncStatus_PointerReleased(object sender, PointerReleasedEventArgs e)
+        {
+            Window.ViewModel.AppHost.Device.EnableDeviceVsync = !Window.ViewModel.AppHost.Device.EnableDeviceVsync;
+
+            Logger.Info?.Print(LogClass.Application, $"VSync toggled to: {Window.ViewModel.AppHost.Device.EnableDeviceVsync}");
+        }
+
+        private void DockedStatus_PointerReleased(object sender, PointerReleasedEventArgs e)
+        {
+            ConfigurationState.Instance.System.EnableDockedMode.Value = !ConfigurationState.Instance.System.EnableDockedMode.Value;
+        }
+
+        private void AspectRatioStatus_PointerReleased(object sender, PointerReleasedEventArgs e)
+        {
+            AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
+
+            ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml b/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml
new file mode 100644
index 0000000000..e83a650462
--- /dev/null
+++ b/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml
@@ -0,0 +1,176 @@
+<UserControl
+    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"
+    xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
+    xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
+    xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
+    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
+    mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+    x:Class="Ryujinx.Ava.UI.Views.Main.MainViewControls"
+    x:CompileBindings="True"
+    x:DataType="viewModels:MainWindowViewModel">
+    <Design.DataContext>
+        <viewModels:MainWindowViewModel />
+    </Design.DataContext>
+    <DockPanel
+        Margin="0,0,0,5"
+        HorizontalAlignment="Stretch">
+        <Button
+            Width="40"
+            MinWidth="40"
+            Margin="5,2,0,2"
+            VerticalAlignment="Stretch"
+            Command="{ReflectionBinding SetListMode}"
+            IsEnabled="{Binding IsGrid}">
+            <ui:FontIcon
+                Margin="0"
+                HorizontalAlignment="Stretch"
+                VerticalAlignment="Center"
+                FontFamily="avares://FluentAvalonia/Fonts#Symbols"
+                Glyph="{helpers:GlyphValueConverter List}" />
+        </Button>
+        <Button
+            Width="40"
+            MinWidth="40"
+            Margin="5,2,5,2"
+            VerticalAlignment="Stretch"
+            Command="{ReflectionBinding SetGridMode}"
+            IsEnabled="{Binding IsList}">
+            <ui:FontIcon
+                Margin="0"
+                HorizontalAlignment="Stretch"
+                VerticalAlignment="Center"
+                FontFamily="avares://FluentAvalonia/Fonts#Symbols"
+                Glyph="{helpers:GlyphValueConverter Grid}" />
+        </Button>
+        <TextBlock
+            Margin="10,0"
+            VerticalAlignment="Center"
+            Text="{locale:Locale IconSize}"
+            ToolTip.Tip="{locale:Locale IconSizeTooltip}" />
+        <Slider
+            Width="150"
+            Height="35"
+            Margin="5,-10,5,0"
+            VerticalAlignment="Center"
+            IsSnapToTickEnabled="True"
+            Maximum="4"
+            Minimum="1"
+            TickFrequency="1"
+            ToolTip.Tip="{locale:Locale IconSizeTooltip}"
+            Value="{Binding GridSizeScale}" />
+        <CheckBox
+            Margin="0"
+            VerticalAlignment="Center"
+            IsChecked="{Binding ShowNames, Mode=TwoWay}"
+            IsVisible="{Binding IsGrid}">
+            <TextBlock Margin="5,3,0,0" Text="{locale:Locale CommonShowNames}" />
+        </CheckBox>
+        <TextBox
+            Name="SearchBox"
+            MinWidth="200"
+            Margin="5,0,5,0"
+            HorizontalAlignment="Right"
+            VerticalAlignment="Center"
+            VerticalContentAlignment="Center"
+            DockPanel.Dock="Right"
+            KeyUp="SearchBox_OnKeyUp"
+            Text="{Binding SearchText}"
+            Watermark="{locale:Locale MenuSearch}" />
+        <ui:DropDownButton
+            Width="150"
+            HorizontalAlignment="Right"
+            VerticalAlignment="Center"
+            Content="{Binding SortName}"
+            DockPanel.Dock="Right">
+            <ui:DropDownButton.Flyout>
+                <Flyout Placement="Bottom">
+                    <StackPanel
+                        Margin="0"
+                        HorizontalAlignment="Stretch"
+                        Orientation="Vertical">
+                        <StackPanel>
+                            <RadioButton
+                                Checked="Sort_Checked"
+                                Content="{locale:Locale CommonFavorite}"
+                                GroupName="Sort"
+                                IsChecked="{Binding IsSortedByFavorite, Mode=OneTime}"
+                                Tag="Favorite" />
+                            <RadioButton
+                                Checked="Sort_Checked"
+                                Content="{locale:Locale GameListHeaderApplication}"
+                                GroupName="Sort"
+                                IsChecked="{Binding IsSortedByTitle, Mode=OneTime}"
+                                Tag="Title" />
+                            <RadioButton
+                                Checked="Sort_Checked"
+                                Content="{locale:Locale GameListHeaderDeveloper}"
+                                GroupName="Sort"
+                                IsChecked="{Binding IsSortedByDeveloper, Mode=OneTime}"
+                                Tag="Developer" />
+                            <RadioButton
+                                Checked="Sort_Checked"
+                                Content="{locale:Locale GameListHeaderTimePlayed}"
+                                GroupName="Sort"
+                                IsChecked="{Binding IsSortedByTimePlayed, Mode=OneTime}"
+                                Tag="TotalTimePlayed" />
+                            <RadioButton
+                                Checked="Sort_Checked"
+                                Content="{locale:Locale GameListHeaderLastPlayed}"
+                                GroupName="Sort"
+                                IsChecked="{Binding IsSortedByLastPlayed, Mode=OneTime}"
+                                Tag="LastPlayed" />
+                            <RadioButton
+                                Checked="Sort_Checked"
+                                Content="{locale:Locale GameListHeaderFileExtension}"
+                                GroupName="Sort"
+                                IsChecked="{Binding IsSortedByType, Mode=OneTime}"
+                                Tag="FileType" />
+                            <RadioButton
+                                Checked="Sort_Checked"
+                                Content="{locale:Locale GameListHeaderFileSize}"
+                                GroupName="Sort"
+                                IsChecked="{Binding IsSortedBySize, Mode=OneTime}"
+                                Tag="FileSize" />
+                            <RadioButton
+                                Checked="Sort_Checked"
+                                Content="{locale:Locale GameListHeaderPath}"
+                                GroupName="Sort"
+                                IsChecked="{Binding IsSortedByPath, Mode=OneTime}"
+                                Tag="Path" />
+                        </StackPanel>
+                        <Border
+                            Width="60"
+                            Height="2"
+                            Margin="5"
+                            HorizontalAlignment="Stretch"
+                            BorderBrush="White"
+                            BorderThickness="0,1,0,0">
+                            <Separator Height="0" HorizontalAlignment="Stretch" />
+                        </Border>
+                        <RadioButton
+                            Checked="Order_Checked"
+                            Content="{locale:Locale OrderAscending}"
+                            GroupName="Order"
+                            IsChecked="{Binding IsAscending, Mode=OneTime}"
+                            Tag="Ascending" />
+                        <RadioButton
+                            Checked="Order_Checked"
+                            Content="{locale:Locale OrderDescending}"
+                            GroupName="Order"
+                            IsChecked="{Binding !IsAscending, Mode=OneTime}"
+                            Tag="Descending" />
+                    </StackPanel>
+                </Flyout>
+            </ui:DropDownButton.Flyout>
+        </ui:DropDownButton>
+        <TextBlock
+            Margin="10,0"
+            HorizontalAlignment="Right"
+            VerticalAlignment="Center"
+            DockPanel.Dock="Right"
+            Text="{locale:Locale CommonSort}" />
+    </DockPanel>
+</UserControl>
\ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs b/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs
new file mode 100644
index 0000000000..841d59dec9
--- /dev/null
+++ b/Ryujinx.Ava/UI/Views/Main/MainViewControls.axaml.cs
@@ -0,0 +1,54 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Interactivity;
+using Ryujinx.Ava.Common;
+using Ryujinx.Ava.UI.ViewModels;
+using Ryujinx.Ava.UI.Windows;
+using System;
+
+namespace Ryujinx.Ava.UI.Views.Main
+{
+    public partial class MainViewControls : UserControl
+    {
+        public MainWindowViewModel ViewModel;
+    
+        public MainViewControls()
+        {
+            InitializeComponent();
+        }
+
+        protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+        {
+            base.OnAttachedToVisualTree(e);
+
+            if (this.VisualRoot is MainWindow window)
+            {
+                ViewModel = window.ViewModel;
+            }
+
+            DataContext = ViewModel;
+        }
+
+        public void Sort_Checked(object sender, RoutedEventArgs args)
+        {
+            if (sender is RadioButton button)
+            {
+                ViewModel.Sort(Enum.Parse<ApplicationSort>(button.Tag.ToString()));
+            }
+        }
+    
+        public void Order_Checked(object sender, RoutedEventArgs args)
+        {
+            if (sender is RadioButton button)
+            {
+                ViewModel.Sort(button.Tag.ToString() != "Descending");
+            }
+        }
+    
+        private void SearchBox_OnKeyUp(object sender, KeyEventArgs e)
+        {
+            ViewModel.SearchText = SearchBox.Text;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Windows/MainWindow.axaml b/Ryujinx.Ava/UI/Windows/MainWindow.axaml
index 63d939a8e2..c3d34e75df 100644
--- a/Ryujinx.Ava/UI/Windows/MainWindow.axaml
+++ b/Ryujinx.Ava/UI/Windows/MainWindow.axaml
@@ -2,15 +2,16 @@
     x:Class="Ryujinx.Ava.UI.Windows.MainWindow"
     xmlns="https://github.com/avaloniaui"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-    xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-    xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-    xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
-    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
     xmlns:window="clr-namespace:Ryujinx.Ava.UI.Windows"
+    xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
     xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
-    Title="Ryujinx"
+    xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
+    xmlns:main="clr-namespace:Ryujinx.Ava.UI.Views.Main"
+    Cursor="{Binding Cursor}"
+    Title="{Binding Title}"
+    WindowState="{Binding WindowState}"
     Width="1280"
     Height="777"
     MinWidth="1092"
@@ -66,206 +67,8 @@
                 VerticalAlignment="Stretch"
                 IsVisible="{Binding ShowMenuAndStatusBar}"
                 Orientation="Vertical">
-                <DockPanel HorizontalAlignment="Stretch">
-                    <Menu
-                        Name="Menu"
-                        Height="35"
-                        Margin="0"
-                        HorizontalAlignment="Left">
-                        <Menu.ItemsPanel>
-                            <ItemsPanelTemplate>
-                                <DockPanel Margin="0" HorizontalAlignment="Stretch" />
-                            </ItemsPanelTemplate>
-                        </Menu.ItemsPanel>
-                        <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarFile}">
-                            <MenuItem
-                                Command="{ReflectionBinding OpenFile}"
-                                Header="{locale:Locale MenuBarFileOpenFromFile}"
-                                IsEnabled="{Binding EnableNonGameRunningControls}"
-                                ToolTip.Tip="{locale:Locale LoadApplicationFileTooltip}" />
-                            <MenuItem
-                                Command="{ReflectionBinding OpenFolder}"
-                                Header="{locale:Locale MenuBarFileOpenUnpacked}"
-                                IsEnabled="{Binding EnableNonGameRunningControls}"
-                                ToolTip.Tip="{locale:Locale LoadApplicationFolderTooltip}" />
-                            <MenuItem Header="{locale:Locale MenuBarFileOpenApplet}" IsEnabled="{Binding IsAppletMenuActive}">
-                                <MenuItem
-                                    Command="{ReflectionBinding OpenMiiApplet}"
-                                    Header="Mii Edit Applet"
-                                    ToolTip.Tip="{locale:Locale MenuBarFileOpenAppletOpenMiiAppletToolTip}" />
-                            </MenuItem>
-                            <Separator />
-                            <MenuItem
-                                Command="{ReflectionBinding OpenRyujinxFolder}"
-                                Header="{locale:Locale MenuBarFileOpenEmuFolder}"
-                                ToolTip.Tip="{locale:Locale OpenRyujinxFolderTooltip}" />
-                            <MenuItem
-                                Command="{ReflectionBinding OpenLogsFolder}"
-                                Header="{locale:Locale MenuBarFileOpenLogsFolder}"
-                                ToolTip.Tip="{locale:Locale OpenRyujinxLogsTooltip}" />
-                            <Separator />
-                            <MenuItem
-                                Command="{ReflectionBinding CloseWindow}"
-                                Header="{locale:Locale MenuBarFileExit}"
-                                ToolTip.Tip="{locale:Locale ExitTooltip}" />
-                        </MenuItem>
-                        <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarOptions}">
-                            <MenuItem
-                                Command="{ReflectionBinding ToggleFullscreen}"
-                                Header="{locale:Locale MenuBarOptionsToggleFullscreen}"
-                                InputGesture="F11" />
-                            <MenuItem>
-                                <MenuItem.Icon>
-                                    <CheckBox IsChecked="{Binding StartGamesInFullscreen, Mode=TwoWay}"
-                                              MinWidth="250">
-                                        <TextBlock Text="{locale:Locale MenuBarOptionsStartGamesInFullscreen}"/>
-                                    </CheckBox>
-                                </MenuItem.Icon>
-                            </MenuItem>
-                            <MenuItem IsVisible="{Binding ShowConsoleVisible}">
-                                <MenuItem.Icon>
-                                    <CheckBox IsChecked="{Binding ShowConsole, Mode=TwoWay}"
-                                              MinWidth="250">
-                                        <TextBlock Text="{locale:Locale MenuBarOptionsShowConsole}"/>
-                                    </CheckBox>
-                                </MenuItem.Icon>
-                            </MenuItem>
-                            <Separator />
-                            <MenuItem Header="{locale:Locale MenuBarOptionsChangeLanguage}">
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="de_DE"
-                                    Header="Deutsch" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="en_US"
-                                    Header="English (US)" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="es_ES"
-                                    Header="Español (ES)" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="fr_FR"
-                                    Header="Français" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="it_IT"
-                                    Header="Italiano" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="pt_BR"
-                                    Header="Português (BR)" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="tr_TR"
-                                    Header="Türkçe" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="el_GR"
-                                    Header="Ελληνικά" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="pl_PL"
-                                    Header="Polski" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="ru_RU"
-                                    Header="Русский" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="zh_CN"
-                                    Header="简体中文" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="zh_TW"
-                                    Header="繁體中文" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="ja_JP"
-                                    Header="日本語" />
-                                <MenuItem
-                                    Command="{ReflectionBinding ChangeLanguage}"
-                                    CommandParameter="ko_KR"
-                                    Header="한국어" />
-                            </MenuItem>
-                            <Separator />
-                            <MenuItem
-                                Command="{ReflectionBinding OpenSettings}"
-                                Header="{locale:Locale MenuBarOptionsSettings}"
-                                ToolTip.Tip="{locale:Locale OpenSettingsTooltip}" />
-                            <MenuItem
-                                Command="{ReflectionBinding ManageProfiles}"
-                                Header="{locale:Locale MenuBarOptionsManageUserProfiles}"
-                                IsEnabled="{Binding EnableNonGameRunningControls}"
-                                ToolTip.Tip="{locale:Locale OpenProfileManagerTooltip}" />
-                        </MenuItem>
-                        <MenuItem
-                            Name="ActionsMenuItem"
-                            VerticalAlignment="Center"
-                            Header="{locale:Locale MenuBarActions}"
-                            IsEnabled="{Binding IsGameRunning}">
-                            <MenuItem
-                                Click="PauseEmulation_Click"
-                                Header="{locale:Locale MenuBarOptionsPauseEmulation}"
-                                InputGesture="{Binding PauseKey}"
-                                IsEnabled="{Binding !IsPaused}"
-                                IsVisible="{Binding !IsPaused}" />
-                            <MenuItem
-                                Click="ResumeEmulation_Click"
-                                Header="{locale:Locale MenuBarOptionsResumeEmulation}"
-                                InputGesture="{Binding PauseKey}"
-                                IsEnabled="{Binding IsPaused}"
-                                IsVisible="{Binding IsPaused}" />
-                            <MenuItem
-                                Click="StopEmulation_Click"
-                                Header="{locale:Locale MenuBarOptionsStopEmulation}"
-                                InputGesture="Escape"
-                                IsEnabled="{Binding IsGameRunning}"
-                                ToolTip.Tip="{locale:Locale StopEmulationTooltip}" />
-                            <MenuItem Command="{ReflectionBinding SimulateWakeUpMessage}" Header="{locale:Locale MenuBarOptionsSimulateWakeUpMessage}" />
-                            <Separator />
-                            <MenuItem
-                                Name="ScanAmiiboMenuItem"
-                                AttachedToVisualTree="ScanAmiiboMenuItem_AttachedToVisualTree"
-                                Command="{ReflectionBinding OpenAmiiboWindow}"
-                                Header="{locale:Locale MenuBarActionsScanAmiibo}"
-                                IsEnabled="{Binding IsAmiiboRequested}" />
-                            <MenuItem
-                                Command="{ReflectionBinding TakeScreenshot}"
-                                Header="{locale:Locale MenuBarFileToolsTakeScreenshot}"
-                                InputGesture="{Binding ScreenshotKey}"
-                                IsEnabled="{Binding IsGameRunning}" />
-                            <MenuItem
-                                Command="{ReflectionBinding HideUi}"
-                                Header="{locale:Locale MenuBarFileToolsHideUi}"
-                                InputGesture="{Binding ShowUiKey}"
-                                IsEnabled="{Binding IsGameRunning}" />
-                            <MenuItem
-                                Command="{ReflectionBinding OpenCheatManagerForCurrentApp}"
-                                Header="{locale:Locale GameListContextMenuManageCheat}"
-                                IsEnabled="{Binding IsGameRunning}" />
-                        </MenuItem>
-                        <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarTools}">
-                            <MenuItem Header="{locale:Locale MenuBarToolsInstallFirmware}" IsEnabled="{Binding EnableNonGameRunningControls}">
-                                <MenuItem Command="{ReflectionBinding InstallFirmwareFromFile}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromFile}" />
-                                <MenuItem Command="{ReflectionBinding InstallFirmwareFromFolder}" Header="{locale:Locale MenuBarFileToolsInstallFirmwareFromDirectory}" />
-                            </MenuItem>
-                        </MenuItem>
-                        <MenuItem VerticalAlignment="Center" Header="{locale:Locale MenuBarHelp}">
-                            <MenuItem
-                                Name="UpdateMenuItem"
-                                Command="{ReflectionBinding CheckForUpdates}"
-                                Header="{locale:Locale MenuBarHelpCheckForUpdates}"
-                                ToolTip.Tip="{locale:Locale CheckUpdatesTooltip}" />
-                            <Separator />
-                            <MenuItem
-                                Command="{ReflectionBinding OpenAboutWindow}"
-                                Header="{locale:Locale MenuBarHelpAbout}"
-                                ToolTip.Tip="{locale:Locale OpenAboutTooltip}" />
-                        </MenuItem>
-                    </Menu>
-                </DockPanel>
+                <main:MainMenuBarView 
+                    Name="MenuBarView" />
             </StackPanel>
             <ContentControl
                 Name="MainContent"
@@ -277,171 +80,14 @@
                 BorderThickness="0,0,0,0"
                 DockPanel.Dock="Top"
                 IsVisible="{Binding ShowContent}">
-                <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
+                <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Name="GameLibrary">
                     <Grid.RowDefinitions>
                         <RowDefinition Height="Auto" />
                         <RowDefinition Height="*" />
                     </Grid.RowDefinitions>
-                    <DockPanel
-                        Grid.Row="0"
-                        Margin="0,0,0,5"
-                        HorizontalAlignment="Stretch">
-                        <Button
-                            Width="40"
-                            MinWidth="40"
-                            Margin="5,2,0,2"
-                            VerticalAlignment="Stretch"
-                            Command="{ReflectionBinding SetListMode}"
-                            IsEnabled="{Binding IsGrid}">
-                            <ui:FontIcon
-                                Margin="0"
-                                HorizontalAlignment="Stretch"
-                                VerticalAlignment="Center"
-                                FontFamily="avares://FluentAvalonia/Fonts#Symbols"
-                                Glyph="{helpers:GlyphValueConverter List}" />
-                        </Button>
-                        <Button
-                            Width="40"
-                            MinWidth="40"
-                            Margin="5,2,5,2"
-                            VerticalAlignment="Stretch"
-                            Command="{ReflectionBinding SetGridMode}"
-                            IsEnabled="{Binding IsList}">
-                            <ui:FontIcon
-                                Margin="0"
-                                HorizontalAlignment="Stretch"
-                                VerticalAlignment="Center"
-                                FontFamily="avares://FluentAvalonia/Fonts#Symbols"
-                                Glyph="{helpers:GlyphValueConverter Grid}" />
-                        </Button>
-                        <TextBlock
-                            Margin="10,0"
-                            VerticalAlignment="Center"
-                            Text="{locale:Locale IconSize}"
-                            ToolTip.Tip="{locale:Locale IconSizeTooltip}" />
-                        <Slider
-                            Width="150"
-                            Height="35"
-                            Margin="5,-10,5,0"
-                            VerticalAlignment="Center"
-                            IsSnapToTickEnabled="True"
-                            Maximum="4"
-                            Minimum="1"
-                            TickFrequency="1"
-                            ToolTip.Tip="{locale:Locale IconSizeTooltip}"
-                            Value="{Binding GridSizeScale}" />
-                        <CheckBox
-                            Margin="0"
-                            VerticalAlignment="Center"
-                            IsChecked="{Binding ShowNames, Mode=TwoWay}"
-                            IsVisible="{Binding IsGrid}">
-                            <TextBlock Margin="5,3,0,0" Text="{locale:Locale CommonShowNames}" />
-                        </CheckBox>
-                        <TextBox
-                            Name="SearchBox"
-                            MinWidth="200"
-                            Margin="5,0,5,0"
-                            HorizontalAlignment="Right"
-                            VerticalAlignment="Center"
-                            VerticalContentAlignment="Center"
-                            DockPanel.Dock="Right"
-                            KeyUp="SearchBox_OnKeyUp"
-                            Text="{Binding SearchText}"
-                            Watermark="{locale:Locale MenuSearch}" />
-                        <ui:DropDownButton
-                            Width="150"
-                            HorizontalAlignment="Right"
-                            VerticalAlignment="Center"
-                            Content="{Binding SortName}"
-                            DockPanel.Dock="Right">
-                            <ui:DropDownButton.Flyout>
-                                <Flyout Placement="Bottom">
-                                    <StackPanel
-                                        Margin="0"
-                                        HorizontalAlignment="Stretch"
-                                        Orientation="Vertical">
-                                        <StackPanel>
-                                            <RadioButton
-                                                Checked="Sort_Checked"
-                                                Content="{locale:Locale CommonFavorite}"
-                                                GroupName="Sort"
-                                                IsChecked="{Binding IsSortedByFavorite, Mode=OneTime}"
-                                                Tag="Favorite" />
-                                            <RadioButton
-                                                Checked="Sort_Checked"
-                                                Content="{locale:Locale GameListHeaderApplication}"
-                                                GroupName="Sort"
-                                                IsChecked="{Binding IsSortedByTitle, Mode=OneTime}"
-                                                Tag="Title" />
-                                            <RadioButton
-                                                Checked="Sort_Checked"
-                                                Content="{locale:Locale GameListHeaderDeveloper}"
-                                                GroupName="Sort"
-                                                IsChecked="{Binding IsSortedByDeveloper, Mode=OneTime}"
-                                                Tag="Developer" />
-                                            <RadioButton
-                                                Checked="Sort_Checked"
-                                                Content="{locale:Locale GameListHeaderTimePlayed}"
-                                                GroupName="Sort"
-                                                IsChecked="{Binding IsSortedByTimePlayed, Mode=OneTime}"
-                                                Tag="TotalTimePlayed" />
-                                            <RadioButton
-                                                Checked="Sort_Checked"
-                                                Content="{locale:Locale GameListHeaderLastPlayed}"
-                                                GroupName="Sort"
-                                                IsChecked="{Binding IsSortedByLastPlayed, Mode=OneTime}"
-                                                Tag="LastPlayed" />
-                                            <RadioButton
-                                                Checked="Sort_Checked"
-                                                Content="{locale:Locale GameListHeaderFileExtension}"
-                                                GroupName="Sort"
-                                                IsChecked="{Binding IsSortedByType, Mode=OneTime}"
-                                                Tag="FileType" />
-                                            <RadioButton
-                                                Checked="Sort_Checked"
-                                                Content="{locale:Locale GameListHeaderFileSize}"
-                                                GroupName="Sort"
-                                                IsChecked="{Binding IsSortedBySize, Mode=OneTime}"
-                                                Tag="FileSize" />
-                                            <RadioButton
-                                                Checked="Sort_Checked"
-                                                Content="{locale:Locale GameListHeaderPath}"
-                                                GroupName="Sort"
-                                                IsChecked="{Binding IsSortedByPath, Mode=OneTime}"
-                                                Tag="Path" />
-                                        </StackPanel>
-                                        <Border
-                                            Width="60"
-                                            Height="2"
-                                            Margin="5"
-                                            HorizontalAlignment="Stretch"
-                                            BorderBrush="White"
-                                            BorderThickness="0,1,0,0">
-                                            <Separator Height="0" HorizontalAlignment="Stretch" />
-                                        </Border>
-                                        <RadioButton
-                                            Checked="Order_Checked"
-                                            Content="{locale:Locale OrderAscending}"
-                                            GroupName="Order"
-                                            IsChecked="{Binding IsAscending, Mode=OneTime}"
-                                            Tag="Ascending" />
-                                        <RadioButton
-                                            Checked="Order_Checked"
-                                            Content="{locale:Locale OrderDescending}"
-                                            GroupName="Order"
-                                            IsChecked="{Binding !IsAscending, Mode=OneTime}"
-                                            Tag="Descending" />
-                                    </StackPanel>
-                                </Flyout>
-                            </ui:DropDownButton.Flyout>
-                        </ui:DropDownButton>
-                        <TextBlock
-                            Margin="10,0"
-                            HorizontalAlignment="Right"
-                            VerticalAlignment="Center"
-                            DockPanel.Dock="Right"
-                            Text="{locale:Locale CommonSort}" />
-                    </DockPanel>
+                    <main:MainViewControls
+                        Name="ViewControls"
+                        Grid.Row="0"/>
                     <controls:GameListView
                         x:Name="GameList"
                         Grid.Row="1"
@@ -513,7 +159,8 @@
                             IsVisible="{Binding ShowLoadProgress}"
                             Text="{Binding LoadHeading}"
                             TextAlignment="Left"
-                            TextWrapping="Wrap" />
+                            TextWrapping="Wrap"
+                            MaxWidth="500" />
                         <Border
                             Grid.Row="1"
                             Margin="10"
@@ -530,7 +177,6 @@
                                 Margin="0"
                                 Padding="0"
                                 HorizontalAlignment="Stretch"
-                                Background="{Binding ProgressBarBackgroundColor}"
                                 ClipToBounds="True"
                                 CornerRadius="5"
                                 Foreground="{Binding ProgressBarForegroundColor}"
@@ -546,226 +192,14 @@
                             FontSize="18"
                             IsVisible="{Binding ShowLoadProgress}"
                             Text="{Binding CacheLoadStatus}"
-                            TextAlignment="Left" />
+                            TextAlignment="Left"
+                            MaxWidth="500" />
                     </Grid>
                 </Grid>
             </Grid>
-            <Grid
-                Name="StatusBar"
-                Grid.Row="2"
-                Margin="0"
-                MinHeight="22"
-                HorizontalAlignment="Stretch"
-                VerticalAlignment="Bottom"
-                Background="{DynamicResource ThemeContentBackgroundColor}"
-                DockPanel.Dock="Bottom"
-                IsVisible="{Binding ShowMenuAndStatusBar}">
-                <Grid.ColumnDefinitions>
-                    <ColumnDefinition Width="Auto" />
-                    <ColumnDefinition Width="Auto" />
-                    <ColumnDefinition Width="*" />
-                    <ColumnDefinition Width="Auto" />
-                </Grid.ColumnDefinitions>
-                <StackPanel
-                    Grid.Column="0"
-                    Margin="5"
-                    VerticalAlignment="Center"
-                    IsVisible="{Binding EnableNonGameRunningControls}">
-                    <Grid Margin="0">
-                        <Grid.ColumnDefinitions>
-                            <ColumnDefinition Width="Auto" />
-                            <ColumnDefinition Width="Auto" />
-                            <ColumnDefinition />
-                        </Grid.ColumnDefinitions>
-                        <Button
-                            Width="25"
-                            Height="25"
-                            MinWidth="0"
-                            Margin="0,0,5,0"
-                            VerticalAlignment="Center"
-                            Background="Transparent"
-                            Command="{ReflectionBinding LoadApplications}">
-                            <ui:SymbolIcon
-                                Width="50"
-                                Height="100"
-                                Symbol="Refresh" />
-                        </Button>
-                        <TextBlock
-                            Name="LoadStatus"
-                            Grid.Column="1"
-                            Margin="0,0,5,0"
-                            VerticalAlignment="Center"
-                            IsVisible="{Binding EnableNonGameRunningControls}"
-                            Text="{locale:Locale StatusBarGamesLoaded}" />
-                        <ProgressBar
-                            Name="LoadProgressBar"
-                            Grid.Column="2"
-                            Height="6"
-                            VerticalAlignment="Center"
-                            Foreground="{DynamicResource HighlightColor}"
-                            IsVisible="{Binding EnableNonGameRunningControls}"
-                            Maximum="{Binding StatusBarProgressMaximum}"
-                            Value="{Binding StatusBarProgressValue}" />
-                    </Grid>
-                </StackPanel>
-                <StackPanel
-                    Grid.Column="1"
-                    Margin="0,2"
-                    HorizontalAlignment="Left"
-                    VerticalAlignment="Center"
-                    IsVisible="{Binding IsGameRunning}"
-                    Orientation="Horizontal">
-                    <TextBlock
-                        Name="VsyncStatus"
-                        Margin="5,0,5,0"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        Foreground="{Binding VsyncColor}"
-                        IsVisible="{Binding !ShowLoadProgress}"
-                        PointerReleased="VsyncStatus_PointerReleased"
-                        Text="VSync"
-                        TextAlignment="Left" />
-                    <Border
-                        Width="2"
-                        Height="12"
-                        Margin="0"
-                        BorderBrush="Gray"
-                        BorderThickness="1"
-                        IsVisible="{Binding !ShowLoadProgress}" />
-                    <TextBlock
-                        Name="DockedStatus"
-                        Margin="5,0,5,0"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        IsVisible="{Binding !ShowLoadProgress}"
-                        PointerReleased="DockedStatus_PointerReleased"
-                        Text="{Binding DockedStatusText}"
-                        TextAlignment="Left" />
-                    <Border
-                        Width="2"
-                        Height="12"
-                        Margin="0"
-                        BorderBrush="Gray"
-                        BorderThickness="1"
-                        IsVisible="{Binding !ShowLoadProgress}" />
-                    <TextBlock
-                        Name="AspectRatioStatus"
-                        Margin="5,0,5,0"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        IsVisible="{Binding !ShowLoadProgress}"
-                        PointerReleased="AspectRatioStatus_PointerReleased"
-                        Text="{Binding AspectRatioStatusText}"
-                        TextAlignment="Left" />
-                    <Border
-                        Width="2"
-                        Height="12"
-                        Margin="0"
-                        BorderBrush="Gray"
-                        BorderThickness="1"
-                        IsVisible="{Binding !ShowLoadProgress}" />
-                    <ui:ToggleSplitButton
-                        Name="VolumeStatus"
-                        Padding="5,0,5,0"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        VerticalContentAlignment="Center"
-                        Background="{DynamicResource ThemeContentBackgroundColor}"
-                        BorderThickness="0"
-                        Content="{Binding VolumeStatusText}"
-                        IsChecked="{Binding VolumeMuted}"
-                        IsVisible="{Binding !ShowLoadProgress}">
-                        <ui:ToggleSplitButton.Flyout>
-                            <Flyout Placement="Bottom" ShowMode="TransientWithDismissOnPointerMoveAway">
-                                <Grid Margin="0">
-                                    <Slider
-                                        MaxHeight="40"
-                                        Width="150"
-                                        Margin="0"
-                                        Padding="0"
-                                        IsSnapToTickEnabled="True"
-                                        LargeChange="0.05"
-                                        Maximum="1"
-                                        Minimum="0"
-                                        SmallChange="0.01"
-                                        TickFrequency="0.05"
-                                        ToolTip.Tip="{locale:Locale AudioVolumeTooltip}"
-                                        Value="{Binding Volume}" />
-                                </Grid>
-                            </Flyout>
-                        </ui:ToggleSplitButton.Flyout>
-                    </ui:ToggleSplitButton>
-                    <Border
-                        Width="2"
-                        Height="12"
-                        Margin="0"
-                        BorderBrush="Gray"
-                        BorderThickness="1"
-                        IsVisible="{Binding !ShowLoadProgress}" />
-                    <TextBlock
-                        Margin="5,0,5,0"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        IsVisible="{Binding !ShowLoadProgress}"
-                        Text="{Binding GameStatusText}"
-                        TextAlignment="Left" />
-                    <Border
-                        Width="2"
-                        Height="12"
-                        Margin="0"
-                        BorderBrush="Gray"
-                        BorderThickness="1"
-                        IsVisible="{Binding !ShowLoadProgress}" />
-                    <TextBlock
-                        Margin="5,0,5,0"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        IsVisible="{Binding !ShowLoadProgress}"
-                        Text="{Binding FifoStatusText}"
-                        TextAlignment="Left" />
-                    <Border
-                        Width="2"
-                        Height="12"
-                        Margin="0"
-                        BorderBrush="Gray"
-                        BorderThickness="1"
-                        IsVisible="{Binding !ShowLoadProgress}" />
-                    <TextBlock
-                        Margin="5,0,5,0"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        IsVisible="{Binding !ShowLoadProgress}"
-                        Text="{Binding BackendText}"
-                        TextAlignment="Left" />
-                    <Border
-                        Width="2"
-                        Height="12"
-                        Margin="0"
-                        BorderBrush="Gray"
-                        BorderThickness="1"
-                        IsVisible="{Binding !ShowLoadProgress}" />
-                    <TextBlock
-                        Margin="5,0,5,0"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        IsVisible="{Binding !ShowLoadProgress}"
-                        Text="{Binding GpuNameText}"
-                        TextAlignment="Left" />
-                </StackPanel>
-                <StackPanel
-                    Grid.Column="3"
-                    Margin="0,0,5,0"
-                    VerticalAlignment="Center"
-                    IsVisible="{Binding ShowFirmwareStatus}"
-                    Orientation="Horizontal">
-                    <TextBlock
-                        Name="FirmwareStatus"
-                        Margin="0"
-                        HorizontalAlignment="Right"
-                        VerticalAlignment="Center"
-                        Text="{locale:Locale StatusBarSystemVersion}" />
-                </StackPanel>
-            </Grid>
+            <main:MainStatusBarView 
+                Name="StatusBarView"
+                Grid.Row="2" />
         </Grid>
     </Grid>
-</window:StyleableWindow>
+</window:StyleableWindow>
\ No newline at end of file
diff --git a/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs b/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
index b2d822c3d3..3c4534c541 100644
--- a/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
+++ b/Ryujinx.Ava/UI/Windows/MainWindow.axaml.cs
@@ -1,19 +1,14 @@
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Input;
-using Avalonia.Interactivity;
-using Avalonia.Media;
 using Avalonia.Threading;
 using FluentAvalonia.UI.Controls;
 using Ryujinx.Ava.Common;
 using Ryujinx.Ava.Common.Locale;
 using Ryujinx.Ava.Input;
 using Ryujinx.Ava.UI.Applet;
-using Ryujinx.Ava.UI.Controls;
 using Ryujinx.Ava.UI.Helpers;
-using Ryujinx.Ava.UI.Models;
 using Ryujinx.Ava.UI.ViewModels;
-using Ryujinx.Common.Configuration;
 using Ryujinx.Common.Logging;
 using Ryujinx.Graphics.Gpu;
 using Ryujinx.HLE.FileSystem;
@@ -25,11 +20,9 @@ using Ryujinx.Ui.App.Common;
 using Ryujinx.Ui.Common;
 using Ryujinx.Ui.Common.Configuration;
 using Ryujinx.Ui.Common.Helper;
-using SixLabors.ImageSharp.PixelFormats;
 using System;
 using System.ComponentModel;
 using System.IO;
-using System.Threading;
 using System.Threading.Tasks;
 using InputManager = Ryujinx.Input.HLE.InputManager;
 
@@ -38,19 +31,14 @@ namespace Ryujinx.Ava.UI.Windows
     public partial class MainWindow : StyleableWindow
     {
         internal static MainWindowViewModel MainWindowViewModel { get; private set; }
-        private bool _canUpdate;
-        private bool _isClosing;
-        private bool _isLoading;
 
-        private Control _mainViewContent;
+        private bool _isLoading;
 
         private UserChannelPersistence _userChannelPersistence;
         private static bool _deferLoad;
         private static string _launchPath;
         private static bool _startFullscreen;
-        private string _currentEmulatedGamePath;
         internal readonly AvaHostUiHandler UiHandler;
-        private AutoResetEvent _rendererWaitEvent;
 
         public VirtualFileSystem VirtualFileSystem { get; private set; }
         public ContentManager ContentManager { get; private set; }
@@ -58,30 +46,17 @@ namespace Ryujinx.Ava.UI.Windows
 
         public LibHacHorizonManager LibHacHorizonManager { get; private set; }
 
-        internal AppHost AppHost { get; private set; }
         public InputManager InputManager { get; private set; }
 
-        internal RendererHost RendererControl { get; private set; }
         internal MainWindowViewModel ViewModel { get; private set; }
         public SettingsWindow SettingsWindow { get; set; }
 
-        public bool CanUpdate
-        {
-            get => _canUpdate;
-            set
-            {
-                _canUpdate = value;
-
-                Dispatcher.UIThread.InvokeAsync(() => UpdateMenuItem.IsEnabled = _canUpdate);
-            }
-        }
-
         public static bool ShowKeyErrorOnLoad { get; set; }
         public ApplicationLibrary ApplicationLibrary { get; set; }
 
         public MainWindow()
         {
-            ViewModel = new MainWindowViewModel(this);
+            ViewModel = new MainWindowViewModel();
 
             MainWindowViewModel = ViewModel;
 
@@ -92,10 +67,10 @@ namespace Ryujinx.Ava.UI.Windows
 
             UiHandler = new AvaHostUiHandler(this);
 
-            Title = $"Ryujinx {Program.Version}";
+            ViewModel.Title = $"Ryujinx {Program.Version}";
 
             // NOTE: Height of MenuBar and StatusBar is not usable here, since it would still be 0 at this point.
-            double barHeight = MenuBar.MinHeight + StatusBar.MinHeight;
+            double barHeight = MenuBar.MinHeight + StatusBarView.StatusBar.MinHeight;
             Height = ((Height - barHeight) / Program.WindowScaleFactor) + barHeight;
             Width /= Program.WindowScaleFactor;
 
@@ -103,14 +78,37 @@ namespace Ryujinx.Ava.UI.Windows
             {
                 Initialize();
 
-                ViewModel.Initialize();
-
                 InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
 
+                ViewModel.Initialize(
+                    ContentManager,
+                    ApplicationLibrary,
+                    VirtualFileSystem,
+                    AccountManager,
+                    InputManager,
+                    _userChannelPersistence,
+                    LibHacHorizonManager,
+                    UiHandler,
+                    ShowLoading,
+                    SwitchToGameControl,
+                    SetMainContent,
+                    this);
+
+                ViewModel.RefreshFirmwareStatus();
+
                 LoadGameList();
+
+                this.GetObservable(IsActiveProperty).Subscribe(IsActiveChanged);
             }
 
-            _rendererWaitEvent = new AutoResetEvent(false);
+            ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
+            ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
+            ViewModel.ReloadGameList += ReloadGameList;
+        }
+
+        private void IsActiveChanged(bool obj)
+        {
+            ViewModel.IsActive = obj;
         }
 
         public void LoadGameList()
@@ -122,45 +120,51 @@ namespace Ryujinx.Ava.UI.Windows
 
             _isLoading = true;
 
-            ViewModel.LoadApplications();
+            LoadApplications();
 
             _isLoading = false;
         }
 
-        private void Update_StatusBar(object sender, StatusUpdatedEventArgs args)
-        {
-            if (ViewModel.ShowMenuAndStatusBar && !ViewModel.ShowLoadProgress)
-            {
-                Dispatcher.UIThread.InvokeAsync(() =>
-                {
-                    if (args.VSyncEnabled)
-                    {
-                        ViewModel.VsyncColor = new SolidColorBrush(Color.Parse("#ff2eeac9"));
-                    }
-                    else
-                    {
-                        ViewModel.VsyncColor = new SolidColorBrush(Color.Parse("#ffff4554"));
-                    }
-
-                    ViewModel.DockedStatusText = args.DockedMode;
-                    ViewModel.AspectRatioStatusText = args.AspectRatio;
-                    ViewModel.GameStatusText = args.GameStatus;
-                    ViewModel.VolumeStatusText = args.VolumeStatus;
-                    ViewModel.FifoStatusText = args.FifoStatus;
-                    ViewModel.GpuNameText = args.GpuName;
-                    ViewModel.BackendText = args.GpuBackend;
-
-                    ViewModel.ShowStatusSeparator = true;
-                });
-            }
-        }
-
         protected override void HandleScalingChanged(double scale)
         {
             Program.DesktopScaleFactor = scale;
             base.HandleScalingChanged(scale);
         }
 
+        public void AddApplication(ApplicationData applicationData)
+        {
+            Dispatcher.UIThread.InvokeAsync(() =>
+            {
+                ViewModel.Applications.Add(applicationData);
+            });
+        }
+
+        private void ApplicationLibrary_ApplicationAdded(object sender, ApplicationAddedEventArgs e)
+        {
+            AddApplication(e.AppData);
+        }
+
+        private void ApplicationLibrary_ApplicationCountUpdated(object sender, ApplicationCountUpdatedEventArgs e)
+        {
+            LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarGamesLoaded, e.NumAppsLoaded, e.NumAppsFound);
+
+            Dispatcher.UIThread.Post(() =>
+            {
+                ViewModel.StatusBarProgressValue   = e.NumAppsLoaded;
+                ViewModel.StatusBarProgressMaximum = e.NumAppsFound;
+
+                if (e.NumAppsFound == 0)
+                {
+                    StatusBarView.LoadProgressBar.IsVisible = false;
+                }
+
+                if (e.NumAppsLoaded == e.NumAppsFound)
+                {
+                    StatusBarView.LoadProgressBar.IsVisible = false;
+                }
+            });
+        }
+
         public void Application_Opened(object sender, ApplicationOpenedEventArgs args)
         {
             if (args.Application != null)
@@ -169,50 +173,12 @@ namespace Ryujinx.Ava.UI.Windows
 
                 string path = new FileInfo(args.Application.Path).FullName;
 
-                LoadApplication(path);
+                ViewModel.LoadApplication(path);
             }
 
             args.Handled = true;
         }
 
-        public async Task PerformanceCheck()
-        {
-            if (ConfigurationState.Instance.Logger.EnableTrace.Value)
-            {
-                string mainMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckLoggingEnabledMessage];
-                string secondaryMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckLoggingEnabledConfirmMessage];
-
-                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(mainMessage, secondaryMessage,
-                    LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance[LocaleKeys.InputDialogNo],
-                    LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
-
-                if (result != UserResult.Yes)
-                {
-                    ConfigurationState.Instance.Logger.EnableTrace.Value = false;
-
-                    SaveConfig();
-                }
-            }
-
-            if (!string.IsNullOrWhiteSpace(ConfigurationState.Instance.Graphics.ShadersDumpPath.Value))
-            {
-                string mainMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckShaderDumpEnabledMessage];
-                string secondaryMessage =
-                    LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckShaderDumpEnabledConfirmMessage];
-
-                UserResult result = await ContentDialogHelper.CreateConfirmationDialog(mainMessage, secondaryMessage,
-                    LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance[LocaleKeys.InputDialogNo],
-                    LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
-
-                if (result != UserResult.Yes)
-                {
-                    ConfigurationState.Instance.Graphics.ShadersDumpPath.Value = "";
-
-                    SaveConfig();
-                }
-            }
-        }
-
         internal static void DeferLoadApplication(string launchPathArg, bool startFullscreenArg)
         {
             _deferLoad = true;
@@ -220,109 +186,6 @@ namespace Ryujinx.Ava.UI.Windows
             _startFullscreen = startFullscreenArg;
         }
 
-#pragma warning disable CS1998
-        public async void LoadApplication(string path, bool startFullscreen = false, string titleName = "")
-#pragma warning restore CS1998
-        {
-            if (AppHost != null)
-            {
-                await ContentDialogHelper.CreateInfoDialog(
-                    LocaleManager.Instance[LocaleKeys.DialogLoadAppGameAlreadyLoadedMessage],
-                    LocaleManager.Instance[LocaleKeys.DialogLoadAppGameAlreadyLoadedSubMessage],
-                    LocaleManager.Instance[LocaleKeys.InputDialogOk],
-                    "",
-                    LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
-
-                return;
-            }
-
-#if RELEASE
-            await PerformanceCheck();
-#endif
-
-            Logger.RestartTime();
-
-            if (ViewModel.SelectedIcon == null)
-            {
-                ViewModel.SelectedIcon = ApplicationLibrary.GetApplicationIcon(path);
-            }
-
-            PrepareLoadScreen();
-
-            _mainViewContent = MainContent.Content as Control;
-
-            RendererControl = new RendererHost(ConfigurationState.Instance.Logger.GraphicsDebugLevel);
-            if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.OpenGl)
-            {
-                RendererControl.CreateOpenGL();
-            }
-            else
-            {
-                RendererControl.CreateVulkan();
-            }
-
-            AppHost = new AppHost(RendererControl, InputManager, path, VirtualFileSystem, ContentManager, AccountManager, _userChannelPersistence, this);
-
-            Dispatcher.UIThread.Post(async () =>
-            {
-                if (!await AppHost.LoadGuestApplication())
-                {
-                    AppHost.DisposeContext();
-                    AppHost = null;
-
-                    return;
-                }
-
-                CanUpdate = false;
-                ViewModel.LoadHeading = string.IsNullOrWhiteSpace(titleName) ? string.Format(LocaleManager.Instance[LocaleKeys.LoadingHeading], AppHost.Device.Application.TitleName) : titleName;
-                ViewModel.TitleName   = string.IsNullOrWhiteSpace(titleName) ? AppHost.Device.Application.TitleName : titleName;
-
-                SwitchToGameControl(startFullscreen);
-
-                _currentEmulatedGamePath = path;
-
-                Thread gameThread = new(InitializeGame)
-                {
-                    Name = "GUI.WindowThread"
-                };
-                gameThread.Start();
-            });
-        }
-
-        private void InitializeGame()
-        {
-            RendererControl.RendererInitialized += GlRenderer_Created;
-
-            AppHost.StatusUpdatedEvent += Update_StatusBar;
-            AppHost.AppExit += AppHost_AppExit;
-
-            _rendererWaitEvent.WaitOne();
-
-            AppHost?.Start();
-
-            AppHost.DisposeContext();
-        }
-
-
-        private void HandleRelaunch()
-        {
-            if (_userChannelPersistence.PreviousIndex != -1 && _userChannelPersistence.ShouldRestart)
-            {
-                _userChannelPersistence.ShouldRestart = false;
-
-                Dispatcher.UIThread.Post(() =>
-                {
-                    LoadApplication(_currentEmulatedGamePath);
-                });
-            }
-            else
-            {
-                // otherwise, clear state.
-                _userChannelPersistence = new UserChannelPersistence();
-                _currentEmulatedGamePath = null;
-            }
-        }
-
         public void SwitchToGameControl(bool startFullscreen = false)
         {
             ViewModel.ShowLoadProgress = false;
@@ -331,14 +194,10 @@ namespace Ryujinx.Ava.UI.Windows
 
             Dispatcher.UIThread.InvokeAsync(() =>
             {
-                MainContent.Content = RendererControl;
-
-                if (startFullscreen && WindowState != WindowState.FullScreen)
+                if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
                 {
                     ViewModel.ToggleFullscreen();
                 }
-
-                RendererControl.Focus();
             });
         }
 
@@ -350,71 +209,16 @@ namespace Ryujinx.Ava.UI.Windows
 
             Dispatcher.UIThread.InvokeAsync(() =>
             {
-                if (startFullscreen && WindowState != WindowState.FullScreen)
+                if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
                 {
                     ViewModel.ToggleFullscreen();
                 }
             });
         }
 
-        private void GlRenderer_Created(object sender, EventArgs e)
-        {
-            ShowLoading();
-
-            _rendererWaitEvent.Set();
-        }
-
-        private void AppHost_AppExit(object sender, EventArgs e)
-        {
-            if (_isClosing)
-            {
-                return;
-            }
-
-            ViewModel.IsGameRunning = false;
-
-            Dispatcher.UIThread.InvokeAsync(() =>
-            {
-                ViewModel.ShowMenuAndStatusBar = true;
-                ViewModel.ShowContent = true;
-                ViewModel.ShowLoadProgress = false;
-                ViewModel.IsLoadingIndeterminate = false;
-                CanUpdate = true;
-                Cursor = Cursor.Default;
-
-                if (MainContent.Content != _mainViewContent)
-                {
-                    MainContent.Content = _mainViewContent;
-                }
-
-                AppHost = null;
-
-                HandleRelaunch();
-            });
-
-            RendererControl.RendererInitialized -= GlRenderer_Created;
-            RendererControl = null;
-
-            ViewModel.SelectedIcon = null;
-
-            Dispatcher.UIThread.InvokeAsync(() =>
-            {
-                Title = $"Ryujinx {Program.Version}";
-            });
-        }
-
-        public void Sort_Checked(object sender, RoutedEventArgs args)
-        {
-            if (sender is RadioButton button)
-            {
-                var sort = Enum.Parse<ApplicationSort>(button.Tag.ToString());
-                ViewModel.Sort(sort);
-            }
-        }
-
         protected override void HandleWindowStateChanged(WindowState state)
         {
-            WindowState = state;
+            ViewModel.WindowState = state;
 
             if (state != WindowState.Minimized)
             {
@@ -422,15 +226,6 @@ namespace Ryujinx.Ava.UI.Windows
             }
         }
 
-        public void Order_Checked(object sender, RoutedEventArgs args)
-        {
-            if (sender is RadioButton button)
-            {
-                var tag = button.Tag.ToString();
-                ViewModel.Sort(tag != "Descending");
-            }
-        }
-
         private void Initialize()
         {
             _userChannelPersistence = new UserChannelPersistence();
@@ -457,8 +252,6 @@ namespace Ryujinx.Ava.UI.Windows
             VirtualFileSystem.ReloadKeySet();
 
             ApplicationHelper.Initialize(VirtualFileSystem, AccountManager, LibHacHorizonManager.RyujinxClient, this);
-
-            RefreshFirmwareStatus();
         }
 
         protected void CheckLaunchState()
@@ -475,7 +268,7 @@ namespace Ryujinx.Ava.UI.Windows
             {
                 _deferLoad = false;
 
-                LoadApplication(_launchPath, _startFullscreen);
+                ViewModel.LoadApplication(_launchPath, _startFullscreen);
             }
 
             if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false, this))
@@ -487,35 +280,9 @@ namespace Ryujinx.Ava.UI.Windows
             }
         }
 
-        public void RefreshFirmwareStatus()
-        {
-            SystemVersion version = null;
-            try
-            {
-                version = ContentManager.GetCurrentFirmwareVersion();
-            }
-            catch (Exception) { }
-
-            bool hasApplet = false;
-
-            if (version != null)
-            {
-                LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarSystemVersion,
-                    version.VersionString);
-
-                hasApplet = version.Major > 3;
-            }
-            else
-            {
-                LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarSystemVersion, "0.0");
-            }
-
-            ViewModel.IsAppletMenuActive = hasApplet;
-        }
-
         private void Load()
         {
-            VolumeStatus.Click += VolumeStatus_CheckedChanged;
+            StatusBarView.VolumeStatus.Click += VolumeStatus_CheckedChanged;
 
             GameGrid.ApplicationOpened += Application_Opened;
 
@@ -535,6 +302,19 @@ namespace Ryujinx.Ava.UI.Windows
             CheckLaunchState();
         }
 
+        private void SetMainContent(Control content = null)
+        {
+            if (content == null)
+            {
+                content = GameLibrary;
+            }
+
+            if (MainContent.Content != content)
+            {
+                MainContent.Content = content;
+            }
+        }
+
         public static void UpdateGraphicsConfig()
         {
             GraphicsConfig.ResScale                   = ConfigurationState.Instance.Graphics.ResScale == -1 ? ConfigurationState.Instance.Graphics.ResScaleCustom : ConfigurationState.Instance.Graphics.ResScale;
@@ -553,99 +333,6 @@ namespace Ryujinx.Ava.UI.Windows
             HotKeyManager.SetHotKey(ExitHotKey,        new KeyGesture(Key.Escape));
         }
 
-        public static void SaveConfig()
-        {
-            ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-        }
-
-        public void UpdateGameMetadata(string titleId)
-        {
-            ApplicationLibrary.LoadAndSaveMetaData(titleId, appMetadata =>
-            {
-                if (DateTime.TryParse(appMetadata.LastPlayed, out DateTime lastPlayedDateTime))
-                {
-                    double sessionTimePlayed = DateTime.UtcNow.Subtract(lastPlayedDateTime).TotalSeconds;
-
-                    appMetadata.TimePlayed += Math.Round(sessionTimePlayed, MidpointRounding.AwayFromZero);
-                }
-            });
-        }
-
-        private void PrepareLoadScreen()
-        {
-            using MemoryStream stream = new MemoryStream(ViewModel.SelectedIcon);
-            using var gameIconBmp = SixLabors.ImageSharp.Image.Load<Bgra32>(stream);
-
-            var dominantColor = IconColorPicker.GetFilteredColor(gameIconBmp).ToPixel<Bgra32>();
-
-            const int ColorDivisor = 4;
-
-            Color progressFgColor = Color.FromRgb(dominantColor.R, dominantColor.G, dominantColor.B);
-            Color progressBgColor = Color.FromRgb(
-                (byte)(dominantColor.R / ColorDivisor),
-                (byte)(dominantColor.G / ColorDivisor),
-                (byte)(dominantColor.B / ColorDivisor));
-
-            ViewModel.ProgressBarForegroundColor = new SolidColorBrush(progressFgColor);
-            ViewModel.ProgressBarBackgroundColor = new SolidColorBrush(progressBgColor);
-        }
-
-        private void SearchBox_OnKeyUp(object sender, KeyEventArgs e)
-        {
-            ViewModel.SearchText = SearchBox.Text;
-        }
-
-        private async void StopEmulation_Click(object sender, RoutedEventArgs e)
-        {
-            if (AppHost != null)
-            {
-                await AppHost.ShowExitPrompt();
-            }
-        }
-
-        private async void PauseEmulation_Click(object sender, RoutedEventArgs e)
-        {
-            await Task.Run(() =>
-            {
-                AppHost?.Pause();
-            });
-        }
-
-        private async void ResumeEmulation_Click(object sender, RoutedEventArgs e)
-        {
-            await Task.Run(() =>
-            {
-                AppHost?.Resume();
-            });
-        }
-
-        private void ScanAmiiboMenuItem_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
-        {
-            if (sender is MenuItem)
-            {
-                ViewModel.IsAmiiboRequested = AppHost.Device.System.SearchingForAmiibo(out _);
-            }
-        }
-
-        private void VsyncStatus_PointerReleased(object sender, PointerReleasedEventArgs e)
-        {
-            AppHost.Device.EnableDeviceVsync = !AppHost.Device.EnableDeviceVsync;
-
-            Logger.Info?.Print(LogClass.Application, $"VSync toggled to: {AppHost.Device.EnableDeviceVsync}");
-        }
-
-        private void DockedStatus_PointerReleased(object sender, PointerReleasedEventArgs e)
-        {
-            ConfigurationState.Instance.System.EnableDockedMode.Value = !ConfigurationState.Instance.System.EnableDockedMode.Value;
-        }
-
-        private void AspectRatioStatus_PointerReleased(object sender, PointerReleasedEventArgs e)
-        {
-            AspectRatio aspectRatio = ConfigurationState.Instance.Graphics.AspectRatio.Value;
-
-            ConfigurationState.Instance.Graphics.AspectRatio.Value = (int)aspectRatio + 1 > Enum.GetNames(typeof(AspectRatio)).Length - 1 ? AspectRatio.Fixed4x3 : aspectRatio + 1;
-        }
-
         private void VolumeStatus_CheckedChanged(object sender, SplitButtonClickEventArgs e)
         {
             var volumeSplitButton = sender as ToggleSplitButton;
@@ -653,20 +340,20 @@ namespace Ryujinx.Ava.UI.Windows
             {
                 if (!volumeSplitButton.IsChecked)
                 {
-                    AppHost.Device.SetVolume(ConfigurationState.Instance.System.AudioVolume);
+                    ViewModel.AppHost.Device.SetVolume(ConfigurationState.Instance.System.AudioVolume);
                 }
                 else
                 {
-                    AppHost.Device.SetVolume(0);
+                    ViewModel.AppHost.Device.SetVolume(0);
                 }
 
-                ViewModel.Volume = AppHost.Device.GetVolume();
+                ViewModel.Volume = ViewModel.AppHost.Device.GetVolume();
             }
         }
 
         protected override void OnClosing(CancelEventArgs e)
         {
-            if (!_isClosing && AppHost != null && ConfigurationState.Instance.ShowConfirmExit)
+            if (!ViewModel.IsClosing && ViewModel.AppHost != null && ConfigurationState.Instance.ShowConfirmExit)
             {
                 e.Cancel = true;
 
@@ -675,14 +362,14 @@ namespace Ryujinx.Ava.UI.Windows
                 return;
             }
 
-            _isClosing = true;
+            ViewModel.IsClosing = true;
 
-            if (AppHost != null)
+            if (ViewModel.AppHost != null)
             {
-                AppHost.AppExit -= AppHost_AppExit;
-                AppHost.AppExit += (sender, e) =>
+                ViewModel.AppHost.AppExit -= ViewModel.AppHost_AppExit;
+                ViewModel.AppHost.AppExit += (sender, e) =>
                 {
-                    AppHost = null;
+                    ViewModel.AppHost = null;
 
                     Dispatcher.UIThread.Post(() =>
                     {
@@ -691,7 +378,7 @@ namespace Ryujinx.Ava.UI.Windows
                         Close();
                     });
                 };
-                AppHost?.Stop();
+                ViewModel.AppHost?.Stop();
 
                 e.Cancel = true;
 
@@ -709,13 +396,43 @@ namespace Ryujinx.Ava.UI.Windows
         {
             Dispatcher.UIThread.InvokeAsync(async () =>
            {
-               _isClosing = await ContentDialogHelper.CreateExitDialog();
+               ViewModel.IsClosing = await ContentDialogHelper.CreateExitDialog();
 
-               if (_isClosing)
+               if (ViewModel.IsClosing)
                {
                    Close();
                }
            });
         }
+
+        public async void LoadApplications()
+        {
+            await Dispatcher.UIThread.InvokeAsync(() =>
+            {
+                ViewModel.Applications.Clear();
+
+                StatusBarView.LoadProgressBar.IsVisible = true;
+                ViewModel.StatusBarProgressMaximum      = 0;
+                ViewModel.StatusBarProgressValue        = 0;
+
+                LocaleManager.Instance.UpdateDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0);
+            });
+
+            ReloadGameList();
+        }
+
+        private void ReloadGameList()
+        {
+            if (_isLoading)
+            {
+                return;
+            }
+
+            _isLoading = true;
+
+            ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs.Value, ConfigurationState.Instance.System.Language);
+
+            _isLoading = false;
+        }
     }
 }
\ No newline at end of file