Implement OutputAccessLogToSdCard and expose an FS access log option (#700)
* Add OutputAccessLogToSdCard * Add config options for the FS access log
This commit is contained in:
parent
5c1bc52409
commit
350a3667f7
9 changed files with 136 additions and 20 deletions
|
@ -6,6 +6,8 @@ namespace Ryujinx.Common.Logging
|
||||||
Stub,
|
Stub,
|
||||||
Info,
|
Info,
|
||||||
Warning,
|
Warning,
|
||||||
Error
|
Error,
|
||||||
|
Guest,
|
||||||
|
AccessLog
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,12 @@ namespace Ryujinx.Common.Logging
|
||||||
m_EnabledLevels = new bool[Enum.GetNames(typeof(LogLevel)).Length];
|
m_EnabledLevels = new bool[Enum.GetNames(typeof(LogLevel)).Length];
|
||||||
m_EnabledClasses = new bool[Enum.GetNames(typeof(LogClass)).Length];
|
m_EnabledClasses = new bool[Enum.GetNames(typeof(LogClass)).Length];
|
||||||
|
|
||||||
m_EnabledLevels[(int)LogLevel.Stub] = true;
|
m_EnabledLevels[(int)LogLevel.Stub] = true;
|
||||||
m_EnabledLevels[(int)LogLevel.Info] = true;
|
m_EnabledLevels[(int)LogLevel.Info] = true;
|
||||||
m_EnabledLevels[(int)LogLevel.Warning] = true;
|
m_EnabledLevels[(int)LogLevel.Warning] = true;
|
||||||
m_EnabledLevels[(int)LogLevel.Error] = true;
|
m_EnabledLevels[(int)LogLevel.Error] = true;
|
||||||
|
m_EnabledLevels[(int)LogLevel.Guest] = true;
|
||||||
|
m_EnabledLevels[(int)LogLevel.AccessLog] = true;
|
||||||
|
|
||||||
for (int index = 0; index < m_EnabledClasses.Length; index++)
|
for (int index = 0; index < m_EnabledClasses.Length; index++)
|
||||||
{
|
{
|
||||||
|
@ -101,6 +103,16 @@ namespace Ryujinx.Common.Logging
|
||||||
Print(LogLevel.Stub, logClass, GetFormattedMessage(logClass, "Stubbed. " + message, caller), obj);
|
Print(LogLevel.Stub, logClass, GetFormattedMessage(logClass, "Stubbed. " + message, caller), obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void PrintGuest(LogClass logClass, string message, [CallerMemberName] string caller = "")
|
||||||
|
{
|
||||||
|
Print(LogLevel.Guest, logClass, GetFormattedMessage(logClass, message, caller));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PrintAccessLog(LogClass logClass, string message)
|
||||||
|
{
|
||||||
|
Print(LogLevel.AccessLog, logClass, message);
|
||||||
|
}
|
||||||
|
|
||||||
private static void Print(LogLevel logLevel, LogClass logClass, string message)
|
private static void Print(LogLevel logLevel, LogClass logClass, string message)
|
||||||
{
|
{
|
||||||
if (m_EnabledLevels[(int)logLevel] && m_EnabledClasses[(int)logClass])
|
if (m_EnabledLevels[(int)logLevel] && m_EnabledClasses[(int)logClass])
|
||||||
|
|
|
@ -105,6 +105,8 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
public IntegrityCheckLevel FsIntegrityCheckLevel { get; set; }
|
public IntegrityCheckLevel FsIntegrityCheckLevel { get; set; }
|
||||||
|
|
||||||
|
public int GlobalAccessLogMode { get; set; }
|
||||||
|
|
||||||
internal long HidBaseAddress { get; private set; }
|
internal long HidBaseAddress { get; private set; }
|
||||||
|
|
||||||
public Horizon(Switch device)
|
public Horizon(Switch device)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using LibHac;
|
using LibHac;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
using LibHac.Fs.NcaUtils;
|
using LibHac.Fs.NcaUtils;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.HLE.FileSystem;
|
using Ryujinx.HLE.FileSystem;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.Utilities;
|
using Ryujinx.HLE.Utilities;
|
||||||
|
@ -32,7 +33,8 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||||
{ 200, OpenDataStorageByCurrentProcess },
|
{ 200, OpenDataStorageByCurrentProcess },
|
||||||
{ 202, OpenDataStorageByDataId },
|
{ 202, OpenDataStorageByDataId },
|
||||||
{ 203, OpenPatchDataStorageByCurrentProcess },
|
{ 203, OpenPatchDataStorageByCurrentProcess },
|
||||||
{ 1005, GetGlobalAccessLogMode }
|
{ 1005, GetGlobalAccessLogMode },
|
||||||
|
{ 1006, OutputAccessLogToSdCard }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +210,20 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
|
||||||
// GetGlobalAccessLogMode() -> u32 logMode
|
// GetGlobalAccessLogMode() -> u32 logMode
|
||||||
public long GetGlobalAccessLogMode(ServiceCtx context)
|
public long GetGlobalAccessLogMode(ServiceCtx context)
|
||||||
{
|
{
|
||||||
context.ResponseData.Write(0);
|
int mode = context.Device.System.GlobalAccessLogMode;
|
||||||
|
|
||||||
|
context.ResponseData.Write(mode);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OutputAccessLogToSdCard(buffer<bytes, 5> log_text)
|
||||||
|
public long OutputAccessLogToSdCard(ServiceCtx context)
|
||||||
|
{
|
||||||
|
string message = ReadUtf8StringSend(context);
|
||||||
|
|
||||||
|
// FS ends each line with a newline. Remove it because Ryujinx logging adds its own newline
|
||||||
|
Logger.PrintAccessLog(LogClass.ServiceFs, message.TrimEnd('\n'));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,8 @@ namespace Ryujinx.HLE.HOS.Services.Lm
|
||||||
|
|
||||||
sb.AppendLine("Guest log:");
|
sb.AppendLine("Guest log:");
|
||||||
|
|
||||||
|
sb.AppendLine($" Log level: {(LmLogLevel)level}");
|
||||||
|
|
||||||
while (ms.Position < ms.Length)
|
while (ms.Position < ms.Length)
|
||||||
{
|
{
|
||||||
byte type = reader.ReadByte();
|
byte type = reader.ReadByte();
|
||||||
|
@ -86,14 +88,7 @@ namespace Ryujinx.HLE.HOS.Services.Lm
|
||||||
|
|
||||||
string text = sb.ToString();
|
string text = sb.ToString();
|
||||||
|
|
||||||
switch((LmLogLevel)level)
|
Logger.PrintGuest(LogClass.ServiceLm, text);
|
||||||
{
|
|
||||||
case LmLogLevel.Trace: Logger.PrintDebug (LogClass.ServiceLm, text); break;
|
|
||||||
case LmLogLevel.Info: Logger.PrintInfo (LogClass.ServiceLm, text); break;
|
|
||||||
case LmLogLevel.Warning: Logger.PrintWarning(LogClass.ServiceLm, text); break;
|
|
||||||
case LmLogLevel.Error: Logger.PrintError (LogClass.ServiceLm, text); break;
|
|
||||||
case LmLogLevel.Critical: Logger.PrintError (LogClass.ServiceLm, text); break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -72,5 +72,28 @@ namespace Ryujinx.HLE.Utilities
|
||||||
return Encoding.UTF8.GetString(ms.ToArray());
|
return Encoding.UTF8.GetString(ms.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string ReadUtf8StringSend(ServiceCtx context, int index = 0)
|
||||||
|
{
|
||||||
|
long position = context.Request.SendBuff[index].Position;
|
||||||
|
long size = context.Request.SendBuff[index].Size;
|
||||||
|
|
||||||
|
using (MemoryStream ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
while (size-- > 0)
|
||||||
|
{
|
||||||
|
byte value = context.Memory.ReadByte(position++);
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ms.WriteByte(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(ms.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
// Enable print error logs
|
// Enable print error logs
|
||||||
"logging_enable_error": true,
|
"logging_enable_error": true,
|
||||||
|
|
||||||
|
// Enable printing guest logs
|
||||||
|
"logging_enable_guest": true,
|
||||||
|
|
||||||
|
// Enable printing FS access logs. fs_global_access_log_mode must be 2 or 3
|
||||||
|
"logging_enable_fs_access_log": false,
|
||||||
|
|
||||||
// Filtered log classes, in a JSON array, eg. `[ "Loader", "ServiceFs" ]`
|
// Filtered log classes, in a JSON array, eg. `[ "Loader", "ServiceFs" ]`
|
||||||
"logging_filtered_classes": [ ],
|
"logging_filtered_classes": [ ],
|
||||||
|
|
||||||
|
@ -44,6 +50,9 @@
|
||||||
// Enable integrity checks on Switch content files
|
// Enable integrity checks on Switch content files
|
||||||
"enable_fs_integrity_checks": true,
|
"enable_fs_integrity_checks": true,
|
||||||
|
|
||||||
|
// Sets the "GlobalAccessLogMode". Possible modes are 0-3
|
||||||
|
"fs_global_access_log_mode": 0,
|
||||||
|
|
||||||
// Enable or disable aggressive CPU optimizations
|
// Enable or disable aggressive CPU optimizations
|
||||||
"enable_aggressive_cpu_opts": true,
|
"enable_aggressive_cpu_opts": true,
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,16 @@ namespace Ryujinx
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool LoggingEnableError { get; private set; }
|
public bool LoggingEnableError { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables printing guest log messages
|
||||||
|
/// </summary>
|
||||||
|
public bool LoggingEnableGuest { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables printing FS access log messages
|
||||||
|
/// </summary>
|
||||||
|
public bool LoggingEnableFsAccessLog { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Controls which log messages are written to the log targets
|
/// Controls which log messages are written to the log targets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -92,6 +102,11 @@ namespace Ryujinx
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableFsIntegrityChecks { get; private set; }
|
public bool EnableFsIntegrityChecks { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables FS access log output to the console. Possible modes are 0-3
|
||||||
|
/// </summary>
|
||||||
|
public int FsGlobalAccessLogMode { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enable or Disable aggressive CPU optimizations
|
/// Enable or Disable aggressive CPU optimizations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -184,11 +199,13 @@ namespace Ryujinx
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.SetEnable(LogLevel.Debug, Instance.LoggingEnableDebug);
|
Logger.SetEnable(LogLevel.Debug, Instance.LoggingEnableDebug);
|
||||||
Logger.SetEnable(LogLevel.Stub, Instance.LoggingEnableStub);
|
Logger.SetEnable(LogLevel.Stub, Instance.LoggingEnableStub);
|
||||||
Logger.SetEnable(LogLevel.Info, Instance.LoggingEnableInfo);
|
Logger.SetEnable(LogLevel.Info, Instance.LoggingEnableInfo);
|
||||||
Logger.SetEnable(LogLevel.Warning, Instance.LoggingEnableWarn);
|
Logger.SetEnable(LogLevel.Warning, Instance.LoggingEnableWarn);
|
||||||
Logger.SetEnable(LogLevel.Error, Instance.LoggingEnableError);
|
Logger.SetEnable(LogLevel.Error, Instance.LoggingEnableError);
|
||||||
|
Logger.SetEnable(LogLevel.Guest, Instance.LoggingEnableGuest);
|
||||||
|
Logger.SetEnable(LogLevel.AccessLog, Instance.LoggingEnableFsAccessLog);
|
||||||
|
|
||||||
if (Instance.LoggingFilteredClasses.Length > 0)
|
if (Instance.LoggingFilteredClasses.Length > 0)
|
||||||
{
|
{
|
||||||
|
@ -220,6 +237,8 @@ namespace Ryujinx
|
||||||
? IntegrityCheckLevel.ErrorOnInvalid
|
? IntegrityCheckLevel.ErrorOnInvalid
|
||||||
: IntegrityCheckLevel.None;
|
: IntegrityCheckLevel.None;
|
||||||
|
|
||||||
|
device.System.GlobalAccessLogMode = Instance.FsGlobalAccessLogMode;
|
||||||
|
|
||||||
if (Instance.EnableAggressiveCpuOpts)
|
if (Instance.EnableAggressiveCpuOpts)
|
||||||
{
|
{
|
||||||
Optimizations.AssumeStrictAbiCompliance = true;
|
Optimizations.AssumeStrictAbiCompliance = true;
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
"logging_enable_info",
|
"logging_enable_info",
|
||||||
"logging_enable_warn",
|
"logging_enable_warn",
|
||||||
"logging_enable_error",
|
"logging_enable_error",
|
||||||
|
"logging_enable_guest",
|
||||||
|
"logging_enable_fs_access_log",
|
||||||
"logging_filtered_classes",
|
"logging_filtered_classes",
|
||||||
"enable_file_log",
|
"enable_file_log",
|
||||||
"system_language",
|
"system_language",
|
||||||
|
@ -17,6 +19,7 @@
|
||||||
"enable_vsync",
|
"enable_vsync",
|
||||||
"enable_multicore_scheduling",
|
"enable_multicore_scheduling",
|
||||||
"enable_fs_integrity_checks",
|
"enable_fs_integrity_checks",
|
||||||
|
"fs_global_access_log_mode",
|
||||||
"enable_aggressive_cpu_opts",
|
"enable_aggressive_cpu_opts",
|
||||||
"controller_type",
|
"controller_type",
|
||||||
"enable_keyboard",
|
"enable_keyboard",
|
||||||
|
@ -265,6 +268,28 @@
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"logging_enable_guest": {
|
||||||
|
"$id": "#/properties/logging_enable_guest",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Logging Enable Guest",
|
||||||
|
"description": "Enables printing guest log messages",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"logging_enable_fs_access": {
|
||||||
|
"$id": "#/properties/logging_enable_fs_access_log",
|
||||||
|
"type": "boolean",
|
||||||
|
"title": "Logging Enable FS Access Log",
|
||||||
|
"description": "Enables printing FS access log messages",
|
||||||
|
"default": true,
|
||||||
|
"examples": [
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
]
|
||||||
|
},
|
||||||
"logging_filtered_classes": {
|
"logging_filtered_classes": {
|
||||||
"$id": "#/properties/logging_filtered_classes",
|
"$id": "#/properties/logging_filtered_classes",
|
||||||
"type": "array",
|
"type": "array",
|
||||||
|
@ -412,6 +437,20 @@
|
||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"fs_global_access_log_mode": {
|
||||||
|
"$id": "#/properties/fs_global_access_log_mode",
|
||||||
|
"type": "integer",
|
||||||
|
"title": "Enable FS access log",
|
||||||
|
"description": "Enables FS access log output. Possible modes are 0-3. Modes 2 and 3 output to the console.",
|
||||||
|
"default": 0,
|
||||||
|
"minimum": 0,
|
||||||
|
"examples": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3
|
||||||
|
]
|
||||||
|
},
|
||||||
"enable_aggressive_cpu_opts": {
|
"enable_aggressive_cpu_opts": {
|
||||||
"$id": "#/properties/enable_aggressive_cpu_opts",
|
"$id": "#/properties/enable_aggressive_cpu_opts",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|
Loading…
Reference in a new issue