From 701203bedd301de0c529d0c91af40017d94420fc Mon Sep 17 00:00:00 2001 From: Thog Date: Mon, 11 Feb 2019 23:52:33 +0100 Subject: [PATCH] Implement GetApplicationControlData --- Ryujinx.HLE/HOS/Horizon.cs | 2 + .../Ns/IApplicationManagerInterface.cs | 214 +++++++++++++++++- .../HOS/Services/Pm/IShellInterface.cs | 2 +- 3 files changed, 211 insertions(+), 7 deletions(-) diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index 8a419af343..672c9f7f9d 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -102,6 +102,8 @@ namespace Ryujinx.HLE.HOS public Horizon(Switch device) { + ControlData = new Nacp(); + Device = device; State = new SystemStateMgr(); diff --git a/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs b/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs index f36b26e6f0..9874206166 100644 --- a/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Ns/IApplicationManagerInterface.cs @@ -1,6 +1,9 @@ -using Ryujinx.Common.Logging; +using LibHac; +using Ryujinx.Common.Logging; using Ryujinx.HLE.HOS.Ipc; +using System; using System.Collections.Generic; +using System.Text; namespace Ryujinx.HLE.HOS.Services.Ns { @@ -10,8 +13,6 @@ namespace Ryujinx.HLE.HOS.Services.Ns public override IReadOnlyDictionary Commands => _commands; - private bool _isInitialized; - public IApplicationManagerInterface() { _commands = new Dictionary @@ -20,12 +21,213 @@ namespace Ryujinx.HLE.HOS.Services.Ns }; } - // TODO: implement this at some point public long GetApplicationControlData(ServiceCtx context) { - Logger.PrintStub(LogClass.ServiceNs, "Stubbed."); + long position = context.Request.ReceiveBuff[0].Position; - return 0xDEAD; + Nacp nacp = context.Device.System.ControlData; + + for (int i = 0; i < 0x10; i++) + { + NacpDescription description = nacp.Descriptions[i]; + + byte[] titleData = new byte[0x200]; + byte[] developerData = new byte[0x100]; + + if (description !=null && description.Title != null) + { + byte[] titleDescriptionData = Encoding.ASCII.GetBytes(description.Title); + Buffer.BlockCopy(titleDescriptionData, 0, titleData, 0, titleDescriptionData.Length); + + } + + if (description != null && description.Developer != null) + { + byte[] developerDescriptionData = Encoding.ASCII.GetBytes(description.Developer); + Buffer.BlockCopy(developerDescriptionData, 0, developerData, 0, developerDescriptionData.Length); + } + + context.Memory.WriteBytes(position, titleData); + context.Memory.WriteBytes(position + 0x200, developerData); + + position += i * 0x300; + } + + byte[] isbn = new byte[0x25]; + + if (nacp.Isbn != null) + { + byte[] isbnData = Encoding.ASCII.GetBytes(nacp.Isbn); + Buffer.BlockCopy(isbnData, 0, isbn, 0, isbnData.Length); + } + + context.Memory.WriteBytes(position, isbn); + position += isbn.Length; + + context.Memory.WriteByte(position, nacp.StartupUserAccount); + context.Memory.WriteByte(position + 1, nacp.TouchScreenUsageMode); + context.Memory.WriteByte(position + 2, nacp.AocRegistrationType); + position += 3; + + context.Memory.WriteInt32(position, nacp.AttributeFlag); + position += 4; + + context.Memory.WriteUInt32(position, nacp.SupportedLanguageFlag); + position += 4; + + context.Memory.WriteUInt32(position, nacp.ParentalControlFlag); + position += 4; + + context.Memory.WriteByte(position, nacp.Screenshot); + context.Memory.WriteByte(position + 1, nacp.VideoCapture); + context.Memory.WriteByte(position + 2, nacp.DataLossConfirmation); + context.Memory.WriteByte(position + 3, nacp.PlayLogPolicy); + position += 4; + + context.Memory.WriteUInt64(position, nacp.PresenceGroupId); + position += 8; + + for (int i = 0; i < nacp.RatingAge.Length; i++) + { + context.Memory.WriteSByte(position, nacp.RatingAge[i]); + position++; + } + + byte[] displayVersion = new byte[0x10]; + + if (nacp.DisplayVersion != null) + { + byte[] displayVersionData = Encoding.ASCII.GetBytes(nacp.DisplayVersion); + Buffer.BlockCopy(displayVersionData, 0, displayVersion, 0, displayVersionData.Length); + } + + context.Memory.WriteBytes(position, displayVersion); + position += displayVersion.Length; + + context.Memory.WriteUInt64(position, nacp.AddOnContentBaseId); + position += 8; + + context.Memory.WriteUInt64(position, nacp.SaveDataOwnerId); + position += 8; + + context.Memory.WriteInt64(position, nacp.UserAccountSaveDataSize); + position += 8; + + context.Memory.WriteInt64(position, nacp.UserAccountSaveDataJournalSize); + position += 8; + + context.Memory.WriteInt64(position, nacp.DeviceSaveDataSize); + position += 8; + + context.Memory.WriteInt64(position, nacp.DeviceSaveDataJournalSize); + position += 8; + + context.Memory.WriteInt64(position, nacp.BcatDeliveryCacheStorageSize); + position += 8; + + byte[] applicationErrorCodeCategory = new byte[0x8]; + + if (nacp.ApplicationErrorCodeCategory != null) + { + byte[] applicationErrorCodeCategoryData = Encoding.ASCII.GetBytes(nacp.ApplicationErrorCodeCategory); + Buffer.BlockCopy(applicationErrorCodeCategoryData, 0, applicationErrorCodeCategoryData, 0, applicationErrorCodeCategoryData.Length); + } + + context.Memory.WriteBytes(position, applicationErrorCodeCategory); + position += applicationErrorCodeCategory.Length; + + for (int i = 0; i < nacp.LocalCommunicationId.Length; i++) + { + context.Memory.WriteUInt64(position, nacp.LocalCommunicationId[i]); + position += 8; + } + + context.Memory.WriteByte(position, nacp.LogoType); + context.Memory.WriteByte(position + 1, nacp.LogoHandling); + context.Memory.WriteByte(position + 2, nacp.RuntimeAddOnContentInstall); + + byte[] reserved000 = new byte[0x3]; + context.Memory.WriteBytes(position + 3, reserved000); + position += 3; + position += reserved000.Length; + + context.Memory.WriteByte(position, nacp.CrashReport); + context.Memory.WriteByte(position + 1, nacp.Hdcp); + context.Memory.WriteUInt64(position + 2, nacp.SeedForPseudoDeviceId); + position += 10; + + byte[] bcatPassphrase = new byte[65]; + if (nacp.BcatPassphrase != null) + { + byte[] bcatPassphraseData = Encoding.ASCII.GetBytes(nacp.BcatPassphrase); + Buffer.BlockCopy(bcatPassphraseData, 0, bcatPassphrase, 0, bcatPassphraseData.Length); + } + + context.Memory.WriteBytes(position, bcatPassphrase); + position += bcatPassphrase.Length; + + context.Memory.WriteByte(position, nacp.Reserved01); + position++; + + byte[] reserved02 = new byte[0x6]; + context.Memory.WriteBytes(position, reserved02); + position += reserved02.Length; + + context.Memory.WriteInt64(position, nacp.UserAccountSaveDataSizeMax); + position += 8; + + context.Memory.WriteInt64(position, nacp.UserAccountSaveDataJournalSizeMax); + position += 8; + + context.Memory.WriteInt64(position, nacp.DeviceSaveDataSizeMax); + position += 8; + + context.Memory.WriteInt64(position, nacp.DeviceSaveDataJournalSizeMax); + position += 8; + + context.Memory.WriteInt64(position, nacp.TemporaryStorageSize); + position += 8; + + context.Memory.WriteInt64(position, nacp.CacheStorageSize); + position += 8; + + context.Memory.WriteInt64(position, nacp.CacheStorageJournalSize); + position += 8; + + context.Memory.WriteInt64(position, nacp.CacheStorageDataAndJournalSizeMax); + position += 8; + + context.Memory.WriteInt16(position, nacp.CacheStorageIndex); + position += 2; + + byte[] reserved03 = new byte[0x6]; + context.Memory.WriteBytes(position, reserved03); + position += reserved03.Length; + + + for (int i = 0; i < 16; i++) + { + ulong value = 0; + + if (nacp.PlayLogQueryableApplicationId.Count > i) + { + value = nacp.PlayLogQueryableApplicationId[i]; + } + + context.Memory.WriteUInt64(position, value); + position += 8; + } + + context.Memory.WriteByte(position, nacp.PlayLogQueryCapability); + position++; + + context.Memory.WriteByte(position, nacp.RepairFlag); + position++; + + context.Memory.WriteByte(position, nacp.ProgramIndex); + position++; + + return 0; } } } diff --git a/Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs b/Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs index 5e4d9327ca..8880b3348e 100644 --- a/Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Pm/IShellInterface.cs @@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Pm // GetApplicationPid() -> u64 public long GetApplicationPid(ServiceCtx context) { - // FIXME: This is wrong but needed to make hbmenu works + // FIXME: This is wrong but needed to make hb loader works // TODO: Change this when we will have a way to process via a PM like interface. long pid = context.Process.Pid;