forked from Mirror/Ryujinx
Implement many objects, improve logging. (#42)
* Implement many objects, improve logging. Change and rename folders of Services Add Logging of IpcMessage. Add "lm" Log Service. Parse Errors of SetTerminateResult Add Svc Calls. Add many object implementations. * Corrections Forgotten Debug Conf * Corrections 2 * Corrections 3 * Corrections 4
This commit is contained in:
parent
fba0bf8732
commit
e174100474
69 changed files with 660 additions and 27 deletions
|
@ -26,6 +26,10 @@
|
||||||
|
|
||||||
Enable the Fatal Logging (Enabled in Debug recommanded).
|
Enable the Fatal Logging (Enabled in Debug recommanded).
|
||||||
|
|
||||||
|
- `Logging_Enable_Ipc` *(bool)*
|
||||||
|
|
||||||
|
Enable the Ipc Message Logging.
|
||||||
|
|
||||||
- `Logging_Enable_LogFile` *(bool)*
|
- `Logging_Enable_LogFile` *(bool)*
|
||||||
|
|
||||||
Enable writing the logging inside a Ryujinx.log file.
|
Enable writing the logging inside a Ryujinx.log file.
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace Ryujinx.Core
|
||||||
public static bool LoggingEnableWarn { get; private set; }
|
public static bool LoggingEnableWarn { get; private set; }
|
||||||
public static bool LoggingEnableError { get; private set; }
|
public static bool LoggingEnableError { get; private set; }
|
||||||
public static bool LoggingEnableFatal { 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 bool LoggingEnableLogFile { get; private set; }
|
||||||
|
|
||||||
public static JoyCon FakeJoyCon { 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"));
|
LoggingEnableWarn = Convert.ToBoolean(Parser.Value("Logging_Enable_Warn"));
|
||||||
LoggingEnableError = Convert.ToBoolean(Parser.Value("Logging_Enable_Error"));
|
LoggingEnableError = Convert.ToBoolean(Parser.Value("Logging_Enable_Error"));
|
||||||
LoggingEnableFatal = Convert.ToBoolean(Parser.Value("Logging_Enable_Fatal"));
|
LoggingEnableFatal = Convert.ToBoolean(Parser.Value("Logging_Enable_Fatal"));
|
||||||
|
LoggingEnableIpc = Convert.ToBoolean(Parser.Value("Logging_Enable_Ipc"));
|
||||||
LoggingEnableLogFile = Convert.ToBoolean(Parser.Value("Logging_Enable_LogFile"));
|
LoggingEnableLogFile = Convert.ToBoolean(Parser.Value("Logging_Enable_LogFile"));
|
||||||
|
|
||||||
FakeJoyCon = new JoyCon
|
FakeJoyCon = new JoyCon
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using System;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Ryujinx.Core
|
namespace Ryujinx.Core
|
||||||
{
|
{
|
||||||
|
@ -9,13 +11,14 @@ namespace Ryujinx.Core
|
||||||
private static Stopwatch ExecutionTime = new Stopwatch();
|
private static Stopwatch ExecutionTime = new Stopwatch();
|
||||||
private const string LogFileName = "Ryujinx.log";
|
private const string LogFileName = "Ryujinx.log";
|
||||||
|
|
||||||
public static bool EnableInfo = Config.LoggingEnableInfo;
|
private static bool EnableInfo = Config.LoggingEnableInfo;
|
||||||
public static bool EnableTrace = Config.LoggingEnableTrace;
|
private static bool EnableTrace = Config.LoggingEnableTrace;
|
||||||
public static bool EnableDebug = Config.LoggingEnableDebug;
|
private static bool EnableDebug = Config.LoggingEnableDebug;
|
||||||
public static bool EnableWarn = Config.LoggingEnableWarn;
|
private static bool EnableWarn = Config.LoggingEnableWarn;
|
||||||
public static bool EnableError = Config.LoggingEnableError;
|
private static bool EnableError = Config.LoggingEnableError;
|
||||||
public static bool EnableFatal = Config.LoggingEnableFatal;
|
private static bool EnableFatal = Config.LoggingEnableFatal;
|
||||||
public static bool EnableLogFile = Config.LoggingEnableLogFile;
|
private static bool EnableIpc = Config.LoggingEnableIpc;
|
||||||
|
private static bool EnableLogFile = Config.LoggingEnableLogFile;
|
||||||
|
|
||||||
static Logging()
|
static Logging()
|
||||||
{
|
{
|
||||||
|
@ -128,5 +131,79 @@ namespace Ryujinx.Core
|
||||||
LogFile(Text);
|
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 "<null>";
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle.Handles
|
||||||
public AThread Thread { get; private set; }
|
public AThread Thread { get; private set; }
|
||||||
|
|
||||||
public int ProcessorId { 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;
|
public int ThreadId => Thread.ThreadId;
|
||||||
|
|
||||||
|
|
179
Ryujinx.Core/OsHle/Ipc/IpcLog.cs
Normal file
179
Ryujinx.Core/OsHle/Ipc/IpcLog.cs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,8 @@ namespace Ryujinx.Core.OsHle.Ipc
|
||||||
|
|
||||||
public IpcMessage(byte[] Data, long CmdPtr, bool Domain) : this()
|
public IpcMessage(byte[] Data, long CmdPtr, bool Domain) : this()
|
||||||
{
|
{
|
||||||
|
Logging.Ipc(Data, CmdPtr, Domain);
|
||||||
|
|
||||||
using (MemoryStream MS = new MemoryStream(Data))
|
using (MemoryStream MS = new MemoryStream(Data))
|
||||||
{
|
{
|
||||||
BinaryReader Reader = new BinaryReader(MS);
|
BinaryReader Reader = new BinaryReader(MS);
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices
|
|
||||||
{
|
|
||||||
enum ErrorModule
|
|
||||||
{
|
|
||||||
Fs = 2,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{ 1, PopLaunchParameter },
|
{ 1, PopLaunchParameter },
|
||||||
{ 20, EnsureSaveData },
|
{ 20, EnsureSaveData },
|
||||||
{ 21, GetDesiredLanguage },
|
{ 21, GetDesiredLanguage },
|
||||||
|
{ 22, SetTerminateResult },
|
||||||
{ 40, NotifyRunning }
|
{ 40, NotifyRunning }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -52,6 +54,18 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
return 0;
|
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)
|
public long NotifyRunning(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
Context.ResponseData.Write(1);
|
Context.ResponseData.Write(1);
|
|
@ -13,14 +13,21 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
{
|
{
|
||||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||||
{
|
{
|
||||||
|
{ 1, Exit },
|
||||||
{ 10, SetScreenShotPermission },
|
{ 10, SetScreenShotPermission },
|
||||||
{ 11, SetOperationModeChangedNotification },
|
{ 11, SetOperationModeChangedNotification },
|
||||||
{ 12, SetPerformanceModeChangedNotification },
|
{ 12, SetPerformanceModeChangedNotification },
|
||||||
{ 13, SetFocusHandlingMode },
|
{ 13, SetFocusHandlingMode },
|
||||||
|
{ 14, SetRestartMessageEnabled },
|
||||||
{ 16, SetOutOfFocusSuspendingEnabled }
|
{ 16, SetOutOfFocusSuspendingEnabled }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long Exit(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public long SetScreenShotPermission(ServiceCtx Context)
|
public long SetScreenShotPermission(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
||||||
|
@ -51,6 +58,13 @@ namespace Ryujinx.Core.OsHle.IpcServices.Am
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long SetRestartMessageEnabled(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public long SetOutOfFocusSuspendingEnabled(ServiceCtx Context)
|
public long SetOutOfFocusSuspendingEnabled(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
63
Ryujinx.Core/OsHle/Services/ErrorModule.cs
Normal file
63
Ryujinx.Core/OsHle/Services/ErrorModule.cs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,17 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
||||||
|
|
||||||
public IActiveApplicationDeviceList()
|
public IActiveApplicationDeviceList()
|
||||||
{
|
{
|
||||||
m_Commands = new Dictionary<int, ServiceProcessRequest>() { };
|
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||||
|
{
|
||||||
|
{ 0, ActivateVibrationDevice }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public long ActivateVibrationDevice(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
int VibrationDeviceHandle = Context.RequestData.ReadInt32();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,6 +24,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
||||||
{ 103, ActivateNpad },
|
{ 103, ActivateNpad },
|
||||||
{ 120, SetNpadJoyHoldType },
|
{ 120, SetNpadJoyHoldType },
|
||||||
{ 121, GetNpadJoyHoldType },
|
{ 121, GetNpadJoyHoldType },
|
||||||
|
{ 200, GetVibrationDeviceInfo },
|
||||||
{ 203, CreateActiveVibrationDeviceList },
|
{ 203, CreateActiveVibrationDeviceList },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -88,6 +89,15 @@ namespace Ryujinx.Core.OsHle.IpcServices.Hid
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long GetVibrationDeviceInfo(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
int VibrationDeviceHandle = Context.RequestData.ReadInt32();
|
||||||
|
|
||||||
|
Context.ResponseData.Write(0L); //VibrationDeviceInfoForIpc
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public long CreateActiveVibrationDeviceList(ServiceCtx Context)
|
public long CreateActiveVibrationDeviceList(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
MakeObject(Context, new IActiveApplicationDeviceList());
|
MakeObject(Context, new IActiveApplicationDeviceList());
|
143
Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
Normal file
143
Ryujinx.Core/OsHle/Services/Lm/ILogger.cs
Normal file
|
@ -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<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
|
public ILogger()
|
||||||
|
{
|
||||||
|
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||||
|
{
|
||||||
|
{ 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using static Ryujinx.Core.OsHle.IpcServices.ObjHelper;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Lm
|
namespace Ryujinx.Core.OsHle.IpcServices.Lm
|
||||||
{
|
{
|
||||||
class ServiceLm : IIpcService
|
class ServiceLm : IIpcService
|
||||||
|
@ -21,6 +23,8 @@ namespace Ryujinx.Core.OsHle.IpcServices.Lm
|
||||||
{
|
{
|
||||||
Context.Session.Initialize();
|
Context.Session.Initialize();
|
||||||
|
|
||||||
|
MakeObject(Context, new ILogger());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,19 @@
|
||||||
using Ryujinx.Core.OsHle.Ipc;
|
using Ryujinx.Core.OsHle.Ipc;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.Core.OsHle.IpcServices.Time
|
namespace Ryujinx.Core.OsHle.IpcServices.Ns
|
||||||
{
|
{
|
||||||
class ITimeZoneService : IIpcService
|
class ServiceNs : IIpcService
|
||||||
{
|
{
|
||||||
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
private Dictionary<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
public ITimeZoneService()
|
public ServiceNs()
|
||||||
{
|
{
|
||||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||||
{
|
{
|
||||||
//...
|
//{ 1, Function }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@ using Ryujinx.Core.OsHle.IpcServices.Friend;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.FspSrv;
|
using Ryujinx.Core.OsHle.IpcServices.FspSrv;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.Hid;
|
using Ryujinx.Core.OsHle.IpcServices.Hid;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.Lm;
|
using Ryujinx.Core.OsHle.IpcServices.Lm;
|
||||||
|
using Ryujinx.Core.OsHle.IpcServices.Ns;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
using Ryujinx.Core.OsHle.IpcServices.NvServices;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.Pctl;
|
using Ryujinx.Core.OsHle.IpcServices.Pctl;
|
||||||
using Ryujinx.Core.OsHle.IpcServices.Pl;
|
using Ryujinx.Core.OsHle.IpcServices.Pl;
|
||||||
|
@ -24,6 +25,7 @@ namespace Ryujinx.Core.OsHle.IpcServices
|
||||||
switch (Name)
|
switch (Name)
|
||||||
{
|
{
|
||||||
case "acc:u0": return new ServiceAcc();
|
case "acc:u0": return new ServiceAcc();
|
||||||
|
case "aoc:u": return new ServiceNs();
|
||||||
case "apm": return new ServiceApm();
|
case "apm": return new ServiceApm();
|
||||||
case "apm:p": return new ServiceApm();
|
case "apm:p": return new ServiceApm();
|
||||||
case "appletOE": return new ServiceAppletOE();
|
case "appletOE": return new ServiceAppletOE();
|
||||||
|
@ -42,6 +44,8 @@ namespace Ryujinx.Core.OsHle.IpcServices
|
||||||
case "time:s": return new ServiceTime();
|
case "time:s": return new ServiceTime();
|
||||||
case "time:u": return new ServiceTime();
|
case "time:u": return new ServiceTime();
|
||||||
case "vi:m": return new ServiceVi();
|
case "vi:m": return new ServiceVi();
|
||||||
|
case "vi:s": return new ServiceVi();
|
||||||
|
case "vi:u": return new ServiceVi();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotImplementedException(Name);
|
throw new NotImplementedException(Name);
|
69
Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs
Normal file
69
Ryujinx.Core/OsHle/Services/Time/ITimeZoneService.cs
Normal file
|
@ -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<int, ServiceProcessRequest> m_Commands;
|
||||||
|
|
||||||
|
public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
|
||||||
|
|
||||||
|
private static DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
|
||||||
|
|
||||||
|
public ITimeZoneService()
|
||||||
|
{
|
||||||
|
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||||
|
{
|
||||||
|
{ 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,8 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{ 0x09, SvcStartThread },
|
{ 0x09, SvcStartThread },
|
||||||
{ 0x0b, SvcSleepThread },
|
{ 0x0b, SvcSleepThread },
|
||||||
{ 0x0c, SvcGetThreadPriority },
|
{ 0x0c, SvcGetThreadPriority },
|
||||||
|
{ 0x0d, SvcSetThreadPriority },
|
||||||
|
{ 0x0f, SvcSetThreadCoreMask },
|
||||||
{ 0x13, SvcMapSharedMemory },
|
{ 0x13, SvcMapSharedMemory },
|
||||||
{ 0x14, SvcUnmapSharedMemory },
|
{ 0x14, SvcUnmapSharedMemory },
|
||||||
{ 0x15, SvcCreateTransferMemory },
|
{ 0x15, SvcCreateTransferMemory },
|
||||||
|
@ -44,6 +46,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{ 0x1f, SvcConnectToNamedPort },
|
{ 0x1f, SvcConnectToNamedPort },
|
||||||
{ 0x21, SvcSendSyncRequest },
|
{ 0x21, SvcSendSyncRequest },
|
||||||
{ 0x22, SvcSendSyncRequestWithUserBuffer },
|
{ 0x22, SvcSendSyncRequestWithUserBuffer },
|
||||||
|
{ 0x25, SvcGetThreadId },
|
||||||
{ 0x26, SvcBreak },
|
{ 0x26, SvcBreak },
|
||||||
{ 0x27, SvcOutputDebugString },
|
{ 0x27, SvcOutputDebugString },
|
||||||
{ 0x29, SvcGetInfo }
|
{ 0x29, SvcGetInfo }
|
||||||
|
|
|
@ -81,5 +81,44 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
//TODO: Error codes.
|
//TODO: Error codes.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SvcSetThreadPriority(AThreadState ThreadState)
|
||||||
|
{
|
||||||
|
int Handle = (int)ThreadState.X1;
|
||||||
|
int Prio = (int)ThreadState.X0;
|
||||||
|
|
||||||
|
HThread Thread = Ns.Os.Handles.GetData<HThread>(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<HThread>(Handle);
|
||||||
|
|
||||||
|
if (Thread != null)
|
||||||
|
{
|
||||||
|
ThreadState.X1 = (ulong)Thread.ThreadId;
|
||||||
|
ThreadState.X0 = (int)SvcResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Error codes.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -16,6 +16,9 @@ Logging_Enable_Error = true
|
||||||
#Enabled print fatal logs
|
#Enabled print fatal logs
|
||||||
Logging_Enable_Fatal = true
|
Logging_Enable_Fatal = true
|
||||||
|
|
||||||
|
#Enabled print Ipc logs
|
||||||
|
Logging_Enable_Ipc = false
|
||||||
|
|
||||||
#Saved logs into Ryujinx.log
|
#Saved logs into Ryujinx.log
|
||||||
Logging_Enable_LogFile = false
|
Logging_Enable_LogFile = false
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue