From a79b39b91347816ea14677b58af738b70df03e9c Mon Sep 17 00:00:00 2001
From: Ac_K <Acoustik666@gmail.com>
Date: Mon, 28 Jun 2021 20:54:45 +0200
Subject: no name: Mii Editor applet support (#2419)

* no name: Mii Editor applet support

* addresses gdkchan feedback

* Fix comment

* Bypass MountCounter of MiiDatabaseManager

* Fix GetSettingsPlatformRegion

* Disable Applet Menu for unsupported firmwares
---
 Ryujinx.Common/Logging/LogClass.cs                 |   1 +
 Ryujinx.HLE/HOS/Horizon.cs                         |  36 ++++---
 .../ILibraryAppletProxy.cs                         | 105 +++++++++++++++++++++
 .../ISystemAppletProxy.cs                          |   4 +-
 .../LibraryAppletProxy/AppletStandalone.cs         |  16 ++++
 .../ILibraryAppletSelfAccessor.cs                  |  78 +++++++++++++++
 .../IProcessWindingController.cs                   |  24 +++++
 .../SystemAppletProxy/IAppletCommonFunctions.cs    |   7 ++
 .../SystemAppletProxy/ICommonStateGetter.cs        |  14 +++
 .../SystemAppletProxy/IDisplayController.cs        | 101 +++++++++++++++++++-
 .../SystemAppletProxy/ISelfController.cs           |  13 ++-
 .../Am/AppletAE/IAllSystemAppletProxiesService.cs  |  10 ++
 .../Am/AppletAE/Types/AppletIdentityInfo.cs        |  12 +++
 .../Am/AppletAE/Types/AppletProcessLaunchReason.cs |  12 +++
 .../Am/AppletAE/Types/LibraryAppletInfo.cs         |  11 +++
 .../Am/AppletAE/Types/LibraryAppletMode.cs         |  14 +++
 .../ApplicationProxyService/IApplicationProxy.cs   |   4 +-
 Ryujinx.HLE/HOS/Services/Am/ResultCode.cs          |   2 +
 Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs    |   9 ++
 Ryujinx.HLE/HOS/Services/Mii/Helper.cs             |   2 +-
 .../HOS/Services/Mii/IImageDatabaseService.cs      |  35 ++++++-
 Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs |   6 +-
 .../HOS/Services/Settings/ISystemSettingsServer.cs |  15 +++
 .../HOS/Services/Settings/Types/PlatformRegion.cs  |   8 ++
 Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs      |   8 +-
 Ryujinx/Ui/MainWindow.cs                           |  47 ++++++++-
 Ryujinx/Ui/MainWindow.glade                        |  30 +++++-
 27 files changed, 591 insertions(+), 33 deletions(-)
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/AppletStandalone.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletIdentityInfo.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletProcessLaunchReason.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/LibraryAppletInfo.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/LibraryAppletMode.cs
 create mode 100644 Ryujinx.HLE/HOS/Services/Settings/Types/PlatformRegion.cs

diff --git a/Ryujinx.Common/Logging/LogClass.cs b/Ryujinx.Common/Logging/LogClass.cs
index c2d2f55e..30e3409d 100644
--- a/Ryujinx.Common/Logging/LogClass.cs
+++ b/Ryujinx.Common/Logging/LogClass.cs
@@ -37,6 +37,7 @@ namespace Ryujinx.Common.Logging
         ServiceLdn,
         ServiceLdr,
         ServiceLm,
+        ServiceMii,
         ServiceMm,
         ServiceNfc,
         ServiceNfp,
diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs
index 3034d107..a4ed7c37 100644
--- a/Ryujinx.HLE/HOS/Horizon.cs
+++ b/Ryujinx.HLE/HOS/Horizon.cs
@@ -45,10 +45,11 @@ namespace Ryujinx.HLE.HOS
 
     public class Horizon : IDisposable
     {
-        internal const int HidSize  = 0x40000;
-        internal const int FontSize = 0x1100000;
-        internal const int IirsSize = 0x8000;
-        internal const int TimeSize = 0x1000;
+        internal const int HidSize                 = 0x40000;
+        internal const int FontSize                = 0x1100000;
+        internal const int IirsSize                = 0x8000;
+        internal const int TimeSize                = 0x1000;
+        internal const int AppletCaptureBufferSize = 0x384000;
 
         internal KernelContext KernelContext { get; }
 
@@ -82,6 +83,9 @@ namespace Ryujinx.HLE.HOS
         internal KSharedMemory HidSharedMem  { get; private set; }
         internal KSharedMemory FontSharedMem { get; private set; }
         internal KSharedMemory IirsSharedMem { get; private set; }
+
+        internal KTransferMemory AppletCaptureBufferTransfer { get; private set; }
+
         internal SharedFontManager Font { get; private set; }
 
         internal AccountManager AccountManager { get; private set; }
@@ -129,25 +133,29 @@ namespace Ryujinx.HLE.HOS
             // region used that is used is Application, so we can use the other ones for anything.
             KMemoryRegionManager region = KernelContext.MemoryManager.MemoryRegions[(int)MemoryRegion.NvServices];
 
-            ulong hidPa  = region.Address;
-            ulong fontPa = region.Address + HidSize;
-            ulong iirsPa = region.Address + HidSize + FontSize;
-            ulong timePa = region.Address + HidSize + FontSize + IirsSize;
+            ulong hidPa                 = region.Address;
+            ulong fontPa                = region.Address + HidSize;
+            ulong iirsPa                = region.Address + HidSize + FontSize;
+            ulong timePa                = region.Address + HidSize + FontSize + IirsSize;
+            ulong appletCaptureBufferPa = region.Address + HidSize + FontSize + IirsSize + TimeSize;
 
-            KPageList hidPageList  = new KPageList();
-            KPageList fontPageList = new KPageList();
-            KPageList iirsPageList = new KPageList();
-            KPageList timePageList = new KPageList();
+            KPageList hidPageList                 = new KPageList();
+            KPageList fontPageList                = new KPageList();
+            KPageList iirsPageList                = new KPageList();
+            KPageList timePageList                = new KPageList();
+            KPageList appletCaptureBufferPageList = new KPageList();
 
-            hidPageList.AddRange(hidPa,  HidSize  / KPageTableBase.PageSize);
+            hidPageList.AddRange(hidPa, HidSize / KPageTableBase.PageSize);
             fontPageList.AddRange(fontPa, FontSize / KPageTableBase.PageSize);
             iirsPageList.AddRange(iirsPa, IirsSize / KPageTableBase.PageSize);
             timePageList.AddRange(timePa, TimeSize / KPageTableBase.PageSize);
+            appletCaptureBufferPageList.AddRange(appletCaptureBufferPa, AppletCaptureBufferSize / KPageTableBase.PageSize);
 
             var hidStorage = new SharedMemoryStorage(KernelContext, hidPageList);
             var fontStorage = new SharedMemoryStorage(KernelContext, fontPageList);
             var iirsStorage = new SharedMemoryStorage(KernelContext, iirsPageList);
             var timeStorage = new SharedMemoryStorage(KernelContext, timePageList);
+            var appletCaptureBufferStorage = new SharedMemoryStorage(KernelContext, appletCaptureBufferPageList);
 
             HidStorage = hidStorage;
 
@@ -159,6 +167,8 @@ namespace Ryujinx.HLE.HOS
 
             TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, timeStorage, TimeSize);
 
+            AppletCaptureBufferTransfer = new KTransferMemory(KernelContext, appletCaptureBufferStorage);
+
             AppletState = new AppletStateMgr(this);
 
             AppletState.SetFocus(true);
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs
new file mode 100644
index 00000000..b85a39e5
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs
@@ -0,0 +1,105 @@
+using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy;
+using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
+{
+    class ILibraryAppletProxy : IpcService
+    {
+        private readonly long _pid;
+
+        public ILibraryAppletProxy(long pid)
+        {
+            _pid = pid;
+        }
+
+        [CommandHipc(0)]
+        // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
+        public ResultCode GetCommonStateGetter(ServiceCtx context)
+        {
+            MakeObject(context, new ICommonStateGetter(context));
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(1)]
+        // GetSelfController() -> object<nn::am::service::ISelfController>
+        public ResultCode GetSelfController(ServiceCtx context)
+        {
+            MakeObject(context, new ISelfController(context, _pid));
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(2)]
+        // GetWindowController() -> object<nn::am::service::IWindowController>
+        public ResultCode GetWindowController(ServiceCtx context)
+        {
+            MakeObject(context, new IWindowController(_pid));
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(3)]
+        // GetAudioController() -> object<nn::am::service::IAudioController>
+        public ResultCode GetAudioController(ServiceCtx context)
+        {
+            MakeObject(context, new IAudioController());
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(4)]
+        // GetDisplayController() -> object<nn::am::service::IDisplayController>
+        public ResultCode GetDisplayController(ServiceCtx context)
+        {
+            MakeObject(context, new IDisplayController(context));
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(10)]
+        // GetProcessWindingController() -> object<nn::am::service::IProcessWindingController>
+        public ResultCode GetProcessWindingController(ServiceCtx context)
+        {
+            MakeObject(context, new IProcessWindingController());
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(11)]
+        // GetLibraryAppletCreator() -> object<nn::am::service::ILibraryAppletCreator>
+        public ResultCode GetLibraryAppletCreator(ServiceCtx context)
+        {
+            MakeObject(context, new ILibraryAppletCreator());
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(20)]
+        // OpenLibraryAppletSelfAccessor() -> object<nn::am::service::ILibraryAppletSelfAccessor>
+        public ResultCode OpenLibraryAppletSelfAccessor(ServiceCtx context)
+        {
+            MakeObject(context, new ILibraryAppletSelfAccessor(context));
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(21)]
+        // GetAppletCommonFunctions() -> object<nn::am::service::IAppletCommonFunctions>
+        public ResultCode GetAppletCommonFunctions(ServiceCtx context)
+        {
+            MakeObject(context, new IAppletCommonFunctions());
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(1000)]
+        // GetDebugFunctions() -> object<nn::am::service::IDebugFunctions>
+        public ResultCode GetDebugFunctions(ServiceCtx context)
+        {
+            MakeObject(context, new IDebugFunctions());
+
+            return ResultCode.Success;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs
index 7017488d..4c94f9b6 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs
@@ -24,7 +24,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
         // GetSelfController() -> object<nn::am::service::ISelfController>
         public ResultCode GetSelfController(ServiceCtx context)
         {
-            MakeObject(context, new ISelfController(context.Device.System, _pid));
+            MakeObject(context, new ISelfController(context, _pid));
 
             return ResultCode.Success;
         }
@@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
         // GetDisplayController() -> object<nn::am::service::IDisplayController>
         public ResultCode GetDisplayController(ServiceCtx context)
         {
-            MakeObject(context, new IDisplayController());
+            MakeObject(context, new IDisplayController(context));
 
             return ResultCode.Success;
         }
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/AppletStandalone.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/AppletStandalone.cs
new file mode 100644
index 00000000..69967c56
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/AppletStandalone.cs
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
+{
+    class AppletStandalone
+    {
+        public AppletId          AppletId;
+        public LibraryAppletMode LibraryAppletMode;
+        public Queue<byte[]>     InputData;
+
+        public AppletStandalone()
+        {
+            InputData = new Queue<byte[]>();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs
new file mode 100644
index 00000000..00081e1b
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs
@@ -0,0 +1,78 @@
+using Ryujinx.Common;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
+{
+    class ILibraryAppletSelfAccessor : IpcService
+    {
+        private AppletStandalone _appletStandalone = new AppletStandalone();
+
+        public ILibraryAppletSelfAccessor(ServiceCtx context)
+        {
+            if (context.Device.Application.TitleId == 0x0100000000001009)
+            {
+                // Create MiiEdit data.
+                _appletStandalone = new AppletStandalone()
+                {
+                    AppletId          = AppletId.MiiEdit,
+                    LibraryAppletMode = LibraryAppletMode.AllForeground
+                };
+
+                byte[] miiEditInputData = new byte[0x100];
+                miiEditInputData[0] = 0x03; // Hardcoded unknown value.
+
+                _appletStandalone.InputData.Enqueue(miiEditInputData);
+            }
+            else
+            {
+                throw new NotImplementedException($"{context.Device.Application.TitleId} applet is not implemented.");
+            }
+        }
+
+        [CommandHipc(0)]
+        // PopInData() -> object<nn::am::service::IStorage>
+        public ResultCode PopInData(ServiceCtx context)
+        {
+            byte[] appletData = _appletStandalone.InputData.Dequeue();
+
+            if (appletData.Length == 0)
+            {
+                return ResultCode.NotAvailable;
+            }
+
+            MakeObject(context, new IStorage(appletData));
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(11)]
+        // GetLibraryAppletInfo() -> nn::am::service::LibraryAppletInfo
+        public ResultCode GetLibraryAppletInfo(ServiceCtx context)
+        {
+            LibraryAppletInfo libraryAppletInfo = new LibraryAppletInfo()
+            {
+                AppletId          = _appletStandalone.AppletId,
+                LibraryAppletMode = _appletStandalone.LibraryAppletMode
+            };
+
+            context.ResponseData.WriteStruct(libraryAppletInfo);
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(14)]
+        // GetCallerAppletIdentityInfo() -> nn::am::service::AppletIdentityInfo
+        public ResultCode GetCallerAppletIdentityInfo(ServiceCtx context)
+        {
+            AppletIdentifyInfo appletIdentifyInfo = new AppletIdentifyInfo()
+            {
+                AppletId = AppletId.QLaunch,
+                TitleId  = 0x0100000000001000
+            };
+
+            context.ResponseData.WriteStruct(appletIdentifyInfo);
+
+            return ResultCode.Success;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs
new file mode 100644
index 00000000..e6c16734
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs
@@ -0,0 +1,24 @@
+using Ryujinx.Common;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletProxy
+{
+    class IProcessWindingController : IpcService
+    {
+        public IProcessWindingController() { }
+
+        [CommandHipc(0)]
+        // GetLaunchReason() -> nn::am::service::AppletProcessLaunchReason
+        public ResultCode GetLaunchReason(ServiceCtx context)
+        {
+            // NOTE: Flag is set by using an internal field.
+            AppletProcessLaunchReason appletProcessLaunchReason = new AppletProcessLaunchReason()
+            {
+                Flag = 0
+            };
+
+            context.ResponseData.WriteStruct(appletProcessLaunchReason);
+
+            return ResultCode.Success;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs
new file mode 100644
index 00000000..c42202b8
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+    class IAppletCommonFunctions : IpcService
+    {
+        public IAppletCommonFunctions() { }
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
index 9e47f05b..4c862dd6 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
@@ -2,6 +2,8 @@ using Ryujinx.Common.Logging;
 using Ryujinx.HLE.HOS.Ipc;
 using Ryujinx.HLE.HOS.Kernel.Common;
 using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.HLE.HOS.Services.Settings.Types;
+using Ryujinx.HLE.HOS.SystemState;
 using System;
 
 namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
@@ -241,6 +243,18 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
             return (ResultCode)_apmSystemManagerServer.GetCurrentPerformanceConfiguration(context);
         }
 
+        [CommandHipc(300)] // 9.0.0+
+        // GetSettingsPlatformRegion() -> u8
+        public ResultCode GetSettingsPlatformRegion(ServiceCtx context)
+        {
+            PlatformRegion platformRegion = context.Device.System.State.DesiredRegionCode == (uint)RegionCode.China ? PlatformRegion.China : PlatformRegion.Global;
+
+            // FIXME: Call set:sys GetPlatformRegion
+            context.ResponseData.Write((byte)platformRegion);
+
+            return ResultCode.Success;
+        }
+
         [CommandHipc(900)] // 11.0.0+
         // SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled()
         public ResultCode SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(ServiceCtx context)
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs
index 2b04dbb5..d7816de9 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs
@@ -1,7 +1,106 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Common;
+using Ryujinx.HLE.HOS.Kernel.Memory;
+using System;
+
 namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
 {
     class IDisplayController : IpcService
     {
-        public IDisplayController() { }
+        private KTransferMemory _transferMem;
+        private bool            _lastApplicationCaptureBufferAcquired;
+        private bool            _callerAppletCaptureBufferAcquired;
+
+        public IDisplayController(ServiceCtx context)
+        {
+            _transferMem = context.Device.System.AppletCaptureBufferTransfer;
+        }
+
+        [CommandHipc(8)] // 2.0.0+
+        // TakeScreenShotOfOwnLayer(b8, s32)
+        public ResultCode TakeScreenShotOfOwnLayer(ServiceCtx context)
+        {
+            bool unknown1 = context.RequestData.ReadBoolean();
+            int  unknown2 = context.RequestData.ReadInt32();
+
+            Logger.Stub?.PrintStub(LogClass.ServiceAm, new { unknown1, unknown2 });
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(11)]
+        // ReleaseLastApplicationCaptureBuffer()
+        public ResultCode ReleaseLastApplicationCaptureBuffer(ServiceCtx context)
+        {
+            if (!_lastApplicationCaptureBufferAcquired)
+            {
+                return ResultCode.BufferNotAcquired;
+            }
+
+            _lastApplicationCaptureBufferAcquired = false;
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(15)]
+        // ReleaseCallerAppletCaptureBuffer()
+        public ResultCode ReleaseCallerAppletCaptureBuffer(ServiceCtx context)
+        {
+            if (!_callerAppletCaptureBufferAcquired)
+            {
+                return ResultCode.BufferNotAcquired;
+            }
+
+            _callerAppletCaptureBufferAcquired = false;
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(16)]
+        // AcquireLastApplicationCaptureBufferEx() -> (b8, handle<copy>)
+        public ResultCode AcquireLastApplicationCaptureBufferEx(ServiceCtx context)
+        {
+            if (_lastApplicationCaptureBufferAcquired)
+            {
+                return ResultCode.BufferAlreadyAcquired;
+            }
+
+            if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != KernelResult.Success)
+            {
+                throw new InvalidOperationException("Out of handles!");
+            }
+
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+
+            _lastApplicationCaptureBufferAcquired = true;
+
+            context.ResponseData.Write(_lastApplicationCaptureBufferAcquired);
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(18)]
+        // AcquireCallerAppletCaptureBufferEx() -> (b8, handle<copy>)
+        public ResultCode AcquireCallerAppletCaptureBufferEx(ServiceCtx context)
+        {
+            if (_callerAppletCaptureBufferAcquired)
+            {
+                return ResultCode.BufferAlreadyAcquired;
+            }
+
+            if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != KernelResult.Success)
+            {
+                throw new InvalidOperationException("Out of handles!");
+            }
+
+            context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+
+            _callerAppletCaptureBufferAcquired = true;
+
+            context.ResponseData.Write(_callerAppletCaptureBufferAcquired);
+
+            return ResultCode.Success;
+        }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs
index e9af55a0..0ecbd4a0 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs
@@ -35,9 +35,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
         private uint _screenShotImageOrientation = 0;
         private uint _idleTimeDetectionExtension = 0;
 
-        public ISelfController(Horizon system, long pid)
+        public ISelfController(ServiceCtx context, long pid)
         {
-            _libraryAppletLaunchableEvent = new KEvent(system.KernelContext);
+            _libraryAppletLaunchableEvent = new KEvent(context.Device.System.KernelContext);
             _pid = pid;
         }
 
@@ -225,6 +225,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
             return ResultCode.Success;
         }
 
+        [CommandHipc(41)] // 4.0.0+
+        // IsSystemBufferSharingEnabled()
+        public ResultCode IsSystemBufferSharingEnabled(ServiceCtx context)
+        {
+            // NOTE: Service checks a private field and return an error if the SystemBufferSharing is disabled.
+
+            return ResultCode.NotImplemented;
+        }
+
         [CommandHipc(44)] // 10.0.0+
         // CreateManagedDisplaySeparableLayer() -> (u64, u64)
         public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context)
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs
index 2f5e86ba..926234f5 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/IAllSystemAppletProxiesService.cs
@@ -15,5 +15,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
 
             return ResultCode.Success;
         }
+
+        [CommandHipc(200)]
+        [CommandHipc(201)] // 3.0.0+
+        // OpenLibraryAppletProxy(u64, pid, handle<copy>) -> object<nn::am::service::ILibraryAppletProxy>
+        public ResultCode OpenLibraryAppletProxy(ServiceCtx context)
+        {
+            MakeObject(context, new ILibraryAppletProxy(context.Request.HandleDesc.PId));
+
+            return ResultCode.Success;
+        }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletIdentityInfo.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletIdentityInfo.cs
new file mode 100644
index 00000000..17a485ab
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletIdentityInfo.cs
@@ -0,0 +1,12 @@
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
+{
+    [StructLayout(LayoutKind.Sequential, Size = 0x10)]
+    struct AppletIdentifyInfo
+    {
+        public AppletId AppletId;
+        public uint     Padding;
+        public ulong    TitleId;
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletProcessLaunchReason.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletProcessLaunchReason.cs
new file mode 100644
index 00000000..6c528337
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/AppletProcessLaunchReason.cs
@@ -0,0 +1,12 @@
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
+{
+    [StructLayout(LayoutKind.Sequential, Size = 0x4)]
+    struct AppletProcessLaunchReason
+    {
+        public byte   Flag;
+        public ushort Unknown1;
+        public byte   Unknown2;
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/LibraryAppletInfo.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/LibraryAppletInfo.cs
new file mode 100644
index 00000000..fc1c11e4
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/LibraryAppletInfo.cs
@@ -0,0 +1,11 @@
+using System.Runtime.InteropServices;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
+{
+    [StructLayout(LayoutKind.Sequential, Size = 0x8)]
+    struct LibraryAppletInfo
+    {
+        public AppletId          AppletId;
+        public LibraryAppletMode LibraryAppletMode;
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/LibraryAppletMode.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/LibraryAppletMode.cs
new file mode 100644
index 00000000..6b9a2284
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/Types/LibraryAppletMode.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
+{
+    [Flags]
+    enum LibraryAppletMode : uint
+    {
+        AllForeground,
+        PartialForeground,
+        NoUi,
+        PartialForegroundWithIndirectDisplay,
+        AllForegroundInitiallyHidden
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs
index 8b67cece..44477922 100644
--- a/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs
@@ -25,7 +25,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
         // GetSelfController() -> object<nn::am::service::ISelfController>
         public ResultCode GetSelfController(ServiceCtx context)
         {
-            MakeObject(context, new ISelfController(context.Device.System, _pid));
+            MakeObject(context, new ISelfController(context, _pid));
 
             return ResultCode.Success;
         }
@@ -52,7 +52,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService
         // GetDisplayController() -> object<nn::am::service::IDisplayController>
         public ResultCode GetDisplayController(ServiceCtx context)
         {
-            MakeObject(context, new IDisplayController());
+            MakeObject(context, new IDisplayController(context));
 
             return ResultCode.Success;
         }
diff --git a/Ryujinx.HLE/HOS/Services/Am/ResultCode.cs b/Ryujinx.HLE/HOS/Services/Am/ResultCode.cs
index 422462e9..5cafff67 100644
--- a/Ryujinx.HLE/HOS/Services/Am/ResultCode.cs
+++ b/Ryujinx.HLE/HOS/Services/Am/ResultCode.cs
@@ -14,6 +14,8 @@ namespace Ryujinx.HLE.HOS.Services.Am
         ObjectInvalid          = (500 << ErrorCodeShift) | ModuleId,
         IStorageInUse          = (502 << ErrorCodeShift) | ModuleId,
         OutOfBounds            = (503 << ErrorCodeShift) | ModuleId,
+        BufferNotAcquired      = (504 << ErrorCodeShift) | ModuleId,
+        BufferAlreadyAcquired  = (505 << ErrorCodeShift) | ModuleId,
         InvalidParameters      = (506 << ErrorCodeShift) | ModuleId,
         OpenedAsWrongType      = (511 << ErrorCodeShift) | ModuleId,
         UnbalancedFatalSection = (512 << ErrorCodeShift) | ModuleId,
diff --git a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
index fd8844c7..bd07c103 100644
--- a/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
+++ b/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs
@@ -499,6 +499,15 @@ namespace Ryujinx.HLE.HOS.Services.Fs
             return (ResultCode)result.Value;
         }
 
+        [CommandHipc(1003)]
+        // DisableAutoSaveDataCreation()
+        public ResultCode DisableAutoSaveDataCreation(ServiceCtx context)
+        {
+            // NOTE: This call does nothing in original service.
+
+            return ResultCode.Success;
+        }
+
         [CommandHipc(1004)]
         // SetGlobalAccessLogMode(u32 mode)
         public ResultCode SetGlobalAccessLogMode(ServiceCtx context)
diff --git a/Ryujinx.HLE/HOS/Services/Mii/Helper.cs b/Ryujinx.HLE/HOS/Services/Mii/Helper.cs
index d5fa98ea..47debd59 100644
--- a/Ryujinx.HLE/HOS/Services/Mii/Helper.cs
+++ b/Ryujinx.HLE/HOS/Services/Mii/Helper.cs
@@ -36,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
         public static UInt128 GetDeviceId()
         {
             // FIXME: call set:sys GetMiiAuthorId
-            return new UInt128(0, 1);
+            return new UInt128("5279754d69694e780000000000000000"); // RyuMiiNx
         }
 
         public static ReadOnlySpan<byte> Ver3FacelineColorTable => new byte[] { 0, 1, 2, 3, 4, 5 };
diff --git a/Ryujinx.HLE/HOS/Services/Mii/IImageDatabaseService.cs b/Ryujinx.HLE/HOS/Services/Mii/IImageDatabaseService.cs
index a9f76902..1792bbb7 100644
--- a/Ryujinx.HLE/HOS/Services/Mii/IImageDatabaseService.cs
+++ b/Ryujinx.HLE/HOS/Services/Mii/IImageDatabaseService.cs
@@ -1,8 +1,41 @@
-namespace Ryujinx.HLE.HOS.Services.Mii
+using Ryujinx.Common.Logging;
+
+namespace Ryujinx.HLE.HOS.Services.Mii
 {
     [Service("miiimg")] // 5.0.0+
     class IImageDatabaseService : IpcService
     {
+        private uint _imageCount;
+        private bool _isDirty;
+
         public IImageDatabaseService(ServiceCtx context) { }
+
+        [CommandHipc(0)]
+        // Initialize(b8) -> b8
+        public ResultCode Initialize(ServiceCtx context)
+        {
+            // TODO: Service uses MiiImage:/database.dat if true, seems to use hardcoded data if false.
+            bool useHardcodedData = context.RequestData.ReadBoolean();
+
+            _imageCount = 0;
+            _isDirty    = false;
+
+            context.ResponseData.Write(_isDirty);
+
+            Logger.Stub?.PrintStub(LogClass.ServiceMii, new { useHardcodedData });
+
+            return ResultCode.Success;
+        }
+
+        [CommandHipc(11)]
+        // GetCount() -> u32
+        public ResultCode GetCount(ServiceCtx context)
+        {
+            context.ResponseData.Write(_imageCount);
+
+            Logger.Stub?.PrintStub(LogClass.ServiceMii);
+
+            return ResultCode.Success;
+        }
     }
 }
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs b/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs
index 4491f2c8..0bf15a7f 100644
--- a/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs
+++ b/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs
@@ -101,6 +101,9 @@ namespace Ryujinx.HLE.HOS.Services.Mii
             // Ensure we have valid data in the database
             _database.Format();
 
+            // TODO: Unmount is currently not implemented properly at dispose, implement that and decrement MountCounter.
+            MountCounter = 0;
+
             MountSave();
         }
 
@@ -151,8 +154,6 @@ namespace Ryujinx.HLE.HOS.Services.Mii
                 }
             }
 
-
-
             return result;
         }
 
@@ -183,6 +184,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
             if (result.IsSuccess())
             {
                 result = _filesystemClient.GetFileSize(out long fileSize, handle);
+
                 if (result.IsSuccess())
                 {
                     if (fileSize == Unsafe.SizeOf<NintendoFigurineDatabase>())
diff --git a/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs b/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs
index 66b768ee..1a437289 100644
--- a/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs
+++ b/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs
@@ -7,6 +7,7 @@ using LibHac.FsSystem.NcaUtils;
 using Ryujinx.Common.Logging;
 using Ryujinx.HLE.FileSystem;
 using Ryujinx.HLE.HOS.SystemState;
+using Ryujinx.HLE.Utilities;
 using System;
 using System.IO;
 using System.Text;
@@ -271,6 +272,20 @@ namespace Ryujinx.HLE.HOS.Services.Settings
             return ResultCode.Success;
         }
 
+        [CommandHipc(90)]
+        // GetMiiAuthorId() -> nn::util::Uuid
+        public ResultCode GetMiiAuthorId(ServiceCtx context)
+        {
+            // NOTE: If miiAuthorId is null ResultCode.NullMiiAuthorIdBuffer is returned.
+            //       Doesn't occur in our case.
+
+            UInt128 miiAuthorId = Mii.Helper.GetDeviceId();
+
+            miiAuthorId.Write(context.ResponseData);
+
+            return ResultCode.Success;
+        }
+
         public byte[] GetFirmwareData(Switch device)
         {
             const ulong SystemVersionTitleId = 0x0100000000000809;
diff --git a/Ryujinx.HLE/HOS/Services/Settings/Types/PlatformRegion.cs b/Ryujinx.HLE/HOS/Services/Settings/Types/PlatformRegion.cs
new file mode 100644
index 00000000..b8ef8e8e
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Settings/Types/PlatformRegion.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Settings.Types
+{
+    enum PlatformRegion
+    {
+        Global = 1,
+        China  = 2
+    }
+}
\ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs b/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
index 2a6f327b..f0b95f55 100644
--- a/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
+++ b/Ryujinx.HLE/HOS/SystemState/SystemStateMgr.cs
@@ -55,11 +55,11 @@ namespace Ryujinx.HLE.HOS.SystemState
 
             DesiredTitleLanguage = language switch
             {
-                SystemLanguage.Taiwanese or
-                SystemLanguage.TraditionalChinese => TitleLanguage.Taiwanese,
+                SystemLanguage.Taiwanese         => TitleLanguage.Taiwanese,
+                SystemLanguage.TraditionalChinese or
                 SystemLanguage.Chinese or
-                SystemLanguage.SimplifiedChinese  => TitleLanguage.Chinese,
-                _                                 => Enum.Parse<TitleLanguage>(Enum.GetName(typeof(SystemLanguage), language)),
+                SystemLanguage.SimplifiedChinese => TitleLanguage.Chinese,
+                _                                => Enum.Parse<TitleLanguage>(Enum.GetName(typeof(SystemLanguage), language)),
             };
         }
 
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index 9eb6f303..113ac639 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -3,6 +3,7 @@ using ARMeilleure.Translation.PTC;
 using Gtk;
 using LibHac.Common;
 using LibHac.FsSystem;
+using LibHac.FsSystem.NcaUtils;
 using LibHac.Ns;
 using Ryujinx.Audio.Backends.Dummy;
 using Ryujinx.Audio.Backends.OpenAL;
@@ -87,6 +88,10 @@ namespace Ryujinx.Ui
         [GUI] Box             _statusBar;
         [GUI] MenuItem        _optionMenu;
         [GUI] MenuItem        _manageUserProfiles;
+        [GUI] MenuItem        _fileMenu;
+        [GUI] MenuItem        _loadApplicationFile;
+        [GUI] MenuItem        _loadApplicationFolder;
+        [GUI] MenuItem        _appletMenu;
         [GUI] MenuItem        _actionMenu;
         [GUI] MenuItem        _stopEmulation;
         [GUI] MenuItem        _simulateWakeUpMessage;
@@ -165,6 +170,7 @@ namespace Ryujinx.Ui
             _applicationLibrary.ApplicationAdded        += Application_Added;
             _applicationLibrary.ApplicationCountUpdated += ApplicationCount_Updated;
 
+            _fileMenu.StateChanged   += FileMenu_StateChanged;
             _actionMenu.StateChanged += ActionMenu_StateChanged;
             _optionMenu.StateChanged += OptionMenu_StateChanged;
 
@@ -575,7 +581,15 @@ namespace Ryujinx.Ui
 
                 SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
 
-                bool isDirectory = Directory.Exists(path);
+                bool isDirectory     = Directory.Exists(path);
+                bool isFirmwareTitle = false;
+
+                if (path.StartsWith("@SystemContent"))
+                {
+                    path = _virtualFileSystem.SwitchPathToSystemPath(path);
+
+                    isFirmwareTitle = true;
+                }
 
                 if (!SetupValidator.CanStartApplication(_contentManager, path, out UserError userError))
                 {
@@ -636,7 +650,13 @@ namespace Ryujinx.Ui
 
                 Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}");
 
-                if (Directory.Exists(path))
+                if (isFirmwareTitle)
+                {
+                    Logger.Info?.Print(LogClass.Application, "Loading as Firmware Title (NCA).");
+
+                    _emulationContext.LoadNca(path);
+                }
+                else if (Directory.Exists(path))
                 {
                     string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
 
@@ -1100,6 +1120,20 @@ namespace Ryujinx.Ui
             }
         }
 
+        private void FileMenu_StateChanged(object o, StateChangedArgs args)
+        {
+            _appletMenu.Sensitive            = _emulationContext == null && _contentManager.GetCurrentFirmwareVersion() != null && _contentManager.GetCurrentFirmwareVersion().Major > 3;
+            _loadApplicationFile.Sensitive   = _emulationContext == null;
+            _loadApplicationFolder.Sensitive = _emulationContext == null;
+        }
+
+        private void Load_Mii_Edit_Applet(object sender, EventArgs args)
+        {
+            string contentPath = _contentManager.GetInstalledContentPath(0x0100000000001009, StorageId.NandSystem, NcaContentType.Program);
+
+            LoadApplication(contentPath);
+        }
+
         private void Open_Ryu_Folder(object sender, EventArgs args)
         {
             OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
@@ -1217,6 +1251,15 @@ namespace Ryujinx.Ui
 
                                     GtkDialog.CreateInfoDialog(dialogTitle, message);
                                     Logger.Info?.Print(LogClass.Application, message);
+
+                                    // Purge Applet Cache.
+
+                                    DirectoryInfo miiEditorCacheFolder = new DirectoryInfo(System.IO.Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
+
+                                    if (miiEditorCacheFolder.Exists)
+                                    {
+                                        miiEditorCacheFolder.Delete(true);
+                                    }
                                 });
                             }
                             catch (Exception ex)
diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade
index 129b768e..e974d878 100644
--- a/Ryujinx/Ui/MainWindow.glade
+++ b/Ryujinx/Ui/MainWindow.glade
@@ -19,7 +19,7 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <child>
-              <object class="GtkMenuItem" id="FileMenu">
+              <object class="GtkMenuItem" id="_fileMenu">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
                 <property name="label" translatable="yes">File</property>
@@ -29,7 +29,7 @@
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <child>
-                      <object class="GtkMenuItem" id="LoadApplicationFile">
+                      <object class="GtkMenuItem" id="_loadApplicationFile">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="tooltip_text" translatable="yes">Open a file chooser to chose a switch compatible file to load</property>
@@ -39,7 +39,7 @@
                       </object>
                     </child>
                     <child>
-                      <object class="GtkMenuItem" id="LoadApplicationFolder">
+                      <object class="GtkMenuItem" id="_loadApplicationFolder">
                         <property name="visible">True</property>
                         <property name="can_focus">False</property>
                         <property name="tooltip_text" translatable="yes">Open a file chooser to chose a switch compatible, unpacked application to load</property>
@@ -48,6 +48,30 @@
                         <signal name="activate" handler="Load_Application_Folder" swapped="no"/>
                       </object>
                     </child>
+                    <child>
+                      <object class="GtkMenuItem" id="_appletMenu">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">Load Applet</property>
+                        <property name="use_underline">True</property>
+                        <child type="submenu">
+                          <object class="GtkMenu">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <child>
+                              <object class="GtkMenuItem" id="LoadMiiEditApplet">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                                <property name="tooltip_text" translatable="yes">Open Mii Editor Applet in Standalone mode</property>
+                                <property name="label" translatable="yes">Mii Editor</property>
+                                <property name="use_underline">True</property>
+                                <signal name="activate" handler="Load_Mii_Edit_Applet" swapped="no"/>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                    </child>
                     <child>
                       <object class="GtkSeparatorMenuItem">
                         <property name="visible">True</property>
-- 
cgit v1.2.3-70-g09d2