From fe2d83df4de74e886249b3e01ca6a9536ed53f22 Mon Sep 17 00:00:00 2001 From: GabCoolDude Date: Mon, 3 Feb 2025 12:33:48 +0100 Subject: [PATCH 1/7] Initial Ryujinx log reader logic, unfinished Added checks for homebrew and metal. Started on the log reader logic with getting the application info, the emulator info, and the settings info. --- .../Services/LogAnalysis/AnalysisResult.cs | 13 +- src/Bot/Services/LogAnalysis/Regexes.cs | 8 + src/Bot/Services/LogAnalysis/RyuLogReader.cs | 256 ++++++++++++++++++ 3 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 src/Bot/Services/LogAnalysis/RyuLogReader.cs diff --git a/src/Bot/Services/LogAnalysis/AnalysisResult.cs b/src/Bot/Services/LogAnalysis/AnalysisResult.cs index adc1333f..127583d5 100644 --- a/src/Bot/Services/LogAnalysis/AnalysisResult.cs +++ b/src/Bot/Services/LogAnalysis/AnalysisResult.cs @@ -1,4 +1,6 @@ -namespace RyuBot.Services; +using System.Collections; + +namespace RyuBot.Services; public struct LogAnalysis { @@ -11,9 +13,9 @@ public LogAnalysis(string rawLogText, LogAnalysisService service) } public string RawLogContent { get; } - public List LogErrors; + public List LogErrors; public HardwareInfo Hardware; - public EmulatorInfo Emulator; + public EmulatorInfo EmulatorInfo; public GameInfo Game; public Settings Settings; } @@ -30,12 +32,15 @@ public class EmulatorInfo { public (RyujinxVersion VersionType, string VersionString) Version { get; set; } public string Firmware { get; set; } - public List EnabledLogs { get; set; } = []; + public string EnabledLogs { get; set; } } public class GameInfo { public string Name { get; set; } + public string AppId { get; set; } + public string AppIdBids { get; set; } + public string BuildIDs { get; set; } public string Errors { get; set; } public string Mods { get; set; } public string Cheats { get; set; } diff --git a/src/Bot/Services/LogAnalysis/Regexes.cs b/src/Bot/Services/LogAnalysis/Regexes.cs index 20c5d727..a6f09dae 100644 --- a/src/Bot/Services/LogAnalysis/Regexes.cs +++ b/src/Bot/Services/LogAnalysis/Regexes.cs @@ -9,7 +9,9 @@ public static partial class LogAnalysisPatterns public static readonly Regex OriginalProjectVersion = OriginalProjectVersionRegex(); public static readonly Regex OriginalProjectLdnVersion = OriginalProjectLdnVersionRegex(); public static readonly Regex PrVersion = PrVersionRegex(); + public static readonly Regex OriginalPrVersion = OriginalPrVersionRegex(); public static readonly Regex MirrorVersion = MirrorVersionRegex(); + public static readonly Regex CustomVersion = CustomVersionRegex(); [GeneratedRegex(@"^1\.2\.\d+$")] private static partial Regex StableVersionRegex(); @@ -26,6 +28,12 @@ public static partial class LogAnalysisPatterns [GeneratedRegex(@"^1\.2\.\d\+([a-f]|\d){7}$")] private static partial Regex PrVersionRegex(); + [GeneratedRegex(@"^1\.1\.\d\+([a-f]|\d){7}$")] + private static partial Regex OriginalPrVersionRegex(); + [GeneratedRegex(@"^r\.(\d|\w){7}$")] private static partial Regex MirrorVersionRegex(); + + // Greem please put a regex here idk how to do them + private static partial Regex CustomVersionRegex(); } \ No newline at end of file diff --git a/src/Bot/Services/LogAnalysis/RyuLogReader.cs b/src/Bot/Services/LogAnalysis/RyuLogReader.cs new file mode 100644 index 00000000..a11e1fd4 --- /dev/null +++ b/src/Bot/Services/LogAnalysis/RyuLogReader.cs @@ -0,0 +1,256 @@ +using System.Text.RegularExpressions; + +namespace RyuBot.Services; + +public class RyuLogReader +{ + public LogAnalysis log; + + double ConvertGiBtoMiB(double GiB) + { + return Math.Round(GiB * 1024); + } + + static bool IsHomebrew(string logFile) + { + Match m = Regex.Match(logFile, "Load.*Application: Loading as [Hh]omebrew"); + if (m.Success) return true; + if (!m.Success) return false; + else return false; + } + + static bool IsUsingMetal(string logFile) + { + Match m = Regex.Match(logFile, "Gpu : Backend \\(Metal\\): Metal"); + if (m.Success) return true; + if (!m.Success) return false; + else return false; + } + + void GetAppInfo() + { + MatchCollection gameNameMatch = Regex.Matches(log.RawLogContent, @"Loader [A-Za-z]*: Application Loaded:\s([^;\n\r]*)", RegexOptions.Multiline); + if (!gameNameMatch.None()) + { + string gameName = gameNameMatch[-1].ToString().Trim(); + + string appID; + Match appIDMatch = Regex.Match(gameName, @".* \[([a-zA-Z0-9]*)\]"); + if (appIDMatch.Success) + { + appID = appIDMatch.Groups[1].Value.Trim().ToUpper(); + } + else + { + appID = "Unknown"; + } + + MatchCollection bidsMatchAll = Regex.Matches(log.RawLogContent, + @"Build ids found for (?:title|application) ([a-zA-Z0-9]*):[\n\r]*((?:\s+.*[\n\r]+)+)"); + if (!bidsMatchAll.None() && bidsMatchAll.Count > 0) + { + // this whole thing might not work properly + string bidsMatch = bidsMatchAll[-1].ToString(); + string appIDFromBids; + string BuildIDs; + + if (bidsMatch[0].ToString() is not null) + { + appIDFromBids = bidsMatch[0].ToString().Trim().ToUpper(); + } + else + { + appIDFromBids = "Unknown"; + } + if (bidsMatch[1].ToString() is not null) + { + // this might not work + BuildIDs = bidsMatch[1].ToString().Trim().ToUpper(); + } else + { + BuildIDs = "Unknown"; + } + + log.Game.Name = gameName; + log.Game.AppId = appID; + log.Game.AppIdBids = appIDFromBids; + log.Game.BuildIDs = BuildIDs; + } + } + } + + static bool ContainsError(string[] searchTerm, List errors) + { + foreach (string term in searchTerm) + { + foreach (string errorLines in errors) + { + string line = errorLines.JoinToString("\n"); + if (term.Contains(line)) + { + return true; + } + } + } + return false; + } + + void GetErrors() + { + List errors = new List(); + List currentErrorsLines = new List(); + bool errorLine = false; + + foreach (string line in log.RawLogContent.Split("\n")) + { + if (line.IsNullOrWhitespace()) + { + continue; + } + + if (line.Contains("|E|")) + { + currentErrorsLines = [line]; + errors.AddRange(currentErrorsLines); + errorLine = true; + } + else if (errorLine && line[0].ToString() == "") + { + currentErrorsLines.AddRange(line); + } + } + + if (currentErrorsLines.Count > 0) + { + errors.AddRange(currentErrorsLines); + } + + log.LogErrors = errors; + } + + string[] sizes = ["KB", "KiB", "MB", "MiB", "GB", "GiB"]; + + void GetHardwareInfo() + { + // CPU + Match cpuMatch = Regex.Match(log.RawLogContent, @"CPU:\s([^;\n\r]*)", RegexOptions.Multiline); + if (cpuMatch.Success) + { + log.Hardware.Cpu = cpuMatch.Groups[1].Value.TrimEnd(); + } + else + { + log.Hardware.Cpu = "Unknown"; + } + + // RAM + Match ramMatch = Regex.Match(log.RawLogContent, + @$"RAM: Total ([\d.]+) ({sizes}) ; Available ([\d.]+) ({sizes})", RegexOptions.Multiline); + if (ramMatch.Success) + { + double ramAvailable = ConvertGiBtoMiB(Convert.ToDouble(ramMatch.Groups[3].Value)); + double ramTotal = ConvertGiBtoMiB(Convert.ToDouble(ramMatch.Groups[1].Value)); + log.Hardware.Ram = $"{ramAvailable:.0f}/{ramTotal:.0f} MiB"; + } + else + { + log.Hardware.Ram = "Unknown"; + } + + // Operating System (OS) + Match osMatch = Regex.Match(log.RawLogContent, @"Operating System:\s([^;\n\r]*)", RegexOptions.Multiline); + if (osMatch.Success) + { + log.Hardware.Os = osMatch.Groups[1].Value.TrimEnd(); + } + else + { + log.Hardware.Os = "Unknown"; + } + + // GPU + Match gpuMatch = Regex.Match(log.RawLogContent, @"PrintGpuInformation:\s([^;\n\r]*)", + RegexOptions.Multiline); + if (gpuMatch.Success) + { + log.Hardware.Gpu = gpuMatch.Groups[1].Value.TrimEnd(); + // If android logs starts showing up, we can detect android GPUs here + } + else + { + log.Hardware.Gpu = "Unknown"; + } + } + + void GetEmuInfo() + { + // Ryujinx Version check + foreach (string line in log.RawLogContent.Split("\n")) + { + // Greem's Stable build + if (LogAnalysisPatterns.StableVersion.IsMatch(line)) + { + log.EmulatorInfo.Version = (RyujinxVersion.Stable, line.Split("\n")[-1].Trim()); + } + // Greem's Canary build + else if (LogAnalysisPatterns.CanaryVersion.IsMatch(line)) + { + log.EmulatorInfo.Version = (RyujinxVersion.Canary, line.Split("\n")[-1].Trim()); + } + // Custom build + else if (LogAnalysisPatterns.CustomVersion.IsMatch(line)) + { + log.EmulatorInfo.Version = (RyujinxVersion.Custom, line.Split("\n")[-1].Trim()); + } + // PR build + else if (LogAnalysisPatterns.PrVersion.IsMatch(line) || LogAnalysisPatterns.OriginalPrVersion.IsMatch(line)) + { + log.EmulatorInfo.Version = (RyujinxVersion.Pr, line.Split("\n")[-1].Trim()); + } + // Original Project build + else if (LogAnalysisPatterns.OriginalProjectVersion.IsMatch(line)) + { + log.EmulatorInfo.Version = (RyujinxVersion.OriginalProject, line.Split("\n")[-1].Trim()); + } + // Original Project LDN build + else if (LogAnalysisPatterns.OriginalProjectLdnVersion.IsMatch(line)) + { + log.EmulatorInfo.Version = (RyujinxVersion.OriginalProjectLdn, line.Split("\n")[-1].Trim()); + } + } + + // Logs Enabled ? + Match logsMatch = Regex.Match(log.RawLogContent, @"Logs Enabled:\s([^;\n\r]*)", RegexOptions.Multiline); + if (logsMatch.Success) + { + log.EmulatorInfo.EnabledLogs = logsMatch.Groups[1].Value.TrimEnd(); + } + else + { + log.EmulatorInfo.EnabledLogs = "Unknown"; + } + + // Firmware + Match firmwareMatch = Regex.Match(log.RawLogContent, @"Firmware Version:\s([^;\n\r]*)", RegexOptions.Multiline); + if (firmwareMatch.Success) + { + log.EmulatorInfo.Firmware = firmwareMatch.Groups[-1].Value.Trim(); + } + else + { + log.EmulatorInfo.Firmware = "Unknown"; + } + + } + + void GetSettingValue() + { + Match settingMatch = Regex.Match(log.RawLogContent, @"LogValueChange:\s([^;\n\r]*)"); + if (settingMatch.Success) + { + // Unfinished + } + + } + +} From 9f7d2ef04b5312c3384137773264e54a0292b07d Mon Sep 17 00:00:00 2001 From: GabCoolDude Date: Thu, 6 Feb 2025 15:05:37 +0100 Subject: [PATCH 2/7] Add 'GetSettings' method --- .../Services/LogAnalysis/AnalysisResult.cs | 8 +- src/Bot/Services/LogAnalysis/Regexes.cs | 4 - src/Bot/Services/LogAnalysis/RyuLogReader.cs | 170 ++++++++++++++---- 3 files changed, 139 insertions(+), 43 deletions(-) diff --git a/src/Bot/Services/LogAnalysis/AnalysisResult.cs b/src/Bot/Services/LogAnalysis/AnalysisResult.cs index 127583d5..f150a40d 100644 --- a/src/Bot/Services/LogAnalysis/AnalysisResult.cs +++ b/src/Bot/Services/LogAnalysis/AnalysisResult.cs @@ -1,6 +1,4 @@ -using System.Collections; - -namespace RyuBot.Services; +namespace RyuBot.Services; public struct LogAnalysis { @@ -59,9 +57,11 @@ public class Settings public bool Pptc { get; set; } public bool ShaderCache { get; set; } public string VSyncMode { get; set; } - public bool? Hypervisor { get; set; } + public string Hypervisor { get; set; } public string ResScale { get; set; } public string AnisotropicFiltering { get; set; } public string AspectRatio { get; set; } public bool TextureRecompression { get; set; } + public string CustomVSyncInterval { get; set; } + public string MultiplayerMode { get; set; } } \ No newline at end of file diff --git a/src/Bot/Services/LogAnalysis/Regexes.cs b/src/Bot/Services/LogAnalysis/Regexes.cs index a6f09dae..6c63fbfc 100644 --- a/src/Bot/Services/LogAnalysis/Regexes.cs +++ b/src/Bot/Services/LogAnalysis/Regexes.cs @@ -11,7 +11,6 @@ public static partial class LogAnalysisPatterns public static readonly Regex PrVersion = PrVersionRegex(); public static readonly Regex OriginalPrVersion = OriginalPrVersionRegex(); public static readonly Regex MirrorVersion = MirrorVersionRegex(); - public static readonly Regex CustomVersion = CustomVersionRegex(); [GeneratedRegex(@"^1\.2\.\d+$")] private static partial Regex StableVersionRegex(); @@ -33,7 +32,4 @@ public static partial class LogAnalysisPatterns [GeneratedRegex(@"^r\.(\d|\w){7}$")] private static partial Regex MirrorVersionRegex(); - - // Greem please put a regex here idk how to do them - private static partial Regex CustomVersionRegex(); } \ No newline at end of file diff --git a/src/Bot/Services/LogAnalysis/RyuLogReader.cs b/src/Bot/Services/LogAnalysis/RyuLogReader.cs index a11e1fd4..fead6a71 100644 --- a/src/Bot/Services/LogAnalysis/RyuLogReader.cs +++ b/src/Bot/Services/LogAnalysis/RyuLogReader.cs @@ -29,7 +29,8 @@ static bool IsUsingMetal(string logFile) void GetAppInfo() { - MatchCollection gameNameMatch = Regex.Matches(log.RawLogContent, @"Loader [A-Za-z]*: Application Loaded:\s([^;\n\r]*)", RegexOptions.Multiline); + MatchCollection gameNameMatch = Regex.Matches(log.RawLogContent, + @"Loader [A-Za-z]*: Application Loaded:\s([^;\n\r]*)", RegexOptions.Multiline); if (!gameNameMatch.None()) { string gameName = gameNameMatch[-1].ToString().Trim(); @@ -54,7 +55,7 @@ void GetAppInfo() string appIDFromBids; string BuildIDs; - if (bidsMatch[0].ToString() is not null) + if (bidsMatch[0].ToString() != null) { appIDFromBids = bidsMatch[0].ToString().Trim().ToUpper(); } @@ -62,7 +63,7 @@ void GetAppInfo() { appIDFromBids = "Unknown"; } - if (bidsMatch[1].ToString() is not null) + if (bidsMatch[1].ToString() != null) { // this might not work BuildIDs = bidsMatch[1].ToString().Trim().ToUpper(); @@ -152,21 +153,16 @@ void GetHardwareInfo() double ramTotal = ConvertGiBtoMiB(Convert.ToDouble(ramMatch.Groups[1].Value)); log.Hardware.Ram = $"{ramAvailable:.0f}/{ramTotal:.0f} MiB"; } - else - { - log.Hardware.Ram = "Unknown"; - } + else { log.Hardware.Ram = "Unknown"; } // Operating System (OS) - Match osMatch = Regex.Match(log.RawLogContent, @"Operating System:\s([^;\n\r]*)", RegexOptions.Multiline); + Match osMatch = Regex.Match(log.RawLogContent, @"Operating System:\s([^;\n\r]*)", + RegexOptions.Multiline); if (osMatch.Success) { log.Hardware.Os = osMatch.Groups[1].Value.TrimEnd(); } - else - { - log.Hardware.Os = "Unknown"; - } + else { log.Hardware.Os = "Unknown"; } // GPU Match gpuMatch = Regex.Match(log.RawLogContent, @"PrintGpuInformation:\s([^;\n\r]*)", @@ -176,10 +172,7 @@ void GetHardwareInfo() log.Hardware.Gpu = gpuMatch.Groups[1].Value.TrimEnd(); // If android logs starts showing up, we can detect android GPUs here } - else - { - log.Hardware.Gpu = "Unknown"; - } + else { log.Hardware.Gpu = "Unknown"; } } void GetEmuInfo() @@ -197,11 +190,6 @@ void GetEmuInfo() { log.EmulatorInfo.Version = (RyujinxVersion.Canary, line.Split("\n")[-1].Trim()); } - // Custom build - else if (LogAnalysisPatterns.CustomVersion.IsMatch(line)) - { - log.EmulatorInfo.Version = (RyujinxVersion.Custom, line.Split("\n")[-1].Trim()); - } // PR build else if (LogAnalysisPatterns.PrVersion.IsMatch(line) || LogAnalysisPatterns.OriginalPrVersion.IsMatch(line)) { @@ -217,38 +205,150 @@ void GetEmuInfo() { log.EmulatorInfo.Version = (RyujinxVersion.OriginalProjectLdn, line.Split("\n")[-1].Trim()); } + // Custom build + else + { + log.EmulatorInfo.Version = (RyujinxVersion.Custom, line.Split("\n")[-1].Trim()); + } } // Logs Enabled ? - Match logsMatch = Regex.Match(log.RawLogContent, @"Logs Enabled:\s([^;\n\r]*)", RegexOptions.Multiline); + Match logsMatch = Regex.Match(log.RawLogContent, @"Logs Enabled:\s([^;\n\r]*)", + RegexOptions.Multiline); if (logsMatch.Success) { log.EmulatorInfo.EnabledLogs = logsMatch.Groups[1].Value.TrimEnd(); } - else - { - log.EmulatorInfo.EnabledLogs = "Unknown"; - } + else { log.EmulatorInfo.EnabledLogs = "Unknown"; } // Firmware - Match firmwareMatch = Regex.Match(log.RawLogContent, @"Firmware Version:\s([^;\n\r]*)", RegexOptions.Multiline); + Match firmwareMatch = Regex.Match(log.RawLogContent, @"Firmware Version:\s([^;\n\r]*)", + RegexOptions.Multiline); if (firmwareMatch.Success) { log.EmulatorInfo.Firmware = firmwareMatch.Groups[-1].Value.Trim(); } - else - { - log.EmulatorInfo.Firmware = "Unknown"; - } + else { log.EmulatorInfo.Firmware = "Unknown"; } } - void GetSettingValue() + void GetSettings() { - Match settingMatch = Regex.Match(log.RawLogContent, @"LogValueChange:\s([^;\n\r]*)"); - if (settingMatch.Success) + + MatchCollection settingsMatch = Regex.Matches(log.RawLogContent, @"LogValueChange:\s([^;\n\r]*)", + RegexOptions.Multiline); + + foreach (string line in log.RawLogContent.Split("\n")) { - // Unfinished + switch (settingsMatch[0].Groups[1].Value.Trim()) + { + // Resolution Scale + case "ResScaleCustom set to:": + case "ResScale set to:": + log.Settings.ResScale = settingsMatch[0].Groups[2].Value.Trim(); + switch (log.Settings.ResScale) + { + case "1": + log.Settings.ResScale = "Native (720p/1080p)"; + break; + case "2": + log.Settings.ResScale = "2x (1440p/2060p(4K))"; + break; + case "3": + log.Settings.ResScale = "3x (2160p(4K)/3240p)"; + break; + case "4": + log.Settings.ResScale = "4x (3240p/4320p)"; + break; + case "-1": + log.Settings.ResScale = "Custom"; + break; + } + + break; + // Anisotropic Filtering + case "MaxAnisotropy set to:": + log.Settings.AnisotropicFiltering = settingsMatch[0].Groups[2].Value.Trim(); + break; + // Aspect Ratio + case "AspectRatio set to:": + log.Settings.AspectRatio = settingsMatch[0].Groups[2].Value.Trim(); + switch (log.Settings.AspectRatio) + { + case "Fixed16x9": + log.Settings.AspectRatio = "16:9"; + break; + // TODO: add more aspect ratios + } + + break; + // Graphics Backend + case "GraphicsBackend set to:": + log.Settings.GraphicsBackend = settingsMatch[0].Groups[2].Value.Trim(); + break; + // Custom VSync Interval + case "CustomVSyncInterval set to:": + log.Settings.CustomVSyncInterval = settingsMatch[0].Groups[2].Value.Trim(); + break; + // Shader cache + case "EnableShaderCache set to: True": + log.Settings.ShaderCache = true; + break; + case "EnableShaderCache set to: False": + log.Settings.ShaderCache = false; + break; + // Docked or Handheld + case "EnableDockedMode set to: True": + log.Settings.Docked = true; + break; + case "EnableDockedMode set to: False": + log.Settings.Docked = false; + break; + // PPTC Cache + case "EnablePtc set to: True": + log.Settings.Pptc = true; + break; + case "EnablePtc set to: False": + log.Settings.Pptc = false; + break; + // FS Integrity check + case "EnableFsIntegrityChecks set to: True": + log.Settings.FsIntegrityChecks = true; + break; + case "EnableFsIntegrityChecks set to: False": + log.Settings.FsIntegrityChecks = false; + break; + // Audio Backend + case "AudioBackend set to:": + log.Settings.AudioBackend = settingsMatch[0].Groups[2].Value.Trim(); + break; + // Memory Manager Mode + case "MemoryManagerMode set to:": + log.Settings.MemoryManager = settingsMatch[0].Groups[2].Value.Trim(); + switch (log.Settings.MemoryManager) + { + case "HostMappedUnsafe": + log.Settings.MemoryManager = "Unsafe"; + break; + // TODO: Add more memory manager modes + } + + break; + // Hypervisor + case "UseHypervisor set to:": + log.Settings.Hypervisor = settingsMatch[0].Groups[2].Value.Trim(); + // If the OS is windows or linux, set hypervisor to 'N/A' because it's only on macos + if (log.Hardware.Os.ToLower() == "windows" || log.Hardware.Os.ToLower() == "linux") + { + log.Settings.Hypervisor = "N/A"; + } + + break; + // Ldn Mode + case "MultiplayerMode set to:": + log.Settings.MultiplayerMode = settingsMatch[0].Groups[2].Value.Trim(); + break; + } } } From 32ec6a6c967b623fa6f1be9a8484009129ea8f73 Mon Sep 17 00:00:00 2001 From: GabCoolDude Date: Fri, 7 Feb 2025 14:00:23 +0100 Subject: [PATCH 3/7] Add Mods, Cheats, and app name methods --- src/Bot/Services/LogAnalysis/RyuLogReader.cs | 228 ++++++++++++------- 1 file changed, 142 insertions(+), 86 deletions(-) diff --git a/src/Bot/Services/LogAnalysis/RyuLogReader.cs b/src/Bot/Services/LogAnalysis/RyuLogReader.cs index fead6a71..d0c81a63 100644 --- a/src/Bot/Services/LogAnalysis/RyuLogReader.cs +++ b/src/Bot/Services/LogAnalysis/RyuLogReader.cs @@ -4,8 +4,8 @@ namespace RyuBot.Services; public class RyuLogReader { - public LogAnalysis log; - + public LogAnalysis Log; + double ConvertGiBtoMiB(double GiB) { return Math.Round(GiB * 1024); @@ -29,7 +29,7 @@ static bool IsUsingMetal(string logFile) void GetAppInfo() { - MatchCollection gameNameMatch = Regex.Matches(log.RawLogContent, + MatchCollection gameNameMatch = Regex.Matches(Log.RawLogContent, @"Loader [A-Za-z]*: Application Loaded:\s([^;\n\r]*)", RegexOptions.Multiline); if (!gameNameMatch.None()) { @@ -46,7 +46,7 @@ void GetAppInfo() appID = "Unknown"; } - MatchCollection bidsMatchAll = Regex.Matches(log.RawLogContent, + MatchCollection bidsMatchAll = Regex.Matches(Log.RawLogContent, @"Build ids found for (?:title|application) ([a-zA-Z0-9]*):[\n\r]*((?:\s+.*[\n\r]+)+)"); if (!bidsMatchAll.None() && bidsMatchAll.Count > 0) { @@ -63,19 +63,21 @@ void GetAppInfo() { appIDFromBids = "Unknown"; } + if (bidsMatch[1].ToString() != null) { // this might not work BuildIDs = bidsMatch[1].ToString().Trim().ToUpper(); - } else + } + else { BuildIDs = "Unknown"; } - - log.Game.Name = gameName; - log.Game.AppId = appID; - log.Game.AppIdBids = appIDFromBids; - log.Game.BuildIDs = BuildIDs; + + Log.Game.Name = gameName; + Log.Game.AppId = appID; + Log.Game.AppIdBids = appIDFromBids; + Log.Game.BuildIDs = BuildIDs; } } } @@ -93,6 +95,7 @@ static bool ContainsError(string[] searchTerm, List errors) } } } + return false; } @@ -102,7 +105,7 @@ void GetErrors() List currentErrorsLines = new List(); bool errorLine = false; - foreach (string line in log.RawLogContent.Split("\n")) + foreach (string line in Log.RawLogContent.Split("\n")) { if (line.IsNullOrWhitespace()) { @@ -125,210 +128,225 @@ void GetErrors() { errors.AddRange(currentErrorsLines); } - - log.LogErrors = errors; + + Log.LogErrors = errors; } - string[] sizes = ["KB", "KiB", "MB", "MiB", "GB", "GiB"]; + string[] _sizes = ["KB", "KiB", "MB", "MiB", "GB", "GiB"]; void GetHardwareInfo() { // CPU - Match cpuMatch = Regex.Match(log.RawLogContent, @"CPU:\s([^;\n\r]*)", RegexOptions.Multiline); + Match cpuMatch = Regex.Match(Log.RawLogContent, @"CPU:\s([^;\n\r]*)", RegexOptions.Multiline); if (cpuMatch.Success) { - log.Hardware.Cpu = cpuMatch.Groups[1].Value.TrimEnd(); + Log.Hardware.Cpu = cpuMatch.Groups[1].Value.TrimEnd(); } else { - log.Hardware.Cpu = "Unknown"; + Log.Hardware.Cpu = "Unknown"; } - + // RAM - Match ramMatch = Regex.Match(log.RawLogContent, - @$"RAM: Total ([\d.]+) ({sizes}) ; Available ([\d.]+) ({sizes})", RegexOptions.Multiline); + Match ramMatch = Regex.Match(Log.RawLogContent, + @$"RAM: Total ([\d.]+) ({_sizes}) ; Available ([\d.]+) ({_sizes})", RegexOptions.Multiline); if (ramMatch.Success) { double ramAvailable = ConvertGiBtoMiB(Convert.ToDouble(ramMatch.Groups[3].Value)); double ramTotal = ConvertGiBtoMiB(Convert.ToDouble(ramMatch.Groups[1].Value)); - log.Hardware.Ram = $"{ramAvailable:.0f}/{ramTotal:.0f} MiB"; + Log.Hardware.Ram = $"{ramAvailable:.0f}/{ramTotal:.0f} MiB"; + } + else + { + Log.Hardware.Ram = "Unknown"; } - else { log.Hardware.Ram = "Unknown"; } // Operating System (OS) - Match osMatch = Regex.Match(log.RawLogContent, @"Operating System:\s([^;\n\r]*)", + Match osMatch = Regex.Match(Log.RawLogContent, @"Operating System:\s([^;\n\r]*)", RegexOptions.Multiline); if (osMatch.Success) { - log.Hardware.Os = osMatch.Groups[1].Value.TrimEnd(); + Log.Hardware.Os = osMatch.Groups[1].Value.TrimEnd(); + } + else + { + Log.Hardware.Os = "Unknown"; } - else { log.Hardware.Os = "Unknown"; } // GPU - Match gpuMatch = Regex.Match(log.RawLogContent, @"PrintGpuInformation:\s([^;\n\r]*)", + Match gpuMatch = Regex.Match(Log.RawLogContent, @"PrintGpuInformation:\s([^;\n\r]*)", RegexOptions.Multiline); if (gpuMatch.Success) { - log.Hardware.Gpu = gpuMatch.Groups[1].Value.TrimEnd(); + Log.Hardware.Gpu = gpuMatch.Groups[1].Value.TrimEnd(); // If android logs starts showing up, we can detect android GPUs here } - else { log.Hardware.Gpu = "Unknown"; } + else + { + Log.Hardware.Gpu = "Unknown"; + } } void GetEmuInfo() { // Ryujinx Version check - foreach (string line in log.RawLogContent.Split("\n")) + foreach (string line in Log.RawLogContent.Split("\n")) { // Greem's Stable build if (LogAnalysisPatterns.StableVersion.IsMatch(line)) { - log.EmulatorInfo.Version = (RyujinxVersion.Stable, line.Split("\n")[-1].Trim()); - } + Log.EmulatorInfo.Version = (RyujinxVersion.Stable, line.Split("\n")[-1].Trim()); + } // Greem's Canary build else if (LogAnalysisPatterns.CanaryVersion.IsMatch(line)) { - log.EmulatorInfo.Version = (RyujinxVersion.Canary, line.Split("\n")[-1].Trim()); + Log.EmulatorInfo.Version = (RyujinxVersion.Canary, line.Split("\n")[-1].Trim()); } // PR build else if (LogAnalysisPatterns.PrVersion.IsMatch(line) || LogAnalysisPatterns.OriginalPrVersion.IsMatch(line)) { - log.EmulatorInfo.Version = (RyujinxVersion.Pr, line.Split("\n")[-1].Trim()); - } + Log.EmulatorInfo.Version = (RyujinxVersion.Pr, line.Split("\n")[-1].Trim()); + } // Original Project build else if (LogAnalysisPatterns.OriginalProjectVersion.IsMatch(line)) { - log.EmulatorInfo.Version = (RyujinxVersion.OriginalProject, line.Split("\n")[-1].Trim()); - } + Log.EmulatorInfo.Version = (RyujinxVersion.OriginalProject, line.Split("\n")[-1].Trim()); + } // Original Project LDN build else if (LogAnalysisPatterns.OriginalProjectLdnVersion.IsMatch(line)) { - log.EmulatorInfo.Version = (RyujinxVersion.OriginalProjectLdn, line.Split("\n")[-1].Trim()); + Log.EmulatorInfo.Version = (RyujinxVersion.OriginalProjectLdn, line.Split("\n")[-1].Trim()); } // Custom build else { - log.EmulatorInfo.Version = (RyujinxVersion.Custom, line.Split("\n")[-1].Trim()); - } + Log.EmulatorInfo.Version = (RyujinxVersion.Custom, line.Split("\n")[-1].Trim()); + } } - + // Logs Enabled ? - Match logsMatch = Regex.Match(log.RawLogContent, @"Logs Enabled:\s([^;\n\r]*)", + Match logsMatch = Regex.Match(Log.RawLogContent, @"Logs Enabled:\s([^;\n\r]*)", RegexOptions.Multiline); if (logsMatch.Success) { - log.EmulatorInfo.EnabledLogs = logsMatch.Groups[1].Value.TrimEnd(); + Log.EmulatorInfo.EnabledLogs = logsMatch.Groups[1].Value.TrimEnd(); + } + else + { + Log.EmulatorInfo.EnabledLogs = "Unknown"; } - else { log.EmulatorInfo.EnabledLogs = "Unknown"; } - + // Firmware - Match firmwareMatch = Regex.Match(log.RawLogContent, @"Firmware Version:\s([^;\n\r]*)", + Match firmwareMatch = Regex.Match(Log.RawLogContent, @"Firmware Version:\s([^;\n\r]*)", RegexOptions.Multiline); if (firmwareMatch.Success) { - log.EmulatorInfo.Firmware = firmwareMatch.Groups[-1].Value.Trim(); + Log.EmulatorInfo.Firmware = firmwareMatch.Groups[-1].Value.Trim(); + } + else + { + Log.EmulatorInfo.Firmware = "Unknown"; } - else { log.EmulatorInfo.Firmware = "Unknown"; } - + } void GetSettings() { - - MatchCollection settingsMatch = Regex.Matches(log.RawLogContent, @"LogValueChange:\s([^;\n\r]*)", + + MatchCollection settingsMatch = Regex.Matches(Log.RawLogContent, @"LogValueChange:\s([^;\n\r]*)", RegexOptions.Multiline); - - foreach (string line in log.RawLogContent.Split("\n")) + + foreach (string line in settingsMatch) { - switch (settingsMatch[0].Groups[1].Value.Trim()) + switch (line) { // Resolution Scale case "ResScaleCustom set to:": case "ResScale set to:": - log.Settings.ResScale = settingsMatch[0].Groups[2].Value.Trim(); - switch (log.Settings.ResScale) + Log.Settings.ResScale = settingsMatch[0].Groups[2].Value.Trim(); + switch (Log.Settings.ResScale) { case "1": - log.Settings.ResScale = "Native (720p/1080p)"; + Log.Settings.ResScale = "Native (720p/1080p)"; break; case "2": - log.Settings.ResScale = "2x (1440p/2060p(4K))"; + Log.Settings.ResScale = "2x (1440p/2060p(4K))"; break; case "3": - log.Settings.ResScale = "3x (2160p(4K)/3240p)"; + Log.Settings.ResScale = "3x (2160p(4K)/3240p)"; break; case "4": - log.Settings.ResScale = "4x (3240p/4320p)"; + Log.Settings.ResScale = "4x (3240p/4320p(8K))"; break; case "-1": - log.Settings.ResScale = "Custom"; + Log.Settings.ResScale = "Custom"; break; } - + break; // Anisotropic Filtering case "MaxAnisotropy set to:": - log.Settings.AnisotropicFiltering = settingsMatch[0].Groups[2].Value.Trim(); + Log.Settings.AnisotropicFiltering = settingsMatch[0].Groups[2].Value.Trim(); break; // Aspect Ratio case "AspectRatio set to:": - log.Settings.AspectRatio = settingsMatch[0].Groups[2].Value.Trim(); - switch (log.Settings.AspectRatio) + Log.Settings.AspectRatio = settingsMatch[0].Groups[2].Value.Trim(); + switch (Log.Settings.AspectRatio) { case "Fixed16x9": - log.Settings.AspectRatio = "16:9"; + Log.Settings.AspectRatio = "16:9"; break; // TODO: add more aspect ratios } - + break; // Graphics Backend case "GraphicsBackend set to:": - log.Settings.GraphicsBackend = settingsMatch[0].Groups[2].Value.Trim(); + Log.Settings.GraphicsBackend = settingsMatch[0].Groups[2].Value.Trim(); break; // Custom VSync Interval case "CustomVSyncInterval set to:": - log.Settings.CustomVSyncInterval = settingsMatch[0].Groups[2].Value.Trim(); + Log.Settings.CustomVSyncInterval = settingsMatch[0].Groups[2].Value.Trim(); break; // Shader cache case "EnableShaderCache set to: True": - log.Settings.ShaderCache = true; + Log.Settings.ShaderCache = true; break; case "EnableShaderCache set to: False": - log.Settings.ShaderCache = false; + Log.Settings.ShaderCache = false; break; // Docked or Handheld case "EnableDockedMode set to: True": - log.Settings.Docked = true; + Log.Settings.Docked = true; break; case "EnableDockedMode set to: False": - log.Settings.Docked = false; + Log.Settings.Docked = false; break; // PPTC Cache case "EnablePtc set to: True": - log.Settings.Pptc = true; + Log.Settings.Pptc = true; break; case "EnablePtc set to: False": - log.Settings.Pptc = false; + Log.Settings.Pptc = false; break; // FS Integrity check case "EnableFsIntegrityChecks set to: True": - log.Settings.FsIntegrityChecks = true; + Log.Settings.FsIntegrityChecks = true; break; case "EnableFsIntegrityChecks set to: False": - log.Settings.FsIntegrityChecks = false; + Log.Settings.FsIntegrityChecks = false; break; // Audio Backend case "AudioBackend set to:": - log.Settings.AudioBackend = settingsMatch[0].Groups[2].Value.Trim(); + Log.Settings.AudioBackend = settingsMatch[0].Groups[2].Value.Trim(); break; // Memory Manager Mode case "MemoryManagerMode set to:": - log.Settings.MemoryManager = settingsMatch[0].Groups[2].Value.Trim(); - switch (log.Settings.MemoryManager) + Log.Settings.MemoryManager = settingsMatch[0].Groups[2].Value.Trim(); + switch (Log.Settings.MemoryManager) { case "HostMappedUnsafe": - log.Settings.MemoryManager = "Unsafe"; + Log.Settings.MemoryManager = "Unsafe"; break; // TODO: Add more memory manager modes } @@ -336,21 +354,59 @@ void GetSettings() break; // Hypervisor case "UseHypervisor set to:": - log.Settings.Hypervisor = settingsMatch[0].Groups[2].Value.Trim(); + Log.Settings.Hypervisor = settingsMatch[0].Groups[2].Value.Trim(); // If the OS is windows or linux, set hypervisor to 'N/A' because it's only on macos - if (log.Hardware.Os.ToLower() == "windows" || log.Hardware.Os.ToLower() == "linux") + if (Log.Hardware.Os.ToLower() == "windows" || Log.Hardware.Os.ToLower() == "linux") { - log.Settings.Hypervisor = "N/A"; + Log.Settings.Hypervisor = "N/A"; } break; // Ldn Mode case "MultiplayerMode set to:": - log.Settings.MultiplayerMode = settingsMatch[0].Groups[2].Value.Trim(); + Log.Settings.MultiplayerMode = settingsMatch[0].Groups[2].Value.Trim(); + break; + // This is just in case EVERYTHING fails + default: + Log.Settings.ResScale = "Failed"; + Log.Settings.AnisotropicFiltering = "Failed"; + Log.Settings.AspectRatio = "Failed"; + Log.Settings.GraphicsBackend = "Failed"; + Log.Settings.CustomVSyncInterval = "Failed"; + Log.Settings.ShaderCache = false; + Log.Settings.Docked = false; + Log.Settings.Pptc = false; + Log.Settings.FsIntegrityChecks = false; + Log.Settings.AudioBackend = "Failed"; + Log.Settings.MemoryManager = "Failed"; + Log.Settings.Hypervisor = "Failed"; break; } } - } + + void GetMods() + { + MatchCollection modsMatch = Regex.Matches(Log.RawLogContent, + "Found\\s(enabled)?\\s?mod\\s\\'(.+?)\\'\\s(\\[.+?\\])"); + Log.Game.Mods += modsMatch; + } + + void GetCheats() + { + MatchCollection cheatsMatch = Regex.Matches(Log.RawLogContent, + @"Installing cheat\s'(.+)'(?!\s\d{2}:\d{2}:\d{2}\.\d{3}\s\|E\|\sTamperMachine\sCompile)"); + Log.Game.Cheats += cheatsMatch; + } + + void GetAppName() + { + Match appNameMatch = Regex.Match(Log.RawLogContent, + @"Loader [A-Za-z]*: Application Loaded:\s([^;\n\r]*)", + RegexOptions.Multiline); + Log.Game.Name += appNameMatch; + } + + +} -} From 5f7f2ebe994a21ade6b84a506d55b7473e016cc5 Mon Sep 17 00:00:00 2001 From: GabCoolDude Date: Fri, 7 Feb 2025 23:45:20 +0100 Subject: [PATCH 4/7] Notes logic --- .../Services/LogAnalysis/AnalysisResult.cs | 13 +- src/Bot/Services/LogAnalysis/Notes.cs | 82 ++++ src/Bot/Services/LogAnalysis/RyuLogReader.cs | 462 +++++++++++++----- 3 files changed, 433 insertions(+), 124 deletions(-) create mode 100644 src/Bot/Services/LogAnalysis/Notes.cs diff --git a/src/Bot/Services/LogAnalysis/AnalysisResult.cs b/src/Bot/Services/LogAnalysis/AnalysisResult.cs index f150a40d..490e3707 100644 --- a/src/Bot/Services/LogAnalysis/AnalysisResult.cs +++ b/src/Bot/Services/LogAnalysis/AnalysisResult.cs @@ -11,9 +11,13 @@ public LogAnalysis(string rawLogText, LogAnalysisService service) } public string RawLogContent { get; } - public List LogErrors; + public List Errors; + public List Notes; + // Fatal errors are errors that prevent the log from being scanned + public List FatalErrors; + public HardwareInfo Hardware; - public EmulatorInfo EmulatorInfo; + public EmulatorInfo Emulator; public GameInfo Game; public Settings Settings; } @@ -23,6 +27,7 @@ public class HardwareInfo public string Cpu { get; set; } public string Gpu { get; set; } public string Ram { get; set; } + public string RamAvailable { get; set; } public string Os { get; set; } } @@ -31,6 +36,7 @@ public class EmulatorInfo public (RyujinxVersion VersionType, string VersionString) Version { get; set; } public string Firmware { get; set; } public string EnabledLogs { get; set; } + public string Timestamp { get; set; } } public class GameInfo @@ -39,7 +45,6 @@ public class GameInfo public string AppId { get; set; } public string AppIdBids { get; set; } public string BuildIDs { get; set; } - public string Errors { get; set; } public string Mods { get; set; } public string Cheats { get; set; } } @@ -62,6 +67,6 @@ public class Settings public string AnisotropicFiltering { get; set; } public string AspectRatio { get; set; } public bool TextureRecompression { get; set; } - public string CustomVSyncInterval { get; set; } + public bool CustomVSyncInterval { get; set; } public string MultiplayerMode { get; set; } } \ No newline at end of file diff --git a/src/Bot/Services/LogAnalysis/Notes.cs b/src/Bot/Services/LogAnalysis/Notes.cs new file mode 100644 index 00000000..2e005aac --- /dev/null +++ b/src/Bot/Services/LogAnalysis/Notes.cs @@ -0,0 +1,82 @@ +namespace RyuBot.Services; + +public class Notes +{ + public readonly string AMDOpenGL = "⚠️ **AMD GPU users should consider using Vulkan graphics backend**"; + public readonly string IntelOpenGL = "⚠️ **Intel GPU users should consider using Vulkan graphics backend**"; + public readonly string IntelMac = "⚠️ **Intel Macs are not supported.**"; + public readonly string Rosetta = "🔴 **Rosetta should be disabled**"; + public readonly string DebugLogs = "⚠️ **Debug logs enabled will have a negative impact on performance**"; + + public readonly string MissingLogs = "⚠️ **Logs settings are not default. Consider enabled `Info`, " + + "`Warning`, `Error` and `Guest` logs.**"; + + public readonly string DummyAudio = "⚠️ Dummy audio backend, consider changing to SDL2."; + public readonly string Pptc = "🔴 **PPTC cache should be enabled**"; + public readonly string ShaderCache = "🔴 **Shader cache should be enabled.**"; + + public readonly string SoftwareMemory = "🔴 **`Software` setting in Memory Manager Mode will give slower " + + "performance than the default setting of `Host unchecked`.**"; + + public readonly string MissingServices = "⚠️ `Ignore Missing Services` being enabled can cause instability."; + + public readonly string FSIntegrity = + "⚠️ Disabling file integrity checks may cause corrupted dumps to not be detected."; + + public readonly string VSync = "⚠️ V-Sync disabled can cause instability like games running faster than " + + "intended or longer load times."; + + public readonly string IgnoreApplet = + "⚠️ `Ignore Applets` can cause instability like games not functioning correctly."; + + public readonly string HashError = "🔴 Dump error detected. Investigate possible bad game/firmware dump issues."; + public readonly string GameCrashed = "🔴 The game itself crashed, not Ryujinx."; + public readonly string MissingKeys = "⚠️ Keys or firmware out of date, consider updating them."; + + public readonly string PermissionError = "🔴 File permission error. Consider deleting save directory and " + + "allowing Ryujinx to make a new one."; + + public readonly string FSTargetError = "🔴 Save not found error. Consider starting game without a save file or " + + "using a new save file."; + + public readonly string ServiceError = "⚠️ Consider enabling `Ignore Missing Services` in Ryujinx settings."; + public readonly string VramError = "⚠️ Consider enabling `Texture Recompression` in Ryujinx settings."; + public readonly string DefaultProfile = "⚠️ Default user profile in use, consider creating a custom one."; + public readonly string SaveDataIndex = "🔴 **Save data index for the game may be corrupted.**"; + public readonly string DramSize = "⚠️ `DRAM size` should only be increased for 4K mods."; + public readonly string BackendThreadingAuto = "🔴 **Graphics Backend Multithreading should be set to `Auto`.**"; + + public readonly string CustomRefreshRate = "⚠️ Custom Refresh Rate is experimental, it should only be " + + "enabled in specific cases."; + + public readonly string Firmware = + "❌ **Nintendo Switch firmware not found**, consider adding your keys and firmware."; + + public readonly string Metal = "⚠️ **The Metal backend is experimental. " + + "If you're experiencing issues, switch to Vulkan or Auto.**"; + + public readonly string ShaderCacheCollision = + "⚠️ Cache collision detected. Investigate possible shader cache issues."; + + public readonly string ShaderCacheCorruption = + "⚠️ Cache corruption detected. Investigate possible shader cache issues."; +} + +public class FatalErrors +{ + public readonly string Custom = "⚠️ **Custom builds are not officially supported**"; + + public readonly string OriginalLDN = + "**The old Ryujinx LDN build no longer works. Please update to " + + "[this version](). *Yes, it has LDN functionality.***"; + + public readonly string Original = + "**⚠️ It seems you're still using the original Ryujinx. " + + "Please update to [this version]()," + + " as that's what this Discord server is for.**"; + + public readonly string Mirror = + "**It seems you're using the other Ryujinx fork, ryujinx-mirror. " + + "Please update to [this version](), " + + "as that's what this Discord server is for; or go to their Discord server for support.**"; +} \ No newline at end of file diff --git a/src/Bot/Services/LogAnalysis/RyuLogReader.cs b/src/Bot/Services/LogAnalysis/RyuLogReader.cs index d0c81a63..f9b27ae3 100644 --- a/src/Bot/Services/LogAnalysis/RyuLogReader.cs +++ b/src/Bot/Services/LogAnalysis/RyuLogReader.cs @@ -4,7 +4,9 @@ namespace RyuBot.Services; public class RyuLogReader { - public LogAnalysis Log; + private LogAnalysis _log; + private Notes _notes; + private FatalErrors _fatalErrors; double ConvertGiBtoMiB(double GiB) { @@ -14,22 +16,63 @@ double ConvertGiBtoMiB(double GiB) static bool IsHomebrew(string logFile) { Match m = Regex.Match(logFile, "Load.*Application: Loading as [Hh]omebrew"); - if (m.Success) return true; - if (!m.Success) return false; - else return false; + return m.Success; } static bool IsUsingMetal(string logFile) { Match m = Regex.Match(logFile, "Gpu : Backend \\(Metal\\): Metal"); - if (m.Success) return true; - if (!m.Success) return false; - else return false; + return m.Success; + } + + (RyujinxVersion VersionType, string VersionString) GetEmuVersion() + { + // Ryujinx Version check + foreach (string line in _log.RawLogContent.Split("\n")) + { + // Greem's Stable build + if (LogAnalysisPatterns.StableVersion.IsMatch(line)) + { + return (RyujinxVersion.Stable, line[-1].ToString().Trim()); + } + + // Greem's Canary build + if (LogAnalysisPatterns.CanaryVersion.IsMatch(line)) + { + return (RyujinxVersion.Canary, line[-1].ToString().Trim()); + } + + // PR build + if (LogAnalysisPatterns.PrVersion.IsMatch(line) + || LogAnalysisPatterns.OriginalPrVersion.IsMatch(line)) + { + return (RyujinxVersion.Pr, line[-1].ToString().Trim()); + } + + // Original Project build + if (LogAnalysisPatterns.OriginalProjectVersion.IsMatch(line)) + { + return (RyujinxVersion.OriginalProject, line[-1].ToString().Trim()); + } + + // Original Project LDN build + if (LogAnalysisPatterns.OriginalProjectLdnVersion.IsMatch(line)) + { + return (RyujinxVersion.OriginalProjectLdn, line[-1].ToString().Trim()); + } + + if (LogAnalysisPatterns.MirrorVersion.IsMatch(line)) + { + return (RyujinxVersion.Mirror, line[-1].ToString().Trim()); + } + } + + return (RyujinxVersion.Custom, "1.0.0-dirty"); } void GetAppInfo() { - MatchCollection gameNameMatch = Regex.Matches(Log.RawLogContent, + MatchCollection gameNameMatch = Regex.Matches(_log.RawLogContent, @"Loader [A-Za-z]*: Application Loaded:\s([^;\n\r]*)", RegexOptions.Multiline); if (!gameNameMatch.None()) { @@ -46,7 +89,7 @@ void GetAppInfo() appID = "Unknown"; } - MatchCollection bidsMatchAll = Regex.Matches(Log.RawLogContent, + MatchCollection bidsMatchAll = Regex.Matches(_log.RawLogContent, @"Build ids found for (?:title|application) ([a-zA-Z0-9]*):[\n\r]*((?:\s+.*[\n\r]+)+)"); if (!bidsMatchAll.None() && bidsMatchAll.Count > 0) { @@ -55,7 +98,7 @@ void GetAppInfo() string appIDFromBids; string BuildIDs; - if (bidsMatch[0].ToString() != null) + if (bidsMatch[0].ToString() != "") { appIDFromBids = bidsMatch[0].ToString().Trim().ToUpper(); } @@ -64,7 +107,7 @@ void GetAppInfo() appIDFromBids = "Unknown"; } - if (bidsMatch[1].ToString() != null) + if (bidsMatch[1].ToString() != "") { // this might not work BuildIDs = bidsMatch[1].ToString().Trim().ToUpper(); @@ -74,10 +117,10 @@ void GetAppInfo() BuildIDs = "Unknown"; } - Log.Game.Name = gameName; - Log.Game.AppId = appID; - Log.Game.AppIdBids = appIDFromBids; - Log.Game.BuildIDs = BuildIDs; + _log.Game.Name = gameName; + _log.Game.AppId = appID; + _log.Game.AppIdBids = appIDFromBids; + _log.Game.BuildIDs = BuildIDs; } } } @@ -105,7 +148,7 @@ void GetErrors() List currentErrorsLines = new List(); bool errorLine = false; - foreach (string line in Log.RawLogContent.Split("\n")) + foreach (string line in _log.RawLogContent.Split("\n")) { if (line.IsNullOrWhitespace()) { @@ -129,131 +172,99 @@ void GetErrors() errors.AddRange(currentErrorsLines); } - Log.LogErrors = errors; + _log.Errors = errors; } - string[] _sizes = ["KB", "KiB", "MB", "MiB", "GB", "GiB"]; + readonly string[] _sizes = ["KB", "KiB", "MB", "MiB", "GB", "GiB"]; void GetHardwareInfo() { // CPU - Match cpuMatch = Regex.Match(Log.RawLogContent, @"CPU:\s([^;\n\r]*)", RegexOptions.Multiline); + Match cpuMatch = Regex.Match(_log.RawLogContent, @"CPU:\s([^;\n\r]*)", RegexOptions.Multiline); if (cpuMatch.Success) { - Log.Hardware.Cpu = cpuMatch.Groups[1].Value.TrimEnd(); + _log.Hardware.Cpu = cpuMatch.Groups[1].Value.TrimEnd(); } else { - Log.Hardware.Cpu = "Unknown"; + _log.Hardware.Cpu = "Unknown"; } // RAM - Match ramMatch = Regex.Match(Log.RawLogContent, + Match ramMatch = Regex.Match(_log.RawLogContent, @$"RAM: Total ([\d.]+) ({_sizes}) ; Available ([\d.]+) ({_sizes})", RegexOptions.Multiline); if (ramMatch.Success) { double ramAvailable = ConvertGiBtoMiB(Convert.ToDouble(ramMatch.Groups[3].Value)); double ramTotal = ConvertGiBtoMiB(Convert.ToDouble(ramMatch.Groups[1].Value)); - Log.Hardware.Ram = $"{ramAvailable:.0f}/{ramTotal:.0f} MiB"; + _log.Hardware.Ram = $"{ramAvailable:.0f}/{ramTotal:.0f} MiB"; + _log.Hardware.RamAvailable = ramAvailable.ToString("0.0"); } else { - Log.Hardware.Ram = "Unknown"; + _log.Hardware.Ram = "Unknown"; + _log.Hardware.RamAvailable = "Unknown"; } // Operating System (OS) - Match osMatch = Regex.Match(Log.RawLogContent, @"Operating System:\s([^;\n\r]*)", + Match osMatch = Regex.Match(_log.RawLogContent, @"Operating System:\s([^;\n\r]*)", RegexOptions.Multiline); if (osMatch.Success) { - Log.Hardware.Os = osMatch.Groups[1].Value.TrimEnd(); + _log.Hardware.Os = osMatch.Groups[1].Value.TrimEnd(); } else { - Log.Hardware.Os = "Unknown"; + _log.Hardware.Os = "Unknown"; } // GPU - Match gpuMatch = Regex.Match(Log.RawLogContent, @"PrintGpuInformation:\s([^;\n\r]*)", + Match gpuMatch = Regex.Match(_log.RawLogContent, @"PrintGpuInformation:\s([^;\n\r]*)", RegexOptions.Multiline); if (gpuMatch.Success) { - Log.Hardware.Gpu = gpuMatch.Groups[1].Value.TrimEnd(); + _log.Hardware.Gpu = gpuMatch.Groups[1].Value.TrimEnd(); // If android logs starts showing up, we can detect android GPUs here } else { - Log.Hardware.Gpu = "Unknown"; + _log.Hardware.Gpu = "Unknown"; } } void GetEmuInfo() { - // Ryujinx Version check - foreach (string line in Log.RawLogContent.Split("\n")) - { - // Greem's Stable build - if (LogAnalysisPatterns.StableVersion.IsMatch(line)) - { - Log.EmulatorInfo.Version = (RyujinxVersion.Stable, line.Split("\n")[-1].Trim()); - } - // Greem's Canary build - else if (LogAnalysisPatterns.CanaryVersion.IsMatch(line)) - { - Log.EmulatorInfo.Version = (RyujinxVersion.Canary, line.Split("\n")[-1].Trim()); - } - // PR build - else if (LogAnalysisPatterns.PrVersion.IsMatch(line) || LogAnalysisPatterns.OriginalPrVersion.IsMatch(line)) - { - Log.EmulatorInfo.Version = (RyujinxVersion.Pr, line.Split("\n")[-1].Trim()); - } - // Original Project build - else if (LogAnalysisPatterns.OriginalProjectVersion.IsMatch(line)) - { - Log.EmulatorInfo.Version = (RyujinxVersion.OriginalProject, line.Split("\n")[-1].Trim()); - } - // Original Project LDN build - else if (LogAnalysisPatterns.OriginalProjectLdnVersion.IsMatch(line)) - { - Log.EmulatorInfo.Version = (RyujinxVersion.OriginalProjectLdn, line.Split("\n")[-1].Trim()); - } - // Custom build - else - { - Log.EmulatorInfo.Version = (RyujinxVersion.Custom, line.Split("\n")[-1].Trim()); - } - } + _log.Emulator.Version = GetEmuVersion(); // Logs Enabled ? - Match logsMatch = Regex.Match(Log.RawLogContent, @"Logs Enabled:\s([^;\n\r]*)", + Match logsMatch = Regex.Match(_log.RawLogContent, @"Logs Enabled:\s([^;\n\r]*)", RegexOptions.Multiline); if (logsMatch.Success) { - Log.EmulatorInfo.EnabledLogs = logsMatch.Groups[1].Value.TrimEnd(); + _log.Emulator.EnabledLogs = logsMatch.Groups[1].Value.TrimEnd(); } else { - Log.EmulatorInfo.EnabledLogs = "Unknown"; + _log.Emulator.EnabledLogs = "Unknown"; } // Firmware - Match firmwareMatch = Regex.Match(Log.RawLogContent, @"Firmware Version:\s([^;\n\r]*)", + Match firmwareMatch = Regex.Match(_log.RawLogContent, @"Firmware Version:\s([^;\n\r]*)", RegexOptions.Multiline); if (firmwareMatch.Success) { - Log.EmulatorInfo.Firmware = firmwareMatch.Groups[-1].Value.Trim(); + _log.Emulator.Firmware = firmwareMatch.Groups[-1].Value.Trim(); } else { - Log.EmulatorInfo.Firmware = "Unknown"; + _log.Emulator.Firmware = "Unknown"; } } void GetSettings() { - - MatchCollection settingsMatch = Regex.Matches(Log.RawLogContent, @"LogValueChange:\s([^;\n\r]*)", + MatchCollection settingsMatch = Regex.Matches(_log.RawLogContent, @"LogValueChange:\s([^;\n\r]*)", RegexOptions.Multiline); foreach (string line in settingsMatch) @@ -263,38 +274,38 @@ void GetSettings() // Resolution Scale case "ResScaleCustom set to:": case "ResScale set to:": - Log.Settings.ResScale = settingsMatch[0].Groups[2].Value.Trim(); - switch (Log.Settings.ResScale) + _log.Settings.ResScale = settingsMatch[0].Groups[2].Value.Trim(); + switch (_log.Settings.ResScale) { case "1": - Log.Settings.ResScale = "Native (720p/1080p)"; + _log.Settings.ResScale = "Native (720p/1080p)"; break; case "2": - Log.Settings.ResScale = "2x (1440p/2060p(4K))"; + _log.Settings.ResScale = "2x (1440p/2060p(4K))"; break; case "3": - Log.Settings.ResScale = "3x (2160p(4K)/3240p)"; + _log.Settings.ResScale = "3x (2160p(4K)/3240p)"; break; case "4": - Log.Settings.ResScale = "4x (3240p/4320p(8K))"; + _log.Settings.ResScale = "4x (3240p/4320p(8K))"; break; case "-1": - Log.Settings.ResScale = "Custom"; + _log.Settings.ResScale = "Custom"; break; } break; // Anisotropic Filtering case "MaxAnisotropy set to:": - Log.Settings.AnisotropicFiltering = settingsMatch[0].Groups[2].Value.Trim(); + _log.Settings.AnisotropicFiltering = settingsMatch[0].Groups[2].Value.Trim(); break; // Aspect Ratio case "AspectRatio set to:": - Log.Settings.AspectRatio = settingsMatch[0].Groups[2].Value.Trim(); - switch (Log.Settings.AspectRatio) + _log.Settings.AspectRatio = settingsMatch[0].Groups[2].Value.Trim(); + switch (_log.Settings.AspectRatio) { case "Fixed16x9": - Log.Settings.AspectRatio = "16:9"; + _log.Settings.AspectRatio = "16:9"; break; // TODO: add more aspect ratios } @@ -302,51 +313,59 @@ void GetSettings() break; // Graphics Backend case "GraphicsBackend set to:": - Log.Settings.GraphicsBackend = settingsMatch[0].Groups[2].Value.Trim(); + _log.Settings.GraphicsBackend = settingsMatch[0].Groups[2].Value.Trim(); break; // Custom VSync Interval case "CustomVSyncInterval set to:": - Log.Settings.CustomVSyncInterval = settingsMatch[0].Groups[2].Value.Trim(); + string a = settingsMatch[0].Groups[2].Value.Trim(); + if (a == "False") + { + _log.Settings.CustomVSyncInterval = false; + } + else if (a == "True") + { + _log.Settings.CustomVSyncInterval = true; + } break; // Shader cache case "EnableShaderCache set to: True": - Log.Settings.ShaderCache = true; + _log.Settings.ShaderCache = true; break; case "EnableShaderCache set to: False": - Log.Settings.ShaderCache = false; + _log.Settings.ShaderCache = false; break; // Docked or Handheld case "EnableDockedMode set to: True": - Log.Settings.Docked = true; + _log.Settings.Docked = true; break; case "EnableDockedMode set to: False": - Log.Settings.Docked = false; + _log.Settings.Docked = false; break; // PPTC Cache case "EnablePtc set to: True": - Log.Settings.Pptc = true; + _log.Settings.Pptc = true; break; case "EnablePtc set to: False": - Log.Settings.Pptc = false; + _log.Settings.Pptc = false; break; // FS Integrity check case "EnableFsIntegrityChecks set to: True": - Log.Settings.FsIntegrityChecks = true; + _log.Settings.FsIntegrityChecks = true; break; case "EnableFsIntegrityChecks set to: False": - Log.Settings.FsIntegrityChecks = false; + _log.Settings.FsIntegrityChecks = false; break; // Audio Backend case "AudioBackend set to:": - Log.Settings.AudioBackend = settingsMatch[0].Groups[2].Value.Trim(); + _log.Settings.AudioBackend = settingsMatch[0].Groups[2].Value.Trim(); break; // Memory Manager Mode case "MemoryManagerMode set to:": - Log.Settings.MemoryManager = settingsMatch[0].Groups[2].Value.Trim(); - switch (Log.Settings.MemoryManager) + _log.Settings.MemoryManager = settingsMatch[0].Groups[2].Value.Trim(); + switch (_log.Settings.MemoryManager) { case "HostMappedUnsafe": - Log.Settings.MemoryManager = "Unsafe"; + _log.Settings.MemoryManager = "Unsafe"; break; // TODO: Add more memory manager modes } @@ -354,32 +373,35 @@ void GetSettings() break; // Hypervisor case "UseHypervisor set to:": - Log.Settings.Hypervisor = settingsMatch[0].Groups[2].Value.Trim(); - // If the OS is windows or linux, set hypervisor to 'N/A' because it's only on macos - if (Log.Hardware.Os.ToLower() == "windows" || Log.Hardware.Os.ToLower() == "linux") + _log.Settings.Hypervisor = settingsMatch[0].Groups[2].Value.Trim(); + // If the OS is windows or linux, set hypervisor to 'N/A' because it's only on macOS + if (_log.Hardware.Os.ToLower() == "windows" || _log.Hardware.Os.ToLower() == "linux") { - Log.Settings.Hypervisor = "N/A"; + _log.Settings.Hypervisor = "N/A"; } break; // Ldn Mode case "MultiplayerMode set to:": - Log.Settings.MultiplayerMode = settingsMatch[0].Groups[2].Value.Trim(); + _log.Settings.MultiplayerMode = settingsMatch[0].Groups[2].Value.Trim(); + break; + case "DramSize set to:": + _log.Settings.DramSize = settingsMatch[0].Groups[2].Value.Trim(); break; // This is just in case EVERYTHING fails default: - Log.Settings.ResScale = "Failed"; - Log.Settings.AnisotropicFiltering = "Failed"; - Log.Settings.AspectRatio = "Failed"; - Log.Settings.GraphicsBackend = "Failed"; - Log.Settings.CustomVSyncInterval = "Failed"; - Log.Settings.ShaderCache = false; - Log.Settings.Docked = false; - Log.Settings.Pptc = false; - Log.Settings.FsIntegrityChecks = false; - Log.Settings.AudioBackend = "Failed"; - Log.Settings.MemoryManager = "Failed"; - Log.Settings.Hypervisor = "Failed"; + _log.Settings.ResScale = "Failed"; + _log.Settings.AnisotropicFiltering = "Failed"; + _log.Settings.AspectRatio = "Failed"; + _log.Settings.GraphicsBackend = "Failed"; + _log.Settings.CustomVSyncInterval = false; + _log.Settings.ShaderCache = false; + _log.Settings.Docked = false; + _log.Settings.Pptc = false; + _log.Settings.FsIntegrityChecks = false; + _log.Settings.AudioBackend = "Failed"; + _log.Settings.MemoryManager = "Failed"; + _log.Settings.Hypervisor = "Failed"; break; } } @@ -387,26 +409,226 @@ void GetSettings() void GetMods() { - MatchCollection modsMatch = Regex.Matches(Log.RawLogContent, + MatchCollection modsMatch = Regex.Matches(_log.RawLogContent, "Found\\s(enabled)?\\s?mod\\s\\'(.+?)\\'\\s(\\[.+?\\])"); - Log.Game.Mods += modsMatch; + _log.Game.Mods += modsMatch; } void GetCheats() { - MatchCollection cheatsMatch = Regex.Matches(Log.RawLogContent, + MatchCollection cheatsMatch = Regex.Matches(_log.RawLogContent, @"Installing cheat\s'(.+)'(?!\s\d{2}:\d{2}:\d{2}\.\d{3}\s\|E\|\sTamperMachine\sCompile)"); - Log.Game.Cheats += cheatsMatch; + _log.Game.Cheats += cheatsMatch; } void GetAppName() { - Match appNameMatch = Regex.Match(Log.RawLogContent, + Match appNameMatch = Regex.Match(_log.RawLogContent, @"Loader [A-Za-z]*: Application Loaded:\s([^;\n\r]*)", RegexOptions.Multiline); - Log.Game.Name += appNameMatch; + _log.Game.Name += appNameMatch; } + void GetNotes() + { + string GetControllerNotes() + { + MatchCollection controllerNotesMatch = Regex.Matches(_log.RawLogContent, + @"Hid Configure: ([^\r\n]+)"); + if (controllerNotesMatch.Count != 0) + { + return controllerNotesMatch.ToString(); + } + else { return null; } + } + + string GetOSNotes() + { + if (_log.Hardware.Os.ToLower().Contains("windows") + && !_log.Settings.GraphicsBackend.Contains("Vulkan")) + { + if (_log.Hardware.Gpu.Contains("Intel")) + { + return _notes.IntelOpenGL; + } + if (_log.Hardware.Gpu.Contains("AMD")) + { + return _notes.AMDOpenGL; + } + } + + if (_log.Hardware.Os.ToLower().Contains("macos") && !_log.Hardware.Cpu.Contains("Intel")) + { + return _notes.IntelMac; + } + + return null; + } + + string GetCpuNotes() + { + if (_log.Hardware.Cpu.ToLower().Contains("VirtualApple")) + { + return _notes.Rosetta; + } + + return null; + } + + string GetLogNotes() + { + if (_log.Emulator.EnabledLogs.Contains("Debug")) + { + return _notes.DebugLogs; + } + + if (_log.Emulator.EnabledLogs.Length < 4) + { + return _notes.MissingLogs; + } + + return null; + } + + void GetSettingsNotes() + { + if (_log.Settings.AudioBackend == "Dummy") + { + _log.Notes.Add(_notes.DummyAudio); + } + + if (_log.Settings.Pptc == false) + { + _log.Notes.Add(_notes.Pptc); + } + + if (_log.Settings.ShaderCache == false) + { + _log.Notes.Add(_notes.ShaderCache); + } + + if (_log.Settings.DramSize != "" && !_log.Game.Mods.Contains("4K")) + { + _log.Notes.Add(_notes.DramSize); + } + + if (_log.Settings.MemoryManager == "SoftwarePageTable") + { + _log.Notes.Add(_notes.SoftwareMemory); + } + + if (_log.Settings.VSyncMode == "Unbounded") + { + _log.Notes.Add(_notes.VSync); + } + + if (_log.Settings.FsIntegrityChecks == false) + { + _log.Notes.Add(_notes.FSIntegrity); + } + + if (_log.Settings.BackendThreading == false) + { + _log.Notes.Add(_notes.BackendThreadingAuto); + } + + if (_log.Settings.CustomVSyncInterval) + { + _log.Notes.Add(_notes.CustomRefreshRate); + } + } + + void GetEmulatorNotes() + { + if (ContainsError(["Cache collision found"], _log.Errors)) + { + _log.Errors.Add(_notes.ShaderCacheCollision); + } + + if (ContainsError([ + "ResultFsInvalidIvfcHash", + "ResultFsNonRealDataVerificationFailed",], _log.Errors)) + { + _log.Errors.Add(_notes.HashError); + } + + if (ContainsError([ + "Ryujinx.Graphics.Gpu.Shader.ShaderCache.Initialize()", + "System.IO.InvalidDataException: End of Central Directory record could not be found", + "ICSharpCode.SharpZipLib.Zip.ZipException: Cannot find central directory", + ], _log.Errors)) + { + _log.Errors.Add(_notes.ShaderCacheCorruption); + } + + if (ContainsError(["MissingKeyException"], _log.Errors)) + { + _log.Errors.Add(_notes.MissingKeys); + } + + if (ContainsError(["ResultFsPermissionDenied"], _log.Errors)) + { + _log.Errors.Add(_notes.PermissionError); + } + + if (ContainsError(["ResultFsTargetNotFound"], _log.Errors)) + { + _log.Errors.Add(_notes.FSTargetError); + } + + if (ContainsError(["ServiceNotImplementedException"], _log.Errors)) + { + _log.Errors.Add(_notes.MissingServices); + } + + if (ContainsError(["ErrorOutOfDeviceMemory"], _log.Errors)) + { + _log.Errors.Add(_notes.VramError); + } + } + + Match latestTimestamp = Regex.Matches(_log.RawLogContent, @"(\d{2}:\d{2}:\d{2}\.\d{3})\s+?\|")[-1]; + if (latestTimestamp.Success) + { + _log.Notes.Add("ℹ️ Time elapsed: " + latestTimestamp.Value); + } + + _log.Notes.Add(GetControllerNotes()); + _log.Notes.Add(GetOSNotes()); + _log.Notes.Add(GetCpuNotes()); + + if (_log.Emulator.Firmware == "Unknown" || _log.Emulator.Firmware == null + && _log.Game.Name != "Unknown" || _log.Game.Name == null) + { + _log.Notes.Add(_notes.Firmware); + } + + _log.Notes.Add(GetLogNotes()); + GetSettingsNotes(); + GetEmulatorNotes(); + + if (IsUsingMetal(_log.RawLogContent)) + { + _log.Notes.Add(_notes.Metal); + } + + var ryujinxVersion = GetEmuVersion(); + + if (ryujinxVersion.VersionType == RyujinxVersion.Custom) + { + _log.FatalErrors.Add(_fatalErrors.Custom); + } else if (ryujinxVersion.VersionType == RyujinxVersion.OriginalProjectLdn) + { + _log.FatalErrors.Add(_fatalErrors.OriginalLDN); + } + else if (ryujinxVersion.VersionType == RyujinxVersion.OriginalProject) + { + _log.FatalErrors.Add(_fatalErrors.Original); + } else if (ryujinxVersion.VersionType == RyujinxVersion.Mirror) + { + _log.FatalErrors.Add(_fatalErrors.Mirror); + } + } } From 3fc75211a794606f938739c57d043f2a2e1f9a2c Mon Sep 17 00:00:00 2001 From: GabCoolDude Date: Sat, 8 Feb 2025 10:13:22 +0100 Subject: [PATCH 5/7] Fix variable casing --- src/Bot/Services/LogAnalysis/Notes.cs | 6 +-- src/Bot/Services/LogAnalysis/RyuLogReader.cs | 47 ++++++++++---------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/Bot/Services/LogAnalysis/Notes.cs b/src/Bot/Services/LogAnalysis/Notes.cs index 2e005aac..53089a0a 100644 --- a/src/Bot/Services/LogAnalysis/Notes.cs +++ b/src/Bot/Services/LogAnalysis/Notes.cs @@ -20,7 +20,7 @@ public class Notes public readonly string MissingServices = "⚠️ `Ignore Missing Services` being enabled can cause instability."; - public readonly string FSIntegrity = + public readonly string FsIntegrity = "⚠️ Disabling file integrity checks may cause corrupted dumps to not be detected."; public readonly string VSync = "⚠️ V-Sync disabled can cause instability like games running faster than " + @@ -36,7 +36,7 @@ public class Notes public readonly string PermissionError = "🔴 File permission error. Consider deleting save directory and " + "allowing Ryujinx to make a new one."; - public readonly string FSTargetError = "🔴 Save not found error. Consider starting game without a save file or " + + public readonly string FsTargetError = "🔴 Save not found error. Consider starting game without a save file or " + "using a new save file."; public readonly string ServiceError = "⚠️ Consider enabling `Ignore Missing Services` in Ryujinx settings."; @@ -66,7 +66,7 @@ public class FatalErrors { public readonly string Custom = "⚠️ **Custom builds are not officially supported**"; - public readonly string OriginalLDN = + public readonly string OriginalLdn = "**The old Ryujinx LDN build no longer works. Please update to " + "[this version](). *Yes, it has LDN functionality.***"; diff --git a/src/Bot/Services/LogAnalysis/RyuLogReader.cs b/src/Bot/Services/LogAnalysis/RyuLogReader.cs index f9b27ae3..b70562f7 100644 --- a/src/Bot/Services/LogAnalysis/RyuLogReader.cs +++ b/src/Bot/Services/LogAnalysis/RyuLogReader.cs @@ -78,15 +78,15 @@ void GetAppInfo() { string gameName = gameNameMatch[-1].ToString().Trim(); - string appID; - Match appIDMatch = Regex.Match(gameName, @".* \[([a-zA-Z0-9]*)\]"); - if (appIDMatch.Success) + string appId; + Match appIdMatch = Regex.Match(gameName, @".* \[([a-zA-Z0-9]*)\]"); + if (appIdMatch.Success) { - appID = appIDMatch.Groups[1].Value.Trim().ToUpper(); + appId = appIdMatch.Groups[1].Value.Trim().ToUpper(); } else { - appID = "Unknown"; + appId = "Unknown"; } MatchCollection bidsMatchAll = Regex.Matches(_log.RawLogContent, @@ -95,32 +95,32 @@ void GetAppInfo() { // this whole thing might not work properly string bidsMatch = bidsMatchAll[-1].ToString(); - string appIDFromBids; - string BuildIDs; + string appIdFromBids; + string buildIDs; if (bidsMatch[0].ToString() != "") { - appIDFromBids = bidsMatch[0].ToString().Trim().ToUpper(); + appIdFromBids = bidsMatch[0].ToString().Trim().ToUpper(); } else { - appIDFromBids = "Unknown"; + appIdFromBids = "Unknown"; } if (bidsMatch[1].ToString() != "") { // this might not work - BuildIDs = bidsMatch[1].ToString().Trim().ToUpper(); + buildIDs = bidsMatch[1].ToString().Trim().ToUpper(); } else { - BuildIDs = "Unknown"; + buildIDs = "Unknown"; } _log.Game.Name = gameName; - _log.Game.AppId = appID; - _log.Game.AppIdBids = appIDFromBids; - _log.Game.BuildIDs = BuildIDs; + _log.Game.AppId = appId; + _log.Game.AppIdBids = appIdFromBids; + _log.Game.BuildIDs = buildIDs; } } } @@ -411,14 +411,14 @@ void GetMods() { MatchCollection modsMatch = Regex.Matches(_log.RawLogContent, "Found\\s(enabled)?\\s?mod\\s\\'(.+?)\\'\\s(\\[.+?\\])"); - _log.Game.Mods += modsMatch; + _log.Game.Mods = modsMatch.ToString(); } void GetCheats() { MatchCollection cheatsMatch = Regex.Matches(_log.RawLogContent, @"Installing cheat\s'(.+)'(?!\s\d{2}:\d{2}:\d{2}\.\d{3}\s\|E\|\sTamperMachine\sCompile)"); - _log.Game.Cheats += cheatsMatch; + _log.Game.Cheats = cheatsMatch.ToString(); } void GetAppName() @@ -426,7 +426,7 @@ void GetAppName() Match appNameMatch = Regex.Match(_log.RawLogContent, @"Loader [A-Za-z]*: Application Loaded:\s([^;\n\r]*)", RegexOptions.Multiline); - _log.Game.Name += appNameMatch; + _log.Game.Name = appNameMatch.ToString(); } void GetNotes() @@ -439,10 +439,11 @@ string GetControllerNotes() { return controllerNotesMatch.ToString(); } - else { return null; } + + return null; } - string GetOSNotes() + string GetOsNotes() { if (_log.Hardware.Os.ToLower().Contains("windows") && !_log.Settings.GraphicsBackend.Contains("Vulkan")) @@ -524,7 +525,7 @@ void GetSettingsNotes() if (_log.Settings.FsIntegrityChecks == false) { - _log.Notes.Add(_notes.FSIntegrity); + _log.Notes.Add(_notes.FsIntegrity); } if (_log.Settings.BackendThreading == false) @@ -573,7 +574,7 @@ void GetEmulatorNotes() if (ContainsError(["ResultFsTargetNotFound"], _log.Errors)) { - _log.Errors.Add(_notes.FSTargetError); + _log.Errors.Add(_notes.FsTargetError); } if (ContainsError(["ServiceNotImplementedException"], _log.Errors)) @@ -594,7 +595,7 @@ void GetEmulatorNotes() } _log.Notes.Add(GetControllerNotes()); - _log.Notes.Add(GetOSNotes()); + _log.Notes.Add(GetOsNotes()); _log.Notes.Add(GetCpuNotes()); if (_log.Emulator.Firmware == "Unknown" || _log.Emulator.Firmware == null @@ -619,7 +620,7 @@ void GetEmulatorNotes() _log.FatalErrors.Add(_fatalErrors.Custom); } else if (ryujinxVersion.VersionType == RyujinxVersion.OriginalProjectLdn) { - _log.FatalErrors.Add(_fatalErrors.OriginalLDN); + _log.FatalErrors.Add(_fatalErrors.OriginalLdn); } else if (ryujinxVersion.VersionType == RyujinxVersion.OriginalProject) { From 9815d26c632ebd7790909bed2ed29d7e7e80e220 Mon Sep 17 00:00:00 2001 From: GabCoolDude Date: Sat, 8 Feb 2025 10:28:43 +0100 Subject: [PATCH 6/7] Add missing notes --- src/Bot/Services/LogAnalysis/Notes.cs | 5 +-- src/Bot/Services/LogAnalysis/RyuLogReader.cs | 32 +++++++++++++++++++- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/Bot/Services/LogAnalysis/Notes.cs b/src/Bot/Services/LogAnalysis/Notes.cs index 53089a0a..c92dc91d 100644 --- a/src/Bot/Services/LogAnalysis/Notes.cs +++ b/src/Bot/Services/LogAnalysis/Notes.cs @@ -25,10 +25,7 @@ public class Notes public readonly string VSync = "⚠️ V-Sync disabled can cause instability like games running faster than " + "intended or longer load times."; - - public readonly string IgnoreApplet = - "⚠️ `Ignore Applets` can cause instability like games not functioning correctly."; - + public readonly string HashError = "🔴 Dump error detected. Investigate possible bad game/firmware dump issues."; public readonly string GameCrashed = "🔴 The game itself crashed, not Ryujinx."; public readonly string MissingKeys = "⚠️ Keys or firmware out of date, consider updating them."; diff --git a/src/Bot/Services/LogAnalysis/RyuLogReader.cs b/src/Bot/Services/LogAnalysis/RyuLogReader.cs index b70562f7..5a0487af 100644 --- a/src/Bot/Services/LogAnalysis/RyuLogReader.cs +++ b/src/Bot/Services/LogAnalysis/RyuLogReader.cs @@ -25,6 +25,12 @@ static bool IsUsingMetal(string logFile) return m.Success; } + static bool IsDefaultUserProfile(string logFile) + { + Match m = Regex.Match(logFile, "UserId: 00000000000000010000000000000000"); + return m.Success; + } + (RyujinxVersion VersionType, string VersionString) GetEmuVersion() { // Ryujinx Version check @@ -536,7 +542,12 @@ void GetSettingsNotes() if (_log.Settings.CustomVSyncInterval) { _log.Notes.Add(_notes.CustomRefreshRate); - } + } + + if (_log.Settings.IgnoreMissingServices) + { + _log.Notes.Add(_notes.ServiceError); + } } void GetEmulatorNotes() @@ -586,6 +597,19 @@ void GetEmulatorNotes() { _log.Errors.Add(_notes.VramError); } + + if (ContainsError(["ResultKvdbInvalidKeyValue (2020-0005)"], _log.Errors)) + { + _log.Errors.Add(_notes.SaveDataIndex); + } + + Match gameCrashMatch = + Regex.Match(_log.RawLogContent, "/\\(ResultErrApplicationAborted \\(\\d{4}-\\d{4}\\)\\)/"); + + if (gameCrashMatch.Success) + { + _log.Errors.Add(_notes.GameCrashed); + } } Match latestTimestamp = Regex.Matches(_log.RawLogContent, @"(\d{2}:\d{2}:\d{2}\.\d{3})\s+?\|")[-1]; @@ -593,6 +617,11 @@ void GetEmulatorNotes() { _log.Notes.Add("ℹ️ Time elapsed: " + latestTimestamp.Value); } + + if (IsDefaultUserProfile(_log.RawLogContent)) + { + _log.Notes.Add(_notes.DefaultProfile); + } _log.Notes.Add(GetControllerNotes()); _log.Notes.Add(GetOsNotes()); @@ -629,6 +658,7 @@ void GetEmulatorNotes() { _log.FatalErrors.Add(_fatalErrors.Mirror); } + } } From 2b1daea3fd3d6ff06dd32847e3cbe85d0c839491 Mon Sep 17 00:00:00 2001 From: GabCoolDude Date: Sat, 8 Feb 2025 10:39:51 +0100 Subject: [PATCH 7/7] Finalize log reading --- src/Bot/Services/LogAnalysis/RyuLogReader.cs | 91 +++++--------------- 1 file changed, 21 insertions(+), 70 deletions(-) diff --git a/src/Bot/Services/LogAnalysis/RyuLogReader.cs b/src/Bot/Services/LogAnalysis/RyuLogReader.cs index 5a0487af..7209eba5 100644 --- a/src/Bot/Services/LogAnalysis/RyuLogReader.cs +++ b/src/Bot/Services/LogAnalysis/RyuLogReader.cs @@ -83,17 +83,9 @@ void GetAppInfo() if (!gameNameMatch.None()) { string gameName = gameNameMatch[-1].ToString().Trim(); - - string appId; + Match appIdMatch = Regex.Match(gameName, @".* \[([a-zA-Z0-9]*)\]"); - if (appIdMatch.Success) - { - appId = appIdMatch.Groups[1].Value.Trim().ToUpper(); - } - else - { - appId = "Unknown"; - } + string appId = appIdMatch.Success ? appIdMatch.Groups[1].Value.Trim().ToUpper() : "Unknown"; MatchCollection bidsMatchAll = Regex.Matches(_log.RawLogContent, @"Build ids found for (?:title|application) ([a-zA-Z0-9]*):[\n\r]*((?:\s+.*[\n\r]+)+)"); @@ -101,27 +93,11 @@ void GetAppInfo() { // this whole thing might not work properly string bidsMatch = bidsMatchAll[-1].ToString(); - string appIdFromBids; - string buildIDs; - if (bidsMatch[0].ToString() != "") - { - appIdFromBids = bidsMatch[0].ToString().Trim().ToUpper(); - } - else - { - appIdFromBids = "Unknown"; - } + string appIdFromBids = bidsMatch[0].ToString() != "" ? bidsMatch[0].ToString().Trim().ToUpper() : "Unknown"; - if (bidsMatch[1].ToString() != "") - { - // this might not work - buildIDs = bidsMatch[1].ToString().Trim().ToUpper(); - } - else - { - buildIDs = "Unknown"; - } + // this might not work + string buildIDs = bidsMatch[1].ToString() != "" ? bidsMatch[1].ToString().Trim().ToUpper() : "Unknown"; _log.Game.Name = gameName; _log.Game.AppId = appId; @@ -187,14 +163,7 @@ void GetHardwareInfo() { // CPU Match cpuMatch = Regex.Match(_log.RawLogContent, @"CPU:\s([^;\n\r]*)", RegexOptions.Multiline); - if (cpuMatch.Success) - { - _log.Hardware.Cpu = cpuMatch.Groups[1].Value.TrimEnd(); - } - else - { - _log.Hardware.Cpu = "Unknown"; - } + _log.Hardware.Cpu = cpuMatch.Success ? cpuMatch.Groups[1].Value.TrimEnd() : "Unknown"; // RAM Match ramMatch = Regex.Match(_log.RawLogContent, @@ -215,27 +184,14 @@ void GetHardwareInfo() // Operating System (OS) Match osMatch = Regex.Match(_log.RawLogContent, @"Operating System:\s([^;\n\r]*)", RegexOptions.Multiline); - if (osMatch.Success) - { - _log.Hardware.Os = osMatch.Groups[1].Value.TrimEnd(); - } - else - { - _log.Hardware.Os = "Unknown"; - } + _log.Hardware.Os = osMatch.Success ? osMatch.Groups[1].Value.TrimEnd() : "Unknown"; // GPU Match gpuMatch = Regex.Match(_log.RawLogContent, @"PrintGpuInformation:\s([^;\n\r]*)", RegexOptions.Multiline); - if (gpuMatch.Success) - { - _log.Hardware.Gpu = gpuMatch.Groups[1].Value.TrimEnd(); + _log.Hardware.Gpu = gpuMatch.Success ? gpuMatch.Groups[1].Value.TrimEnd() : // If android logs starts showing up, we can detect android GPUs here - } - else - { - _log.Hardware.Gpu = "Unknown"; - } + "Unknown"; } void GetEmuInfo() @@ -245,26 +201,12 @@ void GetEmuInfo() // Logs Enabled ? Match logsMatch = Regex.Match(_log.RawLogContent, @"Logs Enabled:\s([^;\n\r]*)", RegexOptions.Multiline); - if (logsMatch.Success) - { - _log.Emulator.EnabledLogs = logsMatch.Groups[1].Value.TrimEnd(); - } - else - { - _log.Emulator.EnabledLogs = "Unknown"; - } + _log.Emulator.EnabledLogs = logsMatch.Success ? logsMatch.Groups[1].Value.TrimEnd() : "Unknown"; // Firmware Match firmwareMatch = Regex.Match(_log.RawLogContent, @"Firmware Version:\s([^;\n\r]*)", RegexOptions.Multiline); - if (firmwareMatch.Success) - { - _log.Emulator.Firmware = firmwareMatch.Groups[-1].Value.Trim(); - } - else - { - _log.Emulator.Firmware = "Unknown"; - } + _log.Emulator.Firmware = firmwareMatch.Success ? firmwareMatch.Groups[-1].Value.Trim() : "Unknown"; } @@ -660,6 +602,15 @@ void GetEmulatorNotes() } } + + string GetLastError() + { + if (_log.Errors.Count > 0) + { + return _log.Errors[-1]; + } + + return null; + } } -