diff --git a/src/ARMeilleure/Translation/PTC/Ptc.cs b/src/ARMeilleure/Translation/PTC/Ptc.cs index 2625a46df..b8ce585d0 100644 --- a/src/ARMeilleure/Translation/PTC/Ptc.cs +++ b/src/ARMeilleure/Translation/PTC/Ptc.cs @@ -31,14 +31,11 @@ namespace ARMeilleure.Translation.PTC private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string InnerHeaderMagicString = "PTCihd\0\0"; - private const uint InternalVersion = 7010; //! To be incremented manually for each change to the ARMeilleure project. + private const uint InternalVersion = 7020; //! To be incremented manually for each change to the ARMeilleure project. Your value was 7031, keeping this comment here just so you have the reference. private const string ActualDir = "0"; private const string BackupDir = "1"; - private const string TitleIdTextDefault = "0000000000000000"; - private const string DisplayVersionDefault = "0"; - public static readonly Symbol PageTableSymbol = new(SymbolType.Special, 1); public static readonly Symbol CountTableSymbol = new(SymbolType.Special, 2); public static readonly Symbol DispatchStubSymbol = new(SymbolType.Special, 3); @@ -64,8 +61,7 @@ namespace ARMeilleure.Translation.PTC private bool _disposed; - public string TitleIdText { get; private set; } - public string DisplayVersion { get; private set; } + public PtcCacheInfo CacheInfo { get; private set; } private MemoryManagerType _memoryMode; @@ -92,8 +88,7 @@ namespace ARMeilleure.Translation.PTC _disposed = false; - TitleIdText = TitleIdTextDefault; - DisplayVersion = DisplayVersionDefault; + CacheInfo = new PtcCacheInfo(0, null, null, 0, null, "Unknown", "default"); CachePathActual = string.Empty; CachePathBackup = string.Empty; @@ -101,20 +96,24 @@ namespace ARMeilleure.Translation.PTC Disable(); } - public void Initialize(string titleIdText, string displayVersion, bool enabled, MemoryManagerType memoryMode, string cacheSelector) + public void Initialize(PtcCacheInfo cacheInfo, bool enabled, MemoryManagerType memoryMode) { Wait(); Profiler.Wait(); Profiler.ClearEntries(); - Logger.Info?.Print(LogClass.Ptc, $"Initializing Profiled Persistent Translation Cache v{InternalVersion}\n\t\t (title: {titleIdText}, version: '{displayVersion}', selector: '{cacheSelector}', enabled: {enabled})."); + CacheInfo = cacheInfo; - if (!enabled || string.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault) + Logger.Info?.Print( + LogClass.Ptc, + $"Initializing Profiled Persistent Translation Cache v{InternalVersion}\n\t\t " + + $"(pid: {cacheInfo.ProcessId}, title: {cacheInfo.TitleIdText}, application: {cacheInfo.ApplicationIdText}, " + + $"programIndex: {cacheInfo.ProgramIndex}, version: '{cacheInfo.DisplayVersion}', kind: {cacheInfo.ProcessKind}, " + + $"selector: '{cacheInfo.CacheSelector}', key: '{cacheInfo.CacheKey}', enabled: {enabled})."); + + if (!enabled || cacheInfo.TitleIdText == PtcCacheInfo.TitleIdTextDefault) { - TitleIdText = TitleIdTextDefault; - DisplayVersion = DisplayVersionDefault; - CachePathActual = string.Empty; CachePathBackup = string.Empty; @@ -123,12 +122,10 @@ namespace ARMeilleure.Translation.PTC return; } - TitleIdText = titleIdText; - DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault; _memoryMode = memoryMode; - string workPathActual = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", ActualDir); - string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, TitleIdText, "cache", "cpu", BackupDir); + string workPathActual = Path.Combine(AppDataManager.GamesDirPath, CacheInfo.TitleIdText, "cache", "cpu", ActualDir); + string workPathBackup = Path.Combine(AppDataManager.GamesDirPath, CacheInfo.TitleIdText, "cache", "cpu", BackupDir); if (!Directory.Exists(workPathActual)) { @@ -140,8 +137,14 @@ namespace ARMeilleure.Translation.PTC Directory.CreateDirectory(workPathBackup); } - CachePathActual = Path.Combine(workPathActual, DisplayVersion) + "-" + cacheSelector; - CachePathBackup = Path.Combine(workPathBackup, DisplayVersion) + "-" + cacheSelector; + CachePathActual = Path.Combine(workPathActual, CacheInfo.DisplayVersion) + "-" + CacheInfo.CacheSelector; + CachePathBackup = Path.Combine(workPathBackup, CacheInfo.DisplayVersion) + "-" + CacheInfo.CacheSelector; + + Logger.Info?.Print( + LogClass.Ptc, + $"PPTC cache owner selected (pid: {CacheInfo.ProcessId}, title: {CacheInfo.TitleIdText}, application: {CacheInfo.ApplicationIdText}, " + + $"version: '{CacheInfo.DisplayVersion}', kind: {CacheInfo.ProcessKind}, selector: '{CacheInfo.CacheSelector}', " + + $"key: '{CacheInfo.CacheKey}', path: '{CachePathActual}')."); PreLoad(); Profiler.PreLoad(); @@ -364,7 +367,12 @@ namespace ARMeilleure.Translation.PTC long fileSize = new FileInfo(fileName).Length; - Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} (size: {fileSize} bytes, translated functions: {GetEntriesCount()})."); + Logger.Info?.Print( + LogClass.Ptc, + $"{(isBackup ? "Loaded Backup Translation Cache" : "Loaded Translation Cache")} " + + $"(pid: {CacheInfo.ProcessId}, title: {CacheInfo.TitleIdText}, version: '{CacheInfo.DisplayVersion}', kind: {CacheInfo.ProcessKind}, " + + $"selector: '{CacheInfo.CacheSelector}', key: '{CacheInfo.CacheKey}', path: '{fileName}', " + + $"size: {fileSize} bytes, translated functions: {GetEntriesCount()})."); return true; } @@ -505,7 +513,11 @@ namespace ARMeilleure.Translation.PTC if (fileSize != 0L) { - Logger.Info?.Print(LogClass.Ptc, $"Saved Translation Cache (size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); + Logger.Info?.Print( + LogClass.Ptc, + $"Saved Translation Cache (pid: {CacheInfo.ProcessId}, title: {CacheInfo.TitleIdText}, version: '{CacheInfo.DisplayVersion}', " + + $"kind: {CacheInfo.ProcessKind}, selector: '{CacheInfo.CacheSelector}', key: '{CacheInfo.CacheKey}', " + + $"path: '{fileName}', size: {fileSize} bytes, translated functions: {translatedFuncsCount})."); } } diff --git a/src/ARMeilleure/Translation/PTC/PtcCacheInfo.cs b/src/ARMeilleure/Translation/PTC/PtcCacheInfo.cs new file mode 100644 index 000000000..9c0c2969a --- /dev/null +++ b/src/ARMeilleure/Translation/PTC/PtcCacheInfo.cs @@ -0,0 +1,37 @@ +namespace ARMeilleure.Translation.PTC +{ + public readonly struct PtcCacheInfo + { + public const string TitleIdTextDefault = "0000000000000000"; + public const string ApplicationIdTextDefault = "0000000000000000"; + public const string DisplayVersionDefault = "0"; + + public ulong ProcessId { get; } + public string TitleIdText { get; } + public string ApplicationIdText { get; } + public byte ProgramIndex { get; } + public string DisplayVersion { get; } + public string ProcessKind { get; } + public string CacheSelector { get; } + + public string CacheKey => $"{DisplayVersion}-{CacheSelector}"; + + public PtcCacheInfo( + ulong processId, + string titleIdText, + string applicationIdText, + byte programIndex, + string displayVersion, + string processKind, + string cacheSelector) + { + ProcessId = processId; + TitleIdText = !string.IsNullOrEmpty(titleIdText) ? titleIdText : TitleIdTextDefault; + ApplicationIdText = !string.IsNullOrEmpty(applicationIdText) ? applicationIdText : ApplicationIdTextDefault; + ProgramIndex = programIndex; + DisplayVersion = !string.IsNullOrEmpty(displayVersion) ? displayVersion : DisplayVersionDefault; + ProcessKind = processKind ?? string.Empty; + CacheSelector = string.IsNullOrEmpty(cacheSelector) ? "default" : cacheSelector; + } + } +} diff --git a/src/ARMeilleure/Translation/PTC/PtcProfiler.cs b/src/ARMeilleure/Translation/PTC/PtcProfiler.cs index c46d81cf5..5e7c857ba 100644 --- a/src/ARMeilleure/Translation/PTC/PtcProfiler.cs +++ b/src/ARMeilleure/Translation/PTC/PtcProfiler.cs @@ -23,7 +23,7 @@ namespace ARMeilleure.Translation.PTC { private const string OuterHeaderMagicString = "Pohd\0\0\0\0"; - private const uint InternalVersion = 6698; //! Not to be incremented manually for each change to the ARMeilleure project. + private const uint InternalVersion = 7031; //! Not to be incremented manually for each change to the ARMeilleure project. private static readonly uint[] _migrateInternalVersions = [ @@ -254,7 +254,12 @@ namespace ARMeilleure.Translation.PTC long fileSize = new FileInfo(fileName).Length; - Logger.Info?.Print(LogClass.Ptc, $"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} (size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count})."); + Logger.Info?.Print( + LogClass.Ptc, + $"{(isBackup ? "Loaded Backup Profiling Info" : "Loaded Profiling Info")} " + + $"(pid: {_ptc.CacheInfo.ProcessId}, title: {_ptc.CacheInfo.TitleIdText}, version: '{_ptc.CacheInfo.DisplayVersion}', " + + $"kind: {_ptc.CacheInfo.ProcessKind}, selector: '{_ptc.CacheInfo.CacheSelector}', key: '{_ptc.CacheInfo.CacheKey}', " + + $"path: '{fileName}', size: {fileSize} bytes, profiled functions: {ProfiledFuncs.Count})."); return true; } @@ -375,7 +380,11 @@ namespace ARMeilleure.Translation.PTC if (fileSize != 0L) { - Logger.Info?.Print(LogClass.Ptc, $"Saved Profiling Info (size: {fileSize} bytes, profiled functions: {profiledFuncsCount})."); + Logger.Info?.Print( + LogClass.Ptc, + $"Saved Profiling Info (pid: {_ptc.CacheInfo.ProcessId}, title: {_ptc.CacheInfo.TitleIdText}, version: '{_ptc.CacheInfo.DisplayVersion}', " + + $"kind: {_ptc.CacheInfo.ProcessKind}, selector: '{_ptc.CacheInfo.CacheSelector}', key: '{_ptc.CacheInfo.CacheKey}', " + + $"path: '{fileName}', size: {fileSize} bytes, profiled functions: {profiledFuncsCount})."); } } diff --git a/src/ARMeilleure/Translation/Translator.cs b/src/ARMeilleure/Translation/Translator.cs index f96e71199..b4e5952cf 100644 --- a/src/ARMeilleure/Translation/Translator.cs +++ b/src/ARMeilleure/Translation/Translator.cs @@ -57,9 +57,9 @@ namespace ARMeilleure.Translation FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub; } - public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector) + public IPtcLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled) { - _ptc.Initialize(titleIdText, displayVersion, enabled, Memory.Type, cacheSelector); + _ptc.Initialize(cacheInfo, enabled, Memory.Type); return _ptc; } diff --git a/src/Ryujinx.Cpu/AppleHv/HvCpuContext.cs b/src/Ryujinx.Cpu/AppleHv/HvCpuContext.cs index 784949441..d485b0f42 100644 --- a/src/Ryujinx.Cpu/AppleHv/HvCpuContext.cs +++ b/src/Ryujinx.Cpu/AppleHv/HvCpuContext.cs @@ -1,4 +1,5 @@ using ARMeilleure.Memory; +using ARMeilleure.Translation.PTC; using System.Runtime.Versioning; namespace Ryujinx.Cpu.AppleHv @@ -32,7 +33,7 @@ namespace Ryujinx.Cpu.AppleHv { } - public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector) + public IDiskCacheLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled) { return new DummyDiskCacheLoadState(); } diff --git a/src/Ryujinx.Cpu/ICpuContext.cs b/src/Ryujinx.Cpu/ICpuContext.cs index 1fb3b674d..d943da9d7 100644 --- a/src/Ryujinx.Cpu/ICpuContext.cs +++ b/src/Ryujinx.Cpu/ICpuContext.cs @@ -1,4 +1,5 @@ using System; +using ARMeilleure.Translation.PTC; namespace Ryujinx.Cpu { @@ -44,11 +45,10 @@ namespace Ryujinx.Cpu /// /// If the execution engine is recompiling guest code, this can be used to load cached code from disk. /// - /// Title ID of the application in padded hex form - /// Version of the application + /// Identity and selector for the process-owned disk cache /// True if the cache should be loaded from disk if it exists, false otherwise /// Disk cache load progress reporter and manager - IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector); + IDiskCacheLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled); /// /// Indicates that code has been loaded into guest memory, and that it might be executed in the future. diff --git a/src/Ryujinx.Cpu/Jit/JitCpuContext.cs b/src/Ryujinx.Cpu/Jit/JitCpuContext.cs index a29def8e8..b248f9fe2 100644 --- a/src/Ryujinx.Cpu/Jit/JitCpuContext.cs +++ b/src/Ryujinx.Cpu/Jit/JitCpuContext.cs @@ -1,6 +1,7 @@ using ARMeilleure.Common; using ARMeilleure.Memory; using ARMeilleure.Translation; +using ARMeilleure.Translation.PTC; using Ryujinx.Cpu.Signal; namespace Ryujinx.Cpu.Jit @@ -49,9 +50,9 @@ namespace Ryujinx.Cpu.Jit } /// - public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector) + public IDiskCacheLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled) { - return new JitDiskCacheLoadState(_translator.LoadDiskCache(titleIdText, displayVersion, enabled, cacheSelector)); + return new JitDiskCacheLoadState(_translator.LoadDiskCache(cacheInfo, enabled)); } /// diff --git a/src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs b/src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs index cd38706a0..4745d4052 100644 --- a/src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs +++ b/src/Ryujinx.Cpu/LightningJit/LightningJitCpuContext.cs @@ -1,5 +1,6 @@ using ARMeilleure.Common; using ARMeilleure.Memory; +using ARMeilleure.Translation.PTC; using Ryujinx.Cpu.Jit; using Ryujinx.Cpu.LightningJit.State; @@ -51,7 +52,7 @@ namespace Ryujinx.Cpu.LightningJit } /// - public IDiskCacheLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled, string cacheSelector) + public IDiskCacheLoadState LoadDiskCache(PtcCacheInfo cacheInfo, bool enabled) { return new DummyDiskCacheLoadState(); } diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContext.cs b/src/Ryujinx.HLE/HOS/ArmProcessContext.cs index 9ce57a2a7..2ccba835c 100644 --- a/src/Ryujinx.HLE/HOS/ArmProcessContext.cs +++ b/src/Ryujinx.HLE/HOS/ArmProcessContext.cs @@ -1,4 +1,5 @@ using ARMeilleure.Memory; +using ARMeilleure.Translation.PTC; using Ryujinx.Cpu; using Ryujinx.Graphics.Gpu; using Ryujinx.HLE.HOS.Kernel.Process; @@ -9,12 +10,10 @@ namespace Ryujinx.HLE.HOS interface IArmProcessContext : IProcessContext { IDiskCacheLoadState Initialize( - string titleIdText, - string displayVersion, + PtcCacheInfo cacheInfo, bool diskCacheEnabled, ulong codeAddress, - ulong codeSize, - string cacheSelector); + ulong codeSize); } class ArmProcessContext : IArmProcessContext where T : class, IVirtualMemoryManagerTracked, IMemoryManager @@ -67,15 +66,13 @@ namespace Ryujinx.HLE.HOS } public IDiskCacheLoadState Initialize( - string titleIdText, - string displayVersion, + PtcCacheInfo cacheInfo, bool diskCacheEnabled, ulong codeAddress, - ulong codeSize, - string cacheSelector) + ulong codeSize) { _cpuContext.PrepareCodeRange(codeAddress, codeSize); - return _cpuContext.LoadDiskCache(titleIdText, displayVersion, diskCacheEnabled, cacheSelector); + return _cpuContext.LoadDiskCache(cacheInfo, diskCacheEnabled); } public void InvalidateCacheRegion(ulong address, ulong size) diff --git a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs index ecb3b4dd8..839a9167e 100644 --- a/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs +++ b/src/Ryujinx.HLE/HOS/ArmProcessContextFactory.cs @@ -1,3 +1,4 @@ +using ARMeilleure.Translation.PTC; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Cpu; @@ -8,6 +9,7 @@ using Ryujinx.Cpu.Nce; using Ryujinx.Graphics.Gpu; using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel.Process; +using Ryujinx.HLE.Loaders.Processes; using Ryujinx.Memory; using System; using System.Runtime.InteropServices; @@ -18,8 +20,10 @@ namespace Ryujinx.HLE.HOS { private readonly ITickSource _tickSource; private readonly GpuContext _gpu; - private readonly string _titleIdText; + private readonly ulong _programId; + private readonly byte _programIndex; private readonly string _displayVersion; + private readonly ProcessKind _processKind; private readonly bool _diskCacheEnabled; private readonly string _diskCacheSelector; private readonly ulong _codeAddress; @@ -30,8 +34,10 @@ namespace Ryujinx.HLE.HOS public ArmProcessContextFactory( ITickSource tickSource, GpuContext gpu, - string titleIdText, + ulong programId, + byte programIndex, string displayVersion, + ProcessKind processKind, bool diskCacheEnabled, string diskCacheSelector, ulong codeAddress, @@ -39,8 +45,10 @@ namespace Ryujinx.HLE.HOS { _tickSource = tickSource; _gpu = gpu; - _titleIdText = titleIdText; + _programId = programId; + _programIndex = programIndex; _displayVersion = displayVersion; + _processKind = processKind; _diskCacheEnabled = diskCacheEnabled; _diskCacheSelector = diskCacheSelector; _codeAddress = codeAddress; @@ -160,8 +168,18 @@ namespace Ryujinx.HLE.HOS } string cacheSelector = _diskCacheSelector ?? "default"; + string programIdText = _programId == 0 ? string.Empty : $"{_programId:x16}"; + string applicationIdText = _programId == 0 ? string.Empty : $"{_programId & ~0xFul:x16}"; + PtcCacheInfo cacheInfo = new( + pid, + programIdText, + applicationIdText, + _programIndex, + _displayVersion, + _processKind.ToString(), + cacheSelector); - DiskCacheLoadState = processContext.Initialize(_titleIdText, _displayVersion, _diskCacheEnabled, _codeAddress, _codeSize, cacheSelector); + DiskCacheLoadState = processContext.Initialize(cacheInfo, _diskCacheEnabled, _codeAddress, _codeSize); return processContext; } diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs index 498b6bb7c..c1d70e5cb 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessLoaderHelper.cs @@ -183,8 +183,10 @@ namespace Ryujinx.HLE.Loaders.Processes ArmProcessContextFactory processContextFactory = new( context.Device.System.TickSource, context.Device.Gpu, - string.Empty, - string.Empty, + kip.ProgramId, + 0, + kip.Version.ToString(), + ProcessResult.GetProcessKind(kip.ProgramId), false, null, codeAddress, @@ -392,8 +394,10 @@ namespace Ryujinx.HLE.Loaders.Processes ArmProcessContextFactory processContextFactory = new( context.Device.System.TickSource, context.Device.Gpu, - $"{programId:x16}", + programId, + programIndex, displayVersion, + ProcessResult.GetProcessKind(programId), diskCacheEnabled, diskCacheSelector, codeStart, diff --git a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs index 279268de6..53fdae8e0 100644 --- a/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs +++ b/src/Ryujinx.HLE/Loaders/Processes/ProcessResult.cs @@ -87,7 +87,7 @@ namespace Ryujinx.HLE.Loaders.Processes AllowCodeMemoryForJit = allowCodeMemoryForJit; } - private static ProcessKind GetProcessKind(ulong programId) + internal static ProcessKind GetProcessKind(ulong programId) { if (programId == 0) {