Compare commits

..

3 Commits

Author SHA1 Message Date
Daniel Nylander
d0175a63f4 Merge branch 'Ryubing:master' into master 2025-01-08 09:51:59 +01:00
Daniel Nylander
2d0b679338 Merge branch 'Ryubing:master' into master 2025-01-04 19:28:37 +01:00
Daniel Nylander
aef1185978 Update Swedish translation in locales.json 2024-12-31 19:46:05 +01:00
20 changed files with 3539 additions and 3580 deletions

View File

@@ -42,7 +42,7 @@
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.7.0.2" />
<PackageVersion Include="Gommon" Version="2.7.0.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="Sep" Version="0.6.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />

File diff suppressed because it is too large Load Diff

View File

@@ -284,7 +284,7 @@ namespace Ryujinx.HLE.HOS
ProcessCreationInfo creationInfo = new("Service", 1, 0, 0x8000000, 1, Flags, 0, 0);
uint[] defaultCapabilities = {
(((uint)KScheduler.CpuCoresCount - 1) << 24) + (((uint)KScheduler.CpuCoresCount - 1) << 16) + 0x63F7u,
0x030363F7,
0x1FFFFFCF,
0x207FFFEF,
0x47E0060F,

View File

@@ -63,7 +63,6 @@ namespace Ryujinx.HLE.HOS.Kernel
TickSource = tickSource;
Device = device;
Memory = memory;
KScheduler.CpuCoresCount = device.CpuCoresCount;
Running = true;

View File

@@ -37,7 +37,7 @@ namespace Ryujinx.HLE.HOS.Kernel
return result;
}
process.DefaultCpuCore = KScheduler.CpuCoresCount - 1;
process.DefaultCpuCore = 3;
context.Processes.TryAdd(process.Pid, process);

View File

@@ -277,7 +277,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return result;
}
result = Capabilities.InitializeForUser(capabilities, MemoryManager, IsApplication);
result = Capabilities.InitializeForUser(capabilities, MemoryManager);
if (result != Result.Success)
{

View File

@@ -35,15 +35,15 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
DebuggingFlags &= ~3u;
KernelReleaseVersion = KProcess.KernelVersionPacked;
return Parse(capabilities, memoryManager, false);
return Parse(capabilities, memoryManager);
}
public Result InitializeForUser(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager, bool isApplication)
public Result InitializeForUser(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager)
{
return Parse(capabilities, memoryManager, isApplication);
return Parse(capabilities, memoryManager);
}
private Result Parse(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager, bool isApplication)
private Result Parse(ReadOnlySpan<uint> capabilities, KPageTableBase memoryManager)
{
int mask0 = 0;
int mask1 = 0;
@@ -54,7 +54,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
if (cap.GetCapabilityType() != CapabilityType.MapRange)
{
Result result = ParseCapability(cap, ref mask0, ref mask1, memoryManager, isApplication);
Result result = ParseCapability(cap, ref mask0, ref mask1, memoryManager);
if (result != Result.Success)
{
@@ -120,7 +120,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
return Result.Success;
}
private Result ParseCapability(uint cap, ref int mask0, ref int mask1, KPageTableBase memoryManager, bool isApplication)
private Result ParseCapability(uint cap, ref int mask0, ref int mask1, KPageTableBase memoryManager)
{
CapabilityType code = cap.GetCapabilityType();
@@ -176,11 +176,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore);
AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio);
if (isApplication && lowestCpuCore == 0 && highestCpuCore != 2)
Ryujinx.Common.Logging.Logger.Error?.Print(Ryujinx.Common.Logging.LogClass.Application, $"Application requested cores with index range {lowestCpuCore} to {highestCpuCore}! Report this to @LotP on the Ryujinx/Ryubing discord server (discord.gg/ryujinx)!");
else if (isApplication)
Ryujinx.Common.Logging.Logger.Info?.Print(Ryujinx.Common.Logging.LogClass.Application, $"Application requested cores with index range {lowestCpuCore} to {highestCpuCore}");
break;
}

View File

@@ -2683,7 +2683,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.InvalidCombination;
}
if ((uint)preferredCore > KScheduler.CpuCoresCount - 1)
if ((uint)preferredCore > 3)
{
if ((preferredCore | 2) != -1)
{

View File

@@ -9,11 +9,13 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
partial class KScheduler : IDisposable
{
public const int PrioritiesCount = 64;
public static int CpuCoresCount;
public const int CpuCoresCount = 4;
private const int RoundRobinTimeQuantumMs = 10;
private static int[] _srcCoresHighestPrioThreads;
private static readonly int[] _preemptionPriorities = { 59, 59, 59, 63 };
private static readonly int[] _srcCoresHighestPrioThreads = new int[CpuCoresCount];
private readonly KernelContext _context;
private readonly int _coreId;
@@ -45,16 +47,6 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
_coreId = coreId;
_currentThread = null;
if (_srcCoresHighestPrioThreads == null)
{
_srcCoresHighestPrioThreads = new int[CpuCoresCount];
}
}
private static int PreemptionPriorities(int index)
{
return index == CpuCoresCount - 1 ? 63 : 59;
}
public static ulong SelectThreads(KernelContext context)
@@ -445,7 +437,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
for (int core = 0; core < CpuCoresCount; core++)
{
RotateScheduledQueue(context, core, PreemptionPriorities(core));
RotateScheduledQueue(context, core, _preemptionPriorities[core]);
}
context.CriticalSection.Leave();

View File

@@ -24,14 +24,14 @@ namespace Ryujinx.HLE.HOS.Services
// not large enough.
private const int PointerBufferSize = 0x8000;
private static uint[] _defaultCapabilities => [
(((uint)KScheduler.CpuCoresCount - 1) << 24) + (((uint)KScheduler.CpuCoresCount - 1) << 16) + 0x63F7u,
private readonly static uint[] _defaultCapabilities = {
0x030363F7,
0x1FFFFFCF,
0x207FFFEF,
0x47E0060F,
0x0048BFFF,
0x01007FFF,
];
};
// The amount of time Dispose() will wait to Join() the thread executing the ServerLoop()
private static readonly TimeSpan _threadJoinTimeout = TimeSpan.FromSeconds(3);

View File

@@ -32,8 +32,6 @@ namespace Ryujinx.HLE
public TamperMachine TamperMachine { get; }
public IHostUIHandler UIHandler { get; }
public int CpuCoresCount = 4; //Switch 1 has 4 cores
public VSyncMode VSyncMode { get; set; } = VSyncMode.Switch;
public bool CustomVSyncIntervalEnabled { get; set; } = false;
public int CustomVSyncInterval { get; set; }

View File

@@ -1564,7 +1564,7 @@
"pl_PL": "Wersja",
"pt_BR": "Versão",
"ru_RU": "Версия",
"sv_SE": "",
"sv_SE": "Version",
"th_TH": "เวอร์ชั่น",
"tr_TR": "Sürüm",
"uk_UA": "Версія",
@@ -3264,7 +3264,7 @@
"pl_PL": "",
"pt_BR": "Sistema",
"ru_RU": "Система",
"sv_SE": "",
"sv_SE": "System",
"th_TH": "ระบบ",
"tr_TR": "Sistem",
"uk_UA": "Система",
@@ -3339,7 +3339,7 @@
"pl_PL": "Japonia",
"pt_BR": "Japão",
"ru_RU": "Япония",
"sv_SE": "",
"sv_SE": "Japan",
"th_TH": "ญี่ปุ่น",
"tr_TR": "Japonya",
"uk_UA": "Японія",
@@ -3364,7 +3364,7 @@
"pl_PL": "Stany Zjednoczone",
"pt_BR": "EUA",
"ru_RU": "США",
"sv_SE": "",
"sv_SE": "USA",
"th_TH": "สหรัฐอเมริกา",
"tr_TR": "ABD",
"uk_UA": "США",
@@ -3464,7 +3464,7 @@
"pl_PL": "",
"pt_BR": "Coreia",
"ru_RU": "Корея",
"sv_SE": "",
"sv_SE": "Korea",
"th_TH": "เกาหลี",
"tr_TR": "Kore",
"uk_UA": "Корея",
@@ -3489,7 +3489,7 @@
"pl_PL": "Tajwan",
"pt_BR": "",
"ru_RU": "Тайвань",
"sv_SE": "",
"sv_SE": "Taiwan",
"th_TH": "ไต้หวัน",
"tr_TR": "Tayvan",
"uk_UA": "Тайвань",
@@ -4139,7 +4139,7 @@
"pl_PL": "Atrapa",
"pt_BR": "Nenhuma",
"ru_RU": "Без звука",
"sv_SE": "",
"sv_SE": "Ingenting",
"th_TH": "",
"tr_TR": "Yapay",
"uk_UA": "",
@@ -5664,7 +5664,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"sv_SE": "Ok",
"th_TH": "ตกลง",
"tr_TR": "Tamam",
"uk_UA": "Гаразд",
@@ -12439,7 +12439,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"sv_SE": "{0}: {1}",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
@@ -14289,7 +14289,7 @@
"pl_PL": "Seria Amiibo",
"pt_BR": "Franquia Amiibo",
"ru_RU": "Серия Amiibo",
"sv_SE": "",
"sv_SE": "Amiibo-serien",
"th_TH": "",
"tr_TR": "Amiibo Serisi",
"uk_UA": "Серія Amiibo",
@@ -17439,7 +17439,7 @@
"pl_PL": "Wersja {0}",
"pt_BR": "Versão {0}",
"ru_RU": "Версия {0}",
"sv_SE": "",
"sv_SE": "Version {0}",
"th_TH": "เวอร์ชั่น {0}",
"tr_TR": "Sürüm {0}",
"uk_UA": "Версія {0}",
@@ -17664,7 +17664,7 @@
"pl_PL": "",
"pt_BR": "Ryujinx - Informação",
"ru_RU": "Ryujinx - Информация",
"sv_SE": "",
"sv_SE": "Ryujinx - Info",
"th_TH": "Ryujinx ข้อมูล",
"tr_TR": "Ryujinx - Bilgi",
"uk_UA": "Ryujin x - Інформація",
@@ -19639,7 +19639,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "{0:n0} Мб",
"sv_SE": "",
"sv_SE": "{0:n0} Mb",
"th_TH": "",
"tr_TR": "",
"uk_UA": "{0:n0} Мб",
@@ -20914,7 +20914,7 @@
"pl_PL": "Głoś",
"pt_BR": "",
"ru_RU": "Громкость",
"sv_SE": "",
"sv_SE": "Vol",
"th_TH": "ระดับเสียง",
"tr_TR": "Ses",
"uk_UA": "Гуч.",
@@ -22214,7 +22214,7 @@
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Вертикальная синхронизация:",
"sv_SE": "",
"sv_SE": "VSync:",
"th_TH": "",
"tr_TR": "",
"uk_UA": "Вертикальна синхронізація (VSync):",
@@ -22597,31 +22597,6 @@
"zh_TW": ""
}
},
{
"ID": "CompatibilityListLastUpdated",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Last updated: {0}",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{
"ID": "CompatibilityListWarning",
"Translations": {
@@ -22848,4 +22823,4 @@
}
}
]
}
}

View File

@@ -1,4 +1,4 @@
using DiscordRPC;
using DiscordRPC;
using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Ava;

View File

@@ -12,8 +12,8 @@ namespace Ryujinx.Ava.UI.Helpers
private static readonly Lazy<PlayabilityStatusConverter> _shared = new(() => new());
public static PlayabilityStatusConverter Shared => _shared.Value;
public object Convert(object value, Type _, object __, CultureInfo ___)
=> value.Cast<LocaleKeys>() switch
public object Convert(object? value, Type _, object? __, CultureInfo ___) =>
value.Cast<LocaleKeys>() switch
{
LocaleKeys.CompatibilityListNothing or
LocaleKeys.CompatibilityListBoots or
@@ -22,7 +22,7 @@ namespace Ryujinx.Ava.UI.Helpers
_ => Brushes.ForestGreen
};
public object ConvertBack(object value, Type _, object __, CultureInfo ___)
public object ConvertBack(object? value, Type _, object? __, CultureInfo ___)
=> throw new NotSupportedException();
}
}

View File

@@ -741,10 +741,7 @@ namespace Ryujinx.Ava.UI.ViewModels
Applications.ToObservableChangeSet()
.Filter(Filter)
.Sort(GetComparer())
#pragma warning disable MVVMTK0034
.Bind(out _appsObservableList)
#pragma warning restore MVVMTK0034
.AsObservableList();
.Bind(out _appsObservableList).AsObservableList();
OnPropertyChanged(nameof(AppsObservableList));
}

View File

@@ -32,27 +32,29 @@ namespace Ryujinx.Ava.Utilities
public string GetContentPath(ContentManager contentManager)
=> (contentManager ?? _contentManager)
?.GetInstalledContentPath(ProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
.GetInstalledContentPath(ProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
public bool CanStart(ContentManager contentManager, out ApplicationData appData,
out BlitStruct<ApplicationControlProperty> appControl)
{
contentManager ??= _contentManager;
if (contentManager == null)
goto BadData;
string contentPath = GetContentPath(contentManager);
if (string.IsNullOrEmpty(contentPath))
goto BadData;
if (contentManager == null)
{
appData = null;
appControl = new BlitStruct<ApplicationControlProperty>(0);
return false;
}
appData = new() { Name = Name, Id = ProgramId, Path = GetContentPath(contentManager) };
if (string.IsNullOrEmpty(appData.Path))
{
appControl = new BlitStruct<ApplicationControlProperty>(0);
return false;
}
appControl = StructHelpers.CreateCustomNacpData(Name, Version);
return true;
BadData:
appData = null;
appControl = new BlitStruct<ApplicationControlProperty>(0);
return false;
}
}
}

View File

@@ -1,66 +1,54 @@
using Gommon;
using Humanizer;
using nietras.SeparatedValues;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Common.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace Ryujinx.Ava.Utilities.Compat
{
public struct ColumnIndices(Func<ReadOnlySpan<char>, int> getIndex)
{
public const string TitleIdCol = "\"title_id\"";
public const string GameNameCol = "\"game_name\"";
public const string LabelsCol = "\"labels\"";
public const string StatusCol = "\"status\"";
public const string LastUpdatedCol = "\"last_updated\"";
public readonly int TitleId = getIndex(TitleIdCol);
public readonly int GameName = getIndex(GameNameCol);
public readonly int Labels = getIndex(LabelsCol);
public readonly int Status = getIndex(StatusCol);
public readonly int LastUpdated = getIndex(LastUpdatedCol);
}
public class CompatibilityCsv
{
static CompatibilityCsv()
public static CompatibilityCsv Shared { get; set; }
public CompatibilityCsv(SepReader reader)
{
using Stream csvStream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("RyujinxGameCompatibilityList")!;
csvStream.Position = 0;
var entries = new List<CompatibilityEntry>();
using SepReader reader = Sep.Reader().From(csvStream);
ColumnIndices columnIndices = new(reader.Header.IndexOf);
foreach (var row in reader)
{
entries.Add(new CompatibilityEntry(reader.Header, row));
}
Entries = reader
.Enumerate(row => new CompatibilityEntry(ref columnIndices, row))
.OrderBy(it => it.GameName)
.ToArray();
Logger.Debug?.Print(LogClass.UI, "Compatibility CSV loaded.", "LoadCompatCsv");
Entries = entries.Where(x => x.Status != null)
.OrderBy(it => it.GameName).ToArray();
}
public static CompatibilityEntry[] Entries { get; private set; }
public CompatibilityEntry[] Entries { get; }
}
public class CompatibilityEntry
{
public CompatibilityEntry(ref ColumnIndices indices, SepReader.Row row)
public CompatibilityEntry(SepReaderHeader header, SepReader.Row row)
{
string titleIdRow = ColStr(row[indices.TitleId]);
if (row.ColCount != header.ColNames.Count)
throw new InvalidDataException($"CSV row {row.RowIndex} ({row.ToString()}) has mismatched column count");
var titleIdRow = ColStr(row[header.IndexOf("\"extracted_game_id\"")]);
TitleId = !string.IsNullOrEmpty(titleIdRow)
? titleIdRow
: default(Optional<string>);
GameName = ColStr(row[indices.GameName]).Trim().Trim('"');
Labels = ColStr(row[indices.Labels]).Split(';');
Status = ColStr(row[indices.Status]).ToLower() switch
var issueTitleRow = ColStr(row[header.IndexOf("\"issue_title\"")]);
if (TitleId.HasValue)
issueTitleRow = issueTitleRow.ReplaceIgnoreCase($" - {TitleId}", string.Empty);
GameName = issueTitleRow.Trim().Trim('"');
IssueLabels = ColStr(row[header.IndexOf("\"issue_labels\"")]).Split(';');
Status = ColStr(row[header.IndexOf("\"extracted_status\"")]).ToLower() switch
{
"playable" => LocaleKeys.CompatibilityListPlayable,
"ingame" => LocaleKeys.CompatibilityListIngame,
@@ -70,8 +58,8 @@ namespace Ryujinx.Ava.Utilities.Compat
_ => null
};
if (DateTime.TryParse(ColStr(row[indices.LastUpdated]), out var dt))
LastUpdated = dt;
if (DateTime.TryParse(ColStr(row[header.IndexOf("\"last_event_date\"")]), out var dt))
LastEvent = dt;
return;
@@ -80,32 +68,27 @@ namespace Ryujinx.Ava.Utilities.Compat
public string GameName { get; }
public Optional<string> TitleId { get; }
public string[] Labels { get; }
public string[] IssueLabels { get; }
public LocaleKeys? Status { get; }
public DateTime LastUpdated { get; }
public string LocalizedLastUpdated =>
LocaleManager.FormatDynamicValue(LocaleKeys.CompatibilityListLastUpdated, LastUpdated.Humanize());
public DateTime LastEvent { get; }
public string LocalizedStatus => LocaleManager.Instance[Status!.Value];
public string FormattedTitleId => TitleId
.OrElse(new string(' ', 16));
public string FormattedIssueLabels => Labels
public string FormattedIssueLabels => IssueLabels
.Where(it => !it.StartsWithIgnoreCase("status"))
.Select(FormatLabelName)
.JoinToString(", ");
public override string ToString()
{
StringBuilder sb = new("CompatibilityEntry: {");
var sb = new StringBuilder("CompatibilityEntry: {");
sb.Append($"{nameof(GameName)}=\"{GameName}\", ");
sb.Append($"{nameof(TitleId)}={TitleId}, ");
sb.Append($"{nameof(Labels)}={
Labels.FormatCollection(it => $"\"{it}\"", separator: ", ", prefix: "[", suffix: "]")
}, ");
sb.Append($"{nameof(IssueLabels)}=\"{IssueLabels}\", ");
sb.Append($"{nameof(Status)}=\"{Status}\", ");
sb.Append($"{nameof(LastUpdated)}=\"{LastUpdated}\"");
sb.Append($"{nameof(LastEvent)}=\"{LastEvent}\"");
sb.Append('}');
return sb.ToString();
@@ -161,8 +144,8 @@ namespace Ryujinx.Ava.Utilities.Compat
if (value == string.Empty)
return string.Empty;
char firstChar = value[0];
string rest = value[1..];
var firstChar = value[0];
var rest = value[1..];
return $"{char.ToUpper(firstChar)}{rest}";
}

View File

@@ -44,11 +44,8 @@
ItemsSource="{Binding CurrentEntries}">
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type local:CompatibilityEntry}">
<Grid Width="750"
Margin="5"
ColumnDefinitions="Auto,Auto,Auto,*"
Background="Transparent"
ToolTip.Tip="{Binding LocalizedLastUpdated}">
<Grid Width="750" ColumnDefinitions="Auto,Auto,Auto,*"
Margin="5">
<TextBlock Grid.Column="0"
Text="{Binding GameName}"
Width="320"

View File

@@ -14,6 +14,15 @@ namespace Ryujinx.Ava.Utilities.Compat
{
public static async Task Show()
{
if (CompatibilityCsv.Shared is null)
{
await using Stream csvStream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("RyujinxGameCompatibilityList")!;
csvStream.Position = 0;
CompatibilityCsv.Shared = new CompatibilityCsv(Sep.Reader().From(csvStream));
}
ContentDialog contentDialog = new()
{
PrimaryButtonText = string.Empty,
@@ -42,7 +51,7 @@ namespace Ryujinx.Ava.Utilities.Compat
InitializeComponent();
}
private void TextBox_OnTextChanged(object sender, TextChangedEventArgs e)
private void TextBox_OnTextChanged(object? sender, TextChangedEventArgs e)
{
if (DataContext is not CompatibilityViewModel cvm)
return;

View File

@@ -11,13 +11,14 @@ namespace Ryujinx.Ava.Utilities.Compat
{
[ObservableProperty] private bool _onlyShowOwnedGames = true;
private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityCsv.Entries;
private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityCsv.Shared.Entries;
private readonly string[] _ownedGameTitleIds = [];
private readonly ApplicationLibrary _appLibrary;
public IEnumerable<CompatibilityEntry> CurrentEntries => OnlyShowOwnedGames
? _currentEntries.Where(x =>
x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid)))
x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid))
|| _appLibrary.Applications.Items.Any(a => a.Name.EqualsIgnoreCase(x.GameName)))
: _currentEntries;
public CompatibilityViewModel() {}
@@ -38,11 +39,11 @@ namespace Ryujinx.Ava.Utilities.Compat
{
if (string.IsNullOrEmpty(searchTerm))
{
SetEntries(CompatibilityCsv.Entries);
SetEntries(CompatibilityCsv.Shared.Entries);
return;
}
SetEntries(CompatibilityCsv.Entries.Where(x =>
SetEntries(CompatibilityCsv.Shared.Entries.Where(x =>
x.GameName.ContainsIgnoreCase(searchTerm)
|| x.TitleId.Check(tid => tid.ContainsIgnoreCase(searchTerm))));
}