aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS/Services/Am
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-08-16 20:47:36 -0300
committerGitHub <noreply@github.com>2018-08-16 20:47:36 -0300
commit521751795a1c97c0d97f6f8904a3be69b13d3a9d (patch)
tree942a05899c40e2de6d92a38b93a494bd96ee64b8 /Ryujinx.HLE/HOS/Services/Am
parent182d716867ae477c2b15a5332430dc2641fa1cc3 (diff)
Code style fixes and nits on the HLE project (#355)
* Some style fixes and nits on ITimeZoneService * Remove some unneeded usings * Remove the Ryujinx.HLE.OsHle.Handles namespace * Remove hbmenu automatic load on process exit * Rename Ns to Device, rename Os to System, rename SystemState to State * Move Exceptions and Utilities out of OsHle * Rename OsHle to HOS * Rename OsHle folder to HOS * IManagerDisplayService and ISystemDisplayService style fixes * BsdError shouldn't be public * Add a empty new line before using static * Remove unused file * Some style fixes on NPDM * Exit gracefully when the application is closed * Code style fixes on IGeneralService * Add 0x prefix on values printed as hex * Small improvements on finalization code * Move ProcessId and ThreadId out of AThreadState * Rename VFs to FileSystem * FsAccessHeader shouldn't be public. Also fix file names casing * More case changes on NPDM * Remove unused files * Move using to the correct place on NPDM * Use properties on KernelAccessControlMmio * Address PR feedback
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Am')
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AmErr.cs7
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/FocusState.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IAllSystemAppletProxiesService.cs27
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IApplicationCreator.cs20
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IApplicationFunctions.cs117
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IApplicationProxy.cs83
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IApplicationProxyService.cs27
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IAudioController.cs72
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs115
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IDebugFunctions.cs20
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IDisplayController.cs20
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IGlobalStateController.cs20
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs46
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs71
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/ILibraryAppletCreator.cs37
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/ISelfController.cs145
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IStorage.cs31
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IStorageAccessor.cs83
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/ISystemAppletProxy.cs99
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/IWindowController.cs38
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/MessageInfo.cs9
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/OperationMode.cs8
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/StorageHelper.cs27
23 files changed, 1130 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Am/AmErr.cs b/Ryujinx.HLE/HOS/Services/Am/AmErr.cs
new file mode 100644
index 00000000..4e7771b8
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/AmErr.cs
@@ -0,0 +1,7 @@
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ static class AmErr
+ {
+ public const int NoMessages = 3;
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/FocusState.cs b/Ryujinx.HLE/HOS/Services/Am/FocusState.cs
new file mode 100644
index 00000000..e8ae7223
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/FocusState.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ enum FocusState
+ {
+ InFocus = 1,
+ OutOfFocus = 2
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IAllSystemAppletProxiesService.cs b/Ryujinx.HLE/HOS/Services/Am/IAllSystemAppletProxiesService.cs
new file mode 100644
index 00000000..2d44526a
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IAllSystemAppletProxiesService.cs
@@ -0,0 +1,27 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IAllSystemAppletProxiesService : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IAllSystemAppletProxiesService()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 100, OpenSystemAppletProxy }
+ };
+ }
+
+ public long OpenSystemAppletProxy(ServiceCtx Context)
+ {
+ MakeObject(Context, new ISystemAppletProxy());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IApplicationCreator.cs b/Ryujinx.HLE/HOS/Services/Am/IApplicationCreator.cs
new file mode 100644
index 00000000..c5ed09f5
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IApplicationCreator.cs
@@ -0,0 +1,20 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IApplicationCreator : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IApplicationCreator()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ //...
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IApplicationFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/IApplicationFunctions.cs
new file mode 100644
index 00000000..0a10d2a6
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IApplicationFunctions.cs
@@ -0,0 +1,117 @@
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.Logging;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IApplicationFunctions : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IApplicationFunctions()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 1, PopLaunchParameter },
+ { 20, EnsureSaveData },
+ { 21, GetDesiredLanguage },
+ { 22, SetTerminateResult },
+ { 23, GetDisplayVersion },
+ { 40, NotifyRunning },
+ { 50, GetPseudoDeviceId },
+ { 66, InitializeGamePlayRecording },
+ { 67, SetGamePlayRecordingState }
+ };
+ }
+
+ public long PopLaunchParameter(ServiceCtx Context)
+ {
+ //Only the first 0x18 bytes of the Data seems to be actually used.
+ MakeObject(Context, new IStorage(StorageHelper.MakeLaunchParams()));
+
+ return 0;
+ }
+
+ public long EnsureSaveData(ServiceCtx Context)
+ {
+ long UIdLow = Context.RequestData.ReadInt64();
+ long UIdHigh = Context.RequestData.ReadInt64();
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ Context.ResponseData.Write(0L);
+
+ return 0;
+ }
+
+ public long GetDesiredLanguage(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(Context.Device.System.State.DesiredLanguageCode);
+
+ return 0;
+ }
+
+ public long SetTerminateResult(ServiceCtx Context)
+ {
+ int ErrorCode = Context.RequestData.ReadInt32();
+
+ string Result = GetFormattedErrorCode(ErrorCode);
+
+ Context.Device.Log.PrintInfo(LogClass.ServiceAm, $"Result = 0x{ErrorCode:x8} ({Result}).");
+
+ return 0;
+ }
+
+ private string GetFormattedErrorCode(int ErrorCode)
+ {
+ int Module = (ErrorCode >> 0) & 0x1ff;
+ int Description = (ErrorCode >> 9) & 0x1fff;
+
+ return $"{(2000 + Module):d4}-{Description:d4}";
+ }
+
+ public long GetDisplayVersion(ServiceCtx Context)
+ {
+ //FIXME: Need to check correct version on a switch.
+ Context.ResponseData.Write(1L);
+ Context.ResponseData.Write(0L);
+
+ return 0;
+ }
+
+ public long NotifyRunning(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(1);
+
+ return 0;
+ }
+
+ public long GetPseudoDeviceId(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ Context.ResponseData.Write(0L);
+ Context.ResponseData.Write(0L);
+
+ return 0;
+ }
+
+ public long InitializeGamePlayRecording(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetGamePlayRecordingState(ServiceCtx Context)
+ {
+ int State = Context.RequestData.ReadInt32();
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Am/IApplicationProxy.cs b/Ryujinx.HLE/HOS/Services/Am/IApplicationProxy.cs
new file mode 100644
index 00000000..4003f151
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IApplicationProxy.cs
@@ -0,0 +1,83 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IApplicationProxy : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IApplicationProxy()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, GetCommonStateGetter },
+ { 1, GetSelfController },
+ { 2, GetWindowController },
+ { 3, GetAudioController },
+ { 4, GetDisplayController },
+ { 11, GetLibraryAppletCreator },
+ { 20, GetApplicationFunctions },
+ { 1000, GetDebugFunctions }
+ };
+ }
+
+ public long GetCommonStateGetter(ServiceCtx Context)
+ {
+ MakeObject(Context, new ICommonStateGetter());
+
+ return 0;
+ }
+
+ public long GetSelfController(ServiceCtx Context)
+ {
+ MakeObject(Context, new ISelfController());
+
+ return 0;
+ }
+
+ public long GetWindowController(ServiceCtx Context)
+ {
+ MakeObject(Context, new IWindowController());
+
+ return 0;
+ }
+
+ public long GetAudioController(ServiceCtx Context)
+ {
+ MakeObject(Context, new IAudioController());
+
+ return 0;
+ }
+
+ public long GetDisplayController(ServiceCtx Context)
+ {
+ MakeObject(Context, new IDisplayController());
+
+ return 0;
+ }
+
+ public long GetLibraryAppletCreator(ServiceCtx Context)
+ {
+ MakeObject(Context, new ILibraryAppletCreator());
+
+ return 0;
+ }
+
+ public long GetApplicationFunctions(ServiceCtx Context)
+ {
+ MakeObject(Context, new IApplicationFunctions());
+
+ return 0;
+ }
+
+ public long GetDebugFunctions(ServiceCtx Context)
+ {
+ MakeObject(Context, new IDebugFunctions());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IApplicationProxyService.cs b/Ryujinx.HLE/HOS/Services/Am/IApplicationProxyService.cs
new file mode 100644
index 00000000..fb518af9
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IApplicationProxyService.cs
@@ -0,0 +1,27 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IApplicationProxyService : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IApplicationProxyService()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, OpenApplicationProxy }
+ };
+ }
+
+ public long OpenApplicationProxy(ServiceCtx Context)
+ {
+ MakeObject(Context, new IApplicationProxy());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IAudioController.cs b/Ryujinx.HLE/HOS/Services/Am/IAudioController.cs
new file mode 100644
index 00000000..8968ad72
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IAudioController.cs
@@ -0,0 +1,72 @@
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.Logging;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IAudioController : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IAudioController()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, SetExpectedMasterVolume },
+ { 1, GetMainAppletExpectedMasterVolume },
+ { 2, GetLibraryAppletExpectedMasterVolume },
+ { 3, ChangeMainAppletMasterVolume },
+ { 4, SetTransparentVolumeRate }
+ };
+ }
+
+ public long SetExpectedMasterVolume(ServiceCtx Context)
+ {
+ float AppletVolume = Context.RequestData.ReadSingle();
+ float LibraryAppletVolume = Context.RequestData.ReadSingle();
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long GetMainAppletExpectedMasterVolume(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(1f);
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long GetLibraryAppletExpectedMasterVolume(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(1f);
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long ChangeMainAppletMasterVolume(ServiceCtx Context)
+ {
+ float Unknown0 = Context.RequestData.ReadSingle();
+ long Unknown1 = Context.RequestData.ReadInt64();
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetTransparentVolumeRate(ServiceCtx Context)
+ {
+ float Unknown0 = Context.RequestData.ReadSingle();
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs b/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs
new file mode 100644
index 00000000..3cdfbbdb
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/ICommonStateGetter.cs
@@ -0,0 +1,115 @@
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
+using Ryujinx.HLE.Logging;
+using System.Collections.Generic;
+
+using static Ryujinx.HLE.HOS.ErrorCode;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class ICommonStateGetter : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private KEvent DisplayResolutionChangeEvent;
+
+ public ICommonStateGetter()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, GetEventHandle },
+ { 1, ReceiveMessage },
+ { 5, GetOperationMode },
+ { 6, GetPerformanceMode },
+ { 8, GetBootMode },
+ { 9, GetCurrentFocusState },
+ { 60, GetDefaultDisplayResolution },
+ { 61, GetDefaultDisplayResolutionChangeEvent }
+ };
+
+ DisplayResolutionChangeEvent = new KEvent();
+ }
+
+ public long GetEventHandle(ServiceCtx Context)
+ {
+ KEvent Event = Context.Process.AppletState.MessageEvent;
+
+ int Handle = Context.Process.HandleTable.OpenHandle(Event);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
+ return 0;
+ }
+
+ public long ReceiveMessage(ServiceCtx Context)
+ {
+ if (!Context.Process.AppletState.TryDequeueMessage(out MessageInfo Message))
+ {
+ return MakeError(ErrorModule.Am, AmErr.NoMessages);
+ }
+
+ Context.ResponseData.Write((int)Message);
+
+ return 0;
+ }
+
+ public long GetOperationMode(ServiceCtx Context)
+ {
+ OperationMode Mode = Context.Device.System.State.DockedMode
+ ? OperationMode.Docked
+ : OperationMode.Handheld;
+
+ Context.ResponseData.Write((byte)Mode);
+
+ return 0;
+ }
+
+ public long GetPerformanceMode(ServiceCtx Context)
+ {
+ Apm.PerformanceMode Mode = Context.Device.System.State.DockedMode
+ ? Apm.PerformanceMode.Docked
+ : Apm.PerformanceMode.Handheld;
+
+ Context.ResponseData.Write((int)Mode);
+
+ return 0;
+ }
+
+ public long GetBootMode(ServiceCtx Context)
+ {
+ Context.ResponseData.Write((byte)0); //Unknown value.
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long GetCurrentFocusState(ServiceCtx Context)
+ {
+ Context.ResponseData.Write((byte)Context.Process.AppletState.FocusState);
+
+ return 0;
+ }
+
+ public long GetDefaultDisplayResolution(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(1280);
+ Context.ResponseData.Write(720);
+
+ return 0;
+ }
+
+ public long GetDefaultDisplayResolutionChangeEvent(ServiceCtx Context)
+ {
+ int Handle = Context.Process.HandleTable.OpenHandle(DisplayResolutionChangeEvent);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Am/IDebugFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/IDebugFunctions.cs
new file mode 100644
index 00000000..d86743c0
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IDebugFunctions.cs
@@ -0,0 +1,20 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IDebugFunctions : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IDebugFunctions()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ //...
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IDisplayController.cs b/Ryujinx.HLE/HOS/Services/Am/IDisplayController.cs
new file mode 100644
index 00000000..c4d49579
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IDisplayController.cs
@@ -0,0 +1,20 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IDisplayController : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IDisplayController()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ //...
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IGlobalStateController.cs b/Ryujinx.HLE/HOS/Services/Am/IGlobalStateController.cs
new file mode 100644
index 00000000..e646327f
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IGlobalStateController.cs
@@ -0,0 +1,20 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IGlobalStateController : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IGlobalStateController()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ //...
+ };
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs b/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs
new file mode 100644
index 00000000..95028ca0
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IHomeMenuFunctions.cs
@@ -0,0 +1,46 @@
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
+using Ryujinx.HLE.Logging;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IHomeMenuFunctions : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private KEvent ChannelEvent;
+
+ public IHomeMenuFunctions()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 10, RequestToGetForeground },
+ { 21, GetPopFromGeneralChannelEvent }
+ };
+
+ //ToDo: Signal this Event somewhere in future.
+ ChannelEvent = new KEvent();
+ }
+
+ public long RequestToGetForeground(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long GetPopFromGeneralChannelEvent(ServiceCtx Context)
+ {
+ int Handle = Context.Process.HandleTable.OpenHandle(ChannelEvent);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs
new file mode 100644
index 00000000..e099ec64
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletAccessor.cs
@@ -0,0 +1,71 @@
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
+using Ryujinx.HLE.Logging;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class ILibraryAppletAccessor : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private KEvent StateChangedEvent;
+
+ public ILibraryAppletAccessor()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, GetAppletStateChangedEvent },
+ { 10, Start },
+ { 30, GetResult },
+ { 100, PushInData },
+ { 101, PopOutData }
+ };
+
+ StateChangedEvent = new KEvent();
+ }
+
+ public long GetAppletStateChangedEvent(ServiceCtx Context)
+ {
+ StateChangedEvent.WaitEvent.Set();
+
+ int Handle = Context.Process.HandleTable.OpenHandle(StateChangedEvent);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long Start(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long GetResult(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long PushInData(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long PopOutData(ServiceCtx Context)
+ {
+ MakeObject(Context, new IStorage(StorageHelper.MakeLaunchParams()));
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletCreator.cs b/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletCreator.cs
new file mode 100644
index 00000000..065574c7
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/ILibraryAppletCreator.cs
@@ -0,0 +1,37 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class ILibraryAppletCreator : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public ILibraryAppletCreator()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, CreateLibraryApplet },
+ { 10, CreateStorage }
+ };
+ }
+
+ public long CreateLibraryApplet(ServiceCtx Context)
+ {
+ MakeObject(Context, new ILibraryAppletAccessor());
+
+ return 0;
+ }
+
+ public long CreateStorage(ServiceCtx Context)
+ {
+ long Size = Context.RequestData.ReadInt64();
+
+ MakeObject(Context, new IStorage(new byte[Size]));
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs b/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs
new file mode 100644
index 00000000..ccd96e0d
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/ISelfController.cs
@@ -0,0 +1,145 @@
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.HOS.Kernel;
+using Ryujinx.HLE.Logging;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class ISelfController : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private KEvent LaunchableEvent;
+
+ public ISelfController()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, Exit },
+ { 1, LockExit },
+ { 2, UnlockExit },
+ { 9, GetLibraryAppletLaunchableEvent },
+ { 10, SetScreenShotPermission },
+ { 11, SetOperationModeChangedNotification },
+ { 12, SetPerformanceModeChangedNotification },
+ { 13, SetFocusHandlingMode },
+ { 14, SetRestartMessageEnabled },
+ { 16, SetOutOfFocusSuspendingEnabled },
+ { 19, SetScreenShotImageOrientation },
+ { 50, SetHandlesRequestToDisplay }
+ };
+
+ LaunchableEvent = new KEvent();
+ }
+
+ public long Exit(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long LockExit(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long UnlockExit(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long GetLibraryAppletLaunchableEvent(ServiceCtx Context)
+ {
+ LaunchableEvent.WaitEvent.Set();
+
+ int Handle = Context.Process.HandleTable.OpenHandle(LaunchableEvent);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetScreenShotPermission(ServiceCtx Context)
+ {
+ bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetOperationModeChangedNotification(ServiceCtx Context)
+ {
+ bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetPerformanceModeChangedNotification(ServiceCtx Context)
+ {
+ bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetFocusHandlingMode(ServiceCtx Context)
+ {
+ bool Flag1 = Context.RequestData.ReadByte() != 0 ? true : false;
+ bool Flag2 = Context.RequestData.ReadByte() != 0 ? true : false;
+ bool Flag3 = Context.RequestData.ReadByte() != 0 ? true : false;
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetRestartMessageEnabled(ServiceCtx Context)
+ {
+ bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetOutOfFocusSuspendingEnabled(ServiceCtx Context)
+ {
+ bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetScreenShotImageOrientation(ServiceCtx Context)
+ {
+ int Orientation = Context.RequestData.ReadInt32();
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+
+ public long SetHandlesRequestToDisplay(ServiceCtx Context)
+ {
+ bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
+
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+ }
+}
diff --git a/Ryujinx.HLE/HOS/Services/Am/IStorage.cs b/Ryujinx.HLE/HOS/Services/Am/IStorage.cs
new file mode 100644
index 00000000..10778122
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IStorage.cs
@@ -0,0 +1,31 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IStorage : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public byte[] Data { get; private set; }
+
+ public IStorage(byte[] Data)
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, Open }
+ };
+
+ this.Data = Data;
+ }
+
+ public long Open(ServiceCtx Context)
+ {
+ MakeObject(Context, new IStorageAccessor(this));
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IStorageAccessor.cs b/Ryujinx.HLE/HOS/Services/Am/IStorageAccessor.cs
new file mode 100644
index 00000000..a60cf149
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IStorageAccessor.cs
@@ -0,0 +1,83 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IStorageAccessor : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ private IStorage Storage;
+
+ public IStorageAccessor(IStorage Storage)
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, GetSize },
+ { 10, Write },
+ { 11, Read }
+ };
+
+ this.Storage = Storage;
+ }
+
+ public long GetSize(ServiceCtx Context)
+ {
+ Context.ResponseData.Write((long)Storage.Data.Length);
+
+ return 0;
+ }
+
+ public long Write(ServiceCtx Context)
+ {
+ //TODO: Error conditions.
+ long WritePosition = Context.RequestData.ReadInt64();
+
+ (long Position, long Size) = Context.Request.GetBufferType0x21();
+
+ if (Size > 0)
+ {
+ long MaxSize = Storage.Data.Length - WritePosition;
+
+ if (Size > MaxSize)
+ {
+ Size = MaxSize;
+ }
+
+ byte[] Data = Context.Memory.ReadBytes(Position, Size);
+
+ Buffer.BlockCopy(Data, 0, Storage.Data, (int)WritePosition, (int)Size);
+ }
+
+ return 0;
+ }
+
+ public long Read(ServiceCtx Context)
+ {
+ //TODO: Error conditions.
+ long ReadPosition = Context.RequestData.ReadInt64();
+
+ (long Position, long Size) = Context.Request.GetBufferType0x22();
+
+ byte[] Data;
+
+ if (Storage.Data.Length > Size)
+ {
+ Data = new byte[Size];
+
+ Buffer.BlockCopy(Storage.Data, 0, Data, 0, (int)Size);
+ }
+ else
+ {
+ Data = Storage.Data;
+ }
+
+ Context.Memory.WriteBytes(Position, Data);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/ISystemAppletProxy.cs b/Ryujinx.HLE/HOS/Services/Am/ISystemAppletProxy.cs
new file mode 100644
index 00000000..c08d4018
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/ISystemAppletProxy.cs
@@ -0,0 +1,99 @@
+using Ryujinx.HLE.HOS.Ipc;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class ISystemAppletProxy : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public ISystemAppletProxy()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 0, GetCommonStateGetter },
+ { 1, GetSelfController },
+ { 2, GetWindowController },
+ { 3, GetAudioController },
+ { 4, GetDisplayController },
+ { 11, GetLibraryAppletCreator },
+ { 20, GetHomeMenuFunctions },
+ { 21, GetGlobalStateController },
+ { 22, GetApplicationCreator },
+ { 1000, GetDebugFunctions }
+ };
+ }
+
+ public long GetCommonStateGetter(ServiceCtx Context)
+ {
+ MakeObject(Context, new ICommonStateGetter());
+
+ return 0;
+ }
+
+ public long GetSelfController(ServiceCtx Context)
+ {
+ MakeObject(Context, new ISelfController());
+
+ return 0;
+ }
+
+ public long GetWindowController(ServiceCtx Context)
+ {
+ MakeObject(Context, new IWindowController());
+
+ return 0;
+ }
+
+ public long GetAudioController(ServiceCtx Context)
+ {
+ MakeObject(Context, new IAudioController());
+
+ return 0;
+ }
+
+ public long GetDisplayController(ServiceCtx Context)
+ {
+ MakeObject(Context, new IDisplayController());
+
+ return 0;
+ }
+
+ public long GetLibraryAppletCreator(ServiceCtx Context)
+ {
+ MakeObject(Context, new ILibraryAppletCreator());
+
+ return 0;
+ }
+
+ public long GetHomeMenuFunctions(ServiceCtx Context)
+ {
+ MakeObject(Context, new IHomeMenuFunctions());
+
+ return 0;
+ }
+
+ public long GetGlobalStateController(ServiceCtx Context)
+ {
+ MakeObject(Context, new IGlobalStateController());
+
+ return 0;
+ }
+
+ public long GetApplicationCreator(ServiceCtx Context)
+ {
+ MakeObject(Context, new IApplicationCreator());
+
+ return 0;
+ }
+
+ public long GetDebugFunctions(ServiceCtx Context)
+ {
+ MakeObject(Context, new IDebugFunctions());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/IWindowController.cs b/Ryujinx.HLE/HOS/Services/Am/IWindowController.cs
new file mode 100644
index 00000000..1a5a716f
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/IWindowController.cs
@@ -0,0 +1,38 @@
+using Ryujinx.HLE.HOS.Ipc;
+using Ryujinx.HLE.Logging;
+using System.Collections.Generic;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class IWindowController : IpcService
+ {
+ private Dictionary<int, ServiceProcessRequest> m_Commands;
+
+ public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
+
+ public IWindowController()
+ {
+ m_Commands = new Dictionary<int, ServiceProcessRequest>()
+ {
+ { 1, GetAppletResourceUserId },
+ { 10, AcquireForegroundRights }
+ };
+ }
+
+ public long GetAppletResourceUserId(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ Context.ResponseData.Write(0L);
+
+ return 0;
+ }
+
+ public long AcquireForegroundRights(ServiceCtx Context)
+ {
+ Context.Device.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/MessageInfo.cs b/Ryujinx.HLE/HOS/Services/Am/MessageInfo.cs
new file mode 100644
index 00000000..65fddbed
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/MessageInfo.cs
@@ -0,0 +1,9 @@
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ enum MessageInfo
+ {
+ FocusStateChanged = 0xf,
+ OperationModeChanged = 0x1e,
+ PerformanceModeChanged = 0x1f
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/OperationMode.cs b/Ryujinx.HLE/HOS/Services/Am/OperationMode.cs
new file mode 100644
index 00000000..cb11fff9
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/OperationMode.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ enum OperationMode
+ {
+ Handheld = 0,
+ Docked = 1
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Services/Am/StorageHelper.cs b/Ryujinx.HLE/HOS/Services/Am/StorageHelper.cs
new file mode 100644
index 00000000..b97ffc1e
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Services/Am/StorageHelper.cs
@@ -0,0 +1,27 @@
+using System.IO;
+
+namespace Ryujinx.HLE.HOS.Services.Am
+{
+ class StorageHelper
+ {
+ private const uint LaunchParamsMagic = 0xc79497ca;
+
+ public static byte[] MakeLaunchParams()
+ {
+ //Size needs to be at least 0x88 bytes otherwise application errors.
+ using (MemoryStream MS = new MemoryStream())
+ {
+ BinaryWriter Writer = new BinaryWriter(MS);
+
+ MS.SetLength(0x88);
+
+ Writer.Write(LaunchParamsMagic);
+ Writer.Write(1); //IsAccountSelected? Only lower 8 bits actually used.
+ Writer.Write(1L); //User Id Low (note: User Id needs to be != 0)
+ Writer.Write(0L); //User Id High
+
+ return MS.ToArray();
+ }
+ }
+ }
+}