mirror of
https://git.ryujinx.app/kenji-nx/ryujinx.git
synced 2025-12-16 22:37:06 +00:00
Android fixes and features
* Jit cache eviction (fixes out of memory errors in some games) * Low power PPTC * Fix 'unknown' games displayed when using game folder with subfolders * Turn off NCE and PPTC by default
This commit is contained in:
parent
3af88ad2e6
commit
fda90239bc
58 changed files with 914 additions and 190 deletions
|
|
@ -8,6 +8,9 @@ namespace ARMeilleure
|
|||
// low-core count PPTC
|
||||
public static bool EcoFriendly { get; set; } = false;
|
||||
|
||||
// Jit cache eviction
|
||||
public static bool CacheEviction { get; set; } = false;
|
||||
|
||||
public static bool FastFP { get; set; } = true;
|
||||
|
||||
public static bool AllowLcqInFunctionTable { get; set; } = true;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ using ARMeilleure.CodeGen;
|
|||
using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.Native;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
|
|
@ -17,8 +19,15 @@ namespace ARMeilleure.Translation.Cache
|
|||
private static readonly int _pageSize = (int)MemoryBlock.GetPageSize();
|
||||
private static readonly int _pageMask = _pageSize - 1;
|
||||
|
||||
private const int CodeAlignment = 4; // Bytes.
|
||||
private const int CacheSize = 2047 * 1024 * 1024;
|
||||
private const int CodeAlignment = 4;
|
||||
private const int FullCacheSize = 2047 * 1024 * 1024;
|
||||
private const int ReducedCacheSize = FullCacheSize / 8;
|
||||
|
||||
private const float EvictionTargetPercentage = 0.20f;
|
||||
private const int MaxEntriesToEvictAtOnce = 100;
|
||||
|
||||
// Simple logging configuration
|
||||
private const int LogInterval = 5000; // Log every 5000 allocations
|
||||
|
||||
private static ReservedRegion _jitRegion;
|
||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||
|
|
@ -26,9 +35,33 @@ namespace ARMeilleure.Translation.Cache
|
|||
private static CacheMemoryAllocator _cacheAllocator;
|
||||
|
||||
private static readonly List<CacheEntry> _cacheEntries = [];
|
||||
private static readonly Dictionary<int, EntryUsageStats> _entryUsageStats = [];
|
||||
|
||||
private static readonly Lock _lock = new();
|
||||
private static bool _initialized;
|
||||
private static int _cacheSize;
|
||||
|
||||
// Basic statistics
|
||||
private static int _totalAllocations = 0;
|
||||
private static int _totalEvictions = 0;
|
||||
|
||||
private class EntryUsageStats
|
||||
{
|
||||
public long LastAccessTime { get; private set; }
|
||||
public int UsageCount { get; private set; }
|
||||
|
||||
public EntryUsageStats()
|
||||
{
|
||||
LastAccessTime = DateTime.UtcNow.Ticks;
|
||||
UsageCount = 1;
|
||||
}
|
||||
|
||||
public void UpdateUsage()
|
||||
{
|
||||
LastAccessTime = DateTime.UtcNow.Ticks;
|
||||
UsageCount++;
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
|
|
@ -48,20 +81,22 @@ namespace ARMeilleure.Translation.Cache
|
|||
return;
|
||||
}
|
||||
|
||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
||||
_cacheSize = Optimizations.CacheEviction ? ReducedCacheSize : FullCacheSize;
|
||||
_jitRegion = new ReservedRegion(allocator, (ulong)_cacheSize);
|
||||
|
||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||
{
|
||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||
}
|
||||
|
||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||
_cacheAllocator = new CacheMemoryAllocator(_cacheSize);
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize, _jitRegion.Pointer + Allocate(_pageSize));
|
||||
JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, (uint)_cacheSize, _jitRegion.Pointer + Allocate(_pageSize));
|
||||
}
|
||||
|
||||
Logger.Info?.Print(LogClass.Cpu, $"JIT Cache initialized: Size={_cacheSize / (1024 * 1024)} MB, Eviction={Optimizations.CacheEviction}");
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -73,8 +108,32 @@ namespace ARMeilleure.Translation.Cache
|
|||
lock (_lock)
|
||||
{
|
||||
Debug.Assert(_initialized);
|
||||
_totalAllocations++;
|
||||
|
||||
int funcOffset = Allocate(code.Length);
|
||||
int funcOffset;
|
||||
|
||||
if (Optimizations.CacheEviction)
|
||||
{
|
||||
int codeSize = AlignCodeSize(code.Length);
|
||||
funcOffset = _cacheAllocator.Allocate(codeSize);
|
||||
|
||||
if (funcOffset < 0)
|
||||
{
|
||||
EvictEntries(codeSize);
|
||||
funcOffset = _cacheAllocator.Allocate(codeSize);
|
||||
|
||||
if (funcOffset < 0)
|
||||
{
|
||||
throw new OutOfMemoryException("JIT Cache exhausted even after eviction.");
|
||||
}
|
||||
}
|
||||
|
||||
_jitRegion.ExpandIfNeeded((ulong)funcOffset + (ulong)codeSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
funcOffset = Allocate(code.Length);
|
||||
}
|
||||
|
||||
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
|
||||
|
||||
|
|
@ -106,6 +165,12 @@ namespace ARMeilleure.Translation.Cache
|
|||
|
||||
Add(funcOffset, code.Length, func.UnwindInfo);
|
||||
|
||||
// Simple periodic logging
|
||||
if (_totalAllocations % LogInterval == 0)
|
||||
{
|
||||
LogCacheStatus();
|
||||
}
|
||||
|
||||
return funcPtr;
|
||||
}
|
||||
}
|
||||
|
|
@ -122,6 +187,11 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
||||
_cacheEntries.RemoveAt(entryIndex);
|
||||
|
||||
if (Optimizations.CacheEviction)
|
||||
{
|
||||
_entryUsageStats.Remove(funcOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -179,6 +249,11 @@ namespace ARMeilleure.Translation.Cache
|
|||
}
|
||||
|
||||
_cacheEntries.Insert(index, entry);
|
||||
|
||||
if (Optimizations.CacheEviction)
|
||||
{
|
||||
_entryUsageStats[offset] = new EntryUsageStats();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryFind(int offset, out CacheEntry entry, out int entryIndex)
|
||||
|
|
@ -195,6 +270,12 @@ namespace ARMeilleure.Translation.Cache
|
|||
if (index >= 0)
|
||||
{
|
||||
entry = _cacheEntries[index];
|
||||
|
||||
if (Optimizations.CacheEviction && _entryUsageStats.TryGetValue(offset, out var stats))
|
||||
{
|
||||
stats.UpdateUsage();
|
||||
}
|
||||
|
||||
entryIndex = index;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -204,5 +285,83 @@ namespace ARMeilleure.Translation.Cache
|
|||
entryIndex = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void EvictEntries(int requiredSize)
|
||||
{
|
||||
if (!Optimizations.CacheEviction)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
int targetSpace = Math.Max(requiredSize, (int)(_cacheSize * EvictionTargetPercentage));
|
||||
int freedSpace = 0;
|
||||
int evictedCount = 0;
|
||||
|
||||
var entriesWithStats = _cacheEntries
|
||||
.Where(e => _entryUsageStats.ContainsKey(e.Offset))
|
||||
.Select(e => new {
|
||||
Entry = e,
|
||||
Stats = _entryUsageStats[e.Offset],
|
||||
Score = CalculateEvictionScore(_entryUsageStats[e.Offset])
|
||||
})
|
||||
.OrderBy(x => x.Score)
|
||||
.Take(MaxEntriesToEvictAtOnce)
|
||||
.ToList();
|
||||
|
||||
foreach (var item in entriesWithStats)
|
||||
{
|
||||
int entrySize = AlignCodeSize(item.Entry.Size);
|
||||
|
||||
int entryIndex = _cacheEntries.BinarySearch(item.Entry);
|
||||
if (entryIndex >= 0)
|
||||
{
|
||||
_cacheAllocator.Free(item.Entry.Offset, entrySize);
|
||||
_cacheEntries.RemoveAt(entryIndex);
|
||||
_entryUsageStats.Remove(item.Entry.Offset);
|
||||
|
||||
freedSpace += entrySize;
|
||||
evictedCount++;
|
||||
|
||||
if (freedSpace >= targetSpace)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_totalEvictions += evictedCount;
|
||||
|
||||
Logger.Info?.Print(LogClass.Cpu, $"JIT Cache: Evicted {evictedCount} entries, freed {freedSpace / (1024 * 1024.0):F2} MB");
|
||||
}
|
||||
}
|
||||
|
||||
private static double CalculateEvictionScore(EntryUsageStats stats)
|
||||
{
|
||||
long currentTime = DateTime.UtcNow.Ticks;
|
||||
long ageInTicks = currentTime - stats.LastAccessTime;
|
||||
|
||||
double ageInSeconds = ageInTicks / 10_000_000.0;
|
||||
|
||||
const double usageWeight = 1.0;
|
||||
const double ageWeight = 2.0;
|
||||
|
||||
double usageScore = Math.Log10(stats.UsageCount + 1) * usageWeight;
|
||||
double ageScore = (10.0 / (ageInSeconds + 1.0)) * ageWeight;
|
||||
|
||||
return usageScore + ageScore;
|
||||
}
|
||||
|
||||
private static void LogCacheStatus()
|
||||
{
|
||||
int estimatedUsedSize = _cacheEntries.Sum(e => AlignCodeSize(e.Size));
|
||||
double usagePercentage = 100.0 * estimatedUsedSize / _cacheSize;
|
||||
|
||||
Logger.Info?.Print(LogClass.Cpu,
|
||||
$"JIT Cache status: entries={_cacheEntries.Count}, " +
|
||||
$"est. used={estimatedUsedSize / (1024 * 1024.0):F2} MB ({usagePercentage:F1}%), " +
|
||||
$"evictions={_totalEvictions}, allocations={_totalAllocations}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using ARMeilleure.Instructions;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
private const string OuterHeaderMagicString = "PTCohd\0\0";
|
||||
private const string InnerHeaderMagicString = "PTCihd\0\0";
|
||||
|
||||
private const uint InternalVersion = 6998; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
private const uint InternalVersion = 7008; //! To be incremented manually for each change to the ARMeilleure project.
|
||||
|
||||
private const string ActualDir = "0";
|
||||
private const string BackupDir = "1";
|
||||
|
|
@ -563,6 +563,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
if (AreCarriersEmpty() || ContainsBlacklistedFunctions())
|
||||
{
|
||||
ResetCarriersIfNeeded();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -869,7 +870,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
|
||||
Debug.Assert(Profiler.IsAddressInStaticCodeRange(address));
|
||||
|
||||
TranslatedFunction func = translator.Translate(address, executionMode, highCq);
|
||||
TranslatedFunction func = translator.Translate(address, executionMode, highCq, pptcTranslation: true);
|
||||
|
||||
if (func == null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
|
||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false)
|
||||
internal TranslatedFunction Translate(ulong address, ExecutionMode mode, bool highCq, bool singleStep = false, bool pptcTranslation = false)
|
||||
{
|
||||
var context = new ArmEmitterContext(
|
||||
Memory,
|
||||
|
|
@ -246,7 +246,12 @@ namespace ARMeilleure.Translation
|
|||
context.Branch(context.GetLabel(address));
|
||||
}
|
||||
|
||||
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter);
|
||||
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter, pptcTranslation);
|
||||
|
||||
if (cfg == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
ulong funcSize = funcRange.End - funcRange.Start;
|
||||
|
||||
|
|
@ -321,7 +326,8 @@ namespace ARMeilleure.Translation
|
|||
ArmEmitterContext context,
|
||||
Block[] blocks,
|
||||
out Range range,
|
||||
out Counter<uint> counter)
|
||||
out Counter<uint> counter,
|
||||
bool pptcTranslation)
|
||||
{
|
||||
counter = null;
|
||||
|
||||
|
|
@ -406,6 +412,14 @@ namespace ARMeilleure.Translation
|
|||
if (opCode.Instruction.Emitter != null)
|
||||
{
|
||||
opCode.Instruction.Emitter(context);
|
||||
// if we're pre-compiling PPTC functions, and we hit an Undefined instruction as the first
|
||||
// instruction in the block, mark the function as blacklisted
|
||||
// this way, we don't pre-compile Exlaunch hooks, which allows ExeFS mods to run with PPTC
|
||||
if (pptcTranslation && opCode.Instruction.Name == InstName.Und && blkIndex == 0)
|
||||
{
|
||||
range = new Range(rangeStart, rangeEnd);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,20 +1,46 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<RuntimeIdentifiers>win-x64;osx-x64;linux-x64;win-arm64;osx-arm64;linux-arm64</RuntimeIdentifiers>
|
||||
<AssemblyName>Kenjinx.Headless</AssemblyName>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<Version>2.0.3</Version>
|
||||
<DefineConstants Condition=" '$(ExtraDefineConstants)' != '' ">$(DefineConstants);$(ExtraDefineConstants)</DefineConstants>
|
||||
<SigningCertificate Condition=" '$(SigningCertificate)' == '' ">-</SigningCertificate>
|
||||
<ApplicationIcon>Kenjinx.ico</ApplicationIcon>
|
||||
<IncludeSourceRevisionInInformationalVersion Condition="'$(Configuration)'=='Release'">false</IncludeSourceRevisionInInformationalVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == '' AND '$(BuildingInsideVisualStudio)' == 'true'">
|
||||
<RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('Windows'))">win-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('OSX'))">osx-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('Linux'))">linux-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<SelfContained>true</SelfContained>
|
||||
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<TrimMode>partial</TrimMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'win-arm64'">
|
||||
<PublishTrimmed>false</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTK.Core" />
|
||||
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' == 'win-x64' OR '$(RuntimeIdentifier)' == 'win-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.Linux" Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.macOS" Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies.Windows" Condition="'$(RuntimeIdentifier)' == 'win-x64' OR '$(RuntimeIdentifier)' == 'win-arm64'" />
|
||||
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64'" />
|
||||
<PackageReference Include="Silk.NET.Vulkan" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" />
|
||||
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />
|
||||
<PackageReference Include="SPB" />
|
||||
<PackageReference Include="SharpZipLib" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
|
||||
|
|
@ -39,6 +65,10 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\distribution\windows\alsoft.ini" Condition="'$(RuntimeIdentifier)' == 'win-x64' OR '$(RuntimeIdentifier)' == 'win-arm64'">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>alsoft.ini</TargetPath>
|
||||
</Content>
|
||||
<Content Include="..\..\distribution\legal\THIRDPARTY.md">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>THIRDPARTY.md</TargetPath>
|
||||
|
|
@ -47,6 +77,7 @@
|
|||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
<TargetPath>LICENSE.txt</TargetPath>
|
||||
</Content>
|
||||
<Content Include="Kenjinx.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64'" >
|
||||
|
|
|
|||
|
|
@ -470,6 +470,7 @@ namespace Ryujinx.Ava
|
|||
public void Start()
|
||||
{
|
||||
ARMeilleure.Optimizations.EcoFriendly = ConfigurationState.Instance.System.EnableLowPowerPtc;
|
||||
ARMeilleure.Optimizations.CacheEviction = ConfigurationState.Instance.System.EnableJitCacheEviction;
|
||||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "VSync",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (ذاكرة التخزين المؤقت للترجمة المستمرة)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "التحقق من سلامة نظام الملفات",
|
||||
"SettingsTabSystemAudioBackend": "خلفية الصوت:",
|
||||
"SettingsTabSystemAudioBackendDummy": "زائف",
|
||||
|
|
@ -589,7 +590,8 @@
|
|||
"TimeTooltip": "تغيير وقت النظام",
|
||||
"VSyncToggleTooltip": "محاكاة المزامنة العمودية للجهاز. في الأساس محدد الإطار لغالبية الألعاب؛ قد يؤدي تعطيله إلى تشغيل الألعاب بسرعة أعلى أو جعل شاشات التحميل تستغرق وقتا أطول أو تتعطل.\n\nيمكن تبديله داخل اللعبة باستخدام مفتاح التشغيل السريع الذي تفضله (F1 افتراضيا). نوصي بالقيام بذلك إذا كنت تخطط لتعطيله.\n\nاتركه ممكنا إذا لم تكن متأكدا.",
|
||||
"PptcToggleTooltip": "يحفظ وظائف JIT المترجمة بحيث لا تحتاج إلى ترجمتها في كل مرة يتم فيها تحميل اللعبة.\n\nيقلل من التقطيع ويسرع بشكل ملحوظ أوقات التشغيل بعد التشغيل الأول للعبة.\n\nاتركه ممكنا إذا لم تكن متأكدا.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "قم بتحميل PPTC باستخدام ثلث كمية النوى",
|
||||
"JitCacheEvictionToggleTooltip": "م بتمكين إخلاء JIT Cache لإدارة الذاكرة بكفاءة",
|
||||
"FsIntegrityToggleTooltip": "يتحقق من وجود ملفات تالفة عند تشغيل لعبة ما، وإذا تم اكتشاف ملفات تالفة، فسيتم عرض خطأ تجزئة في السجل.\n\nليس له أي تأثير على الأداء ويهدف إلى المساعدة في استكشاف الأخطاء وإصلاحها.\n\nاتركه مفعلا إذا كنت غير متأكد.",
|
||||
"AudioBackendTooltip": "يغير الواجهة الخلفية المستخدمة لتقديم الصوت.\n\nSDL2 هو الخيار المفضل، بينما يتم استخدام OpenAL وSoundIO كبديلين. زائف لن يكون لها صوت.\n\nاضبط على SDL2 إذا لم تكن متأكدا.",
|
||||
"MemoryManagerTooltip": "تغيير كيفية تعيين ذاكرة الضيف والوصول إليها. يؤثر بشكل كبير على أداء وحدة المعالجة المركزية التي تمت محاكاتها.\n\nاضبط على المضيف غير محدد إذا لم تكن متأكدا.",
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@
|
|||
"SettingsTabSystemEnableVsync": "VSync",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Kleinleistungs-PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit-Cache-Räumung",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS Integritätsprüfung",
|
||||
"SettingsTabSystemAudioBackend": "Audio-Backend:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Ohne Funktion",
|
||||
|
|
@ -591,6 +592,7 @@
|
|||
"VSyncToggleTooltip": "Vertikale Synchronisierung der emulierten Konsole. Diese Option ist quasi ein Frame-Limiter für die meisten Spiele; die Deaktivierung kann dazu führen, dass Spiele mit höherer Geschwindigkeit laufen oder Ladebildschirme länger benötigen/hängen bleiben.\n\nKann beim Spielen mit einem frei wählbaren Hotkey ein- und ausgeschaltet werden (standardmäßig F1). \n\nIm Zweifelsfall AN lassen.",
|
||||
"PptcToggleTooltip": "Speichert übersetzte JIT-Funktionen, sodass jene nicht jedes Mal übersetzt werden müssen, wenn das Spiel geladen wird.\n\nVerringert Stottern und die Zeit beim zweiten und den darauffolgenden Startvorgängen eines Spiels erheblich.\n\nIm Zweifelsfall AN lassen.",
|
||||
"LowPowerPptcToggleTooltip": "Lädt den PPTC mit einem Drittel der verfügbaren Prozessorkernen",
|
||||
"JitCacheEvictionToggleTooltip": "Aktivieren Sie die JIT-Cache-Eviction, um den Speicher effizient zu verwalten",
|
||||
"FsIntegrityToggleTooltip": "Prüft beim Startvorgang auf beschädigte Dateien und zeigt bei beschädigten Dateien einen Hash-Fehler (Hash Error) im Log an.\n\nDiese Einstellung hat keinen Einfluss auf die Leistung und hilft bei der Fehlersuche.\n\nIm Zweifelsfall AN lassen.",
|
||||
"AudioBackendTooltip": "Ändert das Backend, das zum Rendern von Audio verwendet wird.\n\nSDL2 ist das bevorzugte Audio-Backend, OpenAL und SoundIO sind als Alternativen vorhanden. Dummy wird keinen Audio-Output haben.\n\nIm Zweifelsfall SDL2 auswählen.",
|
||||
"MemoryManagerTooltip": "Ändert wie der Gastspeicher abgebildet wird und wie auf ihn zugegriffen wird. Beinflusst die Leistung der emulierten CPU erheblich.\n\nIm Zweifelsfall Host ungeprüft auswählen.",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "Ενεργοποίηση Κατακόρυφου Συγχρονισμού",
|
||||
"SettingsTabSystemEnablePptc": "Ενεργοποίηση PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Ενεργοποίηση Ελέγχων Ακεραιότητας FS",
|
||||
"SettingsTabSystemAudioBackend": "Backend Ήχου:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Απενεργοποιημένο",
|
||||
|
|
@ -589,7 +590,8 @@
|
|||
"TimeTooltip": "Αλλαγή Ώρας Συστήματος",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"PptcToggleTooltip": "Ενεργοποιεί ή απενεργοποιεί το PPTC",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Φορτώστε το PPTC χρησιμοποιώντας το ένα τρίτο της ποσότητας πυρήνων",
|
||||
"JitCacheEvictionToggleTooltip": "Ενεργοποιήστε την εξαγωγή JIT Cache για αποτελεσματική διαχείριση της μνήμης",
|
||||
"FsIntegrityToggleTooltip": "Ενεργοποιεί τους ελέγχους ακεραιότητας σε αρχεία περιεχομένου παιχνιδιού",
|
||||
"AudioBackendTooltip": "Αλλαγή ήχου υποστήριξης",
|
||||
"MemoryManagerTooltip": "Αλλάξτε τον τρόπο αντιστοίχισης και πρόσβασης στη μνήμη επισκέπτη. Επηρεάζει σε μεγάλο βαθμό την απόδοση της προσομοίωσης της CPU.",
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@
|
|||
"SettingsTabSystemCustomVSyncIntervalValue": "Custom Refresh Rate Value:",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC cache",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS Integrity Checks",
|
||||
"SettingsTabSystemAudioBackend": "Audio Backend:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
|
|
@ -621,7 +622,8 @@
|
|||
"MatchTimeTooltip": "Sync System Time to match your PC's current date & time.",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"PptcToggleTooltip": "Saves translated JIT functions so that they do not need to be translated every time the game loads.\n\nReduces stuttering and significantly speeds up boot times after the first boot of a game.\n\nLeave ON if unsure.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores",
|
||||
"JitCacheEvictionToggleTooltip": "Enable JIT Cache eviction to manage memory efficiently",
|
||||
"FsIntegrityToggleTooltip": "Checks for corrupt files when booting a game, and if corrupt files are detected, displays a hash error in the log.\n\nHas no impact on performance and is meant to help troubleshooting.\n\nLeave ON if unsure.",
|
||||
"AudioBackendTooltip": "Changes the backend used to render audio.\n\nSDL2 is the preferred one, while OpenAL and SoundIO are used as fallbacks. Dummy will have no sound.\n\nSet to SDL2 if unsure.",
|
||||
"MemoryManagerTooltip": "Change how guest memory is mapped and accessed. Greatly affects emulated CPU performance.\n\nSet to HOST UNCHECKED if unsure.",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "Sincronización vertical",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Cache de Traducción de Perfil Persistente)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Comprobar integridad de los archivos",
|
||||
"SettingsTabSystemAudioBackend": "Motor de audio:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Vacio",
|
||||
|
|
@ -589,7 +590,8 @@
|
|||
"TimeTooltip": "Cambia la hora del sistema",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"PptcToggleTooltip": "Guarda funciones de JIT traducidas para que no sea necesario traducirlas cada vez que el juego carga.\n\nReduce los tirones y acelera significativamente el tiempo de inicio de los juegos después de haberlos ejecutado al menos una vez.\n\nActívalo si no sabes qué hacer.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Cargue el PPTC usando un tercio de la cantidad de núcleos",
|
||||
"JitCacheEvictionToggleTooltip": "Habilite el desalojo de JIT Cache para administrar la memoria de manera eficiente",
|
||||
"FsIntegrityToggleTooltip": "Comprueba si hay archivos corruptos en los juegos que ejecutes al abrirlos, y si detecta archivos corruptos, muestra un error de Hash en los registros.\n\nEsto no tiene impacto alguno en el rendimiento y está pensado para ayudar a resolver problemas.\n\nActívalo si no sabes qué hacer.",
|
||||
"AudioBackendTooltip": "Cambia el motor usado para renderizar audio.\n\nSDL2 es el preferido, mientras que OpenAL y SoundIO se usan si hay problemas con este. Dummy no produce audio.\n\nSelecciona SDL2 si no sabes qué hacer.",
|
||||
"MemoryManagerTooltip": "Cambia la forma de mapear y acceder a la memoria del guest. Afecta en gran medida al rendimiento de la CPU emulada.\n\nSelecciona \"Host sin verificación\" si no sabes qué hacer.",
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@
|
|||
"SettingsTabSystemEnableVsync": "Synchronisation verticale (VSync)",
|
||||
"SettingsTabSystemEnablePptc": "Activer le PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Activer la vérification de l'intégrité du système de fichiers",
|
||||
"SettingsTabSystemAudioBackend": "Bibliothèque Audio :",
|
||||
"SettingsTabSystemAudioBackendDummy": "Factice",
|
||||
|
|
@ -592,7 +593,8 @@
|
|||
"MatchTimeTooltip": "Resynchronise la Date du Système pour qu'elle soit la même que celle du PC.",
|
||||
"VSyncToggleTooltip": "La synchronisation verticale de la console émulée. Essentiellement un limiteur de trame pour la majorité des jeux ; le désactiver peut entraîner un fonctionnement plus rapide des jeux ou prolonger ou bloquer les écrans de chargement.\n\nPeut être activé ou désactivé en jeu avec un raccourci clavier de votre choix (F1 par défaut). Nous recommandons de le faire si vous envisagez de le désactiver.\n\nLaissez activé si vous n'êtes pas sûr.",
|
||||
"PptcToggleTooltip": "Sauvegarde les fonctions JIT afin qu'elles n'aient pas besoin d'être à chaque fois recompiler lorsque le jeu se charge.\n\nRéduit les lags et accélère considérablement le temps de chargement après le premier lancement d'un jeu.\n\nLaissez par défaut si vous n'êtes pas sûr.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Chargez le PPTC en utilisant un tiers de la quantité de cœurs",
|
||||
"JitCacheEvictionToggleTooltip": "Activer l'expulsion du cache JIT pour gérer efficacement la mémoire",
|
||||
"FsIntegrityToggleTooltip": "Vérifie si des fichiers sont corrompus lors du lancement d'un jeu, et si des fichiers corrompus sont détectés, affiche une erreur de hachage dans la console.\n\nN'a aucun impact sur les performances et est destiné à aider le dépannage.\n\nLaissez activer en cas d'incertitude.",
|
||||
"AudioBackendTooltip": "Modifie le backend utilisé pour donnée un rendu audio.\n\nSDL2 est préféré, tandis que OpenAL et SoundIO sont utilisés comme backend secondaire. Le backend Dummy (Factice) ne rends aucun son.\n\nLaissez sur SDL2 si vous n'êtes pas sûr.",
|
||||
"MemoryManagerTooltip": "Change la façon dont la mémoire émulée est mappée et utiliser. Cela affecte grandement les performances du processeur.\n\nRéglez sur Host Uncheked en cas d'incertitude.",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "VSync",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS בדיקות תקינות",
|
||||
"SettingsTabSystemAudioBackend": "אחראי שמע:",
|
||||
"SettingsTabSystemAudioBackendDummy": "גולם",
|
||||
|
|
@ -589,7 +590,8 @@
|
|||
"TimeTooltip": "שנה זמן מערכת",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"PptcToggleTooltip": "שומר את פונקציות ה-JIT המתורגמות כך שלא יצטרכו לעבור תרגום שוב כאשר משחק עולה.\n\nמפחית תקיעות ומשפר מהירות עלייה של המערכת אחרי הפתיחה הראשונה של המשחק.\n\nמוטב להשאיר דלוק אם לא בטוחים.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "טען את ה-PPTC באמצעות שליש מכמות הליבות",
|
||||
"JitCacheEvictionToggleTooltip": "אפשר פינוי JIT Cache לניהול זיכרון ביעילות",
|
||||
"FsIntegrityToggleTooltip": "בודק לקבצים שגויים כאשר משחק עולה, ואם מתגלים כאלו, מציג את מזהה השגיאה שלהם לקובץ הלוג.\n\nאין לכך השפעה על הביצועים ונועד לעזור לבדיקה וניפוי שגיאות של האמולטור.\n\nמוטב להשאיר דלוק אם לא בטוחים.",
|
||||
"AudioBackendTooltip": "משנה את אחראי השמע.\n\nSDL2 הוא הנבחר, למראת שOpenAL וגם SoundIO משומשים כאפשרויות חלופיות. אפשרות הDummy לא תשמיע קול כלל.\n\nמוטב להשאיר על SDL2 אם לא בטוחים.",
|
||||
"MemoryManagerTooltip": "שנה איך שזיכרון מארח מיוחד ומונגד. משפיע מאוד על ביצועי המעבד המדומה.\n\nמוטב להשאיר על מארח לא מבוקר אם לא בטוחים.",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "Attiva VSync",
|
||||
"SettingsTabSystemEnablePptc": "Attiva PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Attiva controlli d'integrità FS",
|
||||
"SettingsTabSystemAudioBackend": "Backend audio:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
|
|
@ -590,7 +591,8 @@
|
|||
"MatchTimeTooltip": "Sincronizza data e ora del sistema con quelle del PC.",
|
||||
"VSyncToggleTooltip": "Sincronizzazione verticale della console Emulata. Essenzialmente un limitatore di frame per la maggior parte dei giochi; disabilitarlo può far girare giochi a velocità più alta, allungare le schermate di caricamento o farle bloccare.\n\nPuò essere attivata in gioco con un tasto di scelta rapida (F1 per impostazione predefinita). Ti consigliamo di farlo se hai intenzione di disabilitarlo.\n\nLascia ON se non sei sicuro.",
|
||||
"PptcToggleTooltip": "Salva le funzioni JIT tradotte in modo che non debbano essere tradotte tutte le volte che si avvia un determinato gioco.\n\nRiduce i fenomeni di stuttering e velocizza sensibilmente gli avvii successivi del gioco.\n\nNel dubbio, lascia l'opzione attiva.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Carica il PPTC utilizzando un terzo della quantità di core",
|
||||
"JitCacheEvictionToggleTooltip": "Abilita l'eliminazione della cache JIT per gestire la memoria in modo efficiente",
|
||||
"FsIntegrityToggleTooltip": "Controlla la presenza di file corrotti quando si avvia un gioco. Se vengono rilevati dei file corrotti, verrà mostrato un errore di hash nel log.\n\nQuesta opzione non influisce sulle prestazioni ed è pensata per facilitare la risoluzione dei problemi.\n\nNel dubbio, lascia l'opzione attiva.",
|
||||
"AudioBackendTooltip": "Cambia il backend usato per riprodurre l'audio.\n\nSDL2 è quello preferito, mentre OpenAL e SoundIO sono usati come ripiego. Dummy non riprodurrà alcun suono.\n\nNel dubbio, imposta l'opzione su SDL2.",
|
||||
"MemoryManagerTooltip": "Cambia il modo in cui la memoria guest è mappata e vi si accede. Influisce notevolmente sulle prestazioni della CPU emulata.\n\nNel dubbio, imposta l'opzione su Host Unchecked.",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "VSync",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "ファイルシステム整合性チェック",
|
||||
"SettingsTabSystemAudioBackend": "音声バックエンド:",
|
||||
"SettingsTabSystemAudioBackendDummy": "ダミー",
|
||||
|
|
@ -589,7 +590,8 @@
|
|||
"TimeTooltip": "システムの時刻を変更します",
|
||||
"VSyncToggleTooltip": "エミュレートされたゲーム機の垂直同期です. 多くのゲームにおいて, フレームリミッタとして機能します. 無効にすると, ゲームが高速で実行されたり, ロード中に時間がかかったり, 止まったりすることがあります.\n\n設定したホットキー(デフォルトではF1)で, ゲーム内で切り替え可能です. 無効にする場合は, この操作を行うことをおすすめします.\n\nよくわからない場合はオンのままにしてください.",
|
||||
"PptcToggleTooltip": "翻訳されたJIT関数をセーブすることで, ゲームをロードするたびに毎回翻訳する処理を不要とします.\n\n一度ゲームを起動すれば,二度目以降の起動時遅延を大きく軽減できます.\n\nよくわからない場合はオンのままにしてください.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "コア数の 3 分の 1 を使用して PPTC をロードします。",
|
||||
"JitCacheEvictionToggleTooltip": "JIT キャッシュのエビクションを有効にしてメモリを効率的に管理する",
|
||||
"FsIntegrityToggleTooltip": "ゲーム起動時にファイル破損をチェックし,破損が検出されたらログにハッシュエラーを表示します..\n\nパフォーマンスには影響なく, トラブルシューティングに役立ちます.\n\nよくわからない場合はオンのままにしてください.",
|
||||
"AudioBackendTooltip": "音声レンダリングに使用するバックエンドを変更します.\n\nSDL2 が優先され, OpenAL と SoundIO はフォールバックとして使用されます. ダミーは音声出力しません.\n\nよくわからない場合は SDL2 を設定してください.",
|
||||
"MemoryManagerTooltip": "ゲストメモリのマップ/アクセス方式を変更します. エミュレートされるCPUのパフォーマンスに大きな影響を与えます.\n\nよくわからない場合は「ホスト,チェックなし」を設定してください.",
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@
|
|||
"SettingsTabSystemEnableVsync": "수직 동기화",
|
||||
"SettingsTabSystemEnablePptc": "PPTC(프로파일된 영구 번역 캐시)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "파일 시스템 무결성 검사",
|
||||
"SettingsTabSystemAudioBackend": "음향 후단부 :",
|
||||
"SettingsTabSystemAudioBackendDummy": "더미",
|
||||
|
|
@ -593,7 +594,8 @@
|
|||
"MatchTimeTooltip": "시스템 시간을 PC의 현재 날짜 및 시간과 일치하도록 다시 동기화합니다.",
|
||||
"VSyncToggleTooltip": "에뮬레이트된 콘솔의 수직 동기화. 기본적으로 대부분의 게임에 대한 프레임 제한 장치로, 비활성화시 게임이 더 빠른 속도로 실행되거나 로딩 화면이 더 오래 걸리거나 멈출 수 있습니다.\n\n게임 내에서 선호하는 핫키로 전환할 수 있습니다(기본값 F1). 핫키를 비활성화할 계획이라면 이 작업을 수행하는 것이 좋습니다.\n\n이 옵션에 대해 잘 모른다면 켜기를 권장드립니다.",
|
||||
"PptcToggleTooltip": "게임이 불러올 때마다 번역할 필요가 없도록 번역된 JIT 기능을 저장합니다.\n\n게임을 처음 부팅한 후 끊김 현상을 줄이고 부팅 시간을 크게 단축합니다.\n\n확실하지 않으면 켜 두세요.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "코어 양의 1/3을 사용하여 PPTC를 로드합니다.",
|
||||
"JitCacheEvictionToggleTooltip": "메모리를 효율적으로 관리하기 위해 JIT 캐시 제거를 활성화합니다.",
|
||||
"FsIntegrityToggleTooltip": "게임을 부팅할 때 손상된 파일을 확인하고 손상된 파일이 감지되면 로그에 해시 오류를 표시합니다.\n\n성능에 영향을 미치지 않으며 문제 해결에 도움이 됩니다.\n\n확실하지 않으면 켜 두세요.",
|
||||
"AudioBackendTooltip": "오디오를 렌더링하는 데 사용되는 백엔드를 변경합니다.\n\nSDL2가 선호되는 반면 OpenAL 및 사운드IO는 폴백으로 사용됩니다. 더미는 소리가 나지 않습니다.\n\n확실하지 않으면 SDL2로 설정하세요.",
|
||||
"MemoryManagerTooltip": "게스트 메모리가 매핑되고 접속되는 방식을 변경합니다. 에뮬레이트된 CPU 성능에 크게 영향을 미칩니다.\n\n확실하지 않은 경우 호스트 확인 안함으로 설정하세요.",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "Synchronizacja pionowa",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Profilowana pamięć podręczna trwałych łłumaczeń)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Sprawdzanie integralności systemu plików",
|
||||
"SettingsTabSystemAudioBackend": "Backend Dżwięku:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Atrapa",
|
||||
|
|
@ -589,7 +590,8 @@
|
|||
"TimeTooltip": "Zmień czas systemowy",
|
||||
"VSyncToggleTooltip": "Synchronizacja pionowa emulowanej konsoli. Zasadniczo ogranicznik klatek dla większości gier; wyłączenie jej może spowodować, że gry będą działać z większą szybkością, ekrany wczytywania wydłużą się lub nawet utkną.\n\nMoże być przełączana w grze za pomocą preferowanego skrótu klawiszowego. Zalecamy to zrobić, jeśli planujesz ją wyłączyć.\n\nW razie wątpliwości pozostaw WŁĄCZONĄ.",
|
||||
"PptcToggleTooltip": "Zapisuje przetłumaczone funkcje JIT, dzięki czemu nie muszą być tłumaczone za każdym razem, gdy gra się ładuje.\n\nZmniejsza zacinanie się i znacznie przyspiesza uruchamianie po pierwszym uruchomieniu gry.\n\nJeśli nie masz pewności, pozostaw WŁĄCZONE",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Załaduj PPTC, używając jednej trzeciej liczby rdzeni",
|
||||
"JitCacheEvictionToggleTooltip": "Włącz eksmisję pamięci podręcznej JIT, aby efektywnie zarządzać pamięcią",
|
||||
"FsIntegrityToggleTooltip": "Sprawdza pliki podczas uruchamiania gry i jeśli zostaną wykryte uszkodzone pliki, wyświetla w dzienniku błąd hash.\n\nNie ma wpływu na wydajność i ma pomóc w rozwiązywaniu problemów.\n\nPozostaw WŁĄCZONE, jeśli nie masz pewności.",
|
||||
"AudioBackendTooltip": "Zmienia backend używany do renderowania dźwięku.\n\nSDL2 jest preferowany, podczas gdy OpenAL i SoundIO są używane jako rezerwy. Dummy nie będzie odtwarzać dźwięku.\n\nW razie wątpliwości ustaw SDL2.",
|
||||
"MemoryManagerTooltip": "Zmień sposób mapowania i uzyskiwania dostępu do pamięci gości. Znacznie wpływa na wydajność emulowanego procesora.\n\nUstaw na HOST UNCHECKED, jeśli nie masz pewności.",
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@
|
|||
"SettingsTabSystemEnableVsync": "Habilitar sincronia vertical",
|
||||
"SettingsTabSystemEnablePptc": "Habilitar PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Habilitar verificação de integridade do sistema de arquivos",
|
||||
"SettingsTabSystemAudioBackend": "Biblioteca de saída de áudio:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Nenhuma",
|
||||
|
|
@ -592,7 +593,8 @@
|
|||
"TimeTooltip": "Mudar a hora do sistema",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"PptcToggleTooltip": "Habilita ou desabilita PPTC",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Carregue o PPTC usando um terço da quantidade de núcleos",
|
||||
"JitCacheEvictionToggleTooltip": "Habilite a remoção do JIT Cache para gerenciar a memória com eficiência",
|
||||
"FsIntegrityToggleTooltip": "Habilita ou desabilita verificação de integridade dos arquivos do jogo",
|
||||
"AudioBackendTooltip": "Mudar biblioteca de áudio",
|
||||
"MemoryManagerTooltip": "Muda como a memória do sistema convidado é acessada. Tem um grande impacto na performance da CPU emulada.",
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@
|
|||
"SettingsTabSystemCustomVSyncIntervalValue": "Значение пользовательской частоты обновления:",
|
||||
"SettingsTabSystemEnablePptc": "Использовать PPTC (Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Проверка целостности файловой системы",
|
||||
"SettingsTabSystemAudioBackend": "Аудио бэкенд:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Без звука",
|
||||
|
|
@ -621,6 +622,7 @@
|
|||
"VSyncToggleTooltip": "Эмуляция вертикальной синхронизации консоли, которая ограничивает количество кадров в секунду в большинстве игр; отключение может привести к тому, что игры будут запущены с более высокой частотой кадров, но загрузка игры может занять больше времени, либо игра не запустится вообще.\n\nМожно включать и выключать эту настройку непосредственно в игре с помощью горячих клавиш (F1 по умолчанию). Если планируете отключить вертикальную синхронизацию, рекомендуем настроить горячие клавиши.\n\nРекомендуется оставить включенным.",
|
||||
"PptcToggleTooltip": "Сохраняет скомпилированные JIT-функции для того, чтобы не преобразовывать их по новой каждый раз при запуске игры.\n\nУменьшает статтеры и значительно ускоряет последующую загрузку игр.\n\nРекомендуется оставить включенным.",
|
||||
"LowPowerPptcToggleTooltip": "Загружает PPTC, используя треть от количества ядер.",
|
||||
"JitCacheEvictionToggleTooltip": "Включите вытеснение JIT-кэша для эффективного управления памятью.",
|
||||
"FsIntegrityToggleTooltip": "Проверяет файлы при загрузке игры и если обнаружены поврежденные файлы, выводит сообщение о поврежденном хэше в журнале.\n\nНе влияет на производительность и необходим для помощи в устранении неполадок.\n\nРекомендуется оставить включенным.",
|
||||
"AudioBackendTooltip": "Изменяет используемый аудио бэкенд для рендера звука.\n\nSDL2 является предпочтительным вариантом, в то время как OpenAL и SoundIO используются в качестве резервных.\n\nРекомендуется использование SDL2.",
|
||||
"MemoryManagerTooltip": "Меняет разметку и доступ к гостевой памяти. Значительно влияет на производительность процессора.\n\nРекомендуется оставить \"Хост не установлен\"",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "VSync",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (แคชโปรไฟล์การแปลแบบถาวร)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "ตรวจสอบความถูกต้องของ FS",
|
||||
"SettingsTabSystemAudioBackend": "ระบบเสียงเบื้องหลัง:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
|
|
@ -589,7 +590,8 @@
|
|||
"TimeTooltip": "เปลี่ยนเวลาของระบบ",
|
||||
"VSyncToggleTooltip": "Vertical Sync ของคอนโซลจำลอง โดยพื้นฐานแล้วเป็นตัวจำกัดเฟรมสำหรับเกมส่วนใหญ่ การปิดใช้งานอาจทำให้เกมทำงานด้วยความเร็วสูงขึ้น หรือทำให้หน้าจอการโหลดใช้เวลานานขึ้นหรือค้าง\n\nสามารถสลับได้ในเกมด้วยปุ่มลัดตามที่คุณต้องการ (F1 เป็นค่าเริ่มต้น) เราขอแนะนำให้ทำเช่นนี้หากคุณวางแผนที่จะปิดการใช้งาน\n\nหากคุณไม่แน่ใจให้ปล่อยไว้อย่างนั้น",
|
||||
"PptcToggleTooltip": "บันทึกฟังก์ชั่น JIT ที่แปลแล้ว ดังนั้นจึงไม่จำเป็นต้องแปลทุกครั้งที่โหลดเกม\n\nลดอาการกระตุกและเร่งความเร็วการบูตได้อย่างมากหลังจากการบูตครั้งแรกของเกม\n\nปล่อยไว้หากคุณไม่แน่ใจ",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "โหลด PPTC โดยใช้หนึ่งในสามของจำนวนคอร์",
|
||||
"JitCacheEvictionToggleTooltip": "เปิดใช้งานการขับไล่ JIT Cache เพื่อจัดการหน่วยความจำอย่างมีประสิทธิภาพ",
|
||||
"FsIntegrityToggleTooltip": "ตรวจสอบไฟล์ที่เสียหายเมื่อบูตเกม และหากตรวจพบไฟล์ที่เสียหาย จะแสดงข้อผิดพลาดของแฮชในบันทึก\n\nไม่มีผลกระทบต่อประสิทธิภาพการทำงานและมีไว้เพื่อช่วยในการแก้ไขปัญหา\n\nปล่อยไว้หากคุณไม่แน่ใจ",
|
||||
"AudioBackendTooltip": "เปลี่ยนแบ็กเอนด์ที่ใช้ในการเรนเดอร์เสียง\n\nSDL2 เป็นที่ต้องการ ในขณะที่ OpenAL และ SoundIO ถูกใช้เป็นทางเลือกสำรอง ดัมมี่จะไม่มีเสียง\n\nปล่อยไว้หากคุณไม่แน่ใจ",
|
||||
"MemoryManagerTooltip": "เปลี่ยนวิธีการแมปและเข้าถึงหน่วยความจำของผู้เยี่ยมชม ส่งผลอย่างมากต่อประสิทธิภาพการทำงานของ CPU ที่จำลอง\n\nตั้งค่าเป็น ไม่ทำการตรวจสอบ โฮสต์ หากคุณไม่แน่ใจ",
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
"SettingsTabSystemEnableVsync": "Dikey Eşitleme",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (Profilli Sürekli Çeviri Önbelleği)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "FS Bütünlük Kontrolleri",
|
||||
"SettingsTabSystemAudioBackend": "Ses Motoru:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Yapay",
|
||||
|
|
@ -589,7 +590,8 @@
|
|||
"TimeTooltip": "Sistem Saatini Değiştir",
|
||||
"VSyncToggleTooltip": "Emulated console's Vertical Sync. Essentially a frame-limiter for the majority of games; disabling it may cause games to run at higher speed or make loading screens take longer or get stuck.\n\nCan be toggled in-game with a hotkey of your preference (F1 by default). We recommend doing this if you plan on disabling it.\n\nLeave ON if unsure.",
|
||||
"PptcToggleTooltip": "Çevrilen JIT fonksiyonlarını oyun her açıldığında çevrilmek zorunda kalmaması için kaydeder.\n\nTeklemeyi azaltır ve ilk açılıştan sonra oyunların ilk açılış süresini ciddi biçimde hızlandırır.\n\nEmin değilseniz aktif halde bırakın.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Çekirdek miktarının üçte birini kullanarak PPTC'yi yükleyin",
|
||||
"JitCacheEvictionToggleTooltip": "Belleği verimli bir şekilde yönetmek için JIT Önbellek tahliyesini etkinleştirin",
|
||||
"FsIntegrityToggleTooltip": "Oyun açarken hatalı dosyaların olup olmadığını kontrol eder, ve hatalı dosya bulursa log dosyasında hash hatası görüntüler.\n\nPerformansa herhangi bir etkisi yoktur ve sorun gidermeye yardımcı olur.\n\nEmin değilseniz aktif halde bırakın.",
|
||||
"AudioBackendTooltip": "Ses çıkış motorunu değiştirir.\n\nSDL2 tercih edilen seçenektir, OpenAL ve SoundIO ise alternatif olarak kullanılabilir. Dummy seçeneğinde ses çıkışı olmayacaktır.\n\nEmin değilseniz SDL2 seçeneğine ayarlayın.",
|
||||
"MemoryManagerTooltip": "Guest hafızasının nasıl tahsis edilip erişildiğini değiştirir. Emüle edilen CPU performansını ciddi biçimde etkiler.\n\nEmin değilseniz HOST UNCHECKED seçeneğine ayarlayın.",
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@
|
|||
"SettingsTabSystemEnableVsync": "Вертикальна синхронізація",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (профільований постійний кеш перекладу)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "Перевірка цілісності FS",
|
||||
"SettingsTabSystemAudioBackend": "Аудіосистема:",
|
||||
"SettingsTabSystemAudioBackendDummy": "Dummy",
|
||||
|
|
@ -593,7 +594,8 @@
|
|||
"MatchTimeTooltip": "Синхронізувати системний час, щоб він відповідав поточній даті та часу вашого ПК.",
|
||||
"VSyncToggleTooltip": "Емульована вертикальна синхронізація консолі. По суті, обмежувач кадрів для більшості ігор; його вимкнення може призвести до того, що ігри працюватимуть на вищій швидкості, екрани завантаження триватимуть довше чи зупинятимуться.\n\nМожна перемикати в грі гарячою клавішею (За умовчанням F1). Якщо ви плануєте вимкнути функцію, рекомендуємо зробити це через гарячу клавішу.\n\nЗалиште увімкненим, якщо не впевнені.",
|
||||
"PptcToggleTooltip": "Зберігає перекладені функції JIT, щоб їх не потрібно було перекладати кожного разу, коли гра завантажується.\n\nЗменшує заїкання та значно прискорює час завантаження після першого завантаження гри.\n\nЗалиште увімкненим, якщо не впевнені.",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "Завантажте PPTC, використовуючи третину кількості ядер",
|
||||
"JitCacheEvictionToggleTooltip": "Увімкніть видалення кешу JIT для ефективного керування пам’яттю",
|
||||
"FsIntegrityToggleTooltip": "Перевіряє наявність пошкоджених файлів під час завантаження гри, і якщо виявлено пошкоджені файли, показує помилку хешу в журналі.\n\nНе впливає на продуктивність і призначений для усунення несправностей.\n\nЗалиште увімкненим, якщо не впевнені.",
|
||||
"AudioBackendTooltip": "Змінює серверну частину, яка використовується для відтворення аудіо.\n\nSDL2 є кращим, тоді як OpenAL і SoundIO використовуються як резервні варіанти. Dummy не матиме звуку.\n\nВстановіть SDL2, якщо не впевнені.",
|
||||
"MemoryManagerTooltip": "Змінює спосіб відображення та доступу до гостьової пам’яті. Значно впливає на продуктивність емульованого ЦП.\n\nВстановіть «Неперевірений хост», якщо не впевнені.",
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@
|
|||
"SettingsTabSystemEnableVsync": "启用垂直同步",
|
||||
"SettingsTabSystemEnablePptc": "开启 PPTC 缓存",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "启用文件系统完整性检查",
|
||||
"SettingsTabSystemAudioBackend": "音频处理引擎:",
|
||||
"SettingsTabSystemAudioBackendDummy": "无",
|
||||
|
|
@ -593,7 +594,8 @@
|
|||
"MatchTimeTooltip": "重新同步系统时间以匹配您电脑的当前日期和时间。",
|
||||
"VSyncToggleTooltip": "模拟控制台的垂直同步,开启后会降低大部分游戏的帧率。关闭后,可以获得更高的帧率,但也可能导致游戏画面加载耗时更长或卡住。\n\n在游戏中可以使用热键进行切换(默认为 F1 键)。\n\n如果不确定,请保持开启状态。",
|
||||
"PptcToggleTooltip": "缓存已编译的游戏指令,这样每次游戏加载时就无需重新编译。\n\n可以减少卡顿和启动时间,提高游戏响应速度。\n\n如果不确定,请保持开启状态。",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "使用三分之一的核心数量加载 PPTC",
|
||||
"JitCacheEvictionToggleTooltip": "启用 JIT 缓存驱逐以有效管理内存",
|
||||
"FsIntegrityToggleTooltip": "启动游戏时检查游戏文件的完整性,并在日志中记录损坏的文件。\n\n对性能没有影响,用于排查故障。\n\n如果不确定,请保持开启状态。",
|
||||
"AudioBackendTooltip": "更改音频处理引擎。\n\n推荐选择“SDL2”,另外“OpenAL”和“SoundIO”可以作为备选,选择“无”将没有声音。\n\n如果不确定,请设置为“SDL2”。",
|
||||
"MemoryManagerTooltip": "更改模拟器内存映射和访问的方式,对模拟器 CPU 的性能影响很大。\n\n如果不确定,请设置为“跳过检查的本机映射”。",
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@
|
|||
"SettingsTabSystemEnableVsync": "垂直同步",
|
||||
"SettingsTabSystemEnablePptc": "PPTC (剖析式持久轉譯快取, Profiled Persistent Translation Cache)",
|
||||
"SettingsTabSystemEnableLowPowerPptc": "Low-power PPTC",
|
||||
"SettingsTabSystemEnableJitCacheEviction": "Jit Cache Eviction",
|
||||
"SettingsTabSystemEnableFsIntegrityChecks": "檔案系統完整性檢查",
|
||||
"SettingsTabSystemAudioBackend": "音效後端:",
|
||||
"SettingsTabSystemAudioBackendDummy": "虛設 (Dummy)",
|
||||
|
|
@ -593,7 +594,8 @@
|
|||
"MatchTimeTooltip": "重新同步系統韌體時間至 PC 目前的日期和時間。",
|
||||
"VSyncToggleTooltip": "模擬遊戲機的垂直同步。對大多數遊戲來說,它本質上是一個幀率限制器;停用它可能會導致遊戲以更高的速度執行,或使載入畫面耗時更長或卡住。\n\n可以在遊戲中使用快速鍵進行切換 (預設為 F1)。如果您打算停用,我們建議您這樣做。\n\n如果不確定,請保持開啟狀態。",
|
||||
"PptcToggleTooltip": "儲存已轉譯的 JIT 函數,這樣每次載入遊戲時就無需再轉譯這些函數。\n\n減少遊戲首次啟動後的卡頓現象,並大大加快啟動時間。\n\n如果不確定,請保持開啟狀態。",
|
||||
"LowPowerPptcToggleTooltip": "Load the PPTC using a third of the amount of cores.",
|
||||
"LowPowerPptcToggleTooltip": "使用三分之一的核心數量加載 PPTC",
|
||||
"JitCacheEvictionToggleTooltip": "啟用 JIT 快取驅逐以有效管理內存",
|
||||
"FsIntegrityToggleTooltip": "在啟動遊戲時檢查損壞的檔案,如果檢測到損壞的檔案,則在日誌中顯示雜湊值錯誤。\n\n對效能沒有影響,旨在幫助排除故障。\n\n如果不確定,請保持開啟狀態。",
|
||||
"AudioBackendTooltip": "變更用於繪製音訊的後端。\n\nSDL2 是首選,而 OpenAL 和 SoundIO 則作為備用。虛設 (Dummy) 將沒有聲音。\n\n如果不確定,請設定為 SDL2。",
|
||||
"MemoryManagerTooltip": "變更客體記憶體的映射和存取方式。這會極大地影響模擬 CPU 效能。\n\n如果不確定,請設定為主體略過檢查模式。",
|
||||
|
|
|
|||
|
|
@ -14,12 +14,19 @@
|
|||
<IncludeSourceRevisionInInformationalVersion Condition="'$(Configuration)'=='Release'">false</IncludeSourceRevisionInInformationalVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == '' AND '$(BuildingInsideVisualStudio)' == 'true'">
|
||||
<RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('Windows'))">win-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('OSX'))">osx-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('Linux'))">linux-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
|
||||
<Exec Command="codesign --entitlements '$(ProjectDir)..\..\distribution\macos\entitlements.xml' -f --deep -s $(SigningCertificate) '$(TargetDir)$(TargetName)'" />
|
||||
</Target>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' != ''">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<SelfContained>true</SelfContained>
|
||||
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<TrimMode>partial</TrimMode>
|
||||
|
|
|
|||
|
|
@ -1223,15 +1223,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
{
|
||||
try
|
||||
{
|
||||
// Creazione di una copia completa di Applications
|
||||
List<ApplicationData> appsCopy;
|
||||
|
||||
lock (_applicationsLock)
|
||||
{
|
||||
appsCopy = new List<ApplicationData>(Applications);
|
||||
}
|
||||
|
||||
// Filtraggio e ordinamento in una lista temporanea
|
||||
var tempApplications = new List<ApplicationData>();
|
||||
|
||||
foreach (var app in appsCopy)
|
||||
{
|
||||
if (Filter(app))
|
||||
|
|
@ -1240,10 +1240,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
}
|
||||
}
|
||||
|
||||
// Ordinamento alfabetico
|
||||
tempApplications.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
// Creazione delle directory di salvataggio
|
||||
foreach (var application in tempApplications)
|
||||
{
|
||||
try
|
||||
|
|
@ -1252,19 +1250,16 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log dell'errore se necessario
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to create save directory for {application.Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Ricreazione dell'observable collection in modo thread-safe
|
||||
Dispatcher.UIThread.InvokeAsync(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (_applicationsLock)
|
||||
{
|
||||
// Ricrea la collezione osservabile in modo più sicuro
|
||||
var source = Applications.ToObservableChangeSet();
|
||||
var filtered = source.Filter(Filter);
|
||||
var sorted = filtered.Sort(GetComparer());
|
||||
|
|
|
|||
|
|
@ -227,6 +227,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
}
|
||||
public bool EnablePptc { get; set; }
|
||||
public bool EnableLowPowerPptc { get; set; }
|
||||
|
||||
public bool EnableJitCacheEviction { get; set; }
|
||||
public bool EnableInternetAccess { get; set; }
|
||||
public bool EnableFsIntegrityChecks { get; set; }
|
||||
public bool IgnoreMissingServices { get; set; }
|
||||
|
|
@ -571,6 +573,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
// CPU
|
||||
EnablePptc = config.System.EnablePtc;
|
||||
EnableLowPowerPptc = config.System.EnableLowPowerPtc;
|
||||
EnableJitCacheEviction = config.System.EnableJitCacheEviction;
|
||||
MemoryMode = (int)config.System.MemoryManagerMode.Value;
|
||||
UseHypervisor = config.System.UseHypervisor;
|
||||
|
||||
|
|
@ -679,6 +682,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||
// CPU
|
||||
config.System.EnablePtc.Value = EnablePptc;
|
||||
config.System.EnableLowPowerPtc.Value = EnableLowPowerPptc;
|
||||
config.System.EnableJitCacheEviction.Value = EnableJitCacheEviction;
|
||||
config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
|
||||
config.System.UseHypervisor.Value = UseHypervisor;
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,10 @@
|
|||
<TextBlock Text="{locale:Locale SettingsTabSystemEnableLowPowerPptc}"
|
||||
ToolTip.Tip="{locale:Locale LowPowerPptcToggleTooltip}" />
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding EnableJitCacheEviction}">
|
||||
<TextBlock Text="{locale:Locale SettingsTabSystemEnableJitCacheEviction}"
|
||||
ToolTip.Tip="{locale:Locale JitCacheEvictionToggleTooltip}" />
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<Separator Height="1" />
|
||||
<TextBlock Classes="h1" Text="{locale:Locale SettingsTabCpuMemory}" />
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ interface KenjinxNativeJna : Library {
|
|||
vSyncMode: Int,
|
||||
enableDockedMode: Boolean,
|
||||
enablePptc: Boolean,
|
||||
enableLowPowerPptc: Boolean,
|
||||
enableJitCacheEviction: Boolean,
|
||||
enableInternetAccess: Boolean,
|
||||
enableFsIntegrityChecks: Boolean,
|
||||
fsGlobalAccessLogMode: Int,
|
||||
|
|
|
|||
|
|
@ -248,4 +248,24 @@ class MainActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun shutdownAndRestart() {
|
||||
// Create an intent to restart the app
|
||||
val packageManager = packageManager
|
||||
val intent = packageManager.getLaunchIntentForPackage(packageName)
|
||||
val componentName = intent?.component
|
||||
val restartIntent = Intent.makeRestartActivityTask(componentName)
|
||||
|
||||
// Clean up resources if needed
|
||||
mainViewModel?.let {
|
||||
// Perform any critical cleanup
|
||||
it.performanceManager?.setTurboMode(false)
|
||||
}
|
||||
|
||||
// Start the new activity directly
|
||||
startActivity(restartIntent)
|
||||
|
||||
// Force immediate process termination
|
||||
Runtime.getRuntime().exit(0)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,10 @@ class GameModel(var file: DocumentFile, val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun isUnknown() : Boolean {
|
||||
return (titleName == "Unknown")
|
||||
}
|
||||
|
||||
fun open(): Int {
|
||||
descriptor = context.contentResolver.openFileDescriptor(file.uri, "rw")
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,11 @@ class HomeViewModel(
|
|||
for(game in loadedCache)
|
||||
{
|
||||
game.getGameInfo()
|
||||
|
||||
if(game.isUnknown())
|
||||
{
|
||||
loadedCache.remove(game);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
|
|
|
|||
|
|
@ -179,6 +179,8 @@ class MainViewModel(val activity: MainActivity) {
|
|||
settings.vSyncMode.ordinal,
|
||||
settings.enableDocked,
|
||||
settings.enablePptc,
|
||||
settings.enableLowPowerPptc,
|
||||
settings.enableJitCacheEviction,
|
||||
false,
|
||||
settings.enableFsIntegrityChecks,
|
||||
settings.fsGlobalAccessLogMode,
|
||||
|
|
@ -285,6 +287,8 @@ class MainViewModel(val activity: MainActivity) {
|
|||
settings.vSyncMode.ordinal,
|
||||
settings.enableDocked,
|
||||
settings.enablePptc,
|
||||
settings.enableLowPowerPptc,
|
||||
settings.enableJitCacheEviction,
|
||||
false,
|
||||
settings.enableFsIntegrityChecks,
|
||||
settings.fsGlobalAccessLogMode,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import androidx.preference.PreferenceManager
|
|||
class QuickSettings(val activity: Activity) {
|
||||
var ignoreMissingServices: Boolean
|
||||
var enablePptc: Boolean
|
||||
var enableLowPowerPptc: Boolean
|
||||
var enableJitCacheEviction: Boolean
|
||||
var enableFsIntegrityChecks: Boolean
|
||||
var fsGlobalAccessLogMode: Int
|
||||
var enableDocked: Boolean
|
||||
|
|
@ -39,11 +41,13 @@ class QuickSettings(val activity: Activity) {
|
|||
|
||||
init {
|
||||
memoryManagerMode = MemoryManagerMode.values()[sharedPref.getInt("memoryManagerMode", MemoryManagerMode.HostMappedUnsafe.ordinal)]
|
||||
useNce = sharedPref.getBoolean("useNce", true)
|
||||
useNce = sharedPref.getBoolean("useNce", false)
|
||||
memoryConfiguration = MemoryConfiguration.values()[sharedPref.getInt("memoryConfiguration", MemoryConfiguration.MemoryConfiguration4GiB.ordinal)]
|
||||
vSyncMode = VSyncMode.values()[sharedPref.getInt("vSyncMode", VSyncMode.Switch.ordinal)]
|
||||
enableDocked = sharedPref.getBoolean("enableDocked", true)
|
||||
enablePptc = sharedPref.getBoolean("enablePptc", true)
|
||||
enableLowPowerPptc = sharedPref.getBoolean("enableLowPowerPptc", false)
|
||||
enableJitCacheEviction = sharedPref.getBoolean("enableJitCacheEviction", true)
|
||||
enableFsIntegrityChecks = sharedPref.getBoolean("enableFsIntegrityChecks", false)
|
||||
fsGlobalAccessLogMode = sharedPref.getInt("fsGlobalAccessLogMode", 0)
|
||||
ignoreMissingServices = sharedPref.getBoolean("ignoreMissingServices", false)
|
||||
|
|
@ -78,6 +82,8 @@ class QuickSettings(val activity: Activity) {
|
|||
editor.putInt("vSyncMode", vSyncMode.ordinal)
|
||||
editor.putBoolean("enableDocked", enableDocked)
|
||||
editor.putBoolean("enablePptc", enablePptc)
|
||||
editor.putBoolean("enableLowPowerPptc", enableLowPowerPptc)
|
||||
editor.putBoolean("enableJitCacheEviction", enableJitCacheEviction)
|
||||
editor.putBoolean("enableFsIntegrityChecks", enableFsIntegrityChecks)
|
||||
editor.putInt("fsGlobalAccessLogMode", fsGlobalAccessLogMode)
|
||||
editor.putBoolean("ignoreMissingServices", ignoreMissingServices)
|
||||
|
|
|
|||
|
|
@ -31,14 +31,6 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
sharedPref = getPreferences()
|
||||
previousFolderCallback = activity.storageHelper!!.onFolderSelected
|
||||
previousFileCallback = activity.storageHelper!!.onFileSelected
|
||||
activity.storageHelper!!.onFolderSelected = { _, folder ->
|
||||
run {
|
||||
val p = folder.getAbsolutePath(activity)
|
||||
val editor = sharedPref.edit()
|
||||
editor?.putString("gameFolder", p)
|
||||
editor?.apply()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPreferences(): SharedPreferences {
|
||||
|
|
@ -52,6 +44,8 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
vSyncMode: MutableState<VSyncMode>,
|
||||
enableDocked: MutableState<Boolean>,
|
||||
enablePptc: MutableState<Boolean>,
|
||||
enableLowPowerPptc: MutableState<Boolean>,
|
||||
enableJitCacheEviction: MutableState<Boolean>,
|
||||
enableFsIntegrityChecks: MutableState<Boolean>,
|
||||
fsGlobalAccessLogMode: MutableState<Int>,
|
||||
ignoreMissingServices: MutableState<Boolean>,
|
||||
|
|
@ -77,11 +71,13 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
enableGraphicsLogs: MutableState<Boolean>
|
||||
) {
|
||||
memoryManagerMode.value = MemoryManagerMode.values()[sharedPref.getInt("memoryManagerMode", MemoryManagerMode.HostMappedUnsafe.ordinal)]
|
||||
useNce.value = sharedPref.getBoolean("useNce", true)
|
||||
useNce.value = sharedPref.getBoolean("useNce", false)
|
||||
memoryConfiguration.value = MemoryConfiguration.values()[sharedPref.getInt("memoryConfiguration", MemoryConfiguration.MemoryConfiguration4GiB.ordinal)]
|
||||
vSyncMode.value = VSyncMode.values()[sharedPref.getInt("vSyncMode", VSyncMode.Switch.ordinal)]
|
||||
enableDocked.value = sharedPref.getBoolean("enableDocked", true)
|
||||
enablePptc.value = sharedPref.getBoolean("enablePptc", true)
|
||||
enableLowPowerPptc.value = sharedPref.getBoolean("enableLowPowerPptc", false)
|
||||
enableJitCacheEviction.value = sharedPref.getBoolean("enableJitCacheEviction", false)
|
||||
enableFsIntegrityChecks.value = sharedPref.getBoolean("enableFsIntegrityChecks", false)
|
||||
fsGlobalAccessLogMode.value = sharedPref.getInt("fsGlobalAccessLogMode", 0)
|
||||
ignoreMissingServices.value = sharedPref.getBoolean("ignoreMissingServices", false)
|
||||
|
|
@ -102,7 +98,7 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
enableErrorLogs.value = sharedPref.getBoolean("enableErrorLogs", true)
|
||||
enableGuestLogs.value = sharedPref.getBoolean("enableGuestLogs", true)
|
||||
enableFsAccessLogs.value = sharedPref.getBoolean("enableFsAccessLogs", false)
|
||||
enableTraceLogs.value = sharedPref.getBoolean("enableStubLogs", false)
|
||||
enableTraceLogs.value = sharedPref.getBoolean("enableTraceLogs", false)
|
||||
enableDebugLogs.value = sharedPref.getBoolean("enableDebugLogs", false)
|
||||
enableGraphicsLogs.value = sharedPref.getBoolean("enableGraphicsLogs", false)
|
||||
}
|
||||
|
|
@ -114,6 +110,8 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
vSyncMode: MutableState<VSyncMode>,
|
||||
enableDocked: MutableState<Boolean>,
|
||||
enablePptc: MutableState<Boolean>,
|
||||
enableLowPowerPptc: MutableState<Boolean>,
|
||||
enableJitCacheEviction: MutableState<Boolean>,
|
||||
enableFsIntegrityChecks: MutableState<Boolean>,
|
||||
fsGlobalAccessLogMode: MutableState<Int>,
|
||||
ignoreMissingServices: MutableState<Boolean>,
|
||||
|
|
@ -146,6 +144,8 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
editor.putInt("vSyncMode", vSyncMode.value.ordinal)
|
||||
editor.putBoolean("enableDocked", enableDocked.value)
|
||||
editor.putBoolean("enablePptc", enablePptc.value)
|
||||
editor.putBoolean("enableLowPowerPptc", enableLowPowerPptc.value)
|
||||
editor.putBoolean("enableJitCacheEviction", enableJitCacheEviction.value)
|
||||
editor.putBoolean("enableFsIntegrityChecks", enableFsIntegrityChecks.value)
|
||||
editor.putInt("fsGlobalAccessLogMode", fsGlobalAccessLogMode.value)
|
||||
editor.putBoolean("ignoreMissingServices", ignoreMissingServices.value)
|
||||
|
|
@ -171,7 +171,6 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
editor.putBoolean("enableGraphicsLogs", enableGraphicsLogs.value)
|
||||
|
||||
editor.apply()
|
||||
activity.storageHelper!!.onFolderSelected = previousFolderCallback
|
||||
|
||||
KenjinxNative.loggingSetEnabled(LogLevel.Info, enableInfoLogs.value)
|
||||
KenjinxNative.loggingSetEnabled(LogLevel.Stub, enableStubLogs.value)
|
||||
|
|
@ -187,6 +186,15 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
fun openGameFolder() {
|
||||
val path = sharedPref.getString("gameFolder", "") ?: ""
|
||||
|
||||
activity.storageHelper!!.onFolderSelected = { _, folder ->
|
||||
val p = folder.getAbsolutePath(activity)
|
||||
val editor = sharedPref.edit()
|
||||
editor.putString("gameFolder", p)
|
||||
editor.apply()
|
||||
activity.storageHelper!!.onFolderSelected = previousFolderCallback
|
||||
activity.shutdownAndRestart()
|
||||
}
|
||||
|
||||
if (path.isEmpty())
|
||||
activity.storageHelper?.storage?.openFolderPicker()
|
||||
else
|
||||
|
|
@ -197,22 +205,20 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
}
|
||||
|
||||
fun selectKey(installState: MutableState<KeyInstallState>) {
|
||||
if (installState.value != KeyInstallState.None)
|
||||
if (installState.value != KeyInstallState.File)
|
||||
return
|
||||
|
||||
activity.storageHelper!!.onFileSelected = { _, files ->
|
||||
run {
|
||||
activity.storageHelper!!.onFileSelected = previousFileCallback
|
||||
val file = files.firstOrNull()
|
||||
file?.apply {
|
||||
if (name == "prod.keys") {
|
||||
selectedKeyFile = file
|
||||
installState.value = KeyInstallState.Query
|
||||
}
|
||||
else {
|
||||
installState.value = KeyInstallState.Cancelled
|
||||
}
|
||||
val file = files.firstOrNull()
|
||||
file?.apply {
|
||||
if (name == "prod.keys") {
|
||||
selectedKeyFile = file
|
||||
installState.value = KeyInstallState.Query
|
||||
} else {
|
||||
installState.value = KeyInstallState.Cancelled
|
||||
}
|
||||
}
|
||||
activity.storageHelper!!.onFileSelected = previousFileCallback
|
||||
}
|
||||
activity.storageHelper?.storage?.openFilePicker()
|
||||
}
|
||||
|
|
@ -221,7 +227,7 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
if (installState.value != KeyInstallState.Query)
|
||||
return
|
||||
if (selectedKeyFile == null) {
|
||||
installState.value = KeyInstallState.None
|
||||
installState.value = KeyInstallState.File
|
||||
return
|
||||
}
|
||||
selectedKeyFile?.apply {
|
||||
|
|
@ -247,37 +253,35 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
|
||||
fun clearKeySelection(installState: MutableState<KeyInstallState>) {
|
||||
selectedKeyFile = null
|
||||
installState.value = KeyInstallState.None
|
||||
installState.value = KeyInstallState.File
|
||||
}
|
||||
|
||||
fun selectFirmware(installState: MutableState<FirmwareInstallState>) {
|
||||
if (installState.value != FirmwareInstallState.None)
|
||||
if (installState.value != FirmwareInstallState.File)
|
||||
return
|
||||
|
||||
activity.storageHelper!!.onFileSelected = { _, files ->
|
||||
run {
|
||||
activity.storageHelper!!.onFileSelected = previousFileCallback
|
||||
val file = files.firstOrNull()
|
||||
file?.apply {
|
||||
if (extension == "xci" || extension == "zip") {
|
||||
installState.value = FirmwareInstallState.Verifying
|
||||
thread {
|
||||
Thread.sleep(1000)
|
||||
val descriptor = activity.contentResolver.openFileDescriptor(file.uri, "rw")
|
||||
descriptor?.use { d ->
|
||||
selectedFirmwareVersion = KenjinxNative.deviceVerifyFirmware(d.fd, extension == "xci")
|
||||
selectedFirmwareFile = file
|
||||
if (!selectedFirmwareVersion.isEmpty()) {
|
||||
installState.value = FirmwareInstallState.Query
|
||||
} else {
|
||||
installState.value = FirmwareInstallState.Cancelled
|
||||
}
|
||||
val file = files.firstOrNull()
|
||||
file?.apply {
|
||||
if (extension == "xci" || extension == "zip") {
|
||||
installState.value = FirmwareInstallState.Verifying
|
||||
thread {
|
||||
val descriptor = activity.contentResolver.openFileDescriptor(file.uri, "rw")
|
||||
descriptor?.use { d ->
|
||||
selectedFirmwareVersion = KenjinxNative.deviceVerifyFirmware(d.fd, extension == "xci")
|
||||
selectedFirmwareFile = file
|
||||
if (!selectedFirmwareVersion.isEmpty()) {
|
||||
installState.value = FirmwareInstallState.Query
|
||||
} else {
|
||||
installState.value = FirmwareInstallState.Cancelled
|
||||
}
|
||||
}
|
||||
} else {
|
||||
installState.value = FirmwareInstallState.Cancelled
|
||||
}
|
||||
} else {
|
||||
installState.value = FirmwareInstallState.Cancelled
|
||||
}
|
||||
}
|
||||
activity.storageHelper!!.onFileSelected = previousFileCallback
|
||||
}
|
||||
activity.storageHelper?.storage?.openFilePicker()
|
||||
}
|
||||
|
|
@ -286,7 +290,7 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
if (installState.value != FirmwareInstallState.Query)
|
||||
return
|
||||
if (selectedFirmwareFile == null) {
|
||||
installState.value = FirmwareInstallState.None
|
||||
installState.value = FirmwareInstallState.File
|
||||
return
|
||||
}
|
||||
selectedFirmwareFile?.apply {
|
||||
|
|
@ -312,18 +316,18 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
fun clearFirmwareSelection(installState: MutableState<FirmwareInstallState>) {
|
||||
selectedFirmwareFile = null
|
||||
selectedFirmwareVersion = ""
|
||||
installState.value = FirmwareInstallState.None
|
||||
installState.value = FirmwareInstallState.File
|
||||
}
|
||||
|
||||
fun importAppData(
|
||||
file: DocumentFile,
|
||||
dataImportState: MutableState<DataImportState>
|
||||
fun resetAppData(
|
||||
dataResetState: MutableState<DataResetState>
|
||||
) {
|
||||
dataImportState.value = DataImportState.Import
|
||||
try {
|
||||
MainActivity.StorageHelper?.apply {
|
||||
val stream = file.openInputStream(storage.context)
|
||||
stream?.apply {
|
||||
dataResetState.value = DataResetState.Reset
|
||||
thread {
|
||||
Thread.sleep(1000)
|
||||
|
||||
try {
|
||||
MainActivity.StorageHelper?.apply {
|
||||
val folders = listOf("bis", "games", "profiles", "system")
|
||||
for (f in folders) {
|
||||
val dir = File(MainActivity.AppPath + "${File.separator}${f}")
|
||||
|
|
@ -333,42 +337,73 @@ class SettingsViewModel(val activity: MainActivity) {
|
|||
|
||||
dir.mkdirs()
|
||||
}
|
||||
ZipInputStream(stream).use { zip ->
|
||||
while (true) {
|
||||
val header = zip.nextEntry ?: break
|
||||
if (!folders.any { header.fileName.startsWith(it) }) {
|
||||
continue
|
||||
}
|
||||
val filePath =
|
||||
MainActivity.AppPath + File.separator + header.fileName
|
||||
}
|
||||
} finally {
|
||||
dataResetState.value = DataResetState.Done
|
||||
KenjinxNative.deviceReloadFilesystem()
|
||||
MainActivity.mainViewModel?.refreshFirmwareVersion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!header.isDirectory) {
|
||||
val bos = BufferedOutputStream(FileOutputStream(filePath))
|
||||
val bytesIn = ByteArray(4096)
|
||||
var read: Int = 0
|
||||
while (zip.read(bytesIn).also { read = it } > 0) {
|
||||
bos.write(bytesIn, 0, read)
|
||||
fun importAppData(
|
||||
file: DocumentFile,
|
||||
dataImportState: MutableState<DataImportState>
|
||||
) {
|
||||
dataImportState.value = DataImportState.Import
|
||||
thread {
|
||||
Thread.sleep(1000)
|
||||
|
||||
try {
|
||||
MainActivity.StorageHelper?.apply {
|
||||
val stream = file.openInputStream(storage.context)
|
||||
stream?.apply {
|
||||
val folders = listOf("bis", "games", "profiles", "system")
|
||||
for (f in folders) {
|
||||
val dir = File(MainActivity.AppPath + "${File.separator}${f}")
|
||||
if (dir.exists()) {
|
||||
dir.deleteRecursively()
|
||||
}
|
||||
|
||||
dir.mkdirs()
|
||||
}
|
||||
ZipInputStream(stream).use { zip ->
|
||||
while (true) {
|
||||
val header = zip.nextEntry ?: break
|
||||
if (!folders.any { header.fileName.startsWith(it) }) {
|
||||
continue
|
||||
}
|
||||
val filePath =
|
||||
MainActivity.AppPath + File.separator + header.fileName
|
||||
|
||||
if (!header.isDirectory) {
|
||||
val bos = BufferedOutputStream(FileOutputStream(filePath))
|
||||
val bytesIn = ByteArray(4096)
|
||||
var read: Int = 0
|
||||
while (zip.read(bytesIn).also { read = it } > 0) {
|
||||
bos.write(bytesIn, 0, read)
|
||||
}
|
||||
bos.close()
|
||||
} else {
|
||||
val dir = File(filePath)
|
||||
dir.mkdir()
|
||||
}
|
||||
bos.close()
|
||||
} else {
|
||||
val dir = File(filePath)
|
||||
dir.mkdir()
|
||||
}
|
||||
}
|
||||
stream.close()
|
||||
}
|
||||
stream.close()
|
||||
}
|
||||
} finally {
|
||||
dataImportState.value = DataImportState.Done
|
||||
KenjinxNative.deviceReloadFilesystem()
|
||||
MainActivity.mainViewModel?.refreshFirmwareVersion()
|
||||
}
|
||||
} finally {
|
||||
dataImportState.value = DataImportState.Done
|
||||
KenjinxNative.deviceReloadFilesystem()
|
||||
MainActivity.mainViewModel?.refreshFirmwareVersion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class KeyInstallState {
|
||||
None,
|
||||
File,
|
||||
Cancelled,
|
||||
Query,
|
||||
Install,
|
||||
|
|
@ -376,7 +411,7 @@ enum class KeyInstallState {
|
|||
}
|
||||
|
||||
enum class FirmwareInstallState {
|
||||
None,
|
||||
File,
|
||||
Cancelled,
|
||||
Verifying,
|
||||
Query,
|
||||
|
|
@ -384,8 +419,14 @@ enum class FirmwareInstallState {
|
|||
Done
|
||||
}
|
||||
|
||||
enum class DataResetState {
|
||||
Query,
|
||||
Reset,
|
||||
Done
|
||||
}
|
||||
|
||||
enum class DataImportState {
|
||||
None,
|
||||
File,
|
||||
Query,
|
||||
Import,
|
||||
Done
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.Create
|
||||
import androidx.compose.material.icons.filled.FileDownload
|
||||
import androidx.compose.material.icons.filled.Home
|
||||
import androidx.compose.material.icons.filled.MailOutline
|
||||
|
|
@ -62,6 +63,7 @@ import kotlin.concurrent.thread
|
|||
import org.kenjinx.android.MainActivity
|
||||
import org.kenjinx.android.providers.DocumentProvider
|
||||
import org.kenjinx.android.viewmodels.DataImportState
|
||||
import org.kenjinx.android.viewmodels.DataResetState
|
||||
import org.kenjinx.android.viewmodels.FirmwareInstallState
|
||||
import org.kenjinx.android.viewmodels.KeyInstallState
|
||||
import org.kenjinx.android.viewmodels.MainViewModel
|
||||
|
|
@ -90,6 +92,8 @@ class SettingViews {
|
|||
val vSyncMode = remember { mutableStateOf(VSyncMode.Switch) }
|
||||
val enableDocked = remember { mutableStateOf(false) }
|
||||
val enablePptc = remember { mutableStateOf(false) }
|
||||
val enableLowPowerPptc = remember { mutableStateOf(false) }
|
||||
val enableJitCacheEviction = remember { mutableStateOf(false) }
|
||||
var enableFsIntegrityChecks = remember { mutableStateOf(false) }
|
||||
var fsGlobalAccessLogMode = remember { mutableStateOf(0) }
|
||||
val ignoreMissingServices = remember { mutableStateOf(false) }
|
||||
|
|
@ -100,12 +104,14 @@ class SettingViews {
|
|||
val maxAnisotropy = remember { mutableStateOf(0f) }
|
||||
val useVirtualController = remember { mutableStateOf(true) }
|
||||
val showKeyDialog = remember { mutableStateOf(false) }
|
||||
val keyInstallState = remember { mutableStateOf(KeyInstallState.None) }
|
||||
val keyInstallState = remember { mutableStateOf(KeyInstallState.File) }
|
||||
val showFirwmareDialog = remember { mutableStateOf(false) }
|
||||
val firmwareInstallState = remember { mutableStateOf(FirmwareInstallState.None) }
|
||||
val firmwareInstallState = remember { mutableStateOf(FirmwareInstallState.File) }
|
||||
val firmwareVersion = remember { mutableStateOf(mainViewModel.firmwareVersion) }
|
||||
val showDataResetDialog = remember { mutableStateOf(false) }
|
||||
val showDataImportDialog = remember { mutableStateOf(false) }
|
||||
val dataImportState = remember { mutableStateOf(DataImportState.None) }
|
||||
val dataResetState = remember { mutableStateOf(DataResetState.Query) }
|
||||
val dataImportState = remember { mutableStateOf(DataImportState.File) }
|
||||
var dataFile = remember { mutableStateOf<DocumentFile?>(null) }
|
||||
val isGrid = remember { mutableStateOf(true) }
|
||||
val useSwitchLayout = remember { mutableStateOf(true) }
|
||||
|
|
@ -131,6 +137,8 @@ class SettingViews {
|
|||
vSyncMode,
|
||||
enableDocked,
|
||||
enablePptc,
|
||||
enableLowPowerPptc,
|
||||
enableJitCacheEviction,
|
||||
enableFsIntegrityChecks,
|
||||
fsGlobalAccessLogMode,
|
||||
ignoreMissingServices,
|
||||
|
|
@ -172,6 +180,8 @@ class SettingViews {
|
|||
vSyncMode,
|
||||
enableDocked,
|
||||
enablePptc,
|
||||
enableLowPowerPptc,
|
||||
enableJitCacheEviction,
|
||||
enableFsIntegrityChecks,
|
||||
fsGlobalAccessLogMode,
|
||||
ignoreMissingServices,
|
||||
|
|
@ -236,23 +246,6 @@ class SettingViews {
|
|||
modifier = Modifier.align(Alignment.CenterVertically)
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp)
|
||||
.padding(horizontal = 8.dp, vertical = 8.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
){
|
||||
ActionButton(
|
||||
onClick = {
|
||||
settingsViewModel.openGameFolder()
|
||||
},
|
||||
text = "Add Game Folder",
|
||||
icon = Icons.Default.Add,
|
||||
modifier = Modifier.weight(1f),
|
||||
isFullWidth = false,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -287,7 +280,40 @@ class SettingViews {
|
|||
isFullWidth = false,
|
||||
)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp)
|
||||
.padding(horizontal = 8.dp, vertical = 8.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
){
|
||||
ActionButton(
|
||||
onClick = {
|
||||
settingsViewModel.openGameFolder()
|
||||
},
|
||||
text = "Add Game Folder",
|
||||
icon = Icons.Default.Add,
|
||||
modifier = Modifier.weight(1f),
|
||||
isFullWidth = false,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(56.dp)
|
||||
.padding(horizontal = 8.dp, vertical = 8.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
ActionButton(
|
||||
onClick = {
|
||||
showDataResetDialog.value = true
|
||||
},
|
||||
text = "Reinit App Data",
|
||||
icon = Icons.Default.Create,
|
||||
modifier = Modifier.weight(1f),
|
||||
isFullWidth = false,
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -359,6 +385,7 @@ class SettingViews {
|
|||
if (keyInstallState.value != KeyInstallState.Install) {
|
||||
showKeyDialog.value = false
|
||||
settingsViewModel.clearKeySelection(keyInstallState)
|
||||
keyInstallState.value = KeyInstallState.File
|
||||
}
|
||||
}
|
||||
) {
|
||||
|
|
@ -378,7 +405,7 @@ class SettingViews {
|
|||
)
|
||||
|
||||
when (keyInstallState.value) {
|
||||
KeyInstallState.None -> {
|
||||
KeyInstallState.File -> {
|
||||
Text(
|
||||
text = "Select a key file to install key from.",
|
||||
modifier = Modifier
|
||||
|
|
@ -437,7 +464,7 @@ class SettingViews {
|
|||
keyInstallState
|
||||
)
|
||||
|
||||
if (keyInstallState.value == KeyInstallState.None) {
|
||||
if (keyInstallState.value == KeyInstallState.File) {
|
||||
showKeyDialog.value = false
|
||||
settingsViewModel.clearKeySelection(keyInstallState)
|
||||
}
|
||||
|
|
@ -561,6 +588,7 @@ class SettingViews {
|
|||
if (firmwareInstallState.value != FirmwareInstallState.Install) {
|
||||
showFirwmareDialog.value = false
|
||||
settingsViewModel.clearFirmwareSelection(firmwareInstallState)
|
||||
firmwareInstallState.value = FirmwareInstallState.File
|
||||
}
|
||||
}
|
||||
) {
|
||||
|
|
@ -580,7 +608,7 @@ class SettingViews {
|
|||
)
|
||||
|
||||
when (firmwareInstallState.value) {
|
||||
FirmwareInstallState.None -> {
|
||||
FirmwareInstallState.File -> {
|
||||
Text(
|
||||
text = "Select a zip or xci file to install firmware from.",
|
||||
modifier = Modifier
|
||||
|
|
@ -635,7 +663,7 @@ class SettingViews {
|
|||
onClick = {
|
||||
settingsViewModel.installFirmware(firmwareInstallState)
|
||||
|
||||
if (firmwareInstallState.value == FirmwareInstallState.None) {
|
||||
if (firmwareInstallState.value == FirmwareInstallState.File) {
|
||||
showFirwmareDialog.value = false
|
||||
settingsViewModel.clearFirmwareSelection(firmwareInstallState)
|
||||
}
|
||||
|
|
@ -779,13 +807,125 @@ class SettingViews {
|
|||
}
|
||||
}
|
||||
}
|
||||
SimpleAlertDialog.Custom(
|
||||
showDialog = showDataResetDialog,
|
||||
onDismissRequest = {
|
||||
if (dataResetState.value != DataResetState.Reset) {
|
||||
showDataResetDialog.value = false
|
||||
dataResetState.value = DataResetState.Query
|
||||
}
|
||||
}
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(16.dp)
|
||||
.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.SpaceBetween,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = "App Data Reinit",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 16.dp),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
|
||||
when (dataResetState.value) {
|
||||
DataResetState.Query -> {
|
||||
Text(
|
||||
text = "Current bis, games, profiles and system folders will be reset. Do you want to continue?",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 8.dp, bottom = 8.dp),
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
thread {
|
||||
settingsViewModel.resetAppData(dataResetState)
|
||||
}
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 8.dp)
|
||||
) {
|
||||
Text(text = "Yes")
|
||||
}
|
||||
Button(
|
||||
onClick = {
|
||||
showDataResetDialog.value = false
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 8.dp)
|
||||
) {
|
||||
Text(text = "No")
|
||||
}
|
||||
}
|
||||
}
|
||||
DataResetState.Reset -> {
|
||||
Text(
|
||||
text = "Resetting app data...",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 8.dp, bottom = 8.dp),
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp)
|
||||
)
|
||||
}
|
||||
DataResetState.Done -> {
|
||||
Text(
|
||||
text = "Data reset completed successfully.",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 8.dp, bottom = 8.dp),
|
||||
textAlign = TextAlign.Start
|
||||
)
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 16.dp)
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
showDataResetDialog.value = false
|
||||
firmwareVersion.value = mainViewModel.firmwareVersion
|
||||
dataResetState.value = DataResetState.Query
|
||||
mainViewModel.userViewModel.refreshUsers()
|
||||
mainViewModel.homeViewModel.requestReload()
|
||||
mainViewModel.activity.shutdownAndRestart()
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(horizontal = 8.dp)
|
||||
) {
|
||||
Text(text = "Close")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SimpleAlertDialog.Custom(
|
||||
showDialog = showDataImportDialog,
|
||||
onDismissRequest = {
|
||||
if (dataImportState.value != DataImportState.Import) {
|
||||
showDataImportDialog.value = false
|
||||
dataFile.value = null
|
||||
dataImportState.value = DataImportState.None
|
||||
dataImportState.value = DataImportState.File
|
||||
}
|
||||
}
|
||||
) {
|
||||
|
|
@ -805,9 +945,9 @@ class SettingViews {
|
|||
)
|
||||
|
||||
when (dataImportState.value) {
|
||||
DataImportState.None -> {
|
||||
DataImportState.File -> {
|
||||
Text(
|
||||
text = "Select a zip file to import app data from.",
|
||||
text = "Select a zip file to import bis, games, profiles and system folders from another Android installation.",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(start = 8.dp, bottom = 8.dp),
|
||||
|
|
@ -854,7 +994,7 @@ class SettingViews {
|
|||
onClick = {
|
||||
showDataImportDialog.value = false
|
||||
dataFile.value = null
|
||||
dataImportState.value = DataImportState.None
|
||||
dataImportState.value = DataImportState.File
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
|
|
@ -942,9 +1082,10 @@ class SettingViews {
|
|||
showDataImportDialog.value = false
|
||||
dataFile.value = null
|
||||
firmwareVersion.value = mainViewModel.firmwareVersion
|
||||
dataImportState.value = DataImportState.None
|
||||
dataImportState.value = DataImportState.File
|
||||
mainViewModel.userViewModel.refreshUsers()
|
||||
mainViewModel.homeViewModel.requestReload()
|
||||
mainViewModel.activity.shutdownAndRestart()
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
|
|
@ -1032,6 +1173,8 @@ class SettingViews {
|
|||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
useNce.SwitchSelector(label = "Enable NCE (Native Code Execution)")
|
||||
enablePptc.SwitchSelector(label = "Enable PPTC (Profiled Persistent Translation Cache)")
|
||||
enableLowPowerPptc.SwitchSelector(label = "Enable Low-Power PPTC")
|
||||
enableJitCacheEviction.SwitchSelector(label = "Enable Jit Cache Eviction")
|
||||
MemoryModeDropdown(
|
||||
selectedMemoryManagerMode = memoryManagerMode.value,
|
||||
onModeSelected = { mode ->
|
||||
|
|
|
|||
|
|
@ -79,6 +79,8 @@ namespace LibKenjinx
|
|||
int vSyncMode,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableLowPowerPtc,
|
||||
bool enableJitCacheEviction,
|
||||
bool enableInternetAccess,
|
||||
bool enableFsIntegrityChecks,
|
||||
int fsGlobalAccessLogMode,
|
||||
|
|
@ -98,6 +100,8 @@ namespace LibKenjinx
|
|||
(VSyncMode)vSyncMode,
|
||||
enableDockedMode,
|
||||
enablePtc,
|
||||
enableLowPowerPtc,
|
||||
enableJitCacheEviction,
|
||||
enableInternetAccess,
|
||||
enableFsIntegrityChecks,
|
||||
fsGlobalAccessLogMode,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ namespace LibKenjinx
|
|||
VSyncMode vSyncMode,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableLowPowerPtc,
|
||||
bool enableJitCacheEviction,
|
||||
bool enableInternetAccess,
|
||||
bool enableFsIntegrityChecks,
|
||||
int fsGlobalAccessLogMode,
|
||||
|
|
@ -45,6 +47,8 @@ namespace LibKenjinx
|
|||
vSyncMode,
|
||||
enableDockedMode,
|
||||
enablePtc,
|
||||
enableLowPowerPtc,
|
||||
enableJitCacheEviction,
|
||||
enableInternetAccess,
|
||||
enableFsIntegrityChecks,
|
||||
fsGlobalAccessLogMode,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using Ryujinx.Graphics.Gpu;
|
|||
using Ryujinx.Graphics.Gpu.Shader;
|
||||
using Ryujinx.Graphics.OpenGL;
|
||||
using Ryujinx.Graphics.Vulkan;
|
||||
using Ryujinx.UI.Common.Configuration;
|
||||
using Silk.NET.Vulkan;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
|
@ -94,6 +95,9 @@ namespace LibKenjinx
|
|||
{
|
||||
return;
|
||||
}
|
||||
ARMeilleure.Optimizations.EcoFriendly = SwitchDevice!.EnableLowPowerPtc;
|
||||
ARMeilleure.Optimizations.CacheEviction = SwitchDevice!.EnableJitCacheEviction;
|
||||
|
||||
var device = SwitchDevice!.EmulationContext!;
|
||||
_gpuDoneEvent = new ManualResetEvent(true);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@ namespace LibKenjinx
|
|||
VSyncMode vSyncMode,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableLowPowerPtc,
|
||||
bool enableJitCacheEviction,
|
||||
bool enableInternetAccess,
|
||||
bool enableFsIntegrityChecks,
|
||||
int fsGlobalAccessLogMode,
|
||||
|
|
@ -55,6 +57,8 @@ namespace LibKenjinx
|
|||
vSyncMode,
|
||||
enableDockedMode,
|
||||
enablePtc,
|
||||
enableLowPowerPtc,
|
||||
enableJitCacheEviction,
|
||||
enableInternetAccess,
|
||||
enableFsIntegrityChecks,
|
||||
fsGlobalAccessLogMode,
|
||||
|
|
|
|||
|
|
@ -419,7 +419,7 @@ namespace LibKenjinx
|
|||
}
|
||||
|
||||
// Return the ControlFS
|
||||
controlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
|
||||
controlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, SwitchDevice.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None);
|
||||
titleId = controlNca?.Header.TitleId.ToString("x16");
|
||||
}
|
||||
|
||||
|
|
@ -486,7 +486,7 @@ namespace LibKenjinx
|
|||
|
||||
if (patchNca != null && controlNca != null)
|
||||
{
|
||||
updatedControlFs = controlNca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None);
|
||||
updatedControlFs = controlNca.OpenFileSystem(NcaSectionType.Data, SwitchDevice.EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -708,6 +708,10 @@ namespace LibKenjinx
|
|||
public InputManager? InputManager { get; set; }
|
||||
public Switch? EmulationContext { get; set; }
|
||||
public IHostUIHandler? HostUiHandler { get; set; }
|
||||
public bool EnableLowPowerPtc { get; set; }
|
||||
public bool EnableJitCacheEviction { get; set; }
|
||||
|
||||
public bool EnableFsIntegrityChecks { get; set; }
|
||||
|
||||
internal void DisposeContext()
|
||||
{
|
||||
|
|
@ -803,6 +807,8 @@ namespace LibKenjinx
|
|||
VSyncMode vSyncMode,
|
||||
bool enableDockedMode,
|
||||
bool enablePtc,
|
||||
bool enableLowPowerPtc,
|
||||
bool enableJitCacheEviction,
|
||||
bool enableInternetAccess,
|
||||
bool enableFsIntegrityChecks,
|
||||
int fsGlobalAccessLogMode,
|
||||
|
|
@ -824,6 +830,10 @@ namespace LibKenjinx
|
|||
renderer = new ThreadedRenderer(renderer);
|
||||
}
|
||||
|
||||
EnableLowPowerPtc = enableLowPowerPtc;
|
||||
EnableJitCacheEviction = enableJitCacheEviction;
|
||||
EnableFsIntegrityChecks = enableFsIntegrityChecks;
|
||||
|
||||
HLEConfiguration configuration = new HLEConfiguration(VirtualFileSystem,
|
||||
LibHacHorizonManager,
|
||||
ContentManager,
|
||||
|
|
@ -839,7 +849,7 @@ namespace LibKenjinx
|
|||
enableDockedMode,
|
||||
enablePtc,
|
||||
enableInternetAccess,
|
||||
enableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||
EnableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||
fsGlobalAccessLogMode,
|
||||
0,
|
||||
timeZone,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,6 @@ namespace Ryujinx.Common
|
|||
|
||||
public static bool IsFlatHubBuild => IsValid && ReleaseChannelOwner.Equals(FlatHubChannelOwner);
|
||||
|
||||
public static string Version => (IsValid || !RuntimeFeature.IsDynamicCodeCompiled) ? (PlatformInfo.IsBionic ? "Android_2.0.3" : BuildVersion) : Assembly.GetEntryAssembly()!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
||||
public static string Version => (IsValid || !RuntimeFeature.IsDynamicCodeCompiled) ? (PlatformInfo.IsBionic ? "Bionic_2.0.3" : BuildVersion) : Assembly.GetEntryAssembly()!.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
using ARMeilleure;
|
||||
using ARMeilleure.Memory;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Memory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Threading;
|
||||
|
|
@ -14,8 +17,15 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
private static readonly int _pageSize = (int)MemoryBlock.GetPageSize();
|
||||
private static readonly int _pageMask = _pageSize - 1;
|
||||
|
||||
private const int CodeAlignment = 4; // Bytes.
|
||||
private const int CacheSize = 2047 * 1024 * 1024;
|
||||
private const int CodeAlignment = 4;
|
||||
private const int FullCacheSize = 2047 * 1024 * 1024;
|
||||
private const int ReducedCacheSize = FullCacheSize / 8;
|
||||
|
||||
private const float EvictionTargetPercentage = 0.20f;
|
||||
private const int MaxEntriesToEvictAtOnce = 100;
|
||||
|
||||
// Simple logging configuration
|
||||
private const int LogInterval = 5000; // Log every 5000 allocations
|
||||
|
||||
private static ReservedRegion _jitRegion;
|
||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||
|
|
@ -23,9 +33,33 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
private static CacheMemoryAllocator _cacheAllocator;
|
||||
|
||||
private static readonly List<CacheEntry> _cacheEntries = [];
|
||||
private static readonly Dictionary<int, EntryUsageStats> _entryUsageStats = [];
|
||||
|
||||
private static readonly Lock _lock = new();
|
||||
private static bool _initialized;
|
||||
private static int _cacheSize;
|
||||
|
||||
// Basic statistics
|
||||
private static int _totalAllocations = 0;
|
||||
private static int _totalEvictions = 0;
|
||||
|
||||
private class EntryUsageStats
|
||||
{
|
||||
public long LastAccessTime { get; private set; }
|
||||
public int UsageCount { get; private set; }
|
||||
|
||||
public EntryUsageStats()
|
||||
{
|
||||
LastAccessTime = DateTime.UtcNow.Ticks;
|
||||
UsageCount = 1;
|
||||
}
|
||||
|
||||
public void UpdateUsage()
|
||||
{
|
||||
LastAccessTime = DateTime.UtcNow.Ticks;
|
||||
UsageCount++;
|
||||
}
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("windows")]
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
|
|
@ -45,15 +79,17 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
return;
|
||||
}
|
||||
|
||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
||||
_cacheSize = Optimizations.CacheEviction ? ReducedCacheSize : FullCacheSize;
|
||||
_jitRegion = new ReservedRegion(allocator, (ulong)_cacheSize);
|
||||
|
||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||
{
|
||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||
}
|
||||
|
||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
||||
_cacheAllocator = new CacheMemoryAllocator(_cacheSize);
|
||||
|
||||
Logger.Info?.Print(LogClass.Cpu, $"Lightning JIT Cache initialized: Size={_cacheSize / (1024 * 1024)} MB, Eviction={Optimizations.CacheEviction}");
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -63,8 +99,32 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
lock (_lock)
|
||||
{
|
||||
Debug.Assert(_initialized);
|
||||
_totalAllocations++;
|
||||
|
||||
int funcOffset = Allocate(code.Length);
|
||||
int funcOffset;
|
||||
|
||||
if (Optimizations.CacheEviction)
|
||||
{
|
||||
int codeSize = AlignCodeSize(code.Length);
|
||||
funcOffset = _cacheAllocator.Allocate(codeSize);
|
||||
|
||||
if (funcOffset < 0)
|
||||
{
|
||||
EvictEntries(codeSize);
|
||||
funcOffset = _cacheAllocator.Allocate(codeSize);
|
||||
|
||||
if (funcOffset < 0)
|
||||
{
|
||||
throw new OutOfMemoryException("JIT Cache exhausted even after eviction.");
|
||||
}
|
||||
}
|
||||
|
||||
_jitRegion.ExpandIfNeeded((ulong)funcOffset + (ulong)codeSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
funcOffset = Allocate(code.Length);
|
||||
}
|
||||
|
||||
IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
|
||||
|
||||
|
|
@ -96,6 +156,12 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
|
||||
Add(funcOffset, code.Length);
|
||||
|
||||
// Simple periodic logging
|
||||
if (_totalAllocations % LogInterval == 0)
|
||||
{
|
||||
LogCacheStatus();
|
||||
}
|
||||
|
||||
return funcPtr;
|
||||
}
|
||||
}
|
||||
|
|
@ -112,6 +178,11 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
{
|
||||
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
||||
_cacheEntries.RemoveAt(entryIndex);
|
||||
|
||||
if (Optimizations.CacheEviction)
|
||||
{
|
||||
_entryUsageStats.Remove(funcOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -169,6 +240,11 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
}
|
||||
|
||||
_cacheEntries.Insert(index, entry);
|
||||
|
||||
if (Optimizations.CacheEviction)
|
||||
{
|
||||
_entryUsageStats[offset] = new EntryUsageStats();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryFind(int offset, out CacheEntry entry, out int entryIndex)
|
||||
|
|
@ -185,6 +261,12 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
if (index >= 0)
|
||||
{
|
||||
entry = _cacheEntries[index];
|
||||
|
||||
if (Optimizations.CacheEviction && _entryUsageStats.TryGetValue(offset, out var stats))
|
||||
{
|
||||
stats.UpdateUsage();
|
||||
}
|
||||
|
||||
entryIndex = index;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -194,5 +276,83 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
entryIndex = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void EvictEntries(int requiredSize)
|
||||
{
|
||||
if (!Optimizations.CacheEviction)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
int targetSpace = Math.Max(requiredSize, (int)(_cacheSize * EvictionTargetPercentage));
|
||||
int freedSpace = 0;
|
||||
int evictedCount = 0;
|
||||
|
||||
var entriesWithStats = _cacheEntries
|
||||
.Where(e => _entryUsageStats.ContainsKey(e.Offset))
|
||||
.Select(e => new {
|
||||
Entry = e,
|
||||
Stats = _entryUsageStats[e.Offset],
|
||||
Score = CalculateEvictionScore(_entryUsageStats[e.Offset])
|
||||
})
|
||||
.OrderBy(x => x.Score)
|
||||
.Take(MaxEntriesToEvictAtOnce)
|
||||
.ToList();
|
||||
|
||||
foreach (var item in entriesWithStats)
|
||||
{
|
||||
int entrySize = AlignCodeSize(item.Entry.Size);
|
||||
|
||||
int entryIndex = _cacheEntries.BinarySearch(item.Entry);
|
||||
if (entryIndex >= 0)
|
||||
{
|
||||
_cacheAllocator.Free(item.Entry.Offset, entrySize);
|
||||
_cacheEntries.RemoveAt(entryIndex);
|
||||
_entryUsageStats.Remove(item.Entry.Offset);
|
||||
|
||||
freedSpace += entrySize;
|
||||
evictedCount++;
|
||||
|
||||
if (freedSpace >= targetSpace)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_totalEvictions += evictedCount;
|
||||
|
||||
Logger.Info?.Print(LogClass.Cpu, $"Lightning JIT Cache: Evicted {evictedCount} entries, freed {freedSpace / (1024 * 1024.0):F2} MB");
|
||||
}
|
||||
}
|
||||
|
||||
private static double CalculateEvictionScore(EntryUsageStats stats)
|
||||
{
|
||||
long currentTime = DateTime.UtcNow.Ticks;
|
||||
long ageInTicks = currentTime - stats.LastAccessTime;
|
||||
|
||||
double ageInSeconds = ageInTicks / 10_000_000.0;
|
||||
|
||||
const double usageWeight = 1.0;
|
||||
const double ageWeight = 2.0;
|
||||
|
||||
double usageScore = Math.Log10(stats.UsageCount + 1) * usageWeight;
|
||||
double ageScore = (10.0 / (ageInSeconds + 1.0)) * ageWeight;
|
||||
|
||||
return usageScore + ageScore;
|
||||
}
|
||||
|
||||
private static void LogCacheStatus()
|
||||
{
|
||||
int estimatedUsedSize = _cacheEntries.Sum(e => AlignCodeSize(e.Size));
|
||||
double usagePercentage = 100.0 * estimatedUsedSize / _cacheSize;
|
||||
|
||||
Logger.Info?.Print(LogClass.Cpu,
|
||||
$"Lightning JIT Cache status: entries={_cacheEntries.Count}, " +
|
||||
$"est. used={estimatedUsedSize / (1024 * 1024.0):F2} MB ({usagePercentage:F1}%), " +
|
||||
$"evictions={_totalEvictions}, allocations={_totalAllocations}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ namespace Ryujinx.Cpu.LightningJit.Cache
|
|||
{
|
||||
private const int CodeAlignment = 4; // Bytes.
|
||||
private const int SharedCacheSize = 2047 * 1024 * 1024;
|
||||
private const int LocalCacheSize = 128 * 1024 * 1024;
|
||||
private const int LocalCacheSize = 256 * 1024 * 1024;
|
||||
|
||||
// How many calls to the same function we allow until we pad the shared cache to force the function to become available there
|
||||
// and allow the guest to take the fast path.
|
||||
|
|
|
|||
|
|
@ -512,13 +512,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
|
|||
if (context.Definitions.Stage == ShaderStage.Fragment && context.Definitions.DualSourceBlend)
|
||||
{
|
||||
IoDefinition firstOutput = outputs.ElementAtOrDefault(0);
|
||||
IoDefinition secondOutput = outputs.ElementAtOrDefault(1);
|
||||
|
||||
if (firstOutput.Location + 1 == secondOutput.Location)
|
||||
{
|
||||
DeclareOutputDualSourceBlendAttribute(context, firstOutput.Location);
|
||||
outputs = outputs.Skip(2);
|
||||
}
|
||||
DeclareOutputDualSourceBlendAttribute(context, firstOutput.Location);
|
||||
outputs = outputs.Skip(2);
|
||||
}
|
||||
|
||||
foreach (var ioDefinition in outputs)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,11 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
|
|||
{
|
||||
public static void RunPass(TransformContext context)
|
||||
{
|
||||
for (int blkIndex = 0; blkIndex < context.Blocks.Length; blkIndex++)
|
||||
{
|
||||
XmadOptimizer.RunPass(context.Blocks[blkIndex]);
|
||||
}
|
||||
|
||||
RunOptimizationPasses(context.Blocks, context.ResourceManager);
|
||||
|
||||
// TODO: Some of those are not optimizations and shouldn't be here.
|
||||
|
|
|
|||
|
|
@ -181,13 +181,29 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
|
||||
private static void EmitOutputsInitialization(EmitterContext context, AttributeUsage attributeUsage, IGpuAccessor gpuAccessor, ShaderStage stage)
|
||||
{
|
||||
// Compute has no output attributes, and fragment is the last stage, so we
|
||||
// don't need to initialize outputs on those stages.
|
||||
if (stage == ShaderStage.Compute || stage == ShaderStage.Fragment)
|
||||
// Compute has no output attributes, so we
|
||||
// don't need to initialize outputs on that stage.
|
||||
if (stage == ShaderStage.Compute)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (stage == ShaderStage.Fragment)
|
||||
{
|
||||
// Fragment is the last stage, so we don't need to
|
||||
// initialize outputs unless we're using DSB, in which
|
||||
// we need to make sure the ouput has a valid value.
|
||||
if (gpuAccessor.QueryGraphicsState().DualSourceBlendEnable)
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
context.Store(StorageKind.Output, IoVariable.FragmentOutputColor, null, Const(1), Const(i), ConstF(0));
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (stage == ShaderStage.Vertex)
|
||||
{
|
||||
InitializeVertexOutputs(context);
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
// If binding 3 is immediately used, use an alternate set of reserved bindings.
|
||||
ReadOnlyCollection<ResourceUsage> uniformUsage = layout.SetUsages[0].Usages;
|
||||
bool hasBinding3 = uniformUsage.Any(x => x.Binding == 3);
|
||||
int[] reserved = isCompute ? Array.Empty<int>() : gd.GetPushDescriptorReservedBindings(hasBinding3);
|
||||
int[] reserved = isCompute ? [] : gd.GetPushDescriptorReservedBindings(hasBinding3);
|
||||
|
||||
// Can't use any of the reserved usages.
|
||||
for (int i = 0; i < uniformUsage.Count; i++)
|
||||
|
|
@ -240,7 +240,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
for (int setIndex = 0; setIndex < sets.Count; setIndex++)
|
||||
{
|
||||
List<ResourceBindingSegment> currentSegments = new();
|
||||
List<ResourceBindingSegment> currentSegments = [];
|
||||
|
||||
ResourceDescriptor currentDescriptor = default;
|
||||
int currentCount = 0;
|
||||
|
|
@ -298,7 +298,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
for (int setIndex = 0; setIndex < setUsages.Count; setIndex++)
|
||||
{
|
||||
List<ResourceBindingSegment> currentSegments = new();
|
||||
List<ResourceBindingSegment> currentSegments = [];
|
||||
|
||||
ResourceUsage currentUsage = default;
|
||||
int currentCount = 0;
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
var sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples);
|
||||
|
||||
var usage = GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, true);
|
||||
var usage = GetImageUsage(info.Format, info.Target, gd.Capabilities);
|
||||
|
||||
var flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit;
|
||||
|
||||
|
|
@ -307,7 +307,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
}
|
||||
}
|
||||
|
||||
public static ImageUsageFlags GetImageUsage(Format format, in HardwareCapabilities capabilities, bool isMsImageStorageSupported, bool extendedUsage)
|
||||
public static ImageUsageFlags GetImageUsage(Format format, Target target, in HardwareCapabilities capabilities)
|
||||
{
|
||||
var usage = DefaultUsageFlags;
|
||||
|
||||
|
|
@ -320,11 +320,19 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
usage |= ImageUsageFlags.ColorAttachmentBit;
|
||||
}
|
||||
|
||||
if ((format.IsImageCompatible() && isMsImageStorageSupported) || extendedUsage)
|
||||
bool isMsImageStorageSupported = capabilities.SupportsShaderStorageImageMultisample;
|
||||
|
||||
if (format.IsImageCompatible() && (isMsImageStorageSupported || !target.IsMultisample()))
|
||||
{
|
||||
usage |= ImageUsageFlags.StorageBit;
|
||||
}
|
||||
|
||||
if (capabilities.SupportsAttachmentFeedbackLoop &&
|
||||
(usage & (ImageUsageFlags.DepthStencilAttachmentBit | ImageUsageFlags.ColorAttachmentBit)) != 0)
|
||||
{
|
||||
usage |= ImageUsageFlags.AttachmentFeedbackLoopBitExt;
|
||||
}
|
||||
|
||||
return usage;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,8 +64,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample();
|
||||
|
||||
var format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported);
|
||||
var usage = TextureStorage.GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, false);
|
||||
|
||||
var usage = TextureStorage.GetImageUsage(info.Format, info.Target, gd.Capabilities);
|
||||
var levels = (uint)info.Levels;
|
||||
var layers = (uint)info.GetLayers();
|
||||
|
||||
|
|
|
|||
|
|
@ -468,9 +468,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
_gd.CommandBufferPool.Return(
|
||||
cbs,
|
||||
stackalloc[] { _imageAvailableSemaphores[semaphoreIndex] },
|
||||
stackalloc[] { PipelineStageFlags.ColorAttachmentOutputBit },
|
||||
stackalloc[] { _renderFinishedSemaphores[semaphoreIndex] });
|
||||
[_imageAvailableSemaphores[semaphoreIndex]],
|
||||
[PipelineStageFlags.ColorAttachmentOutputBit],
|
||||
[_renderFinishedSemaphores[semaphoreIndex]]);
|
||||
|
||||
// TODO: Present queue.
|
||||
var semaphore = _renderFinishedSemaphores[semaphoreIndex];
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process
|
|||
// TODO: Remove once we no longer need to initialize it externally.
|
||||
HandleTable = new KHandleTable();
|
||||
|
||||
_threads = new LinkedList<KThread>();
|
||||
_threads = [];
|
||||
|
||||
Debugger = new HleProcessDebugger(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
|
|||
device.System.KernelContext,
|
||||
metaLoader,
|
||||
nacpData,
|
||||
device.System.EnablePtc,
|
||||
enablePtc,
|
||||
modLoadResult.Hash,
|
||||
true,
|
||||
programName,
|
||||
|
|
|
|||
|
|
@ -305,6 +305,13 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
|
||||
if (string.IsNullOrWhiteSpace(programName))
|
||||
{
|
||||
foreach (ApplicationControlProperty.ApplicationTitle nacpTitles in nacpData.Value.Title)
|
||||
{
|
||||
if (nacpTitles.Name[0] != 0)
|
||||
continue;
|
||||
|
||||
programName = nacpTitles.NameString.ToString();
|
||||
}
|
||||
programName = Array.Find(nacpData.Value.Title.AsReadOnlySpan().ToArray(), x => x.Name[0] != 0).NameString.ToString();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
ulong programId,
|
||||
byte programIndex,
|
||||
byte[] arguments = null,
|
||||
params IExecutable[] executables)
|
||||
params ReadOnlySpan<IExecutable> executables)
|
||||
{
|
||||
context.Device.System.ServiceTable.WaitServicesReady();
|
||||
|
||||
|
|
@ -255,12 +255,17 @@ namespace Ryujinx.HLE.Loaders.Processes
|
|||
ulong codeStart = ((meta.Flags & 1) != 0 ? 0x8000000UL : 0x200000UL) + CodeStartOffset;
|
||||
ulong codeSize = 0;
|
||||
|
||||
IEnumerable<string> buildIds = executables.Select(e => (e switch
|
||||
string[] buildIds = new string[executables.Length];
|
||||
|
||||
for (int i = 0; i < executables.Length; i++)
|
||||
{
|
||||
NsoExecutable nso => Convert.ToHexString(nso.BuildId),
|
||||
NroExecutable nro => Convert.ToHexString(nro.Header.BuildId),
|
||||
_ => string.Empty,
|
||||
}).ToUpper());
|
||||
buildIds[i] = (executables[i] switch
|
||||
{
|
||||
NsoExecutable nso => Convert.ToHexString(nso.BuildId),
|
||||
NroExecutable nro => Convert.ToHexString(nro.Header.BuildId),
|
||||
_ => string.Empty
|
||||
}).ToUpper();
|
||||
}
|
||||
|
||||
NceCpuCodePatch[] nsoPatch = new NceCpuCodePatch[executables.Length];
|
||||
ulong[] nsoBase = new ulong[executables.Length];
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.UI.Common.Configuration
|
|||
/// <summary>
|
||||
/// The current version of the file format
|
||||
/// </summary>
|
||||
public const int CurrentVersion = 58;
|
||||
public const int CurrentVersion = 59;
|
||||
|
||||
/// <summary>
|
||||
/// Version of the configuration file format
|
||||
|
|
@ -240,6 +240,11 @@ namespace Ryujinx.UI.Common.Configuration
|
|||
/// </summary>
|
||||
public bool EnableLowPowerPtc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables JIT cache eviction to avoid out of memory errors in some games
|
||||
/// </summary>
|
||||
public bool EnableJitCacheEviction { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables guest Internet access
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -345,6 +345,11 @@ namespace Ryujinx.UI.Common.Configuration
|
|||
/// </summary>
|
||||
public ReactiveObject<bool> EnableLowPowerPtc { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables JIT cache eviction to avoid out of memory errors in some games
|
||||
/// </summary>
|
||||
public ReactiveObject<bool> EnableJitCacheEviction { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables guest Internet access
|
||||
/// </summary>
|
||||
|
|
@ -405,6 +410,8 @@ namespace Ryujinx.UI.Common.Configuration
|
|||
EnablePtc.Event += static (sender, e) => LogValueChange(e, nameof(EnablePtc));
|
||||
EnableLowPowerPtc = new ReactiveObject<bool>();
|
||||
EnableLowPowerPtc.Event += static (sender, e) => LogValueChange(e, nameof(EnableLowPowerPtc));
|
||||
EnableJitCacheEviction = new ReactiveObject<bool>();
|
||||
EnableJitCacheEviction.Event += static (sender, e) => LogValueChange(e, nameof(EnableJitCacheEviction));
|
||||
EnableInternetAccess = new ReactiveObject<bool>();
|
||||
EnableInternetAccess.Event += static (sender, e) => LogValueChange(e, nameof(EnableInternetAccess));
|
||||
EnableFsIntegrityChecks = new ReactiveObject<bool>();
|
||||
|
|
@ -775,6 +782,7 @@ namespace Ryujinx.UI.Common.Configuration
|
|||
EnableColorSpacePassthrough = Graphics.EnableColorSpacePassthrough,
|
||||
EnablePtc = System.EnablePtc,
|
||||
EnableLowPowerPtc = System.EnableLowPowerPtc,
|
||||
EnableJitCacheEviction = System.EnableJitCacheEviction,
|
||||
EnableInternetAccess = System.EnableInternetAccess,
|
||||
EnableFsIntegrityChecks = System.EnableFsIntegrityChecks,
|
||||
FsGlobalAccessLogMode = System.FsGlobalAccessLogMode,
|
||||
|
|
@ -1648,6 +1656,15 @@ namespace Ryujinx.UI.Common.Configuration
|
|||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
if (configurationFileFormat.Version < 59)
|
||||
{
|
||||
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 59.");
|
||||
|
||||
configurationFileFormat.EnableJitCacheEviction = false;
|
||||
|
||||
configurationFileUpdated = true;
|
||||
}
|
||||
|
||||
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
|
||||
Graphics.ResScale.Value = configurationFileFormat.ResScale;
|
||||
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
|
||||
|
|
@ -1692,6 +1709,7 @@ namespace Ryujinx.UI.Common.Configuration
|
|||
Graphics.EnableColorSpacePassthrough.Value = configurationFileFormat.EnableColorSpacePassthrough;
|
||||
System.EnablePtc.Value = configurationFileFormat.EnablePtc;
|
||||
System.EnableLowPowerPtc.Value = configurationFileFormat.EnableLowPowerPtc;
|
||||
System.EnableJitCacheEviction.Value = configurationFileFormat.EnableJitCacheEviction;
|
||||
System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
|
||||
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
|
||||
System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue