diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy')
16 files changed, 1163 insertions, 0 deletions
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 |
