aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService
diff options
context:
space:
mode:
authorTSR Berry <20988865+TSRBerry@users.noreply.github.com>2023-04-08 01:22:00 +0200
committerMary <thog@protonmail.com>2023-04-27 23:51:14 +0200
commitcee712105850ac3385cd0091a923438167433f9f (patch)
tree4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService
parentcd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff)
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService')
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs105
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs104
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs261
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/AppletStandalone.cs16
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs78
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs24
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs7
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IApplicationCreator.cs7
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAudioController.cs66
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs285
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDebugFunctions.cs7
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs106
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IGlobalStateController.cs7
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs48
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs91
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs432
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs36
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/AlbumReportOption.cs10
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/AppletMessage.cs36
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/FocusState.cs8
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/OperationMode.cs8
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/WirelessPriorityMode.cs9
22 files changed, 1751 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs
new file mode 100644
index 00000000..bf86aaaa
--- /dev/null
+++ b/src/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 ulong _pid;
+
+ public ILibraryAppletProxy(ulong pid)
+ {
+ _pid = pid;
+ }
+
+ [CommandCmif(0)]
+ // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
+ public ResultCode GetCommonStateGetter(ServiceCtx context)
+ {
+ MakeObject(context, new ICommonStateGetter(context));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(1)]
+ // GetSelfController() -> object<nn::am::service::ISelfController>
+ public ResultCode GetSelfController(ServiceCtx context)
+ {
+ MakeObject(context, new ISelfController(context, _pid));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(2)]
+ // GetWindowController() -> object<nn::am::service::IWindowController>
+ public ResultCode GetWindowController(ServiceCtx context)
+ {
+ MakeObject(context, new IWindowController(_pid));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(3)]
+ // GetAudioController() -> object<nn::am::service::IAudioController>
+ public ResultCode GetAudioController(ServiceCtx context)
+ {
+ MakeObject(context, new IAudioController());
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(4)]
+ // GetDisplayController() -> object<nn::am::service::IDisplayController>
+ public ResultCode GetDisplayController(ServiceCtx context)
+ {
+ MakeObject(context, new IDisplayController(context));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(10)]
+ // GetProcessWindingController() -> object<nn::am::service::IProcessWindingController>
+ public ResultCode GetProcessWindingController(ServiceCtx context)
+ {
+ MakeObject(context, new IProcessWindingController());
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(11)]
+ // GetLibraryAppletCreator() -> object<nn::am::service::ILibraryAppletCreator>
+ public ResultCode GetLibraryAppletCreator(ServiceCtx context)
+ {
+ MakeObject(context, new ILibraryAppletCreator());
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(20)]
+ // OpenLibraryAppletSelfAccessor() -> object<nn::am::service::ILibraryAppletSelfAccessor>
+ public ResultCode OpenLibraryAppletSelfAccessor(ServiceCtx context)
+ {
+ MakeObject(context, new ILibraryAppletSelfAccessor(context));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(21)]
+ // GetAppletCommonFunctions() -> object<nn::am::service::IAppletCommonFunctions>
+ public ResultCode GetAppletCommonFunctions(ServiceCtx context)
+ {
+ MakeObject(context, new IAppletCommonFunctions());
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(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/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs
new file mode 100644
index 00000000..dc26d80c
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ISystemAppletProxy.cs
@@ -0,0 +1,104 @@
+using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService
+{
+ class ISystemAppletProxy : IpcService
+ {
+ private readonly ulong _pid;
+
+ public ISystemAppletProxy(ulong pid)
+ {
+ _pid = pid;
+ }
+
+ [CommandCmif(0)]
+ // GetCommonStateGetter() -> object<nn::am::service::ICommonStateGetter>
+ public ResultCode GetCommonStateGetter(ServiceCtx context)
+ {
+ MakeObject(context, new ICommonStateGetter(context));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(1)]
+ // GetSelfController() -> object<nn::am::service::ISelfController>
+ public ResultCode GetSelfController(ServiceCtx context)
+ {
+ MakeObject(context, new ISelfController(context, _pid));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(2)]
+ // GetWindowController() -> object<nn::am::service::IWindowController>
+ public ResultCode GetWindowController(ServiceCtx context)
+ {
+ MakeObject(context, new IWindowController(_pid));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(3)]
+ // GetAudioController() -> object<nn::am::service::IAudioController>
+ public ResultCode GetAudioController(ServiceCtx context)
+ {
+ MakeObject(context, new IAudioController());
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(4)]
+ // GetDisplayController() -> object<nn::am::service::IDisplayController>
+ public ResultCode GetDisplayController(ServiceCtx context)
+ {
+ MakeObject(context, new IDisplayController(context));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(11)]
+ // GetLibraryAppletCreator() -> object<nn::am::service::ILibraryAppletCreator>
+ public ResultCode GetLibraryAppletCreator(ServiceCtx context)
+ {
+ MakeObject(context, new ILibraryAppletCreator());
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(20)]
+ // GetHomeMenuFunctions() -> object<nn::am::service::IHomeMenuFunctions>
+ public ResultCode GetHomeMenuFunctions(ServiceCtx context)
+ {
+ MakeObject(context, new IHomeMenuFunctions(context.Device.System));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(21)]
+ // GetGlobalStateController() -> object<nn::am::service::IGlobalStateController>
+ public ResultCode GetGlobalStateController(ServiceCtx context)
+ {
+ MakeObject(context, new IGlobalStateController());
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(22)]
+ // GetApplicationCreator() -> object<nn::am::service::IApplicationCreator>
+ public ResultCode GetApplicationCreator(ServiceCtx context)
+ {
+ MakeObject(context, new IApplicationCreator());
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(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/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs
new file mode 100644
index 00000000..0057eba3
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletCreator/ILibraryAppletAccessor.cs
@@ -0,0 +1,261 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Applets;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Horizon.Common;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator
+{
+ class ILibraryAppletAccessor : DisposableIpcService
+ {
+ private KernelContext _kernelContext;
+
+ private IApplet _applet;
+
+ private AppletSession _normalSession;
+ private AppletSession _interactiveSession;
+
+ private KEvent _stateChangedEvent;
+ private KEvent _normalOutDataEvent;
+ private KEvent _interactiveOutDataEvent;
+
+ private int _stateChangedEventHandle;
+ private int _normalOutDataEventHandle;
+ private int _interactiveOutDataEventHandle;
+
+ private int _indirectLayerHandle;
+
+ public ILibraryAppletAccessor(AppletId appletId, Horizon system)
+ {
+ _kernelContext = system.KernelContext;
+
+ _stateChangedEvent = new KEvent(system.KernelContext);
+ _normalOutDataEvent = new KEvent(system.KernelContext);
+ _interactiveOutDataEvent = new KEvent(system.KernelContext);
+
+ _applet = AppletManager.Create(appletId, system);
+
+ _normalSession = new AppletSession();
+ _interactiveSession = new AppletSession();
+
+ _applet.AppletStateChanged += OnAppletStateChanged;
+ _normalSession.DataAvailable += OnNormalOutData;
+ _interactiveSession.DataAvailable += OnInteractiveOutData;
+
+ Logger.Info?.Print(LogClass.ServiceAm, $"Applet '{appletId}' created.");
+ }
+
+ private void OnAppletStateChanged(object sender, EventArgs e)
+ {
+ _stateChangedEvent.WritableEvent.Signal();
+ }
+
+ private void OnNormalOutData(object sender, EventArgs e)
+ {
+ _normalOutDataEvent.WritableEvent.Signal();
+ }
+
+ private void OnInteractiveOutData(object sender, EventArgs e)
+ {
+ _interactiveOutDataEvent.WritableEvent.Signal();
+ }
+
+ [CommandCmif(0)]
+ // GetAppletStateChangedEvent() -> handle<copy>
+ public ResultCode GetAppletStateChangedEvent(ServiceCtx context)
+ {
+ if (_stateChangedEventHandle == 0)
+ {
+ if (context.Process.HandleTable.GenerateHandle(_stateChangedEvent.ReadableEvent, out _stateChangedEventHandle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_stateChangedEventHandle);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(10)]
+ // Start()
+ public ResultCode Start(ServiceCtx context)
+ {
+ return (ResultCode)_applet.Start(_normalSession.GetConsumer(), _interactiveSession.GetConsumer());
+ }
+
+ [CommandCmif(20)]
+ // RequestExit()
+ public ResultCode RequestExit(ServiceCtx context)
+ {
+ // TODO: Since we don't support software Applet for now, we can just signals the changed state of the applet.
+ _stateChangedEvent.ReadableEvent.Signal();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(30)]
+ // GetResult()
+ public ResultCode GetResult(ServiceCtx context)
+ {
+ return (ResultCode)_applet.GetResult();
+ }
+
+ [CommandCmif(60)]
+ // PresetLibraryAppletGpuTimeSliceZero()
+ public ResultCode PresetLibraryAppletGpuTimeSliceZero(ServiceCtx context)
+ {
+ // NOTE: This call reset two internal fields to 0 and one internal field to "true".
+ // It seems to be used only with software keyboard inline.
+ // Since we doesn't support applets for now, it's fine to stub it.
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(100)]
+ // PushInData(object<nn::am::service::IStorage>)
+ public ResultCode PushInData(ServiceCtx context)
+ {
+ IStorage data = GetObject<IStorage>(context, 0);
+
+ _normalSession.Push(data.Data);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(101)]
+ // PopOutData() -> object<nn::am::service::IStorage>
+ public ResultCode PopOutData(ServiceCtx context)
+ {
+ if (_normalSession.TryPop(out byte[] data))
+ {
+ MakeObject(context, new IStorage(data));
+
+ _normalOutDataEvent.WritableEvent.Clear();
+
+ return ResultCode.Success;
+ }
+
+ return ResultCode.NotAvailable;
+ }
+
+ [CommandCmif(103)]
+ // PushInteractiveInData(object<nn::am::service::IStorage>)
+ public ResultCode PushInteractiveInData(ServiceCtx context)
+ {
+ IStorage data = GetObject<IStorage>(context, 0);
+
+ _interactiveSession.Push(data.Data);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(104)]
+ // PopInteractiveOutData() -> object<nn::am::service::IStorage>
+ public ResultCode PopInteractiveOutData(ServiceCtx context)
+ {
+ if (_interactiveSession.TryPop(out byte[] data))
+ {
+ MakeObject(context, new IStorage(data));
+
+ _interactiveOutDataEvent.WritableEvent.Clear();
+
+ return ResultCode.Success;
+ }
+
+ return ResultCode.NotAvailable;
+ }
+
+ [CommandCmif(105)]
+ // GetPopOutDataEvent() -> handle<copy>
+ public ResultCode GetPopOutDataEvent(ServiceCtx context)
+ {
+ if (_normalOutDataEventHandle == 0)
+ {
+ if (context.Process.HandleTable.GenerateHandle(_normalOutDataEvent.ReadableEvent, out _normalOutDataEventHandle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_normalOutDataEventHandle);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(106)]
+ // GetPopInteractiveOutDataEvent() -> handle<copy>
+ public ResultCode GetPopInteractiveOutDataEvent(ServiceCtx context)
+ {
+ if (_interactiveOutDataEventHandle == 0)
+ {
+ if (context.Process.HandleTable.GenerateHandle(_interactiveOutDataEvent.ReadableEvent, out _interactiveOutDataEventHandle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_interactiveOutDataEventHandle);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(110)]
+ // NeedsToExitProcess()
+ public ResultCode NeedsToExitProcess(ServiceCtx context)
+ {
+ return ResultCode.Stubbed;
+ }
+
+ [CommandCmif(150)]
+ // RequestForAppletToGetForeground()
+ public ResultCode RequestForAppletToGetForeground(ServiceCtx context)
+ {
+ return ResultCode.Stubbed;
+ }
+
+ [CommandCmif(160)] // 2.0.0+
+ // GetIndirectLayerConsumerHandle() -> u64 indirect_layer_consumer_handle
+ public ResultCode GetIndirectLayerConsumerHandle(ServiceCtx context)
+ {
+ Horizon horizon = _kernelContext.Device.System;
+
+ _indirectLayerHandle = horizon.AppletState.IndirectLayerHandles.Add(_applet);
+
+ context.ResponseData.Write((ulong)_indirectLayerHandle);
+
+ return ResultCode.Success;
+ }
+
+ protected override void Dispose(bool isDisposing)
+ {
+ if (isDisposing)
+ {
+ if (_stateChangedEventHandle != 0)
+ {
+ _kernelContext.Syscall.CloseHandle(_stateChangedEventHandle);
+ }
+
+ if (_normalOutDataEventHandle != 0)
+ {
+ _kernelContext.Syscall.CloseHandle(_normalOutDataEventHandle);
+ }
+
+ if (_interactiveOutDataEventHandle != 0)
+ {
+ _kernelContext.Syscall.CloseHandle(_interactiveOutDataEventHandle);
+ }
+ }
+
+ Horizon horizon = _kernelContext.Device.System;
+
+ horizon.AppletState.IndirectLayerHandles.Delete(_indirectLayerHandle);
+ }
+ }
+}
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/AppletStandalone.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/AppletStandalone.cs
new file mode 100644
index 00000000..69967c56
--- /dev/null
+++ b/src/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/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs
new file mode 100644
index 00000000..176bd632
--- /dev/null
+++ b/src/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.Processes.ActiveApplication.ProgramId == 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.Processes.ActiveApplication.ProgramId} applet is not implemented.");
+ }
+ }
+
+ [CommandCmif(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;
+ }
+
+ [CommandCmif(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;
+ }
+
+ [CommandCmif(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/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/IProcessWindingController.cs
new file mode 100644
index 00000000..6acd18cd
--- /dev/null
+++ b/src/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() { }
+
+ [CommandCmif(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/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs
new file mode 100644
index 00000000..c42202b8
--- /dev/null
+++ b/src/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/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IApplicationCreator.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IApplicationCreator.cs
new file mode 100644
index 00000000..79e5b050
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IApplicationCreator.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class IApplicationCreator : IpcService
+ {
+ public IApplicationCreator() { }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAudioController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAudioController.cs
new file mode 100644
index 00000000..48dd42e4
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAudioController.cs
@@ -0,0 +1,66 @@
+using Ryujinx.Common.Logging;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class IAudioController : IpcService
+ {
+ public IAudioController() { }
+
+ [CommandCmif(0)]
+ // SetExpectedMasterVolume(f32, f32)
+ public ResultCode SetExpectedMasterVolume(ServiceCtx context)
+ {
+ float appletVolume = context.RequestData.ReadSingle();
+ float libraryAppletVolume = context.RequestData.ReadSingle();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(1)]
+ // GetMainAppletExpectedMasterVolume() -> f32
+ public ResultCode GetMainAppletExpectedMasterVolume(ServiceCtx context)
+ {
+ context.ResponseData.Write(1f);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(2)]
+ // GetLibraryAppletExpectedMasterVolume() -> f32
+ public ResultCode GetLibraryAppletExpectedMasterVolume(ServiceCtx context)
+ {
+ context.ResponseData.Write(1f);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(3)]
+ // ChangeMainAppletMasterVolume(f32, u64)
+ public ResultCode ChangeMainAppletMasterVolume(ServiceCtx context)
+ {
+ float unknown0 = context.RequestData.ReadSingle();
+ long unknown1 = context.RequestData.ReadInt64();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(4)]
+ // SetTransparentVolumeRate(f32)
+ public ResultCode SetTransparentVolumeRate(ServiceCtx context)
+ {
+ float unknown0 = context.RequestData.ReadSingle();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
new file mode 100644
index 00000000..381267b0
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs
@@ -0,0 +1,285 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.HLE.HOS.Services.Settings.Types;
+using Ryujinx.HLE.HOS.Services.Vi.RootService.ApplicationDisplayService;
+using Ryujinx.HLE.HOS.SystemState;
+using Ryujinx.Horizon.Common;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class ICommonStateGetter : IpcService
+ {
+ private Apm.ManagerServer _apmManagerServer;
+ private Apm.SystemManagerServer _apmSystemManagerServer;
+ private Lbl.LblControllerServer _lblControllerServer;
+
+ private bool _vrModeEnabled;
+#pragma warning disable CS0414
+ private bool _lcdBacklighOffEnabled;
+ private bool _requestExitToLibraryAppletAtExecuteNextProgramEnabled;
+#pragma warning restore CS0414
+ private int _messageEventHandle;
+ private int _displayResolutionChangedEventHandle;
+
+ public ICommonStateGetter(ServiceCtx context)
+ {
+ _apmManagerServer = new Apm.ManagerServer(context);
+ _apmSystemManagerServer = new Apm.SystemManagerServer(context);
+ _lblControllerServer = new Lbl.LblControllerServer(context);
+ }
+
+ [CommandCmif(0)]
+ // GetEventHandle() -> handle<copy>
+ public ResultCode GetEventHandle(ServiceCtx context)
+ {
+ KEvent messageEvent = context.Device.System.AppletState.MessageEvent;
+
+ if (_messageEventHandle == 0)
+ {
+ if (context.Process.HandleTable.GenerateHandle(messageEvent.ReadableEvent, out _messageEventHandle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_messageEventHandle);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(1)]
+ // ReceiveMessage() -> nn::am::AppletMessage
+ public ResultCode ReceiveMessage(ServiceCtx context)
+ {
+ if (!context.Device.System.AppletState.Messages.TryDequeue(out AppletMessage message))
+ {
+ return ResultCode.NoMessages;
+ }
+
+ KEvent messageEvent = context.Device.System.AppletState.MessageEvent;
+
+ // NOTE: Service checks if current states are different than the stored ones.
+ // Since we don't support any states for now, it's fine to check if there is still messages available.
+
+ if (context.Device.System.AppletState.Messages.IsEmpty)
+ {
+ messageEvent.ReadableEvent.Clear();
+ }
+ else
+ {
+ messageEvent.ReadableEvent.Signal();
+ }
+
+ context.ResponseData.Write((int)message);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(5)]
+ // GetOperationMode() -> u8
+ public ResultCode GetOperationMode(ServiceCtx context)
+ {
+ OperationMode mode = context.Device.System.State.DockedMode
+ ? OperationMode.Docked
+ : OperationMode.Handheld;
+
+ context.ResponseData.Write((byte)mode);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(6)]
+ // GetPerformanceMode() -> nn::apm::PerformanceMode
+ public ResultCode GetPerformanceMode(ServiceCtx context)
+ {
+ return (ResultCode)_apmManagerServer.GetPerformanceMode(context);
+ }
+
+ [CommandCmif(8)]
+ // GetBootMode() -> u8
+ public ResultCode GetBootMode(ServiceCtx context)
+ {
+ context.ResponseData.Write((byte)0); //Unknown value.
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(9)]
+ // GetCurrentFocusState() -> u8
+ public ResultCode GetCurrentFocusState(ServiceCtx context)
+ {
+ context.ResponseData.Write((byte)context.Device.System.AppletState.FocusState);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(50)] // 3.0.0+
+ // IsVrModeEnabled() -> b8
+ public ResultCode IsVrModeEnabled(ServiceCtx context)
+ {
+ context.ResponseData.Write(_vrModeEnabled);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(51)] // 3.0.0+
+ // SetVrModeEnabled(b8)
+ public ResultCode SetVrModeEnabled(ServiceCtx context)
+ {
+ bool vrModeEnabled = context.RequestData.ReadBoolean();
+
+ UpdateVrMode(vrModeEnabled);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(52)] // 4.0.0+
+ // SetLcdBacklighOffEnabled(b8)
+ public ResultCode SetLcdBacklighOffEnabled(ServiceCtx context)
+ {
+ // NOTE: Service sets a private field here, maybe this field is used somewhere else to turned off the backlight.
+ // Since we don't support backlight, it's fine to do nothing.
+
+ _lcdBacklighOffEnabled = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(53)] // 7.0.0+
+ // BeginVrModeEx()
+ public ResultCode BeginVrModeEx(ServiceCtx context)
+ {
+ UpdateVrMode(true);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(54)] // 7.0.0+
+ // EndVrModeEx()
+ public ResultCode EndVrModeEx(ServiceCtx context)
+ {
+ UpdateVrMode(false);
+
+ return ResultCode.Success;
+ }
+
+ private void UpdateVrMode(bool vrModeEnabled)
+ {
+ if (_vrModeEnabled == vrModeEnabled)
+ {
+ return;
+ }
+
+ _vrModeEnabled = vrModeEnabled;
+
+ if (vrModeEnabled)
+ {
+ _lblControllerServer.EnableVrMode();
+ }
+ else
+ {
+ _lblControllerServer.DisableVrMode();
+ }
+
+ // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used.
+ }
+
+ [CommandCmif(60)] // 3.0.0+
+ // GetDefaultDisplayResolution() -> (u32, u32)
+ public ResultCode GetDefaultDisplayResolution(ServiceCtx context)
+ {
+ // NOTE: Original service calls IOperationModeManager::GetDefaultDisplayResolution of omm service.
+ // IOperationModeManager::GetDefaultDisplayResolution of omm service call IManagerDisplayService::GetDisplayResolution of vi service.
+ (ulong width, ulong height) = AndroidSurfaceComposerClient.GetDisplayInfo(context);
+
+ context.ResponseData.Write((uint)width);
+ context.ResponseData.Write((uint)height);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(61)] // 3.0.0+
+ // GetDefaultDisplayResolutionChangeEvent() -> handle<copy>
+ public ResultCode GetDefaultDisplayResolutionChangeEvent(ServiceCtx context)
+ {
+ // NOTE: Original service calls IOperationModeManager::GetDefaultDisplayResolutionChangeEvent of omm service.
+ if (_displayResolutionChangedEventHandle == 0)
+ {
+ if (context.Process.HandleTable.GenerateHandle(context.Device.System.DisplayResolutionChangeEvent.ReadableEvent, out _displayResolutionChangedEventHandle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_displayResolutionChangedEventHandle);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(62)] // 4.0.0+
+ // GetHdcpAuthenticationState() -> s32 state
+ public ResultCode GetHdcpAuthenticationState(ServiceCtx context)
+ {
+ context.ResponseData.Write(0);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(66)] // 6.0.0+
+ // SetCpuBoostMode(u32 cpu_boost_mode)
+ public ResultCode SetCpuBoostMode(ServiceCtx context)
+ {
+ uint cpuBoostMode = context.RequestData.ReadUInt32();
+
+ if (cpuBoostMode > 1)
+ {
+ return ResultCode.InvalidParameters;
+ }
+
+ _apmSystemManagerServer.SetCpuBoostMode((Apm.CpuBoostMode)cpuBoostMode);
+
+ // TODO: It signals an internal event of ICommonStateGetter. We have to determine where this event is used.
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(91)] // 7.0.0+
+ // GetCurrentPerformanceConfiguration() -> nn::apm::PerformanceConfiguration
+ public ResultCode GetCurrentPerformanceConfiguration(ServiceCtx context)
+ {
+ return (ResultCode)_apmSystemManagerServer.GetCurrentPerformanceConfiguration(context);
+ }
+
+ [CommandCmif(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;
+ }
+
+ [CommandCmif(900)] // 11.0.0+
+ // SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled()
+ public ResultCode SetRequestExitToLibraryAppletAtExecuteNextProgramEnabled(ServiceCtx context)
+ {
+ // TODO : Find where the field is used.
+ _requestExitToLibraryAppletAtExecuteNextProgramEnabled = true;
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDebugFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDebugFunctions.cs
new file mode 100644
index 00000000..51a112fd
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDebugFunctions.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class IDebugFunctions : IpcService
+ {
+ public IDebugFunctions() { }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs
new file mode 100644
index 00000000..92c97d86
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IDisplayController.cs
@@ -0,0 +1,106 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Memory;
+using Ryujinx.Horizon.Common;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class IDisplayController : IpcService
+ {
+ private KTransferMemory _transferMem;
+ private bool _lastApplicationCaptureBufferAcquired;
+ private bool _callerAppletCaptureBufferAcquired;
+
+ public IDisplayController(ServiceCtx context)
+ {
+ _transferMem = context.Device.System.AppletCaptureBufferTransfer;
+ }
+
+ [CommandCmif(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;
+ }
+
+ [CommandCmif(11)]
+ // ReleaseLastApplicationCaptureBuffer()
+ public ResultCode ReleaseLastApplicationCaptureBuffer(ServiceCtx context)
+ {
+ if (!_lastApplicationCaptureBufferAcquired)
+ {
+ return ResultCode.BufferNotAcquired;
+ }
+
+ _lastApplicationCaptureBufferAcquired = false;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(15)]
+ // ReleaseCallerAppletCaptureBuffer()
+ public ResultCode ReleaseCallerAppletCaptureBuffer(ServiceCtx context)
+ {
+ if (!_callerAppletCaptureBufferAcquired)
+ {
+ return ResultCode.BufferNotAcquired;
+ }
+
+ _callerAppletCaptureBufferAcquired = false;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(16)]
+ // AcquireLastApplicationCaptureBufferEx() -> (b8, handle<copy>)
+ public ResultCode AcquireLastApplicationCaptureBufferEx(ServiceCtx context)
+ {
+ if (_lastApplicationCaptureBufferAcquired)
+ {
+ return ResultCode.BufferAlreadyAcquired;
+ }
+
+ if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
+
+ _lastApplicationCaptureBufferAcquired = true;
+
+ context.ResponseData.Write(_lastApplicationCaptureBufferAcquired);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(18)]
+ // AcquireCallerAppletCaptureBufferEx() -> (b8, handle<copy>)
+ public ResultCode AcquireCallerAppletCaptureBufferEx(ServiceCtx context)
+ {
+ if (_callerAppletCaptureBufferAcquired)
+ {
+ return ResultCode.BufferAlreadyAcquired;
+ }
+
+ if (context.Process.HandleTable.GenerateHandle(_transferMem, out int handle) != Result.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/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IGlobalStateController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IGlobalStateController.cs
new file mode 100644
index 00000000..24eeefb9
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IGlobalStateController.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class IGlobalStateController : IpcService
+ {
+ public IGlobalStateController() { }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs
new file mode 100644
index 00000000..c7c073ff
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IHomeMenuFunctions.cs
@@ -0,0 +1,48 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.Horizon.Common;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class IHomeMenuFunctions : IpcService
+ {
+ private KEvent _channelEvent;
+ private int _channelEventHandle;
+
+ public IHomeMenuFunctions(Horizon system)
+ {
+ // TODO: Signal this Event somewhere in future.
+ _channelEvent = new KEvent(system.KernelContext);
+ }
+
+ [CommandCmif(10)]
+ // RequestToGetForeground()
+ public ResultCode RequestToGetForeground(ServiceCtx context)
+ {
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(21)]
+ // GetPopFromGeneralChannelEvent() -> handle<copy>
+ public ResultCode GetPopFromGeneralChannelEvent(ServiceCtx context)
+ {
+ if (_channelEventHandle == 0)
+ {
+ if (context.Process.HandleTable.GenerateHandle(_channelEvent.ReadableEvent, out _channelEventHandle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_channelEventHandle);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs
new file mode 100644
index 00000000..fb870c24
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs
@@ -0,0 +1,91 @@
+using Ryujinx.HLE.HOS.Kernel.Memory;
+using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class ILibraryAppletCreator : IpcService
+ {
+ public ILibraryAppletCreator() { }
+
+ [CommandCmif(0)]
+ // CreateLibraryApplet(u32, u32) -> object<nn::am::service::ILibraryAppletAccessor>
+ public ResultCode CreateLibraryApplet(ServiceCtx context)
+ {
+ AppletId appletId = (AppletId)context.RequestData.ReadInt32();
+ int libraryAppletMode = context.RequestData.ReadInt32();
+
+ MakeObject(context, new ILibraryAppletAccessor(appletId, context.Device.System));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(10)]
+ // CreateStorage(u64) -> object<nn::am::service::IStorage>
+ public ResultCode CreateStorage(ServiceCtx context)
+ {
+ long size = context.RequestData.ReadInt64();
+
+ if (size <= 0)
+ {
+ return ResultCode.ObjectInvalid;
+ }
+
+ MakeObject(context, new IStorage(new byte[size]));
+
+ // NOTE: Returns ResultCode.MemoryAllocationFailed if IStorage is null, it doesn't occur in our case.
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(11)]
+ // CreateTransferMemoryStorage(b8, u64, handle<copy>) -> object<nn::am::service::IStorage>
+ public ResultCode CreateTransferMemoryStorage(ServiceCtx context)
+ {
+ bool isReadOnly = (context.RequestData.ReadInt64() & 1) == 0;
+ long size = context.RequestData.ReadInt64();
+ int handle = context.Request.HandleDesc.ToCopy[0];
+
+ KTransferMemory transferMem = context.Process.HandleTable.GetObject<KTransferMemory>(handle);
+
+ if (size <= 0)
+ {
+ return ResultCode.ObjectInvalid;
+ }
+
+ byte[] data = new byte[transferMem.Size];
+
+ transferMem.Creator.CpuMemory.Read(transferMem.Address, data);
+
+ context.Device.System.KernelContext.Syscall.CloseHandle(handle);
+
+ MakeObject(context, new IStorage(data, isReadOnly));
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(12)] // 2.0.0+
+ // CreateHandleStorage(u64, handle<copy>) -> object<nn::am::service::IStorage>
+ public ResultCode CreateHandleStorage(ServiceCtx context)
+ {
+ long size = context.RequestData.ReadInt64();
+ int handle = context.Request.HandleDesc.ToCopy[0];
+
+ KTransferMemory transferMem = context.Process.HandleTable.GetObject<KTransferMemory>(handle);
+
+ if (size <= 0)
+ {
+ return ResultCode.ObjectInvalid;
+ }
+
+ byte[] data = new byte[transferMem.Size];
+
+ transferMem.Creator.CpuMemory.Read(transferMem.Address, data);
+
+ context.Device.System.KernelContext.Syscall.CloseHandle(handle);
+
+ MakeObject(context, new IStorage(data));
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs
new file mode 100644
index 00000000..399e778a
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs
@@ -0,0 +1,432 @@
+using Ryujinx.Common.Logging;
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel.Threading;
+using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types;
+using Ryujinx.Horizon.Common;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class ISelfController : IpcService
+ {
+ private readonly ulong _pid;
+
+ private KEvent _libraryAppletLaunchableEvent;
+ private int _libraryAppletLaunchableEventHandle;
+
+ private KEvent _accumulatedSuspendedTickChangedEvent;
+ private int _accumulatedSuspendedTickChangedEventHandle;
+
+ private object _fatalSectionLock = new object();
+ private int _fatalSectionCount;
+
+ // TODO: Set this when the game goes in suspension (go back to home menu ect), we currently don't support that so we can keep it set to 0.
+ private ulong _accumulatedSuspendedTickValue = 0;
+
+ // TODO: Determine where those fields are used.
+ private bool _screenShotPermission = false;
+ private bool _operationModeChangedNotification = false;
+ private bool _performanceModeChangedNotification = false;
+ private bool _restartMessageEnabled = false;
+ private bool _outOfFocusSuspendingEnabled = false;
+ private bool _handlesRequestToDisplay = false;
+ private bool _autoSleepDisabled = false;
+ private bool _albumImageTakenNotificationEnabled = false;
+ private bool _recordVolumeMuted = false;
+
+ private uint _screenShotImageOrientation = 0;
+ private uint _idleTimeDetectionExtension = 0;
+
+ public ISelfController(ServiceCtx context, ulong pid)
+ {
+ _libraryAppletLaunchableEvent = new KEvent(context.Device.System.KernelContext);
+ _pid = pid;
+ }
+
+ [CommandCmif(0)]
+ // Exit()
+ public ResultCode Exit(ServiceCtx context)
+ {
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(1)]
+ // LockExit()
+ public ResultCode LockExit(ServiceCtx context)
+ {
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(2)]
+ // UnlockExit()
+ public ResultCode UnlockExit(ServiceCtx context)
+ {
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(3)] // 2.0.0+
+ // EnterFatalSection()
+ public ResultCode EnterFatalSection(ServiceCtx context)
+ {
+ lock (_fatalSectionLock)
+ {
+ _fatalSectionCount++;
+ }
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(4)] // 2.0.0+
+ // LeaveFatalSection()
+ public ResultCode LeaveFatalSection(ServiceCtx context)
+ {
+ ResultCode result = ResultCode.Success;
+
+ lock (_fatalSectionLock)
+ {
+ if (_fatalSectionCount != 0)
+ {
+ _fatalSectionCount--;
+ }
+ else
+ {
+ result = ResultCode.UnbalancedFatalSection;
+ }
+ }
+
+ return result;
+ }
+
+ [CommandCmif(9)]
+ // GetLibraryAppletLaunchableEvent() -> handle<copy>
+ public ResultCode GetLibraryAppletLaunchableEvent(ServiceCtx context)
+ {
+ _libraryAppletLaunchableEvent.ReadableEvent.Signal();
+
+ if (_libraryAppletLaunchableEventHandle == 0)
+ {
+ if (context.Process.HandleTable.GenerateHandle(_libraryAppletLaunchableEvent.ReadableEvent, out _libraryAppletLaunchableEventHandle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_libraryAppletLaunchableEventHandle);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(10)]
+ // SetScreenShotPermission(u32)
+ public ResultCode SetScreenShotPermission(ServiceCtx context)
+ {
+ bool screenShotPermission = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { screenShotPermission });
+
+ _screenShotPermission = screenShotPermission;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(11)]
+ // SetOperationModeChangedNotification(b8)
+ public ResultCode SetOperationModeChangedNotification(ServiceCtx context)
+ {
+ bool operationModeChangedNotification = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { operationModeChangedNotification });
+
+ _operationModeChangedNotification = operationModeChangedNotification;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(12)]
+ // SetPerformanceModeChangedNotification(b8)
+ public ResultCode SetPerformanceModeChangedNotification(ServiceCtx context)
+ {
+ bool performanceModeChangedNotification = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { performanceModeChangedNotification });
+
+ _performanceModeChangedNotification = performanceModeChangedNotification;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(13)]
+ // SetFocusHandlingMode(b8, b8, b8)
+ public ResultCode SetFocusHandlingMode(ServiceCtx context)
+ {
+ bool unknownFlag1 = context.RequestData.ReadBoolean();
+ bool unknownFlag2 = context.RequestData.ReadBoolean();
+ bool unknownFlag3 = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { unknownFlag1, unknownFlag2, unknownFlag3 });
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(14)]
+ // SetRestartMessageEnabled(b8)
+ public ResultCode SetRestartMessageEnabled(ServiceCtx context)
+ {
+ bool restartMessageEnabled = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { restartMessageEnabled });
+
+ _restartMessageEnabled = restartMessageEnabled;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(16)] // 2.0.0+
+ // SetOutOfFocusSuspendingEnabled(b8)
+ public ResultCode SetOutOfFocusSuspendingEnabled(ServiceCtx context)
+ {
+ bool outOfFocusSuspendingEnabled = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { outOfFocusSuspendingEnabled });
+
+ _outOfFocusSuspendingEnabled = outOfFocusSuspendingEnabled;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(19)] // 3.0.0+
+ // SetScreenShotImageOrientation(u32)
+ public ResultCode SetScreenShotImageOrientation(ServiceCtx context)
+ {
+ uint screenShotImageOrientation = context.RequestData.ReadUInt32();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { screenShotImageOrientation });
+
+ _screenShotImageOrientation = screenShotImageOrientation;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(40)]
+ // CreateManagedDisplayLayer() -> u64
+ public ResultCode CreateManagedDisplayLayer(ServiceCtx context)
+ {
+ context.Device.System.SurfaceFlinger.CreateLayer(out long layerId, _pid);
+ context.Device.System.SurfaceFlinger.SetRenderLayer(layerId);
+
+ context.ResponseData.Write(layerId);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(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;
+ }
+
+ [CommandCmif(44)] // 10.0.0+
+ // CreateManagedDisplaySeparableLayer() -> (u64, u64)
+ public ResultCode CreateManagedDisplaySeparableLayer(ServiceCtx context)
+ {
+ context.Device.System.SurfaceFlinger.CreateLayer(out long displayLayerId, _pid);
+ context.Device.System.SurfaceFlinger.CreateLayer(out long recordingLayerId, _pid);
+ context.Device.System.SurfaceFlinger.SetRenderLayer(displayLayerId);
+
+ context.ResponseData.Write(displayLayerId);
+ context.ResponseData.Write(recordingLayerId);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(50)]
+ // SetHandlesRequestToDisplay(b8)
+ public ResultCode SetHandlesRequestToDisplay(ServiceCtx context)
+ {
+ bool handlesRequestToDisplay = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { handlesRequestToDisplay });
+
+ _handlesRequestToDisplay = handlesRequestToDisplay;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(62)]
+ // SetIdleTimeDetectionExtension(u32)
+ public ResultCode SetIdleTimeDetectionExtension(ServiceCtx context)
+ {
+ uint idleTimeDetectionExtension = context.RequestData.ReadUInt32();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { idleTimeDetectionExtension });
+
+ _idleTimeDetectionExtension = idleTimeDetectionExtension;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(63)]
+ // GetIdleTimeDetectionExtension() -> u32
+ public ResultCode GetIdleTimeDetectionExtension(ServiceCtx context)
+ {
+ context.ResponseData.Write(_idleTimeDetectionExtension);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { _idleTimeDetectionExtension });
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(65)]
+ // ReportUserIsActive()
+ public ResultCode ReportUserIsActive(ServiceCtx context)
+ {
+ // TODO: Call idle:sys ReportUserIsActive when implemented.
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(67)] //3.0.0+
+ // IsIlluminanceAvailable() -> bool
+ public ResultCode IsIlluminanceAvailable(ServiceCtx context)
+ {
+ // NOTE: This should call IsAmbientLightSensorAvailable through to Lbl, but there's no situation where we'd want false.
+ context.ResponseData.Write(true);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(68)]
+ // SetAutoSleepDisabled(u8)
+ public ResultCode SetAutoSleepDisabled(ServiceCtx context)
+ {
+ bool autoSleepDisabled = context.RequestData.ReadBoolean();
+
+ _autoSleepDisabled = autoSleepDisabled;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(69)]
+ // IsAutoSleepDisabled() -> u8
+ public ResultCode IsAutoSleepDisabled(ServiceCtx context)
+ {
+ context.ResponseData.Write(_autoSleepDisabled);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(71)] //5.0.0+
+ // GetCurrentIlluminanceEx() -> (bool, f32)
+ public ResultCode GetCurrentIlluminanceEx(ServiceCtx context)
+ {
+ // TODO: The light value should be configurable - presumably users using software that takes advantage will want control.
+ context.ResponseData.Write(1); // OverLimit
+ context.ResponseData.Write(10000f); // Lux - 10K lux is ambient light.
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(80)] // 4.0.0+
+ // SetWirelessPriorityMode(s32 wireless_priority_mode)
+ public ResultCode SetWirelessPriorityMode(ServiceCtx context)
+ {
+ WirelessPriorityMode wirelessPriorityMode = (WirelessPriorityMode)context.RequestData.ReadInt32();
+
+ if (wirelessPriorityMode > WirelessPriorityMode.Unknown2)
+ {
+ return ResultCode.InvalidParameters;
+ }
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { wirelessPriorityMode });
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(90)] // 6.0.0+
+ // GetAccumulatedSuspendedTickValue() -> u64
+ public ResultCode GetAccumulatedSuspendedTickValue(ServiceCtx context)
+ {
+ context.ResponseData.Write(_accumulatedSuspendedTickValue);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(91)] // 6.0.0+
+ // GetAccumulatedSuspendedTickChangedEvent() -> handle<copy>
+ public ResultCode GetAccumulatedSuspendedTickChangedEvent(ServiceCtx context)
+ {
+ if (_accumulatedSuspendedTickChangedEventHandle == 0)
+ {
+ _accumulatedSuspendedTickChangedEvent = new KEvent(context.Device.System.KernelContext);
+
+ _accumulatedSuspendedTickChangedEvent.ReadableEvent.Signal();
+
+ if (context.Process.HandleTable.GenerateHandle(_accumulatedSuspendedTickChangedEvent.ReadableEvent, out _accumulatedSuspendedTickChangedEventHandle) != Result.Success)
+ {
+ throw new InvalidOperationException("Out of handles!");
+ }
+ }
+
+ context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_accumulatedSuspendedTickChangedEventHandle);
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(100)] // 7.0.0+
+ // SetAlbumImageTakenNotificationEnabled(u8)
+ public ResultCode SetAlbumImageTakenNotificationEnabled(ServiceCtx context)
+ {
+ bool albumImageTakenNotificationEnabled = context.RequestData.ReadBoolean();
+
+ _albumImageTakenNotificationEnabled = albumImageTakenNotificationEnabled;
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(120)] // 11.0.0+
+ // SaveCurrentScreenshot(s32 album_report_option)
+ public ResultCode SaveCurrentScreenshot(ServiceCtx context)
+ {
+ AlbumReportOption albumReportOption = (AlbumReportOption)context.RequestData.ReadInt32();
+
+ if (albumReportOption > AlbumReportOption.Unknown3)
+ {
+ return ResultCode.InvalidParameters;
+ }
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { albumReportOption });
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(130)] // 13.0.0+
+ // SetRecordVolumeMuted(b8)
+ public ResultCode SetRecordVolumeMuted(ServiceCtx context)
+ {
+ bool recordVolumeMuted = context.RequestData.ReadBoolean();
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { recordVolumeMuted });
+
+ _recordVolumeMuted = recordVolumeMuted;
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs
new file mode 100644
index 00000000..730df5d0
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs
@@ -0,0 +1,36 @@
+using Ryujinx.Common.Logging;
+
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ class IWindowController : IpcService
+ {
+ private readonly ulong _pid;
+
+ public IWindowController(ulong pid)
+ {
+ _pid = pid;
+ }
+
+ [CommandCmif(1)]
+ // GetAppletResourceUserId() -> nn::applet::AppletResourceUserId
+ public ResultCode GetAppletResourceUserId(ServiceCtx context)
+ {
+ long appletResourceUserId = context.Device.System.AppletState.AppletResourceUserIds.Add(_pid);
+
+ context.ResponseData.Write(appletResourceUserId);
+
+ Logger.Stub?.PrintStub(LogClass.ServiceAm, new { appletResourceUserId });
+
+ return ResultCode.Success;
+ }
+
+ [CommandCmif(10)]
+ // AcquireForegroundRights()
+ public ResultCode AcquireForegroundRights(ServiceCtx context)
+ {
+ Logger.Stub?.PrintStub(LogClass.ServiceAm);
+
+ return ResultCode.Success;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/AlbumReportOption.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/AlbumReportOption.cs
new file mode 100644
index 00000000..84fc5c83
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/AlbumReportOption.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types
+{
+ enum AlbumReportOption
+ {
+ OverlayNotDisplayed,
+ OverlayDisplayed,
+ Unknown2,
+ Unknown3
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/AppletMessage.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/AppletMessage.cs
new file mode 100644
index 00000000..2920c329
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/AppletMessage.cs
@@ -0,0 +1,36 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ enum AppletMessage
+ {
+ None = 0,
+ ChangeIntoForeground = 1,
+ ChangeIntoBackground = 2,
+ Exit = 4,
+ ApplicationExited = 6,
+ FocusStateChanged = 15,
+ Resume = 16,
+ DetectShortPressingHomeButton = 20,
+ DetectLongPressingHomeButton = 21,
+ DetectShortPressingPowerButton = 22,
+ DetectMiddlePressingPowerButton = 23,
+ DetectLongPressingPowerButton = 24,
+ RequestToPrepareSleep = 25,
+ FinishedSleepSequence = 26,
+ SleepRequiredByHighTemperature = 27,
+ SleepRequiredByLowBattery = 28,
+ AutoPowerDown = 29,
+ OperationModeChanged = 30,
+ PerformanceModeChanged = 31,
+ DetectReceivingCecSystemStandby = 32,
+ SdCardRemoved = 33,
+ LaunchApplicationRequested = 50,
+ RequestToDisplay = 51,
+ ShowApplicationLogo = 55,
+ HideApplicationLogo = 56,
+ ForceHideApplicationLogo = 57,
+ FloatingApplicationDetected = 60,
+ DetectShortPressingCaptureButton = 90,
+ AlbumScreenShotTaken = 92,
+ AlbumRecordingSaved = 93
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/FocusState.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/FocusState.cs
new file mode 100644
index 00000000..dfd7d7f2
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/FocusState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ enum FocusState
+ {
+ InFocus = 1,
+ OutOfFocus = 2
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/OperationMode.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/OperationMode.cs
new file mode 100644
index 00000000..a82ed476
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/OperationMode.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy
+{
+ enum OperationMode
+ {
+ Handheld = 0,
+ Docked = 1
+ }
+} \ No newline at end of file
diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/WirelessPriorityMode.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/WirelessPriorityMode.cs
new file mode 100644
index 00000000..e8ba9b61
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/Types/WirelessPriorityMode.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy.Types
+{
+ enum WirelessPriorityMode
+ {
+ Default,
+ OptimizedForWlan,
+ Unknown2
+ }
+} \ No newline at end of file