diff --git a/src/Ryujinx.HLE/HOS/Applets/EventObserver.cs b/src/Ryujinx.HLE/HOS/Applets/EventObserver.cs index 35e33e939..9969bc8ae 100644 --- a/src/Ryujinx.HLE/HOS/Applets/EventObserver.cs +++ b/src/Ryujinx.HLE/HOS/Applets/EventObserver.cs @@ -181,6 +181,14 @@ namespace Ryujinx.HLE.HOS.Applets { if (process.State == ProcessState.Exited) { + if (applet.CallerApplet != null) + { + if (applet.CallerApplet.ProcessHandle.IsPaused) + { + applet.CallerApplet.ProcessHandle.SetActivity(false); + } + } + _processHolders.Remove(holder); } else diff --git a/src/Ryujinx.HLE/HOS/Applets/WindowSystem.cs b/src/Ryujinx.HLE/HOS/Applets/WindowSystem.cs index 65e2ff382..212346b1e 100644 --- a/src/Ryujinx.HLE/HOS/Applets/WindowSystem.cs +++ b/src/Ryujinx.HLE/HOS/Applets/WindowSystem.cs @@ -7,6 +7,7 @@ using System.Linq; using Ryujinx.Horizon.Sdk.Applet; using Ryujinx.Common; using Ryujinx.HLE.HOS.Applets.Types; +using System.Collections; using System.Threading; namespace Ryujinx.HLE.HOS.Applets @@ -563,6 +564,10 @@ namespace Ryujinx.HLE.HOS.Applets } } + if (applet == null) + { + return _foregroundRequestedApplet; + } return applet; } @@ -607,6 +612,20 @@ namespace Ryujinx.HLE.HOS.Applets { return _applets.Count > 0; } + + internal RealApplet[] GetApplets() + { + return _applets.Values.ToArray(); + } + + public void PauseOldWindows(ulong pid) + { + RealApplet applet = GetByAruId(pid); + if (applet?.CallerApplet != null) + { + applet.CallerApplet.ProcessHandle.SetActivity(true); + } + } } internal class ButtonPressTracker diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryRealAppletSelfAccessor.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryRealAppletSelfAccessor.cs index fc06582e0..213bee597 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryRealAppletSelfAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryRealAppletSelfAccessor.cs @@ -4,6 +4,7 @@ using Ryujinx.HLE.HOS.Applets; using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.HLE.HOS.SystemState; using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Sdk.Applet; using System; @@ -182,7 +183,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib // CanUseApplicationCore() -> bool public ResultCode CanUseApplicationCore(ServiceCtx context) { - context.ResponseData.Write(false); + context.ResponseData.Write(true); Logger.Stub?.PrintStub(LogClass.ServiceAm); @@ -217,6 +218,29 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib return ResultCode.Success; } + [CommandCmif(60)] + // GetMainAppletApplicationDesiredLanguage() -> nn::os::Language + public ResultCode GetMainAppletApplicationDesiredLanguage(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.ServiceAm); + // TODO: Find a better method to get the desired language. + string language = "en-US"; + switch (context.Device.Configuration.Region) + { + case RegionCode.Japan: + language = "ja"; + break; + case RegionCode.Europe: + language = "fr"; + break; + case RegionCode.Korea: + language = "ko"; + break; + } + context.ResponseData.Write(language); + return ResultCode.Success; + } + [CommandCmif(150)] // ShouldSetGpuTimeSliceManually() -> bool public ResultCode ShouldSetGpuTimeSliceManually(ServiceCtx context) 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 index 8262f31e3..b6acc8a46 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IAppletCommonFunctions.cs @@ -22,5 +22,22 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys Logger.Info?.PrintStub(LogClass.ServiceAm); return ResultCode.Success; } + + [CommandCmif(100)] + // SetApplicationCoreUsageMode() + public ResultCode SetApplicationCoreUsageMode(ServiceCtx context) + { + Logger.Info?.PrintStub(LogClass.ServiceAm); + return ResultCode.Success; + } + + [CommandCmif(300)] // 17.0.0+ + // GetCurrentApplicationId() -> nn::am::detail::IApplicationId + public ResultCode GetCurrentApplicationId(ServiceCtx context) + { + Logger.Info?.PrintStub(LogClass.ServiceAm); + context.ResponseData.Write(context.Device.System.WindowSystem.GetApplicationApplet().ProcessHandle.TitleId); + return ResultCode.Success; + } } } 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 index 7e40c8ee3..c3a6fe27c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ICommonStateGetter.cs @@ -6,6 +6,7 @@ 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 Ryujinx.Horizon.Sdk.Applet; using Ryujinx.Horizon.Sdk.Lbl; using System; @@ -325,6 +326,24 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys return (ResultCode)_apmSystemManagerServer.GetCurrentPerformanceConfiguration(context); } + [CommandCmif(120)] // 13.0.0+ + // GetAppletLaunchedHistory() -> s32, buffer + public ResultCode GetAppletLaunchedHistory(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.ServiceAm); + var buffer = context.Request.ReceiveBuff[0]; + int applets = 0; + Span appletsBuffer = CreateSpanFromBuffer(context, buffer, true); + foreach (var applet in context.Device.System.WindowSystem.GetApplets()) + { + applets++; + appletsBuffer[applets - 1] = applet.AppletId; + } + context.ResponseData.Write((uint)applets); + WriteSpanToBuffer(context, buffer, appletsBuffer); + return ResultCode.Success; + } + [CommandCmif(200)] // GetOperationModeSystemInfo() -> u32 public ResultCode GetOperationModeSystemInfo(ServiceCtx context) 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 index 2250867c8..52772ce91 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ISelfController.cs @@ -193,6 +193,14 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys return ResultCode.Success; } + + [CommandCmif(15)] + // SetScreenShotAppletIdentityInfo() + public ResultCode SetScreenShotAppletIdentityInfo(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.ServiceAm); + return ResultCode.Success; + } [CommandCmif(16)] // 2.0.0+ // SetOutOfFocusSuspendingEnabled(b8) 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 index 895ef8d44..0e84e1fc6 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/IWindowController.cs @@ -24,6 +24,16 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys return ResultCode.Success; } + [CommandCmif(2)] + // GetAppletResourceUserIdOfCallerApplet() -> nn::applet::AppletResourceUserId + public ResultCode GetAppletResourceUserIdOfCallerApplet(ServiceCtx context) + { + ulong appletResourceUserId = _pid; + appletResourceUserId = context.Device.System.WindowSystem.GetByAruId(_pid).CallerApplet.ProcessHandle.TitleId; + context.ResponseData.Write(appletResourceUserId); + Logger.Stub?.PrintStub(LogClass.ServiceAm, new { appletResourceUserId }); + return ResultCode.Success; + } [CommandCmif(10)] @@ -31,6 +41,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys public ResultCode AcquireForegroundRights(ServiceCtx context) { Logger.Stub?.PrintStub(LogClass.ServiceAm); + context.Device.System.WindowSystem.PauseOldWindows(_pid); return ResultCode.Success; } diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumAccessorService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumAccessorService.cs index 3e4f46e06..df567fd98 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumAccessorService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IAlbumAccessorService.cs @@ -284,6 +284,14 @@ namespace Ryujinx.HLE.HOS.Services.Caps var fileId = context.RequestData.ReadStruct(); return LoadImageEx1(320, 180, context, fileId); } + + [CommandCmif(50011)] // 19.0.0+ + // GetAlbumAccessResultForDebug() + public ResultCode GetAlbumAccessResultForDebug(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.ServiceCaps); + return ResultCode.Success; + } public void GetWidthAndHeightFromInputBuffer(AlbumFileId id, out int width, out int height) { diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs index 53904369b..ff8c2f609 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs @@ -13,6 +13,7 @@ using LibHac.Tools.FsSystem.NcaUtils; using System; using System.IO; using System.Runtime.InteropServices; +using ApplicationId = LibHac.ApplicationId; using Path = System.IO.Path; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index f0cf6571f..52a9f5e6c 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -13,11 +13,13 @@ using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Common; using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy; +using Ryujinx.HLE.HOS.Services.Ns.Types; using Ryujinx.HLE.HOS.Services.Pcv; using Ryujinx.Memory; using System; using System.IO; using static Ryujinx.HLE.Utilities.StringUtils; +using ApplicationId = LibHac.ApplicationId; using GameCardHandle = System.UInt32; using IFile = Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.IFile; using IFileSystem = LibHac.FsSrv.Sf.IFileSystem; @@ -45,6 +47,38 @@ namespace Ryujinx.HLE.HOS.Services.Fs return ResultCode.Success; } + + [CommandCmif(7)] // 2.0.0+ + // OpenFileSystemWithPatch(nn::fssrv::sf::FileSystemType filesystem_type, nn::ApplicationId tid) -> object contentFs + public ResultCode OpenFileSystemWithPatch(ServiceCtx context) + { + FileSystemType fileSystemType = (FileSystemType)context.RequestData.ReadInt32(); + ulong titleId = context.RequestData.ReadUInt64(); + string switchPath = string.Empty; + Logger.Stub?.PrintStub(LogClass.ServiceFs); + foreach (RyuApplicationData ryuApplicationData in context.Device.Configuration.Titles) + { + if (titleId == ryuApplicationData.AppId.Value) + { + switchPath = ryuApplicationData.Path; + break; + } + } + + if (switchPath == string.Empty) + { + return ResultCode.PathDoesNotExist; + } + string fullPath = FileSystem.VirtualFileSystem.SwitchPathToSystemPath(switchPath); + ResultCode result = FileSystemProxyHelper.OpenFileSystemFromInternalFile(context, fullPath, out FileSystemProxy.IFileSystem fileSystem); + + if (result == ResultCode.Success) + { + MakeObject(context, fileSystem); + } + + return result; + } [CommandCmif(8)] // OpenFileSystemWithId(nn::fssrv::sf::FileSystemType filesystem_type, nn::ApplicationId tid, buffer, 0x19, 0x301> path) diff --git a/src/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs b/src/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs index 1b50a81ea..7eda34222 100644 --- a/src/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Hid/IHidSystemServer.cs @@ -184,6 +184,14 @@ namespace Ryujinx.HLE.HOS.Services.Hid return ResultCode.Success; } + [CommandCmif(313)] // 9.0.0+ + // GetNpadCaptureButtonAssignment() + public ResultCode GetNpadCaptureButtonAssignment(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.ServiceHid); + return ResultCode.Success; + } + [CommandCmif(314)] // 9.0.0+ // GetAppletFooterUiType(u32) -> u8 public ResultCode GetAppletFooterUiType(ServiceCtx context) diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IDocumentInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IDocumentInterface.cs new file mode 100644 index 000000000..202f894f9 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IDocumentInterface.cs @@ -0,0 +1,23 @@ +using Ryujinx.Common.Logging; + +namespace Ryujinx.HLE.HOS.Services.Ns +{ + class IDocumentInterface : IpcService + { + [CommandCmif(23)] + // ResolveApplicationContentPath() + public ResultCode ResolveApplicationContentPath(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.ServiceNs); + return ResultCode.Success; + } + + [CommandCmif(92)] // 5.0.0+ + // GetRunningApplicationProgramId() -> u64 + public ResultCode GetRunningApplicationProgramId(ServiceCtx context) + { + context.ResponseData.Write(context.Device.Processes.ActiveApplication.ProgramId); + return ResultCode.Success; + } + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationRecordInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationRecordInterface.cs new file mode 100644 index 000000000..1989846d9 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationRecordInterface.cs @@ -0,0 +1,7 @@ +namespace Ryujinx.HLE.HOS.Services.Ns +{ + class IReadOnlyApplicationRecordInterface : IpcService + { + + } +} diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs index b58d1d85c..f56e2f9af 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IServiceGetterInterface.cs @@ -28,6 +28,15 @@ namespace Ryujinx.HLE.HOS.Services.Ns return ResultCode.Success; } + [CommandCmif(7991)] // 5.0.0+ + // GetReadOnlyApplicationRecordInterface() -> object + public ResultCode GetReadOnlyApplicationRecordInterface(ServiceCtx context) + { + MakeObject(context, new IReadOnlyApplicationRecordInterface()); + + return ResultCode.Success; + } + [CommandCmif(7996)] // GetApplicationManagerInterface() -> object public ResultCode GetApplicationManagerInterface(ServiceCtx context) @@ -54,5 +63,14 @@ namespace Ryujinx.HLE.HOS.Services.Ns return ResultCode.Success; } + + [CommandCmif(7999)] + // GetDocumentInterface() -> object + public ResultCode GetDocumentInterface(ServiceCtx context) + { + MakeObject(context, new IDocumentInterface()); + + return ResultCode.Success; + } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IVulnerabilityManagerInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IVulnerabilityManagerInterface.cs index c1ec50bc8..6b57b9774 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/IVulnerabilityManagerInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IVulnerabilityManagerInterface.cs @@ -4,5 +4,13 @@ namespace Ryujinx.HLE.HOS.Services.Ns class IVulnerabilityManagerInterface : IpcService { public IVulnerabilityManagerInterface(ServiceCtx context) { } + + [CommandCmif(1200)] + // NeedsUpdateVulnerability() -> bool + public ResultCode NeedsUpdateVulnerability(ServiceCtx context) + { + context.ResponseData.Write(false); + return ResultCode.Success; + } } } diff --git a/src/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs b/src/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs index 1fd4e74fe..824b318ef 100644 --- a/src/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs +++ b/src/Ryujinx.HLE/HOS/Services/Settings/ISystemSettingsServer.cs @@ -551,6 +551,15 @@ namespace Ryujinx.HLE.HOS.Services.Settings return ResultCode.Success; } + [CommandCmif(183)] + // GetPlatformRegion() -> s32 + public ResultCode GetPlatformRegion(ServiceCtx context) + { + Logger.Stub?.PrintStub(LogClass.ServiceSet); + context.ResponseData.Write(0); + return ResultCode.Success; + } + [CommandCmif(201)] // GetFieldTestingFlag() -> bool public ResultCode GetFieldTestingFlag(ServiceCtx context)