From 0a119806510a54863a0ba4713dd2079b299a653c Mon Sep 17 00:00:00 2001 From: 13xforever Date: Sat, 12 Jul 2025 12:57:28 +0500 Subject: [PATCH 1/9] =?UTF-8?q?update=20win32=20error=20codes=20to=20v23?= =?UTF-8?q?=20("significant=20changes"=20=F0=9F=98=B9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- discord-bot-net.sln | 11 +++++++++++ ...ror_codes_v22.0.txt => win32_error_codes_v23.0.txt | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) rename win32_error_codes_v22.0.txt => win32_error_codes_v23.0.txt (99%) diff --git a/discord-bot-net.sln b/discord-bot-net.sln index 70bdaae3..4d0c58e2 100644 --- a/discord-bot-net.sln +++ b/discord-bot-net.sln @@ -43,6 +43,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceGenerators", "SourceG EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CirrusCiClient", "Clients\CirrusCiClient\CirrusCiClient.csproj", "{897476B0-B80A-4134-A576-8CAEAEA14A28}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Resources", "Resources", "{519297F9-DE0B-48EE-85B6-0DB6B065760E}" + ProjectSection(SolutionItems) = preProject + fortunes.txt = fortunes.txt + fortunes_fortuneandframe.txt = fortunes_fortuneandframe.txt + metacritic_ps3.json = metacritic_ps3.json + names_anidb.txt = names_anidb.txt + names_anilist.txt = names_anilist.txt + names_anime.txt = names_anime.txt + win32_error_codes_v23.0.txt = win32_error_codes_v23.0.txt + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/win32_error_codes_v22.0.txt b/win32_error_codes_v23.0.txt similarity index 99% rename from win32_error_codes_v22.0.txt rename to win32_error_codes_v23.0.txt index 42379025..47d9d817 100644 --- a/win32_error_codes_v22.0.txt +++ b/win32_error_codes_v23.0.txt @@ -1,4 +1,4 @@ -0x00000000 +0x00000000 ERROR_SUCCESS The operation completed successfully. 0x00000000 NERR_Success The operation completed successfully. From 2cfede4500968e0f7f5907ec06d936085573fff0 Mon Sep 17 00:00:00 2001 From: 13xforever Date: Sat, 12 Jul 2025 13:02:09 +0500 Subject: [PATCH 2/9] organize resource files --- .../confusables.txt | 0 fortunes.txt => .resources/fortunes.txt | 0 .../fortunes_fortuneandframe.txt | 0 .../metacritic_ps3.json | 0 names_anidb.txt => .resources/names_anidb.txt | 0 names_anilist.txt => .resources/names_anilist.txt | 0 names_anime.txt => .resources/names_anime.txt | 0 .../win32_error_codes_v23.0.txt | 0 CompatBot/CompatBot.csproj | 6 +++--- HomoglyphConverter/HomoglyphConverter.csproj | 4 ++-- discord-bot-net.sln | 15 ++++++++------- 11 files changed, 13 insertions(+), 12 deletions(-) rename {HomoglyphConverter => .resources}/confusables.txt (100%) rename fortunes.txt => .resources/fortunes.txt (100%) rename fortunes_fortuneandframe.txt => .resources/fortunes_fortuneandframe.txt (100%) rename metacritic_ps3.json => .resources/metacritic_ps3.json (100%) rename names_anidb.txt => .resources/names_anidb.txt (100%) rename names_anilist.txt => .resources/names_anilist.txt (100%) rename names_anime.txt => .resources/names_anime.txt (100%) rename win32_error_codes_v23.0.txt => .resources/win32_error_codes_v23.0.txt (100%) diff --git a/HomoglyphConverter/confusables.txt b/.resources/confusables.txt similarity index 100% rename from HomoglyphConverter/confusables.txt rename to .resources/confusables.txt diff --git a/fortunes.txt b/.resources/fortunes.txt similarity index 100% rename from fortunes.txt rename to .resources/fortunes.txt diff --git a/fortunes_fortuneandframe.txt b/.resources/fortunes_fortuneandframe.txt similarity index 100% rename from fortunes_fortuneandframe.txt rename to .resources/fortunes_fortuneandframe.txt diff --git a/metacritic_ps3.json b/.resources/metacritic_ps3.json similarity index 100% rename from metacritic_ps3.json rename to .resources/metacritic_ps3.json diff --git a/names_anidb.txt b/.resources/names_anidb.txt similarity index 100% rename from names_anidb.txt rename to .resources/names_anidb.txt diff --git a/names_anilist.txt b/.resources/names_anilist.txt similarity index 100% rename from names_anilist.txt rename to .resources/names_anilist.txt diff --git a/names_anime.txt b/.resources/names_anime.txt similarity index 100% rename from names_anime.txt rename to .resources/names_anime.txt diff --git a/win32_error_codes_v23.0.txt b/.resources/win32_error_codes_v23.0.txt similarity index 100% rename from win32_error_codes_v23.0.txt rename to .resources/win32_error_codes_v23.0.txt diff --git a/CompatBot/CompatBot.csproj b/CompatBot/CompatBot.csproj index b733b7c6..756a4686 100644 --- a/CompatBot/CompatBot.csproj +++ b/CompatBot/CompatBot.csproj @@ -31,13 +31,13 @@ - + PreserveNewest - - + + diff --git a/HomoglyphConverter/HomoglyphConverter.csproj b/HomoglyphConverter/HomoglyphConverter.csproj index 3d78965e..cc6d2575 100644 --- a/HomoglyphConverter/HomoglyphConverter.csproj +++ b/HomoglyphConverter/HomoglyphConverter.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/discord-bot-net.sln b/discord-bot-net.sln index 4d0c58e2..68ca7d9a 100644 --- a/discord-bot-net.sln +++ b/discord-bot-net.sln @@ -45,13 +45,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CirrusCiClient", "Clients\C EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Resources", "Resources", "{519297F9-DE0B-48EE-85B6-0DB6B065760E}" ProjectSection(SolutionItems) = preProject - fortunes.txt = fortunes.txt - fortunes_fortuneandframe.txt = fortunes_fortuneandframe.txt - metacritic_ps3.json = metacritic_ps3.json - names_anidb.txt = names_anidb.txt - names_anilist.txt = names_anilist.txt - names_anime.txt = names_anime.txt - win32_error_codes_v23.0.txt = win32_error_codes_v23.0.txt + .resources\confusables.txt = .resources\confusables.txt + .resources\fortunes.txt = .resources\fortunes.txt + .resources\fortunes_fortuneandframe.txt = .resources\fortunes_fortuneandframe.txt + .resources\metacritic_ps3.json = .resources\metacritic_ps3.json + .resources\names_anidb.txt = .resources\names_anidb.txt + .resources\names_anilist.txt = .resources\names_anilist.txt + .resources\names_anime.txt = .resources\names_anime.txt + .resources\win32_error_codes_v23.0.txt = .resources\win32_error_codes_v23.0.txt EndProjectSection EndProject Global From 9c1f3fb9a80b15fd357355033e5b4dd08fa78d97 Mon Sep 17 00:00:00 2001 From: 13xforever Date: Sat, 12 Jul 2025 14:26:37 +0500 Subject: [PATCH 3/9] update syntax in code generators --- .../ConfusablesSourceGenerator.cs | 42 +++++++++-------- .../Win32ErrorsSourceGenerator.cs | 46 ++++++++++--------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/SourceGenerators/ConfusablesSourceGenerator.cs b/SourceGenerators/ConfusablesSourceGenerator.cs index 7455b8d4..e37c72b3 100644 --- a/SourceGenerators/ConfusablesSourceGenerator.cs +++ b/SourceGenerators/ConfusablesSourceGenerator.cs @@ -12,7 +12,7 @@ using Microsoft.CodeAnalysis.Text; namespace SourceGenerators; [Generator(LanguageNames.CSharp)] -public class ConfusablesSourceGenerator : IIncrementalGenerator +public class ConfusablesSourceGenerator: IIncrementalGenerator { private static readonly char[] CommentSplitter = ['#']; private static readonly char[] FieldSplitter = [';']; @@ -102,25 +102,29 @@ public class ConfusablesSourceGenerator : IIncrementalGenerator if (!Version.TryParse(version, out _)) version = ""; - var result = new StringBuilder() - .AppendLine("using System;") - .AppendLine("using System.Collections.Generic;") - .AppendLine() - .AppendLine($"namespace {ns}") - .AppendLine("{") - .AppendLine($" internal static class {cn}") - .AppendLine(" {") - .AppendLine($" public const string Version = \"{version}\";") - .AppendLine() - .AppendLine($" public const string Date = \"{date}\";") - .AppendLine() - .AppendLine(" public static readonly Dictionary Mapping = new()") - .AppendLine(" {"); + var result = new StringBuilder().AppendLine($$""" + using System; + using System.Collections.Generic; + + namespace {{ns}}; + + internal static class {{cn}} + { + public const string Version = "{{version}}"; + public const string Date = "{{date}}"; + public static readonly Dictionary Mapping = new() + { + """ + ); foreach (var kvp in mapping.OrderBy(i => i.Key)) - result.AppendLine($@" [0x{kvp.Key:X5}u] = new[] {{ {string.Join(", ", kvp.Value!.OrderBy(i => i).Select(n => $"0x{n:X5}u"))} }},"); - result.AppendLine(" };") - .AppendLine(" }") - .AppendLine("}"); + result.AppendLine($""" + [0x{kvp.Key:X5}u] = [{string.Join(", ", kvp.Value!.OrderBy(i => i).Select(n => $"0x{n:X5}u"))}], + """); + result.AppendLine(""" + }; + } + """ + ); context.AddSource($"{cn}.Generated.cs", SourceText.From(result.ToString(), Encoding.UTF8)); diff --git a/SourceGenerators/Win32ErrorsSourceGenerator.cs b/SourceGenerators/Win32ErrorsSourceGenerator.cs index 0b394f21..fb53124b 100644 --- a/SourceGenerators/Win32ErrorsSourceGenerator.cs +++ b/SourceGenerators/Win32ErrorsSourceGenerator.cs @@ -10,9 +10,8 @@ using Microsoft.CodeAnalysis.Text; namespace SourceGenerators; [Generator(LanguageNames.CSharp)] -public class Win32ErrorsSourceGenerator : IIncrementalGenerator +public class Win32ErrorsSourceGenerator: IIncrementalGenerator { - private const string Indent = " "; private static readonly char[] Separator = ['\t']; private static readonly DiagnosticDescriptor Win32ErrorFormatError = new( @@ -44,21 +43,21 @@ public class Win32ErrorsSourceGenerator : IIncrementalGenerator if (!args.generatorContext.configOptions.GlobalOptions.TryGetValue("build_property.RootNamespace", out var ns)) ns = args.generatorContext.compilation.AssemblyName; - var cn = "Win32ErrorCodes"; - var result = new StringBuilder() - .AppendLine("using System.Collections.Generic;") - .AppendLine() - .AppendLine($"namespace {ns}") - .AppendLine("{") - .AppendLine($"{Indent}public static class {cn}") - .AppendLine($"{Indent}{{") - .AppendLine($"{Indent}{Indent}public static readonly Dictionary Map = new()") - .AppendLine($"{Indent}{Indent}{{"); + const string cn = "Win32ErrorCodes"; + var result = new StringBuilder().AppendLine($$""" + using System.Collections.Generic; + + namespace {{ns}}; + + public static class {{cn}} + { + public static readonly Dictionary Map = new() + { + """ + ); var previousPos = 0; var line = 0; - var codeLine = 0; - var descLine = 0; using var reader = new StreamReader(stream, Encoding.UTF8, false); while (reader.ReadLine() is string errorCodeLine) { @@ -66,14 +65,14 @@ public class Win32ErrorsSourceGenerator : IIncrementalGenerator if (string.IsNullOrWhiteSpace(errorCodeLine)) continue; - codeLine = line - 1; + var codeLine = line - 1; string? errorNameAndDescriptionLine; do { errorNameAndDescriptionLine = reader.ReadLine(); line++; } while (string.IsNullOrWhiteSpace(errorNameAndDescriptionLine)); - descLine = line - 1; + var descLine = line - 1; var nameDescParts = errorNameAndDescriptionLine.Split(Separator, 2); if (nameDescParts.Length != 2 || !Regex.IsMatch(errorCodeLine, @"0x[0-9a-f]+")) @@ -99,13 +98,16 @@ public class Win32ErrorsSourceGenerator : IIncrementalGenerator var name = nameDescParts[0]; var desc = nameDescParts[1].Replace(@"\", @"\\").Replace("\"", "\\\""); - result.AppendLine($"{Indent}{Indent}{Indent}[{errorCodeLine.Trim()}] = (\"{name.Trim()}\", \"{desc.Trim()}\"),"); + result.AppendLine($""" + [{errorCodeLine.Trim()}] = ("{name.Trim()}", "{desc.Trim()}"), + """ + ); } - - result.AppendLine($"{Indent}{Indent}}};") - .AppendLine($"{Indent}}}") - .AppendLine("}"); - + result.AppendLine(""" + }; + } + """ + ); context.AddSource($"{cn}.Generated.cs", SourceText.From(result.ToString(), Encoding.UTF8)); } } \ No newline at end of file From e3ba48b50f27f2f0985613346af1fe338e5d2c46 Mon Sep 17 00:00:00 2001 From: 13xforever Date: Sat, 12 Jul 2025 17:52:54 +0500 Subject: [PATCH 4/9] add cpu tier info management system --- .resources/cpu_tier_list_v2.5.2.conf | 172 ++++++++++++++++++ CompatBot/CompatBot.csproj | 2 + .../LogParsing/LogParser.RegexPatterns.cs | 4 +- ...ResultFormatter.CurrentSettingsSections.cs | 7 +- ...rserResultFormatter.GeneralNotesSection.cs | 36 +++- ...serResultFormatter.WeirdSettingsSection.cs | 18 +- .../LogParserResultFormatter.cs | 2 +- README.md | 1 + SourceGenerators/CpuTierListGenerator.cs | 99 ++++++++++ discord-bot-net.sln | 1 + 10 files changed, 326 insertions(+), 16 deletions(-) create mode 100644 .resources/cpu_tier_list_v2.5.2.conf create mode 100644 SourceGenerators/CpuTierListGenerator.cs diff --git a/.resources/cpu_tier_list_v2.5.2.conf b/.resources/cpu_tier_list_v2.5.2.conf new file mode 100644 index 00000000..1426a83b --- /dev/null +++ b/.resources/cpu_tier_list_v2.5.2.conf @@ -0,0 +1,172 @@ +; Model names from this list are matched to formatted system info string in bot log +; e.g.: AMD Ryzen 7 9700X | 8 Threads | 31.11 GiB RAM | AVX-512+ | FMA3 +; PAY ATTENTION to model name spelling (e.g. there's no - in ryzen models) + +; Spaces in this list are treated as .* in regex, use \s for space +; e.g: "i9-12900K AVX-512" will generate regex "i9-12900K.*AVX-512" + +; Models are matching as regex as a result (ignoring the letter case) +; e.g.: 12900K will match 12900KF or 12900KS too, but not 12900 + +[S] +Ryzen 9 9950X3D +Ryzen 7 9800X3D +i9-12900K AVX-512 +i7-12700K AVX-512 +Ryzen 9 9950X +Ryzen 7 9700X +i9-14900K +i9-13900KS +Ultra 9 285K +i9-13900K +i7-14700K +Ryzen 9 9900X +Ultra 7 265K +i7-13700K +Ryzen 9 7950X3D +Ryzen 9 7950X +Ryzen 7 7700X +Ryzen 9 7900X +Ryzen 7 7800X3D +Ultra 5 245K + +[A] +i5-14600K +i5-13600K +Ryzen 5 9600X +Ryzen 5 7600X +Ryzen 5 7500F +i7-12700 AVX-512 +i9-12900KS +i9-12900K +i5-12600K AVX-512 +i9-11900K +i7-11700K +i7-12700K +i7-12700 +i5-12600K +i5-12400 AVX-512 +Ryzen 9 7945HX +i9-14900HX +i9-13980HX +i7-14650HX +i7-13620H +i9-12900HX +i9-11980HK +i7-12650H +i9-11950H +i9-11900H +i7-11850H +i7-11800H + +[B] +Ryzen 7 5800X +Ryzen 9 5950X +Ryzen 9 5900X +i5-11600K +i5-13500 +Ryzen 7 5800X3D +Ryzen 7 5700X3D +i5-13400 +Ryzen 7 5700X +i5-12400 +i9-10900K +i7-10700K +i3-12100 AVX-512 +i9-9900K +i5-11400 +Ryzen 5 5600X +Ryzen 7 5700G +Ryzen 7 3800X +Ryzen 7 3700X +i5-10600K +i7-8700K +i3-12100 +Ryzen 9 3950X +Ryzen 9 3900X +Ryzen 5 5600G +Ryzen 5 3600 +i5-10400 +i7-11600H +i5-11400H +; GPD Win Max 2 +Ryzen 7 8840U +Ryzen 7 7840U +Ryzen 5 8640U +; Legion Go +; ROG Ally X +Ryzen Z1 Extreme +; ROG Ally +Ryzen Z1 +Ryzen 9 6900HX +Ryzen 7 6800H +i7-10875H +i7-10870H +i7-10850H +Ryzen 9 5980HX +Ryzen 9 5980HS +Ryzen 9 5900HX +Ryzen 7 5800H +Ryzen 7 5800HS +Ryzen 7 4800H +Ryzen 7 6800U +Ryzen 5 5600H +Ryzen 5 5600HS + +[C] +i5-9600K +i5-8600K +i5-9400 +i5-8400 +Ryzen 7 2700X +i7-7700K +i7-4790K +Ryzen 7 1700 +i7-1165G7 +i7-8750H +i5-8300H +i7-7700HQ +; Steam Deck OLED +; Steam Deck LCD +Custom APU 0405 +; "Intel 7000 - 4000 4c/8t" +; 4xxx-7xxx except U with 5-8 threads +Intel [4-7]\d{3}(?!U) \b[5-8]\sThreads +; "Ryzen 1000 - 2000 8c/16t" +; 1xxxx or 2xxxx with 13-16 threads +Ryzen [12]\d{3} 1[3-6]\sThreads + +[D] +Ryzen 5 2600 +Ryzen 5 1600AF +i5-7600k +i5-6600K +Ryzen 5 3400G +i5-4690K +i5-4690 +i5-1035G1 +i3-N305 +i7-4700MQ +i5-8250U +i5-7300HQ +; "Ryzen 1000 - 2000 6c/12t or worse" +; 1xxx or 2xxx with 1-9 or 10-12 threads +Ryzen [12]\d{3} \b([1-9]|1[0-2])\sThreads +; Any 4c/4t CPU +4\sThreads + +[F] +i3-1005G1 +i3-10110U +Intel N200 +Intel N100 +i5-4300M +Intel N50 +; "Intel 7000 - 100 U Series" +; 7xxx-9xxx or 10xxx or 1xxx +Intel ([7-9]|10?)\d{3}U +; Intel's 2nd and 3rd Gen +Intel [23]\d{3} +;AMD FX CPUs +AMD FX- +;Anything Older \ No newline at end of file diff --git a/CompatBot/CompatBot.csproj b/CompatBot/CompatBot.csproj index 756a4686..533b5c3e 100644 --- a/CompatBot/CompatBot.csproj +++ b/CompatBot/CompatBot.csproj @@ -37,7 +37,9 @@ + + diff --git a/CompatBot/EventHandlers/LogParsing/LogParser.RegexPatterns.cs b/CompatBot/EventHandlers/LogParsing/LogParser.RegexPatterns.cs index 0c16eee6..d2951d85 100644 --- a/CompatBot/EventHandlers/LogParsing/LogParser.RegexPatterns.cs +++ b/CompatBot/EventHandlers/LogParsing/LogParser.RegexPatterns.cs @@ -4,8 +4,8 @@ namespace CompatBot.EventHandlers.LogParsing; internal partial class LogParser { - private const RegexOptions DefaultOptions = RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.ExplicitCapture; - private const RegexOptions DefaultSingleLine = RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.ExplicitCapture; + private const RegexOptions DefaultOptions = RegexOptions.Multiline | RegexOptions.ExplicitCapture; + private const RegexOptions DefaultSingleLine = RegexOptions.Singleline | RegexOptions.ExplicitCapture; [GeneratedRegex(@"(^|.+\d:\d\d:\d\d\.\d{6})\s*(?RPCS3 [^\xC2\xB7]+?)\r?(\n·|$)", DefaultSingleLine)] private static partial Regex Rpcs3LogHeader(); diff --git a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.CurrentSettingsSections.cs b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.CurrentSettingsSections.cs index 8c40be0f..2bb60b50 100644 --- a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.CurrentSettingsSections.cs +++ b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.CurrentSettingsSections.cs @@ -137,9 +137,12 @@ internal static partial class LogParserResult } } var threadCountItem = items["thread_count"]?.Trim(); - systemInfo += $"{Environment.NewLine}{items["cpu_model"]} | {threadCountItem} Thread{(threadCountItem == "1" ? "" : "s")} | {items["memory_amount"]} GiB RAM"; + var cpuAndMemoryInfo = + $"{items["cpu_model"]} | {threadCountItem} Thread{(threadCountItem == "1" ? "" : "s")} | {items["memory_amount"]} GiB RAM"; if (!string.IsNullOrEmpty(items["cpu_extensions"])) - systemInfo += " | " + items["cpu_extensions"]; + cpuAndMemoryInfo += " | " + items["cpu_extensions"]; + systemInfo += $"{Environment.NewLine}{cpuAndMemoryInfo}"; + items["cpu_and_memory_info"] = cpuAndMemoryInfo; } if (items["gpu_info"] is string gpu) systemInfo += $"{Environment.NewLine}GPU: {gpu}"; diff --git a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs index 133240f0..eb4299b4 100644 --- a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs +++ b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs @@ -187,7 +187,39 @@ internal static partial class LogParserResult if (int.TryParse(items["thread_count"], out var threadCount) && threadCount < 4) notes.Add($"⚠️ This CPU only has {threadCount} hardware thread{(threadCount == 1 ? "" : "s")} enabled"); - if (items["cpu_model"] is string cpu) + var cpuModelMatched = false; + if (items["cpu_and_memory_info"] is string cpuAndMemoryInfo) + { + if (CpuTierList.List.FirstOrDefault(i => i.regex.IsMatch(cpuAndMemoryInfo)) is { tier: { Length: >0 } tier } match) + { + var status = items["game_status"] ?? "unknown"; + var msg = tier switch + { + "S" => "ℹ️ This is an **S** Tier CPU", + "A" => "ℹ️ This is an **A** Tier CPU", + "B" => status switch + { + "ingame" => "⚠️ This is a **B** Tier CPU, and may not be sufficient for some ingame titles", + _ => "ℹ️ This is a **B** Tier CPU", + }, + "C" => status switch + { + "playable" => "⚠️ This is a **C** Tier CPU, which is below the recommended system requirements", + _ => "⚠️ This is a **C** Tier CPU, please stick to the playable game titles", + }, + "D" => status switch + { + "playable" => "⚠️ This is a **D** Tier CPU, only lighter playable game titles will work", + _ => "⚠️ This is a **D** Tier CPU, please stick to the lighter playable game titles", + }, + "F" => "❌ This is an **F** Tier CPU, which is below the minimum system requirements", + _ => "❓", + }; + notes.Add($"{msg}"); + cpuModelMatched = true; + } + } + if (!cpuModelMatched && items["cpu_model"] is string cpu) { if (cpu.StartsWith("AMD")) { @@ -383,7 +415,7 @@ internal static partial class LogParserResult // this is a common scenario now that Mega did the version merge from param.sfo /* if (items["game_category"] == "GD") - notes.Add($"❔ Game was booted through the Game Data"); + notes.Add($"❓ Game was booted through the Game Data"); */ if (category is "DG" or "GD") // only disc games should install game data { diff --git a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.WeirdSettingsSection.cs b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.WeirdSettingsSection.cs index a68b399a..ca039627 100644 --- a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.WeirdSettingsSection.cs +++ b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.WeirdSettingsSection.cs @@ -42,7 +42,7 @@ internal static partial class LogParserResult } /* if (items["spu_lower_thread_priority"] == EnabledMark && threadCount > 4) - notes.Add("❔ `Lower SPU thread priority` is enabled on a CPU with enough threads"); + notes.Add("❓ `Lower SPU thread priority` is enabled on a CPU with enough threads"); */ if (items["cpu_model"] is string cpu) { @@ -74,7 +74,7 @@ internal static partial class LogParserResult var isAppleGpu = items["gpu_info"] is string gpuInfoApple && gpuInfoApple.Contains("Apple", StringComparison.OrdinalIgnoreCase); var canUseRelaxedZcull = items["renderer"] is not "Vulkan" || multiItems["vk_ext"].Contains("VK_EXT_depth_range_unrestricted"); if (items["llvm_arch"] is string llvmArch) - notes.Add($"❔ LLVM target CPU architecture override is set to `{llvmArch.Sanitize(replaceBackTicks: true)}`"); + notes.Add($"❓ LLVM target CPU architecture override is set to `{llvmArch.Sanitize(replaceBackTicks: true)}`"); if (items["renderer"] is "D3D12") notes.Add("💢 Do **not** use DX12 renderer"); if (items["renderer"] is "OpenGL" @@ -291,7 +291,7 @@ internal static partial class LogParserResult && int.TryParse(resScale, out var resScaleFactor)) { if (resScaleFactor < 100) - notes.Add($"❔ `Resolution Scale` is `{resScale}%`; this will not increase performance"); + notes.Add($"❓ `Resolution Scale` is `{resScale}%`; this will not increase performance"); if (resScaleFactor != 100 && items["texture_scale_threshold"] is string thresholdStr && int.TryParse(thresholdStr, out var threshold) @@ -335,7 +335,7 @@ internal static partial class LogParserResult notes.Add("⚠️ `Frame Skip` is enabled, please disable"); if (items["cpu_blit"] is EnabledMark && items["write_color_buffers"] is DisabledMark) - notes.Add("❔ `Force CPU Blit` is enabled, but `Write Color Buffers` is disabled"); + notes.Add("❓ `Force CPU Blit` is enabled, but `Write Color Buffers` is disabled"); if (items["zcull_status"] is not null and not "Full" && !canUseRelaxedZcull) notes.Add("⚠️ This GPU does not support `VK_EXT_depth_range_unrestricted` extension, please disable `Relaxed ZCull Sync`"); @@ -432,7 +432,7 @@ internal static partial class LogParserResult if (items["hook_static_functions"] is EnabledMark) notes.Add("⚠️ `Hook Static Functions` is enabled, please disable"); if (items["host_root"] is EnabledMark) - notes.Add("❔ `/host_root/` is enabled"); + notes.Add("❓ `/host_root/` is enabled"); if (items["ppu_threads"] is string ppuThreads && ppuThreads != "2") notes.Add($"⚠️ `PPU Threads` is set to `{ppuThreads.Sanitize()}`; please change it back to `2`"); @@ -455,7 +455,7 @@ internal static partial class LogParserResult else if (af is "Disabled") notes.Add("❌ `Anisotropic Filter` is `Disabled`, please use `Auto` instead"); else if (af is not "Auto" and not "16") - notes.Add($"❔ `Anisotropic Filter` is set to `{af}x`, which makes little sense over `16x` or `Auto`"); + notes.Add($"❓ `Anisotropic Filter` is set to `{af}x`, which makes little sense over `16x` or `Auto`"); } if (items["shader_mode"]?.Contains("Interpreter") is true && isAppleGpu) @@ -463,7 +463,7 @@ internal static partial class LogParserResult else if (items["shader_mode"] == "Interpreter only") notes.Add("⚠️ `Shader Interpreter Only` mode is not accurate and very demanding"); else if (items["shader_mode"]?.StartsWith("Async") is false && !isAppleGpu) - notes.Add("❔ Async shader compilation is disabled"); + notes.Add("❓ Async shader compilation is disabled"); if (items["driver_recovery_timeout"] is string driverRecoveryTimeout && int.TryParse(driverRecoveryTimeout, out var drtValue) && drtValue != 1000000) @@ -551,9 +551,9 @@ internal static partial class LogParserResult } if (items["auto_start_on_boot"] == DisabledMark) - notes.Add("❔ `Automatically start games after boot` is disabled"); + notes.Add("❓ `Automatically start games after boot` is disabled"); else if (items["always_start_on_boot"] == DisabledMark) - notes.Add("❔ `Always start after boot` is disabled"); + notes.Add("❓ `Always start after boot` is disabled"); if (items["custom_config"] != null && notes.Any()) generalNotes.Add("⚠️ To change custom configuration, **Right-click on the game**, then `Configure`"); diff --git a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.cs b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.cs index 5889d63e..cb5ed515 100644 --- a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.cs +++ b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.cs @@ -408,7 +408,7 @@ internal static partial class LogParserResult private static readonly TimeSpan PrehistoricBuild = TimeSpan.FromDays(365); private static readonly char[] PrioritySeparator = [' ']; - private static readonly string[] EmojiPriority = new[]{ "😱", "💢", "‼️", "❗", "❌", "⁉️", "⚠️", "❔", "✅", "ℹ️" } + private static readonly string[] EmojiPriority = new[]{ "😱", "💢", "‼️", "❗", "❌", "⁉️", "⚠️", "❓", "❔", "✅", "ℹ️" } .Select(e => e.TrimEnd('\ufe0f')) .ToArray(); private const string EnabledMark = "[x]"; diff --git a/README.md b/README.md index 53f1d624..1757373b 100644 --- a/README.md +++ b/README.md @@ -72,4 +72,5 @@ External resources that need manual updates ------------------------------------------- * [Unicode Confusables](http://www.unicode.org/Public/security/latest/confusables.txt), for Homoglyph checks * [Windows Error Codes](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/), for error decoding on non-Windows host +* [CPU Tier List](https://rpcs3.net/cputierlist), for CPU model ranking * Optionally pool of names (one name per line), files named as `names_.txt` diff --git a/SourceGenerators/CpuTierListGenerator.cs b/SourceGenerators/CpuTierListGenerator.cs new file mode 100644 index 00000000..1b375f09 --- /dev/null +++ b/SourceGenerators/CpuTierListGenerator.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Text; + +namespace SourceGenerators; + +[Generator(LanguageNames.CSharp)] +public class CpuTierListGenerator: IIncrementalGenerator +{ + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var resourceProvider = context.AdditionalTextsProvider.Where( + static f => Path.GetFileName(f.Path) is {} fname + && fname.StartsWith("cpu_tier_list") + && fname.EndsWith(".conf") + ); + var dataProvider = resourceProvider.Combine(context.AnalyzerConfigOptionsProvider.Combine(context.CompilationProvider)); + context.RegisterSourceOutput(dataProvider, Execute); + } + + private static void Execute(SourceProductionContext context, (AdditionalText resource, (AnalyzerConfigOptionsProvider configOptions, Compilation compilation) generatorContext) args) + { + var resource = args.resource; + using var stream = File.Open(resource.Path, FileMode.Open, FileAccess.Read, FileShare.Read); + if (stream is null) + throw new InvalidOperationException("Failed to open {resource.Path}"); + + if (!args.generatorContext.configOptions.GlobalOptions.TryGetValue("build_property.RootNamespace", out var ns)) + ns = args.generatorContext.compilation.AssemblyName; + const string cn = "CpuTierList"; + var result = new StringBuilder().AppendLine($$""" + using System; + using System.Text.RegularExpressions; + + namespace {{ns}}; + + internal static class {{cn}} + { + private const RegexOptions DefaultOptions = RegexOptions.Singleline | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.Compiled; + """ + ); + using var reader = new StreamReader(stream, Encoding.UTF8, false); + var currentTier = "unknown"; + var idx = 0; + List<(string model, string tier)> tierMap = []; + while (reader.ReadLine() is string line) + { + line = line.Trim(); + if (string.IsNullOrEmpty(line) || line.StartsWith(";") || line.StartsWith("#")) + continue; + + if (line.StartsWith("[")) + { + currentTier = line.Substring(1, line.Length - 2); + result.AppendLine($""" + + // {currentTier} Tier + """ + ); + continue; + } + + tierMap.Add((line, currentTier)); + line = line.Replace(" ", ".*"); + // todo: use generated regex when it's possible https://github.com/dotnet/roslyn/discussions/48358 + /* + result.AppendLine($""" + [GeneratedRegex(@"{line}", DefaultOptions)] + private static partial Regex Model{i++}(); + """ + ); + */ + result.AppendLine($""" + private static readonly Regex Model{idx++} = new(@"{line}", DefaultOptions); + """ + ); + } + result.AppendLine($""" + + public static readonly List<(string model, string tier, Regex regex)> List = [ + """ + ); + for (var i=0; i Date: Sat, 12 Jul 2025 17:56:33 +0500 Subject: [PATCH 5/9] Move tier list version inside the file for simpler update flow --- .resources/{cpu_tier_list_v2.5.2.conf => cpu_tier_list.conf} | 2 ++ discord-bot-net.sln | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) rename .resources/{cpu_tier_list_v2.5.2.conf => cpu_tier_list.conf} (96%) diff --git a/.resources/cpu_tier_list_v2.5.2.conf b/.resources/cpu_tier_list.conf similarity index 96% rename from .resources/cpu_tier_list_v2.5.2.conf rename to .resources/cpu_tier_list.conf index 1426a83b..42a62020 100644 --- a/.resources/cpu_tier_list_v2.5.2.conf +++ b/.resources/cpu_tier_list.conf @@ -1,3 +1,5 @@ +; v2.5.2 https://docs.google.com/spreadsheets/d/1Rpq_2D4Rf3g6O-x2R1fwTSKWvJH7X63kExsVxHnT2Mc/view + ; Model names from this list are matched to formatted system info string in bot log ; e.g.: AMD Ryzen 7 9700X | 8 Threads | 31.11 GiB RAM | AVX-512+ | FMA3 ; PAY ATTENTION to model name spelling (e.g. there's no - in ryzen models) diff --git a/discord-bot-net.sln b/discord-bot-net.sln index 47d1e1d1..28b0b0e3 100644 --- a/discord-bot-net.sln +++ b/discord-bot-net.sln @@ -53,7 +53,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Resources", "Resources", "{ .resources\names_anilist.txt = .resources\names_anilist.txt .resources\names_anime.txt = .resources\names_anime.txt .resources\win32_error_codes_v23.0.txt = .resources\win32_error_codes_v23.0.txt - .resources\cpu_tier_list_v2.5.2.conf = .resources\cpu_tier_list_v2.5.2.conf + .resources\cpu_tier_list.conf = .resources\cpu_tier_list.conf EndProjectSection EndProject Global From 58318b568763b41425af134433757a819237bf26 Mon Sep 17 00:00:00 2001 From: 13xforever Date: Sat, 12 Jul 2025 18:05:01 +0500 Subject: [PATCH 6/9] simplify matching --- ...rserResultFormatter.GeneralNotesSection.cs | 37 ++++++++----------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs index eb4299b4..20bb1550 100644 --- a/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs +++ b/CompatBot/Utils/ResultFormatters/LogParserResultFormatter.GeneralNotesSection.cs @@ -193,30 +193,23 @@ internal static partial class LogParserResult if (CpuTierList.List.FirstOrDefault(i => i.regex.IsMatch(cpuAndMemoryInfo)) is { tier: { Length: >0 } tier } match) { var status = items["game_status"] ?? "unknown"; - var msg = tier switch + var msg = (tier, status) switch { - "S" => "ℹ️ This is an **S** Tier CPU", - "A" => "ℹ️ This is an **A** Tier CPU", - "B" => status switch - { - "ingame" => "⚠️ This is a **B** Tier CPU, and may not be sufficient for some ingame titles", - _ => "ℹ️ This is a **B** Tier CPU", - }, - "C" => status switch - { - "playable" => "⚠️ This is a **C** Tier CPU, which is below the recommended system requirements", - _ => "⚠️ This is a **C** Tier CPU, please stick to the playable game titles", - }, - "D" => status switch - { - "playable" => "⚠️ This is a **D** Tier CPU, only lighter playable game titles will work", - _ => "⚠️ This is a **D** Tier CPU, please stick to the lighter playable game titles", - }, - "F" => "❌ This is an **F** Tier CPU, which is below the minimum system requirements", - _ => "❓", + ("S" or "A", _) => $"ℹ️ This is an **{tier}** Tier CPU", + ("B", "ingame") => "⚠️ This is a **B** Tier CPU, and may not be sufficient for some ingame titles", + ("B", _) => "ℹ️ This is a **B** Tier CPU", + ("C", "playable") => "⚠️ This is a **C** Tier CPU, which is below the recommended system requirements", + ("C", _) => "⚠️ This is a **C** Tier CPU, please stick to the playable game titles", + ("D", "playable") => "⚠️ This is a **D** Tier CPU, only lighter playable game titles will work", + ("D", _) => "⚠️ This is a **D** Tier CPU, please stick to the lighter playable game titles", + ("F", _) => "❌ This is an **F** Tier CPU, which is below the minimum system requirements", + _ => "", }; - notes.Add($"{msg}"); - cpuModelMatched = true; + if (msg is {Length: >0}) + { + notes.Add($"{msg}"); + cpuModelMatched = true; + } } } if (!cpuModelMatched && items["cpu_model"] is string cpu) From d59335094b95c2f2622efa06b90cce74906711a4 Mon Sep 17 00:00:00 2001 From: 13xforever Date: Sat, 12 Jul 2025 18:09:39 +0500 Subject: [PATCH 7/9] upgrade packages --- Clients/CirrusCiClient/CirrusCiClient.csproj | 6 +++--- Clients/CompatApiClient/CompatApiClient.csproj | 2 +- Clients/GithubClient/GithubClient.csproj | 2 +- Clients/IrdLibraryClient/IrdLibraryClient.csproj | 4 ++-- Clients/PsnClient/PsnClient.csproj | 2 +- CompatBot/CompatBot.csproj | 14 +++++++------- Tests/Tests.csproj | 2 +- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Clients/CirrusCiClient/CirrusCiClient.csproj b/Clients/CirrusCiClient/CirrusCiClient.csproj index 14efd676..866fc26a 100644 --- a/Clients/CirrusCiClient/CirrusCiClient.csproj +++ b/Clients/CirrusCiClient/CirrusCiClient.csproj @@ -9,9 +9,9 @@ - - - + + + \ No newline at end of file diff --git a/Clients/CompatApiClient/CompatApiClient.csproj b/Clients/CompatApiClient/CompatApiClient.csproj index b32607b7..b822bc1e 100644 --- a/Clients/CompatApiClient/CompatApiClient.csproj +++ b/Clients/CompatApiClient/CompatApiClient.csproj @@ -8,7 +8,7 @@ - + diff --git a/Clients/GithubClient/GithubClient.csproj b/Clients/GithubClient/GithubClient.csproj index bfc4718c..3ef59637 100644 --- a/Clients/GithubClient/GithubClient.csproj +++ b/Clients/GithubClient/GithubClient.csproj @@ -5,7 +5,7 @@ enable - + diff --git a/Clients/IrdLibraryClient/IrdLibraryClient.csproj b/Clients/IrdLibraryClient/IrdLibraryClient.csproj index e9254496..ad06f2b2 100644 --- a/Clients/IrdLibraryClient/IrdLibraryClient.csproj +++ b/Clients/IrdLibraryClient/IrdLibraryClient.csproj @@ -5,9 +5,9 @@ enable - + - + diff --git a/Clients/PsnClient/PsnClient.csproj b/Clients/PsnClient/PsnClient.csproj index 5b7212a8..f447d2e9 100644 --- a/Clients/PsnClient/PsnClient.csproj +++ b/Clients/PsnClient/PsnClient.csproj @@ -12,7 +12,7 @@ - + diff --git a/CompatBot/CompatBot.csproj b/CompatBot/CompatBot.csproj index 533b5c3e..1fe778bf 100644 --- a/CompatBot/CompatBot.csproj +++ b/CompatBot/CompatBot.csproj @@ -49,21 +49,21 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index e2411ff2..2789c59b 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -7,7 +7,7 @@ - + From 3b54093193caa5f62fb7b4724a9dc9a142d3ae32 Mon Sep 17 00:00:00 2001 From: 13xforever Date: Sat, 12 Jul 2025 18:12:22 +0500 Subject: [PATCH 8/9] upgrade d#+ packages --- CompatBot/CompatBot.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CompatBot/CompatBot.csproj b/CompatBot/CompatBot.csproj index 1fe778bf..1c32f7b4 100644 --- a/CompatBot/CompatBot.csproj +++ b/CompatBot/CompatBot.csproj @@ -44,9 +44,9 @@ - - - + + + From 5a9abe7b421571b3b2f41ebe7a481560abd369de Mon Sep 17 00:00:00 2001 From: 13xforever Date: Sat, 12 Jul 2025 18:19:55 +0500 Subject: [PATCH 9/9] fix name pool importing --- CompatBot/Database/DbImporter.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CompatBot/Database/DbImporter.cs b/CompatBot/Database/DbImporter.cs index 940edf28..26c548c7 100644 --- a/CompatBot/Database/DbImporter.cs +++ b/CompatBot/Database/DbImporter.cs @@ -179,7 +179,7 @@ public static class DbImporter { Config.Log.Debug("Importing name pool…"); var rootDir = Environment.CurrentDirectory; - while (rootDir is not null && !Directory.EnumerateFiles(rootDir, "names_*.txt", SearchOption.TopDirectoryOnly).Any()) + while (rootDir is not null && !Directory.Exists(Path.Combine(rootDir, ".resources"))) rootDir = Path.GetDirectoryName(rootDir); if (rootDir is null) { @@ -187,7 +187,8 @@ public static class DbImporter return wdb.NamePool.Any(); } - var resources = Directory.GetFiles(rootDir, "names_*.txt", SearchOption.TopDirectoryOnly) + var resourcesDir = Path.Combine(rootDir, ".resources"); + var resources = Directory.GetFiles(resourcesDir, "names_*.txt", SearchOption.TopDirectoryOnly) .OrderBy(f => f) .ToList(); if (resources.Count == 0)