diff --git a/CONFIG.md b/CONFIG.md index 09fa13b7b..764eb528d 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -26,6 +26,10 @@ Enable the Fatal Logging (Enabled in Debug recommanded). +- `Logging_Enable_Ipc` *(bool)* + + Enable the Ipc Message Logging. + - `Logging_Enable_LogFile` *(bool)* Enable writing the logging inside a Ryujinx.log file. diff --git a/Ryujinx.Core/Config.cs b/Ryujinx.Core/Config.cs index b97e80b89..7db49319c 100644 --- a/Ryujinx.Core/Config.cs +++ b/Ryujinx.Core/Config.cs @@ -8,12 +8,13 @@ namespace Ryujinx.Core { public static class Config { - public static bool LoggingEnableInfo { get; private set; } - public static bool LoggingEnableTrace { get; private set; } - public static bool LoggingEnableDebug { get; private set; } - public static bool LoggingEnableWarn { get; private set; } - public static bool LoggingEnableError { get; private set; } - public static bool LoggingEnableFatal { get; private set; } + public static bool LoggingEnableInfo { get; private set; } + public static bool LoggingEnableTrace { get; private set; } + public static bool LoggingEnableDebug { get; private set; } + public static bool LoggingEnableWarn { get; private set; } + public static bool LoggingEnableError { get; private set; } + public static bool LoggingEnableFatal { get; private set; } + public static bool LoggingEnableIpc { get; private set; } public static bool LoggingEnableLogFile { get; private set; } public static JoyCon FakeJoyCon { get; private set; } @@ -30,6 +31,7 @@ namespace Ryujinx.Core LoggingEnableWarn = Convert.ToBoolean(Parser.Value("Logging_Enable_Warn")); LoggingEnableError = Convert.ToBoolean(Parser.Value("Logging_Enable_Error")); LoggingEnableFatal = Convert.ToBoolean(Parser.Value("Logging_Enable_Fatal")); + LoggingEnableIpc = Convert.ToBoolean(Parser.Value("Logging_Enable_Ipc")); LoggingEnableLogFile = Convert.ToBoolean(Parser.Value("Logging_Enable_LogFile")); FakeJoyCon = new JoyCon diff --git a/Ryujinx.Core/Logging.cs b/Ryujinx.Core/Logging.cs index e14e5587a..b14f26653 100644 --- a/Ryujinx.Core/Logging.cs +++ b/Ryujinx.Core/Logging.cs @@ -1,6 +1,8 @@ -using System; +using Ryujinx.Core.OsHle.Ipc; +using System; using System.Diagnostics; using System.IO; +using System.Text; namespace Ryujinx.Core { @@ -9,13 +11,14 @@ namespace Ryujinx.Core private static Stopwatch ExecutionTime = new Stopwatch(); private const string LogFileName = "Ryujinx.log"; - public static bool EnableInfo = Config.LoggingEnableInfo; - public static bool EnableTrace = Config.LoggingEnableTrace; - public static bool EnableDebug = Config.LoggingEnableDebug; - public static bool EnableWarn = Config.LoggingEnableWarn; - public static bool EnableError = Config.LoggingEnableError; - public static bool EnableFatal = Config.LoggingEnableFatal; - public static bool EnableLogFile = Config.LoggingEnableLogFile; + private static bool EnableInfo = Config.LoggingEnableInfo; + private static bool EnableTrace = Config.LoggingEnableTrace; + private static bool EnableDebug = Config.LoggingEnableDebug; + private static bool EnableWarn = Config.LoggingEnableWarn; + private static bool EnableError = Config.LoggingEnableError; + private static bool EnableFatal = Config.LoggingEnableFatal; + private static bool EnableIpc = Config.LoggingEnableIpc; + private static bool EnableLogFile = Config.LoggingEnableLogFile; static Logging() { @@ -128,5 +131,79 @@ namespace Ryujinx.Core LogFile(Text); } } + + public static void Ipc(byte[] Data, long CmdPtr, bool Domain) + { + if (EnableIpc) + { + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine(IpcLog.Message(Data, CmdPtr, Domain)); + Console.ResetColor(); + } + } + + //https://www.codeproject.com/Articles/36747/Quick-and-Dirty-HexDump-of-a-Byte-Array + public static string HexDump(byte[] bytes, int bytesPerLine = 16) + { + if (bytes == null) return ""; + int bytesLength = bytes.Length; + + char[] HexChars = "0123456789ABCDEF".ToCharArray(); + + int firstHexColumn = + 8 // 8 characters for the address + + 3; // 3 spaces + + int firstCharColumn = firstHexColumn + + bytesPerLine * 3 // - 2 digit for the hexadecimal value and 1 space + + (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th + + 2; // 2 spaces + + int lineLength = firstCharColumn + + bytesPerLine // - characters to show the ascii value + + Environment.NewLine.Length; // Carriage return and line feed (should normally be 2) + + char[] line = (new String(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray(); + int expectedLines = (bytesLength + bytesPerLine - 1) / bytesPerLine; + StringBuilder result = new StringBuilder(expectedLines * lineLength); + + for (int i = 0; i < bytesLength; i += bytesPerLine) + { + line[0] = HexChars[(i >> 28) & 0xF]; + line[1] = HexChars[(i >> 24) & 0xF]; + line[2] = HexChars[(i >> 20) & 0xF]; + line[3] = HexChars[(i >> 16) & 0xF]; + line[4] = HexChars[(i >> 12) & 0xF]; + line[5] = HexChars[(i >> 8) & 0xF]; + line[6] = HexChars[(i >> 4) & 0xF]; + line[7] = HexChars[(i >> 0) & 0xF]; + + int hexColumn = firstHexColumn; + int charColumn = firstCharColumn; + + for (int j = 0; j < bytesPerLine; j++) + { + if (j > 0 && (j & 7) == 0) hexColumn++; + if (i + j >= bytesLength) + { + line[hexColumn] = ' '; + line[hexColumn + 1] = ' '; + line[charColumn] = ' '; + } + else + { + byte b = bytes[i + j]; + line[hexColumn] = HexChars[(b >> 4) & 0xF]; + line[hexColumn + 1] = HexChars[b & 0xF]; + line[charColumn] = (b < 32 ? '·' : (char)b); + } + hexColumn += 3; + charColumn++; + } + + result.Append(line); + } + return result.ToString(); + } } } diff --git a/Ryujinx.Core/OsHle/Handles/HThread.cs b/Ryujinx.Core/OsHle/Handles/HThread.cs index 8bb276fa8..c631cedc6 100644 --- a/Ryujinx.Core/OsHle/Handles/HThread.cs +++ b/Ryujinx.Core/OsHle/Handles/HThread.cs @@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle.Handles public AThread Thread { get; private set; } public int ProcessorId { get; private set; } - public int Priority { get; private set; } + public int Priority { get; set; } public int ThreadId => Thread.ThreadId; diff --git a/Ryujinx.Core/OsHle/Ipc/IpcLog.cs b/Ryujinx.Core/OsHle/Ipc/IpcLog.cs new file mode 100644 index 000000000..dfec7ccfd --- /dev/null +++ b/Ryujinx.Core/OsHle/Ipc/IpcLog.cs @@ -0,0 +1,179 @@ +using System; +using System.IO; + +namespace Ryujinx.Core.OsHle.Ipc +{ + public static class IpcLog + { + public static string Message(byte[] Data, long CmdPtr, bool Domain) + { + string IpcMessage = ""; + + using (MemoryStream MS = new MemoryStream(Data)) + { + BinaryReader Reader = new BinaryReader(MS); + + int Word0 = Reader.ReadInt32(); + int Word1 = Reader.ReadInt32(); + + int Type = (Word0 & 0xffff); + + int PtrBuffCount = (Word0 >> 16) & 0xf; + int SendBuffCount = (Word0 >> 20) & 0xf; + int RecvBuffCount = (Word0 >> 24) & 0xf; + int XchgBuffCount = (Word0 >> 28) & 0xf; + + int RawDataSize = (Word1 >> 0) & 0x3ff; + int RecvListFlags = (Word1 >> 10) & 0xf; + bool HndDescEnable = ((Word1 >> 31) & 0x1) != 0; + + IpcMessage += Environment.NewLine + $" {Logging.GetExecutionTime()} | IpcMessage >" + Environment.NewLine + + $" Type: {Enum.GetName(typeof(IpcMessageType), Type)}" + Environment.NewLine + + + $" PtrBuffCount: {PtrBuffCount.ToString()}" + Environment.NewLine + + $" SendBuffCount: {SendBuffCount.ToString()}" + Environment.NewLine + + $" RecvBuffCount: {RecvBuffCount.ToString()}" + Environment.NewLine + + $" XchgBuffCount: {XchgBuffCount.ToString()}" + Environment.NewLine + + + $" RawDataSize: {RawDataSize.ToString()}" + Environment.NewLine + + $" RecvListFlags: {RecvListFlags.ToString()}" + Environment.NewLine + + $" HndDescEnable: {HndDescEnable.ToString()}" + Environment.NewLine; + + if (HndDescEnable) + { + int Word = Reader.ReadInt32(); + + bool HasPId = (Word & 1) != 0; + + int[] ToCopy = new int[(Word >> 1) & 0xf]; + int[] ToMove = new int[(Word >> 5) & 0xf]; + + long PId = HasPId ? Reader.ReadInt64() : 0; + + for (int Index = 0; Index < ToCopy.Length; Index++) + { + ToCopy[Index] = Reader.ReadInt32(); + } + + for (int Index = 0; Index < ToMove.Length; Index++) + { + ToMove[Index] = Reader.ReadInt32(); + } + + IpcMessage += Environment.NewLine + " HndDesc:" + Environment.NewLine + + $" PId: {PId.ToString()}" + Environment.NewLine + + $" ToCopy.Length: {ToCopy.Length.ToString()}" + Environment.NewLine + + $" ToMove.Length: {ToMove.Length.ToString()}" + Environment.NewLine; + } + + for (int Index = 0; Index < PtrBuffCount; Index++) + { + long IpcPtrBuffDescWord0 = Reader.ReadUInt32(); + long IpcPtrBuffDescWord1 = Reader.ReadUInt32(); + + long Position = IpcPtrBuffDescWord1; + Position |= (IpcPtrBuffDescWord0 << 20) & 0x0f00000000; + Position |= (IpcPtrBuffDescWord0 << 30) & 0x7000000000; + + int IpcPtrBuffDescIndex = ((int)IpcPtrBuffDescWord0 >> 0) & 0x03f; + IpcPtrBuffDescIndex |= ((int)IpcPtrBuffDescWord0 >> 3) & 0x1c0; + + short Size = (short)(IpcPtrBuffDescWord0 >> 16); + + IpcMessage += Environment.NewLine + $" PtrBuff[{Index}]:" + Environment.NewLine + + $" Position: {Position.ToString()}" + Environment.NewLine + + $" IpcPtrBuffDescIndex: {IpcPtrBuffDescIndex.ToString()}" + Environment.NewLine + + $" Size: {Size.ToString()}" + Environment.NewLine; + } + + ReadIpcBuffValues(Reader, SendBuffCount, IpcMessage, "SendBuff"); + ReadIpcBuffValues(Reader, RecvBuffCount, IpcMessage, "RecvBuff"); + ReadIpcBuffValues(Reader, XchgBuffCount, IpcMessage, "XchgBuff"); + + RawDataSize *= 4; + + long RecvListPos = Reader.BaseStream.Position + RawDataSize; + long Pad0 = 0; + + if ((Reader.BaseStream.Position + CmdPtr & 0xf) != 0) + { + Pad0 = 0x10 - (Reader.BaseStream.Position + CmdPtr & 0xf); + } + + Reader.BaseStream.Seek(Pad0, SeekOrigin.Current); + + int RecvListCount = RecvListFlags - 2; + + if (RecvListCount == 0) + { + RecvListCount = 1; + } + else if (RecvListCount < 0) + { + RecvListCount = 0; + } + + if (Domain && (IpcMessageType)Type == IpcMessageType.Request) + { + int DomWord0 = Reader.ReadInt32(); + + int DomCmd = (DomWord0 & 0xff); + + RawDataSize = (DomWord0 >> 16) & 0xffff; + + int DomObjId = Reader.ReadInt32(); + + Reader.ReadInt64(); //Padding + + IpcMessage += Environment.NewLine + $" Domain:" + Environment.NewLine + + $" DomCmd: {Enum.GetName(typeof(IpcDomCmd), DomCmd)}" + Environment.NewLine + + $" DomObjId: {DomObjId.ToString()}" + Environment.NewLine; + } + + byte[] RawData = Reader.ReadBytes(RawDataSize); + + IpcMessage += Environment.NewLine + $" RawData:" + Environment.NewLine + Logging.HexDump(RawData); + + Reader.BaseStream.Seek(RecvListPos, SeekOrigin.Begin); + + for (int Index = 0; Index < RecvListCount; Index++) + { + long RecvListBuffValue = Reader.ReadInt64(); + long RecvListBuffPosition = RecvListBuffValue & 0xffffffffffff; + long RecvListBuffSize = (short)(RecvListBuffValue >> 48); + + IpcMessage += Environment.NewLine + $" RecvList[{Index}]:" + Environment.NewLine + + $" Value: {RecvListBuffValue.ToString()}" + Environment.NewLine + + $" Position: {RecvListBuffPosition.ToString()}" + Environment.NewLine + + $" Size: {RecvListBuffSize.ToString()}" + Environment.NewLine; + } + } + + return IpcMessage; + } + + private static void ReadIpcBuffValues(BinaryReader Reader, int Count, string IpcMessage, string BufferName) + { + for (int Index = 0; Index < Count; Index++) + { + long Word0 = Reader.ReadUInt32(); + long Word1 = Reader.ReadUInt32(); + long Word2 = Reader.ReadUInt32(); + + long Position = Word1; + Position |= (Word2 << 4) & 0x0f00000000; + Position |= (Word2 << 34) & 0x7000000000; + + long Size = Word0; + Size |= (Word2 << 8) & 0xf00000000; + + int Flags = (int)Word2 & 3; + + IpcMessage += Environment.NewLine + $" {BufferName}[{Index}]:" + Environment.NewLine + + $" Position: {Position.ToString()}" + Environment.NewLine + + $" Flags: {Flags.ToString()}" + Environment.NewLine + + $" Size: {Size.ToString()}" + Environment.NewLine; + } + } + } +} diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs index 447f3f9a6..cc26df108 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs @@ -41,6 +41,8 @@ namespace Ryujinx.Core.OsHle.Ipc public IpcMessage(byte[] Data, long CmdPtr, bool Domain) : this() { + Logging.Ipc(Data, CmdPtr, Domain); + using (MemoryStream MS = new MemoryStream(Data)) { BinaryReader Reader = new BinaryReader(MS); diff --git a/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs b/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs deleted file mode 100644 index 0d15db60a..000000000 --- a/Ryujinx.Core/OsHle/IpcServices/ErrorModule.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Ryujinx.Core.OsHle.IpcServices -{ - enum ErrorModule - { - Fs = 2, - } -} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs b/Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Acc/IManagerForApplication.cs rename to Ryujinx.Core/OsHle/Services/Acc/IManagerForApplication.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs b/Ryujinx.Core/OsHle/Services/Acc/IProfile.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Acc/IProfile.cs rename to Ryujinx.Core/OsHle/Services/Acc/IProfile.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs b/Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Acc/ServiceAcc.cs rename to Ryujinx.Core/OsHle/Services/Acc/ServiceAcc.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs b/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs similarity index 85% rename from Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs rename to Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs index 30020c1d8..6c5beeb3e 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationFunctions.cs +++ b/Ryujinx.Core/OsHle/Services/Am/IApplicationFunctions.cs @@ -1,4 +1,5 @@ using Ryujinx.Core.OsHle.Ipc; +using System; using System.Collections.Generic; using System.IO; @@ -19,6 +20,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am { 1, PopLaunchParameter }, { 20, EnsureSaveData }, { 21, GetDesiredLanguage }, + { 22, SetTerminateResult }, { 40, NotifyRunning } }; } @@ -52,6 +54,18 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am return 0; } + public long SetTerminateResult(ServiceCtx Context) + { + int ErrorCode = Context.RequestData.ReadInt32(); + + int Module = ErrorCode & 0xFF; + int Description = (ErrorCode >> 9) & 0xFFF; + + Logging.Info($"({(ErrorModule)Module}){2000 + Module}-{Description}"); + + return 0; + } + public long NotifyRunning(ServiceCtx Context) { Context.ResponseData.Write(1); diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs b/Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IApplicationProxy.cs rename to Ryujinx.Core/OsHle/Services/Am/IApplicationProxy.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs b/Ryujinx.Core/OsHle/Services/Am/IAudioController.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IAudioController.cs rename to Ryujinx.Core/OsHle/Services/Am/IAudioController.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs b/Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/ICommonStateGetter.cs rename to Ryujinx.Core/OsHle/Services/Am/ICommonStateGetter.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs b/Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IDebugFunctions.cs rename to Ryujinx.Core/OsHle/Services/Am/IDebugFunctions.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs b/Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IDisplayController.cs rename to Ryujinx.Core/OsHle/Services/Am/IDisplayController.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs b/Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/ILibraryAppletCreator.cs rename to Ryujinx.Core/OsHle/Services/Am/ILibraryAppletCreator.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs b/Ryujinx.Core/OsHle/Services/Am/ISelfController.cs similarity index 82% rename from Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs rename to Ryujinx.Core/OsHle/Services/Am/ISelfController.cs index 90ddd54b8..403e4072d 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Am/ISelfController.cs +++ b/Ryujinx.Core/OsHle/Services/Am/ISelfController.cs @@ -13,14 +13,21 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am { m_Commands = new Dictionary() { + { 1, Exit }, { 10, SetScreenShotPermission }, { 11, SetOperationModeChangedNotification }, { 12, SetPerformanceModeChangedNotification }, { 13, SetFocusHandlingMode }, + { 14, SetRestartMessageEnabled }, { 16, SetOutOfFocusSuspendingEnabled } }; } + public long Exit(ServiceCtx Context) + { + return 0; + } + public long SetScreenShotPermission(ServiceCtx Context) { bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; @@ -51,6 +58,13 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am return 0; } + public long SetRestartMessageEnabled(ServiceCtx Context) + { + bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; + + return 0; + } + public long SetOutOfFocusSuspendingEnabled(ServiceCtx Context) { bool Enable = Context.RequestData.ReadByte() != 0 ? true : false; diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs b/Ryujinx.Core/OsHle/Services/Am/IStorage.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IStorage.cs rename to Ryujinx.Core/OsHle/Services/Am/IStorage.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs b/Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IStorageAccessor.cs rename to Ryujinx.Core/OsHle/Services/Am/IStorageAccessor.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs b/Ryujinx.Core/OsHle/Services/Am/IWindowController.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/IWindowController.cs rename to Ryujinx.Core/OsHle/Services/Am/IWindowController.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Am/ServiceAppletOE.cs rename to Ryujinx.Core/OsHle/Services/Am/ServiceAppletOE.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs b/Ryujinx.Core/OsHle/Services/Apm/ISession.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Apm/ISession.cs rename to Ryujinx.Core/OsHle/Services/Apm/ISession.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs b/Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Apm/ServiceApm.cs rename to Ryujinx.Core/OsHle/Services/Apm/ServiceApm.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Aud/IAudioOut.cs rename to Ryujinx.Core/OsHle/Services/Aud/IAudioOut.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs b/Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Aud/IAudioRenderer.cs rename to Ryujinx.Core/OsHle/Services/Aud/IAudioRenderer.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudOut.cs rename to Ryujinx.Core/OsHle/Services/Aud/ServiceAudOut.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs b/Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Aud/ServiceAudRen.cs rename to Ryujinx.Core/OsHle/Services/Aud/ServiceAudRen.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs b/Ryujinx.Core/OsHle/Services/ErrorCode.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/ErrorCode.cs rename to Ryujinx.Core/OsHle/Services/ErrorCode.cs diff --git a/Ryujinx.Core/OsHle/Services/ErrorModule.cs b/Ryujinx.Core/OsHle/Services/ErrorModule.cs new file mode 100644 index 000000000..78af6195d --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/ErrorModule.cs @@ -0,0 +1,63 @@ +namespace Ryujinx.Core.OsHle.IpcServices +{ + enum ErrorModule + { + Kernel = 1, + Fs = 2, + Nvidia_TransferMemory = 3, + Ncm = 5, + Dd = 6, + Lr = 8, + Loader = 9, + IPC_Command_Interface = 10, + IPC = 11, + Pm = 15, + Ns = 16, + Htc = 18, + Sm = 21, + RO_Userland = 22, + SdMmc = 24, + Spl = 26, + Ethc = 100, + I2C = 101, + Settings = 105, + Nifm = 110, + Display = 114, + Ntc = 116, + Fdm = 117, + Pcie = 120, + Friends = 121, + SSL = 123, + Account = 124, + Mii = 126, + Am = 128, + Play_Report = 129, + Pcv = 133, + Omm = 134, + Nim = 137, + Psc = 138, + Usb = 140, + Nsd = 141, + Btm = 143, + Erpt = 147, + Apm = 148, + Audio = 153, + Npns = 154, + Arp = 157, + Boot = 158, + Nfc = 161, + Userland_Assert = 162, + Userland_Crash = 168, + Hid = 203, + Capture = 206, + Libnx = 345, + Homebrew_ABI = 346, + Homebrew_Loader = 347, + libnx_Nvidia_Errors = 348, + Tc = 651, + General_Web_Applet = 800, + Wifi_Web_Auth_Applet = 809, + Whitelisted_Applet = 810, + ShopN = 811 + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs b/Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Friend/IFriendService.cs rename to Ryujinx.Core/OsHle/Services/Friend/IFriendService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs b/Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Friend/ServiceFriend.cs rename to Ryujinx.Core/OsHle/Services/Friend/ServiceFriend.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs b/Ryujinx.Core/OsHle/Services/FspSrv/FsErr.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/FsErr.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/FsErr.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/IDirectory.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/IDirectory.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/IFile.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/IFile.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/IFileSystem.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/IFileSystem.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs b/Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/IStorage.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/IStorage.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/FspSrv/ServiceFspSrv.cs rename to Ryujinx.Core/OsHle/Services/FspSrv/ServiceFspSrv.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs b/Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs similarity index 63% rename from Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs rename to Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs index 020e8e7e6..f6596f429 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Hid/IActiveVibrationDeviceList.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/IActiveVibrationDeviceList.cs @@ -11,7 +11,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid public IActiveApplicationDeviceList() { - m_Commands = new Dictionary() { }; + m_Commands = new Dictionary() + { + { 0, ActivateVibrationDevice } + }; + } + + public long ActivateVibrationDevice(ServiceCtx Context) + { + int VibrationDeviceHandle = Context.RequestData.ReadInt32(); + + return 0; } } } \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs b/Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Hid/IAppletResource.cs rename to Ryujinx.Core/OsHle/Services/Hid/IAppletResource.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs similarity index 89% rename from Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs rename to Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs index 5cca9319e..b0e5f44e2 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Hid/ServiceHid.cs +++ b/Ryujinx.Core/OsHle/Services/Hid/ServiceHid.cs @@ -24,6 +24,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid { 103, ActivateNpad }, { 120, SetNpadJoyHoldType }, { 121, GetNpadJoyHoldType }, + { 200, GetVibrationDeviceInfo }, { 203, CreateActiveVibrationDeviceList }, }; } @@ -88,6 +89,15 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid return 0; } + public long GetVibrationDeviceInfo(ServiceCtx Context) + { + int VibrationDeviceHandle = Context.RequestData.ReadInt32(); + + Context.ResponseData.Write(0L); //VibrationDeviceInfoForIpc + + return 0; + } + public long CreateActiveVibrationDeviceList(ServiceCtx Context) { MakeObject(Context, new IActiveApplicationDeviceList()); diff --git a/Ryujinx.Core/OsHle/IpcServices/IIpcService.cs b/Ryujinx.Core/OsHle/Services/IIpcService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/IIpcService.cs rename to Ryujinx.Core/OsHle/Services/IIpcService.cs diff --git a/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs new file mode 100644 index 000000000..5ee097b6f --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Lm/ILogger.cs @@ -0,0 +1,143 @@ +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace Ryujinx.Core.OsHle.IpcServices.Lm +{ + class ILogger : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + public ILogger() + { + m_Commands = new Dictionary() + { + { 0, Log } + }; + } + + enum Flags + { + Padding, + IsHead, + IsTail + } + + enum Severity + { + Trace, + Info, + Warning, + Error, + Critical + } + + enum Field + { + Padding, + Skip, + Message, + Line, + Filename, + Function, + Module, + Thread + } + + public long Log(ServiceCtx Context) + { + long BufferPosition = Context.Request.PtrBuff[0].Position; + long BufferLen = Context.Request.PtrBuff[0].Size; + + byte[] LogBuffer = AMemoryHelper.ReadBytes(Context.Memory, BufferPosition, (int)BufferLen); + + MemoryStream LogMessage = new MemoryStream(LogBuffer); + BinaryReader bReader = new BinaryReader(LogMessage); + + //Header reading. + long Pid = bReader.ReadInt64(); + long ThreadCxt = bReader.ReadInt64(); + int Infos = bReader.ReadInt32(); + int PayloadLen = bReader.ReadInt32(); + + int iFlags = Infos & 0xFFFF; + int iSeverity = (Infos >> 17) & 0x7F; + int iVerbosity = (Infos >> 25) & 0x7F; + + //ToDo: For now we don't care about Head or Tail Log. + bool IsHeadLog = Convert.ToBoolean(iFlags & (int)Flags.IsHead); + bool IsTailLog = Convert.ToBoolean(iFlags & (int)Flags.IsTail); + + string LogString = "nn::diag::detail::LogImpl()" + Environment.NewLine + Environment.NewLine + + "Header:" + Environment.NewLine + + $" Pid: {Pid}" + Environment.NewLine + + $" ThreadContext: {ThreadCxt}" + Environment.NewLine + + $" Flags: {IsHeadLog}/{IsTailLog}" + Environment.NewLine + + $" Severity: {Enum.GetName(typeof(Severity), iSeverity)}" + Environment.NewLine + + $" Verbosity: {iVerbosity}"; + + LogString += Environment.NewLine + Environment.NewLine + "Message:" + Environment.NewLine; + + string StrMessage = "", StrLine = "", StrFilename = "", StrFunction = "", + StrModule = "", StrThread = ""; + + do + { + byte FieldType = bReader.ReadByte(); + byte FieldSize = bReader.ReadByte(); + + if ((Field)FieldType != Field.Skip || FieldSize != 0) + { + byte[] Message = bReader.ReadBytes(FieldSize); + switch ((Field)FieldType) + { + case Field.Message: + StrMessage = Encoding.UTF8.GetString(Message); + break; + + case Field.Line: + StrLine = BitConverter.ToInt32(Message, 0).ToString(); + break; + + case Field.Filename: + StrFilename = Encoding.UTF8.GetString(Message); + break; + + case Field.Function: + StrFunction = Encoding.UTF8.GetString(Message); + break; + + case Field.Module: + StrModule = Encoding.UTF8.GetString(Message); + break; + + case Field.Thread: + StrThread = Encoding.UTF8.GetString(Message); + break; + } + } + + } + while (LogMessage.Position != PayloadLen + 0x18); // 0x18 - Size of Header LogMessage. + + LogString += StrModule + " > " + StrThread + ": " + StrFilename + "@" + StrFunction + "(" + StrLine + ") '" + StrMessage + "'" + Environment.NewLine; + + switch((Severity)iSeverity) + { + case Severity.Trace: Logging.Trace(LogString); break; + case Severity.Info: Logging.Info(LogString); break; + case Severity.Warning: Logging.Warn(LogString); break; + case Severity.Error: Logging.Error(LogString); break; + case Severity.Critical: Logging.Fatal(LogString); break; + } + + return 0; + } + } +} + \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs b/Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs similarity index 85% rename from Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs rename to Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs index e665253c1..ca3fe35e8 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Lm/ServiceLm.cs +++ b/Ryujinx.Core/OsHle/Services/Lm/ServiceLm.cs @@ -1,6 +1,8 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; +using static Ryujinx.Core.OsHle.IpcServices.ObjHelper; + namespace Ryujinx.Core.OsHle.IpcServices.Lm { class ServiceLm : IIpcService @@ -21,6 +23,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Lm { Context.Session.Initialize(); + MakeObject(Context, new ILogger()); + return 0; } } diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs similarity index 71% rename from Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs rename to Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs index 9875fa2fc..720baa6ec 100644 --- a/Ryujinx.Core/OsHle/IpcServices/Time/ITimeZoneService.cs +++ b/Ryujinx.Core/OsHle/Services/Ns/ServiceNs.cs @@ -1,19 +1,19 @@ using Ryujinx.Core.OsHle.Ipc; using System.Collections.Generic; -namespace Ryujinx.Core.OsHle.IpcServices.Time +namespace Ryujinx.Core.OsHle.IpcServices.Ns { - class ITimeZoneService : IIpcService + class ServiceNs : IIpcService { private Dictionary m_Commands; public IReadOnlyDictionary Commands => m_Commands; - public ITimeZoneService() + public ServiceNs() { m_Commands = new Dictionary() { - //... + //{ 1, Function } }; } } diff --git a/Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/NvServices/ServiceNvDrv.cs rename to Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs b/Ryujinx.Core/OsHle/Services/ObjHelper.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/ObjHelper.cs rename to Ryujinx.Core/OsHle/Services/ObjHelper.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs b/Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Pctl/IParentalControlService.cs rename to Ryujinx.Core/OsHle/Services/Pctl/IParentalControlService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs b/Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Pctl/ServicePctl.cs rename to Ryujinx.Core/OsHle/Services/Pctl/ServicePctl.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs b/Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Pl/ServicePl.cs rename to Ryujinx.Core/OsHle/Services/Pl/ServicePl.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs similarity index 90% rename from Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs rename to Ryujinx.Core/OsHle/Services/ServiceFactory.cs index e9613050f..54fa38ab7 100644 --- a/Ryujinx.Core/OsHle/IpcServices/ServiceFactory.cs +++ b/Ryujinx.Core/OsHle/Services/ServiceFactory.cs @@ -6,6 +6,7 @@ using Ryujinx.Core.OsHle.IpcServices.Friend; using Ryujinx.Core.OsHle.IpcServices.FspSrv; using Ryujinx.Core.OsHle.IpcServices.Hid; using Ryujinx.Core.OsHle.IpcServices.Lm; +using Ryujinx.Core.OsHle.IpcServices.Ns; using Ryujinx.Core.OsHle.IpcServices.NvServices; using Ryujinx.Core.OsHle.IpcServices.Pctl; using Ryujinx.Core.OsHle.IpcServices.Pl; @@ -24,6 +25,7 @@ namespace Ryujinx.Core.OsHle.IpcServices switch (Name) { case "acc:u0": return new ServiceAcc(); + case "aoc:u": return new ServiceNs(); case "apm": return new ServiceApm(); case "apm:p": return new ServiceApm(); case "appletOE": return new ServiceAppletOE(); @@ -42,6 +44,8 @@ namespace Ryujinx.Core.OsHle.IpcServices case "time:s": return new ServiceTime(); case "time:u": return new ServiceTime(); case "vi:m": return new ServiceVi(); + case "vi:s": return new ServiceVi(); + case "vi:u": return new ServiceVi(); } throw new NotImplementedException(Name); diff --git a/Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs b/Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Set/ServiceSet.cs rename to Ryujinx.Core/OsHle/Services/Set/ServiceSet.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs b/Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Sm/ServiceSm.cs rename to Ryujinx.Core/OsHle/Services/Sm/ServiceSm.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs b/Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Time/ISteadyClock.cs rename to Ryujinx.Core/OsHle/Services/Time/ISteadyClock.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs b/Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Time/ISystemClock.cs rename to Ryujinx.Core/OsHle/Services/Time/ISystemClock.cs diff --git a/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs b/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs new file mode 100644 index 000000000..d220824c5 --- /dev/null +++ b/Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs @@ -0,0 +1,69 @@ +using Ryujinx.Core.OsHle.Ipc; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Core.OsHle.IpcServices.Time +{ + class ITimeZoneService : IIpcService + { + private Dictionary m_Commands; + + public IReadOnlyDictionary Commands => m_Commands; + + private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local); + + public ITimeZoneService() + { + m_Commands = new Dictionary() + { + { 101, ToCalendarTimeWithMyRule } + }; + } + + //(nn::time::PosixTime)-> (nn::time::CalendarTime, nn::time::sf::CalendarAdditionalInfo) + public long ToCalendarTimeWithMyRule(ServiceCtx Context) + { + long PosixTime = Context.RequestData.ReadInt64(); + + Epoch = Epoch.AddSeconds(PosixTime).ToLocalTime(); + + /* + struct CalendarTime { + u16_le year; + u8 month; // Starts at 1 + u8 day; // Starts at 1 + u8 hour; + u8 minute; + u8 second; + INSERT_PADDING_BYTES(1); + }; + */ + Context.ResponseData.Write((short)Epoch.Year); + Context.ResponseData.Write((byte)Epoch.Month); + Context.ResponseData.Write((byte)Epoch.Day); + Context.ResponseData.Write((byte)Epoch.Hour); + Context.ResponseData.Write((byte)Epoch.Minute); + Context.ResponseData.Write((byte)Epoch.Second); + Context.ResponseData.Write((byte)0); + + /* Thanks to TuxSH + struct CalendarAdditionalInfo { + u32 tm_wday; //day of week [0,6] (Sunday = 0) + s32 tm_yday; //day of year [0,365] + struct timezone { + char[8] tz_name; + bool isDaylightSavingTime; + s32 utcOffsetSeconds; + }; + }; + */ + Context.ResponseData.Write((int)Epoch.DayOfWeek); + Context.ResponseData.Write(Epoch.DayOfYear); + Context.ResponseData.Write(new byte[8]); + Context.ResponseData.Write(Convert.ToByte(Epoch.IsDaylightSavingTime())); + Context.ResponseData.Write(0); + + return 0; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs b/Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Time/ServiceTime.cs rename to Ryujinx.Core/OsHle/Services/Time/ServiceTime.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs b/Ryujinx.Core/OsHle/Services/Time/SystemClockType.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Time/SystemClockType.cs rename to Ryujinx.Core/OsHle/Services/Time/SystemClockType.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs b/Ryujinx.Core/OsHle/Services/Vi/GbpBuffer.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Android/GbpBuffer.cs rename to Ryujinx.Core/OsHle/Services/Vi/GbpBuffer.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/IApplicationDisplayService.cs rename to Ryujinx.Core/OsHle/Services/Vi/IApplicationDisplayService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs b/Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/IHOSBinderDriver.cs rename to Ryujinx.Core/OsHle/Services/Vi/IHOSBinderDriver.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/IManagerDisplayService.cs rename to Ryujinx.Core/OsHle/Services/Vi/IManagerDisplayService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs b/Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/ISystemDisplayService.cs rename to Ryujinx.Core/OsHle/Services/Vi/ISystemDisplayService.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs b/Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Android/NvFlinger.cs rename to Ryujinx.Core/OsHle/Services/Vi/NvFlinger.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs b/Ryujinx.Core/OsHle/Services/Vi/Parcel.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Android/Parcel.cs rename to Ryujinx.Core/OsHle/Services/Vi/Parcel.cs diff --git a/Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs b/Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs similarity index 100% rename from Ryujinx.Core/OsHle/IpcServices/Vi/ServiceVi.cs rename to Ryujinx.Core/OsHle/Services/Vi/ServiceVi.cs diff --git a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs index 60af1e11d..c5b6da04b 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcHandler.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcHandler.cs @@ -30,6 +30,8 @@ namespace Ryujinx.Core.OsHle.Svc { 0x09, SvcStartThread }, { 0x0b, SvcSleepThread }, { 0x0c, SvcGetThreadPriority }, + { 0x0d, SvcSetThreadPriority }, + { 0x0f, SvcSetThreadCoreMask }, { 0x13, SvcMapSharedMemory }, { 0x14, SvcUnmapSharedMemory }, { 0x15, SvcCreateTransferMemory }, @@ -44,6 +46,7 @@ namespace Ryujinx.Core.OsHle.Svc { 0x1f, SvcConnectToNamedPort }, { 0x21, SvcSendSyncRequest }, { 0x22, SvcSendSyncRequestWithUserBuffer }, + { 0x25, SvcGetThreadId }, { 0x26, SvcBreak }, { 0x27, SvcOutputDebugString }, { 0x29, SvcGetInfo } diff --git a/Ryujinx.Core/OsHle/Svc/SvcThread.cs b/Ryujinx.Core/OsHle/Svc/SvcThread.cs index a635edb15..cc0f980be 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcThread.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcThread.cs @@ -81,5 +81,44 @@ namespace Ryujinx.Core.OsHle.Svc //TODO: Error codes. } + + private void SvcSetThreadPriority(AThreadState ThreadState) + { + int Handle = (int)ThreadState.X1; + int Prio = (int)ThreadState.X0; + + HThread Thread = Ns.Os.Handles.GetData(Handle); + + if (Thread != null) + { + Thread.Priority = Prio; + + ThreadState.X0 = (int)SvcResult.Success; + } + + //TODO: Error codes. + } + + private void SvcSetThreadCoreMask(AThreadState ThreadState) + { + ThreadState.X0 = (int)SvcResult.Success; + + //TODO: Error codes. + } + + private void SvcGetThreadId(AThreadState ThreadState) + { + int Handle = (int)ThreadState.X0; + + HThread Thread = Ns.Os.Handles.GetData(Handle); + + if (Thread != null) + { + ThreadState.X1 = (ulong)Thread.ThreadId; + ThreadState.X0 = (int)SvcResult.Success; + } + + //TODO: Error codes. + } } } \ No newline at end of file diff --git a/Ryujinx/Ryujinx.conf b/Ryujinx/Ryujinx.conf index 7b9af87ac..e8effac1d 100644 --- a/Ryujinx/Ryujinx.conf +++ b/Ryujinx/Ryujinx.conf @@ -16,6 +16,9 @@ Logging_Enable_Error = true #Enabled print fatal logs Logging_Enable_Fatal = true +#Enabled print Ipc logs +Logging_Enable_Ipc = false + #Saved logs into Ryujinx.log Logging_Enable_LogFile = false