diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index cfa4377db..5534cde56 100644 --- a/src/ARMeilleure/Translation/PTC/Ptc.cs +++ b/src/ARMeilleure/Translation/PTC/Ptc.cs @@ -110,7 +110,7 @@ namespace ARMeilleure.Translation.PTC Profiler.Wait(); Profiler.ClearEntries(); - Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache (enabled: {enabled})."); + Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache v{InternalVersion}\n\t\t (title: {titleIdText}, version: '{displayVersion}', selector: '{cacheSelector}', enabled: {enabled})."); if (!enabled || string.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault) { @@ -129,8 +129,6 @@ namespace ARMeilleure.Translation.PTC DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault; _memoryMode = memoryMode; - Logger.Info?.Print(LogClass.Ptc, $"PPTC (v{InternalVersion}) Profile: {DisplayVersion}-{cacheSelector}"); - string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir); string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir); diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs index 28f7ef25f..35ca06727 100644 --- a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs +++ b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs @@ -118,7 +118,9 @@ namespace Ryujinx.HLE.HOS } } - DiskCacheLoadState = processContext.Initialize(_titleIdText, _displayVersion, _diskCacheEnabled, _codeAddress, _codeSize, _diskCacheSelector ?? "default"); + string cacheSelector = _diskCacheSelector ?? "default"; + + DiskCacheLoadState = processContext.Initialize(_titleIdText, _displayVersion, _diskCacheEnabled, _codeAddress, _codeSize, cacheSelector); return processContext; } diff --git a/src/Ryujinx.HLE/HOS/ServiceCtx.cs b/src/Ryujinx.HLE/HOS/ServiceCtx.cs index ba27e12ea..200afaf5e 100644 --- a/src/Ryujinx.HLE/HOS/ServiceCtx.cs +++ b/src/Ryujinx.HLE/HOS/ServiceCtx.cs @@ -16,6 +16,7 @@ namespace Ryujinx.HLE.HOS public IpcMessage Response { get; } public BinaryReader RequestData { get; } public BinaryWriter ResponseData { get; } + public ulong ClientProcessId => Request.HandleDesc.HasPId ? Request.HandleDesc.PId : Process.Pid; public ServiceCtx( Switch device, diff --git a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs index 98af10694..759613752 100644 --- a/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs +++ b/src/Ryujinx.HLE/HOS/Services/Account/Acc/IAccountServiceForApplication.cs @@ -190,7 +190,7 @@ namespace Ryujinx.HLE.HOS.Services.Account.Acc // TODO: Account actually calls nn::arp::detail::IReader::GetApplicationControlProperty() with the current Pid and store the result (NACP file) internally. // But since we use LibHac and we load one Application at a time, it's not necessary. - context.ResponseData.Write((byte)context.Device.Processes.ActiveApplication.ApplicationControlProperties.UserAccountSwitchLock); + context.ResponseData.Write((byte)context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties.UserAccountSwitchLock); Logger.Stub?.PrintStub(LogClass.ServiceAcc); diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs index 7700cac09..cfd35111a 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/ILibraryAppletProxy.cs @@ -79,7 +79,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService // OpenLibraryAppletSelfAccessor() -> object public ResultCode OpenLibraryAppletSelfAccessor(ServiceCtx context) { - MakeObject(context, new ILibraryAppletSelfAccessor(context)); + MakeObject(context, new ILibraryAppletSelfAccessor(context, _pid)); return ResultCode.Success; } 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 index fa986de93..50df65e44 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/LibraryAppletProxy/ILibraryAppletSelfAccessor.cs @@ -8,9 +8,11 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib { private readonly AppletStandalone _appletStandalone = new(); - public ILibraryAppletSelfAccessor(ServiceCtx context) + public ILibraryAppletSelfAccessor(ServiceCtx context, ulong pid) { - if (context.Device.Processes.ActiveApplication.ProgramId == 0x0100000000001009) + ulong programId = context.Device.Processes.GetProcess(pid).ProgramId; + + if (programId == 0x0100000000001009) { // Create MiiEdit data. _appletStandalone = new AppletStandalone() @@ -26,7 +28,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Lib } else { - throw new NotImplementedException($"{context.Device.Processes.ActiveApplication.ProgramId} applet is not implemented."); + throw new NotImplementedException($"{programId} applet is not implemented."); } } diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs index 9986bf824..7f8858896 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/ApplicationProxy/IApplicationFunctions.cs @@ -44,8 +44,9 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati private int _jitLoaded; private readonly LibHac.HorizonClient _horizon; + private readonly ulong _pid; - public IApplicationFunctions(Horizon system) + public IApplicationFunctions(Horizon system, ulong pid) { // TODO: Find where they are signaled. _gpuErrorDetectedSystemEvent = new KEvent(system.KernelContext); @@ -55,6 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati _unknownEvent = new KEvent(system.KernelContext); _horizon = system.LibHacHorizonManager.AmClient; + _pid = pid; } [CommandCmif(1)] @@ -115,11 +117,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati public ResultCode EnsureSaveData(ServiceCtx context) { Uid userId = context.RequestData.ReadStruct().ToLibHacUid(); + var process = context.Device.Processes.GetProcess(_pid); // Mask out the low nibble of the program ID to get the application ID - ApplicationId applicationId = new(context.Device.Processes.ActiveApplication.ProgramId & ~0xFul); + ApplicationId applicationId = new(process.Identity.ApplicationId); - ApplicationControlProperty nacp = context.Device.Processes.ActiveApplication.ApplicationControlProperties; + ApplicationControlProperty nacp = process.ApplicationControlProperties; LibHac.HorizonClient hos = context.Device.System.LibHacHorizonManager.AmClient; LibHac.Result result = hos.Fs.EnsureApplicationSaveData(out long requiredSize, applicationId, in nacp, in userId); @@ -139,7 +142,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati // TODO: When above calls are implemented, switch to using ns:am long desiredLanguageCode = context.Device.System.State.DesiredLanguageCode; - int supportedLanguages = (int)context.Device.Processes.ActiveApplication.ApplicationControlProperties.SupportedLanguageFlag; + int supportedLanguages = (int)context.Device.Processes.GetProcess(_pid).ApplicationControlProperties.SupportedLanguageFlag; int firstSupported = BitOperations.TrailingZeroCount(supportedLanguages); if (firstSupported > (int)TitleLanguage.BrazilianPortuguese) @@ -182,7 +185,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati public ResultCode GetDisplayVersion(ServiceCtx context) { // If an NACP isn't found, the buffer will be all '\0' which seems to be the correct implementation. - context.ResponseData.Write(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion); + context.ResponseData.Write(context.Device.Processes.GetProcess(_pid).ApplicationControlProperties.DisplayVersion); return ResultCode.Success; } @@ -235,11 +238,12 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.Applicati ushort index = (ushort)context.RequestData.ReadUInt64(); long saveSize = context.RequestData.ReadInt64(); long journalSize = context.RequestData.ReadInt64(); + var process = context.Device.Processes.GetProcess(_pid); // Mask out the low nibble of the program ID to get the application ID - ApplicationId applicationId = new(context.Device.Processes.ActiveApplication.ProgramId & ~0xFul); + ApplicationId applicationId = new(process.Identity.ApplicationId); - ApplicationControlProperty nacp = context.Device.Processes.ActiveApplication.ApplicationControlProperties; + ApplicationControlProperty nacp = process.ApplicationControlProperties; LibHac.Result result = _horizon.Fs.CreateApplicationCacheStorage(out long requiredSize, out CacheStorageTargetMedia storageTarget, applicationId, in nacp, index, saveSize, journalSize); diff --git a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs index b24e1bf4f..27a54a51e 100644 --- a/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Am/AppletOE/ApplicationProxyService/IApplicationProxy.cs @@ -70,7 +70,7 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService // GetApplicationFunctions() -> object public ResultCode GetApplicationFunctions(ServiceCtx context) { - MakeObject(context, new IApplicationFunctions(context.Device.System)); + MakeObject(context, new IApplicationFunctions(context.Device.System, _pid)); return ResultCode.Success; } diff --git a/src/Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs b/src/Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs index 26089bddb..b370c3d04 100644 --- a/src/Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs +++ b/src/Ryujinx.HLE/HOS/Services/Arp/ApplicationLaunchProperty.cs @@ -27,13 +27,18 @@ namespace Ryujinx.HLE.HOS.Services.Arp } public static ApplicationLaunchProperty GetByPid(ServiceCtx context) + { + return GetByPid(context, context.ClientProcessId); + } + + public static ApplicationLaunchProperty GetByPid(ServiceCtx context, ulong pid) { // TODO: Handle ApplicationLaunchProperty as array when pid will be supported and return the right item. // For now we can hardcode values, and fix it after GetApplicationLaunchProperty is implemented. return new ApplicationLaunchProperty { - TitleId = context.Device.Processes.ActiveApplication.ProgramId, + TitleId = context.Device.Processes.GetProcess(pid).ProgramId, Version = 0x00, BaseGameStorageId = (byte)StorageId.BuiltInSystem, UpdateGameStorageId = (byte)StorageId.None, diff --git a/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs b/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs index 2ccb7c598..64e9eeca5 100644 --- a/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Caps/IScreenShotApplicationService.cs @@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps byte[] screenshotData = context.Memory.GetSpan(screenshotDataPosition, (int)screenshotDataSize, true).ToArray(); - ResultCode resultCode = context.Device.System.CaptureManager.SaveScreenShot(screenshotData, appletResourceUserId, context.Device.Processes.ActiveApplication.ProgramId, out ApplicationAlbumEntry applicationAlbumEntry); + ResultCode resultCode = context.Device.System.CaptureManager.SaveScreenShot(screenshotData, appletResourceUserId, context.Device.Processes.GetProcess(context.ClientProcessId).ProgramId, out ApplicationAlbumEntry applicationAlbumEntry); context.ResponseData.WriteStruct(applicationAlbumEntry); @@ -98,7 +98,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps byte[] screenshotData = context.Memory.GetSpan(screenshotDataPosition, (int)screenshotDataSize, true).ToArray(); - ResultCode resultCode = context.Device.System.CaptureManager.SaveScreenShot(screenshotData, appletResourceUserId, context.Device.Processes.ActiveApplication.ProgramId, out ApplicationAlbumEntry applicationAlbumEntry); + ResultCode resultCode = context.Device.System.CaptureManager.SaveScreenShot(screenshotData, appletResourceUserId, context.Device.Processes.GetProcess(context.ClientProcessId).ProgramId, out ApplicationAlbumEntry applicationAlbumEntry); context.ResponseData.WriteStruct(applicationAlbumEntry); @@ -143,7 +143,7 @@ namespace Ryujinx.HLE.HOS.Services.Caps byte[] screenshotData = context.Memory.GetSpan(screenshotDataPosition, (int)screenshotDataSize, true).ToArray(); - ResultCode resultCode = context.Device.System.CaptureManager.SaveScreenShot(screenshotData, appletResourceUserId, context.Device.Processes.ActiveApplication.ProgramId, out ApplicationAlbumEntry applicationAlbumEntry); + ResultCode resultCode = context.Device.System.CaptureManager.SaveScreenShot(screenshotData, appletResourceUserId, context.Device.Processes.GetProcess(context.ClientProcessId).ProgramId, out ApplicationAlbumEntry applicationAlbumEntry); context.ResponseData.WriteStruct(applicationAlbumEntry); diff --git a/src/Ryujinx.HLE/HOS/Services/Fatal/IService.cs b/src/Ryujinx.HLE/HOS/Services/Fatal/IService.cs index c3ed92ed0..fe1744918 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fatal/IService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fatal/IService.cs @@ -1,5 +1,6 @@ using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Services.Fatal.Types; +using Ryujinx.HLE.Loaders.Processes; using System; using System.Runtime.InteropServices; using System.Text; @@ -50,12 +51,13 @@ namespace Ryujinx.HLE.HOS.Services.Fatal private ResultCode ThrowFatalWithCpuContextImpl(ServiceCtx context, ResultCode resultCode, ulong pid, FatalPolicy fatalPolicy, ReadOnlySpan cpuContext) { + ProcessResult process = context.Device.Processes.GetProcess(pid); StringBuilder errorReport = new(); errorReport.AppendLine(); errorReport.AppendLine("ErrorReport log:"); - errorReport.AppendLine($"\tTitleId: {context.Device.Processes.ActiveApplication.ProgramIdText}"); + errorReport.AppendLine($"\tTitleId: {process.ProgramIdText}"); errorReport.AppendLine($"\tPid: {pid}"); errorReport.AppendLine($"\tResultCode: {((int)resultCode & 0x1FF) + 2000}-{((int)resultCode >> 9) & 0x3FFF:d4}"); errorReport.AppendLine($"\tFatalPolicy: {fatalPolicy}"); @@ -64,7 +66,7 @@ namespace Ryujinx.HLE.HOS.Services.Fatal { errorReport.AppendLine("CPU Context:"); - if (context.Device.Processes.ActiveApplication.Is64Bit) + if (process.Is64Bit) { CpuContext64 cpuContext64 = MemoryMarshal.Cast(cpuContext)[0]; diff --git a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs index 08ede2b5b..75d8edfb2 100644 --- a/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs +++ b/src/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs @@ -885,7 +885,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs { byte programIndex = context.RequestData.ReadByte(); - if ((context.Device.Processes.ActiveApplication.ProgramId & 0xf) != programIndex) + if (context.Device.Processes.GetProcess(_pid).Identity.ProgramIndex != programIndex) { throw new NotImplementedException($"Accessing storage from other programs is not supported (program index = {programIndex})."); } diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs index 2f764e99f..f5ca0fd82 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -60,7 +60,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator private bool CheckLocalCommunicationIdPermission(ServiceCtx context, ulong localCommunicationIdChecked) { // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. - ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties; + ApplicationControlProperty controlProperty = context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties; foreach (ulong localCommunicationId in controlProperty.LocalCommunicationId) { @@ -438,7 +438,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator if (scanFilter.NetworkId.IntentId.LocalCommunicationId == -1 && NetworkClient.NeedsRealId) { // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. - ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties; + ApplicationControlProperty controlProperty = context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties; scanFilter.NetworkId.IntentId.LocalCommunicationId = (long)controlProperty.LocalCommunicationId[0]; } @@ -613,7 +613,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator if (networkConfig.IntentId.LocalCommunicationId == -1 && NetworkClient.NeedsRealId) { // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. - ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties; + ApplicationControlProperty controlProperty = context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties; networkConfig.IntentId.LocalCommunicationId = (long)controlProperty.LocalCommunicationId[0]; } @@ -948,7 +948,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator if (networkInfo.NetworkId.IntentId.LocalCommunicationId == -1 && NetworkClient.NeedsRealId) { // TODO: Call nn::arp::GetApplicationControlProperty here when implemented. - ApplicationControlProperty controlProperty = context.Device.Processes.ActiveApplication.ApplicationControlProperties; + ApplicationControlProperty controlProperty = context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties; networkInfo.NetworkId.IntentId.LocalCommunicationId = (long)controlProperty.LocalCommunicationId[0]; } @@ -1208,7 +1208,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator } // TODO: Call nn::arp::GetApplicationLaunchProperty here when implemented. - NetworkClient.SetGameVersion(context.Device.Processes.ActiveApplication.ApplicationControlProperties.DisplayVersion); + NetworkClient.SetGameVersion(context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties.DisplayVersion); resultCode = ResultCode.Success; _nifmResultCode = resultCode; diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs index c77358803..2cb921500 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/Aoc/IAddOnContentManager.cs @@ -50,7 +50,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. - return CountAddOnContentImpl(context, context.Device.Processes.ActiveApplication.ProgramId); + return CountAddOnContentImpl(context, context.Device.Processes.GetProcess(pid).ProgramId); } [CommandCmif(3)] @@ -63,7 +63,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. - return ListAddContentImpl(context, context.Device.Processes.ActiveApplication.ProgramId); + return ListAddContentImpl(context, context.Device.Processes.GetProcess(pid).ProgramId); } [CommandCmif(4)] // 1.0.0-6.2.0 @@ -85,7 +85,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. - return GetAddOnContentBaseIdImpl(context, context.Device.Processes.ActiveApplication.ProgramId); + return GetAddOnContentBaseIdImpl(context, context.Device.Processes.GetProcess(pid).ProgramId); } [CommandCmif(6)] // 1.0.0-6.2.0 @@ -107,7 +107,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. - return PrepareAddOnContentImpl(context, context.Device.Processes.ActiveApplication.ProgramId); + return PrepareAddOnContentImpl(context, context.Device.Processes.GetProcess(pid).ProgramId); } [CommandCmif(8)] // 4.0.0+ @@ -138,7 +138,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc // NOTE: Service call arp:r GetApplicationLaunchProperty to get TitleId using the PId. // TODO: Found where stored value is used. - ResultCode resultCode = GetAddOnContentBaseIdFromTitleId(context, context.Device.Processes.ActiveApplication.ProgramId); + ResultCode resultCode = GetAddOnContentBaseIdFromTitleId(context, context.Device.Processes.GetProcess(pid).ProgramId); if (resultCode != ResultCode.Success) { @@ -310,7 +310,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc // NOTE: Service calls arp:r GetApplicationControlProperty to get AddOnContentBaseId using TitleId, // If the call fails, it returns ResultCode.InvalidPid. - _addOnContentBaseId = context.Device.Processes.ActiveApplication.ApplicationControlProperties.AddOnContentBaseId; + _addOnContentBaseId = context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties.AddOnContentBaseId; if (_addOnContentBaseId == 0) { @@ -324,7 +324,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns.Aoc { uint index = context.RequestData.ReadUInt32(); - ResultCode resultCode = GetAddOnContentBaseIdFromTitleId(context, context.Device.Processes.ActiveApplication.ProgramId); + ResultCode resultCode = GetAddOnContentBaseIdFromTitleId(context, titleId); if (resultCode != ResultCode.Success) { diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs index f510da594..a45054aba 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs @@ -19,7 +19,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns ulong position = context.Request.ReceiveBuff[0].Position; - ApplicationControlProperty nacp = context.Device.Processes.ActiveApplication.ApplicationControlProperties; + ApplicationControlProperty nacp = context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties; context.Memory.Write(position, SpanHelpers.AsByteSpan(ref nacp).ToArray()); diff --git a/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationControlDataInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationControlDataInterface.cs index ca7d42b48..971929298 100644 --- a/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationControlDataInterface.cs +++ b/src/Ryujinx.HLE/HOS/Services/Ns/IReadOnlyApplicationControlDataInterface.cs @@ -18,7 +18,7 @@ namespace Ryujinx.HLE.HOS.Services.Ns ulong position = context.Request.ReceiveBuff[0].Position; - ApplicationControlProperty nacp = context.Device.Processes.ActiveApplication.ApplicationControlProperties; + ApplicationControlProperty nacp = context.Device.Processes.GetProcess(context.ClientProcessId).ApplicationControlProperties; context.Memory.Write(position, SpanHelpers.AsByteSpan(ref nacp).ToArray()); diff --git a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs index c36482e41..5e4f415fb 100644 --- a/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs +++ b/src/Ryujinx.HLE/HOS/Services/Pctl/ParentalControlServiceFactory/IParentalControlService.cs @@ -48,21 +48,22 @@ namespace Ryujinx.HLE.HOS.Services.Pctl.ParentalControlServiceFactory { if ((_permissionFlag & 0x40) == 0) { - ulong titleId = ApplicationLaunchProperty.GetByPid(context).TitleId; + ulong titleId = ApplicationLaunchProperty.GetByPid(context, _pid).TitleId; if (titleId != 0) { _titleId = titleId; + var process = context.Device.Processes.GetProcess(_pid); // TODO: Call nn::arp::GetApplicationControlProperty here when implemented, if it return ResultCode.Success we assign fields. - _ratingAge = new int[context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge.Length]; + _ratingAge = new int[process.ApplicationControlProperties.RatingAge.Length]; for (int i = 0; i < _ratingAge.Length; i++) { - _ratingAge[i] = Convert.ToInt32(context.Device.Processes.ActiveApplication.ApplicationControlProperties.RatingAge[i]); + _ratingAge[i] = Convert.ToInt32(process.ApplicationControlProperties.RatingAge[i]); } - _parentalControlFlag = context.Device.Processes.ActiveApplication.ApplicationControlProperties.ParentalControlFlag; + _parentalControlFlag = process.ApplicationControlProperties.ParentalControlFlag; } } diff --git a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs index b34ff0476..3999512ef 100644 --- a/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs +++ b/src/Ryujinx.HLE/HOS/Services/Sdb/Pdm/QueryService/QueryPlayStatisticsManager.cs @@ -2,6 +2,7 @@ using Ryujinx.Common; using Ryujinx.Cpu; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService.Types; +using Ryujinx.HLE.Loaders.Processes; using System; using System.Collections.Generic; using System.Linq; @@ -31,7 +32,8 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService } } - PlayLogQueryCapability queryCapability = (PlayLogQueryCapability)context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryCapability; + ProcessResult process = context.Device.Processes.GetProcess(context.ClientProcessId); + PlayLogQueryCapability queryCapability = (PlayLogQueryCapability)process.ApplicationControlProperties.PlayLogQueryCapability; List titleIds = []; @@ -45,7 +47,7 @@ namespace Ryujinx.HLE.HOS.Services.Sdb.Pdm.QueryService // Check if input title ids are in the whitelist. foreach (ulong titleId in titleIds) { - if (!context.Device.Processes.ActiveApplication.ApplicationControlProperties.PlayLogQueryableApplicationId.AsReadOnlySpan().Contains(titleId)) + if (!process.ApplicationControlProperties.PlayLogQueryableApplicationId.AsReadOnlySpan().Contains(titleId)) { return (ResultCode)Am.ResultCode.ObjectInvalid; } diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessIdentity.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessIdentity.cs new file mode 100644 index 000000000..051e9a18f --- /dev/null +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessIdentity.cs @@ -0,0 +1,34 @@ +namespace Ryujinx.HLE.Loaders.Processes +{ + public readonly struct ProcessIdentity + { + public ulong ProcessId { get; } + public ulong ProgramId { get; } + public ulong ApplicationId { get; } + public byte ProgramIndex { get; } + public string ProgramIdText { get; } + public string DisplayVersion { get; } + public ProcessKind Kind { get; } + + public ProcessIdentity( + ulong processId, + ulong programId, + byte programIndex, + string displayVersion, + ProcessKind kind) + { + ProcessId = processId; + ProgramId = programId; + ProgramIndex = programIndex; + ApplicationId = programId & ~0xFul; + ProgramIdText = $"{programId:x16}"; + DisplayVersion = displayVersion ?? string.Empty; + Kind = kind; + } + + public override string ToString() + { + return $"{Kind} pid={ProcessId} program={ProgramIdText} application={ApplicationId:x16} index={ProgramIndex} version={DisplayVersion}"; + } + } +} diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessKind.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessKind.cs new file mode 100644 index 000000000..eda7c9e86 --- /dev/null +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessKind.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.HLE.Loaders.Processes +{ + public enum ProcessKind + { + Unknown, + Application, + SystemApplication, + SystemApplet, + LibraryApplet, + Homebrew, + } +} diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs index f217ecd0b..f32dc651d 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoader.cs @@ -93,6 +93,23 @@ namespace Ryujinx.HLE.Loaders.Processes _processesByPid = new ConcurrentDictionary(); } + public bool TryGetProcess(ulong pid, out ProcessResult process) + { + return _processesByPid.TryGetValue(pid, out process); + } + + public ProcessResult GetProcess(ulong pid) + { + if (_processesByPid.TryGetValue(pid, out ProcessResult process)) + { + return process; + } + + Logger.Warning?.Print(LogClass.Loader, $"Process metadata for pid {pid} was not found. Falling back to active application metadata."); + + return ActiveApplication; + } + public bool LoadXci(string path, ulong applicationId) { FileStream stream = new(path, FileMode.Open, FileAccess.Read); diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index afd8ebffc..f22dfd1dd 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -436,6 +436,7 @@ namespace Ryujinx.HLE.Loaders.Processes allowCodeMemoryForJit, processContextFactory.DiskCacheLoadState, process.Pid, + programIndex, meta.MainThreadPriority, meta.MainThreadStackSize, device.System.State.DesiredTitleLanguage); diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs index 66bdd57ef..2408afcdb 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs @@ -10,7 +10,7 @@ namespace Ryujinx.HLE.Loaders.Processes { public class ProcessResult { - public static ProcessResult Failed => new(null, new BlitStruct(1), false, false, null, 0, 0, 0, TitleLanguage.AmericanEnglish); + public static ProcessResult Failed => new(null, new BlitStruct(1), false, false, null, 0, 0, 0, 0, TitleLanguage.AmericanEnglish); private readonly byte _mainThreadPriority; private readonly uint _mainThreadStackSize; @@ -28,6 +28,7 @@ namespace Ryujinx.HLE.Loaders.Processes public readonly bool Is64Bit; public readonly bool DiskCacheEnabled; public readonly bool AllowCodeMemoryForJit; + public readonly ProcessIdentity Identity; public ProcessResult( MetaLoader metaLoader, @@ -36,6 +37,7 @@ namespace Ryujinx.HLE.Loaders.Processes bool allowCodeMemoryForJit, IDiskCacheLoadState diskCacheLoadState, ulong pid, + byte programIndex, byte mainThreadPriority, uint mainThreadStackSize, TitleLanguage titleLanguage) @@ -71,6 +73,7 @@ namespace Ryujinx.HLE.Loaders.Processes ProgramId = programId; ProgramIdText = $"{programId:x16}"; Is64Bit = metaLoader.IsProgram64Bit; + Identity = new ProcessIdentity(pid, programId, programIndex, DisplayVersion, GetProcessKind(programId)); } else @@ -84,6 +87,31 @@ namespace Ryujinx.HLE.Loaders.Processes AllowCodeMemoryForJit = allowCodeMemoryForJit; } + private static ProcessKind GetProcessKind(ulong programId) + { + if (programId == 0) + { + return ProcessKind.Application; + } + + if (programId is >= 0x0100000000001000 and <= 0x0100000000001FFF) + { + return ProcessKind.SystemApplet; + } + + if (programId is >= 0x0100000000000800 and <= 0x0100000000000FFF) + { + return ProcessKind.LibraryApplet; + } + + if (programId <= 0x0100000000007FFF) + { + return ProcessKind.SystemApplication; + } + + return ProcessKind.Application; + } + public bool Start(Switch device) { device.Configuration.ContentManager.LoadEntries(device); @@ -109,6 +137,7 @@ namespace Ryujinx.HLE.Loaders.Processes : device.System.ContentManager.GetCurrentFirmwareVersion()?.VersionString ?? "?"; Logger.Info?.Print(LogClass.Loader, $"Application Loaded: {name} v{version} [{ProgramIdText}] [{(Is64Bit ? "64-bit" : "32-bit")}]"); + Logger.Info?.Print(LogClass.Loader, $"Process identity: {Identity}"); return true; }