Compare commits

...

24 Commits

Author SHA1 Message Date
Evan Husted
ff05e03cc8 misc: chore: Remove unused using directives across entire solution. 2025-01-30 20:27:17 -06:00
Evan Husted
e18c6d90c4 misc: chore: Strip extension in GetNameForApplicationId instead of requiring the caller to do it 2025-01-30 20:22:11 -06:00
Evan Husted
9075a3960b misc: chore: Prefix OS, CPU, and RAM lines with the same method name as other system info prints. 2025-01-30 20:18:26 -06:00
Evan Husted
3cf54987d2 misc: chore: More ObservableProperty usage 2025-01-30 20:16:30 -06:00
Evan Husted
9c12f52805 UI: Pretty Atmosphère mod names (#601)
Changes the mods from the Atmosphère folder to show a pretty name
instead of just the name of the folder they're in, because those names
are always just a title ID.

NOTE: The DLC names are from the file names, not retrieved from the
content file itself like the main applications.
2025-01-30 17:41:25 -06:00
Otozinclus
059fc83d4d Add more games to Metal Auto list (#592)
ARMS: Tested every character and every Map, played a cup as well. It
works flawless in my testing. (If it freezes, that is caused by the
Hypervisor, not Metal. You need to disable the Hypervisor for this game)

Luigi's Mansion 2 HD: I tested every world a bit and had no issue. Isaac
said he specifically worked on it as well

Following games were flawless in my testing, but I only tested earlier
parts of the game so far, a late game part might have an issue,
therefore I will further test these in the future:

- Astral Chain
- Bayonetta Origins
- New Pokemon Snap
2025-01-30 17:22:00 -06:00
Evan Husted
04ce7fb764 misc: chore: [ci skip] VSync progression as an extension 2025-01-30 16:54:05 -06:00
Evan Husted
359852b5c0 UI: Change order of VSync mode changing
VSync -> VSync Off -> Custom
is now
VSync -> Custom -> VSync Off

Note that Custom only appears if it's enabled in settings. This has no change if you aren't using custom VSync.
2025-01-30 16:47:40 -06:00
Evan Husted
796674d9cf UI: Allow more freedom changing the Speed value & clamp the visible number to a sane amount of trailing digits 2025-01-30 03:30:50 -06:00
Evan Husted
4efe24a3bc misc: chore: [ci skip] forgot to make that a locale entry 2025-01-30 03:21:42 -06:00
Evan Husted
1a42d1396c UI: Rainbow cycling speed settings
Note: this setting is global, even though it appears in the settings for the individual gamepad. This is simply for consistency; you access all the rainbow stuff in one place.
2025-01-30 03:18:34 -06:00
Evan Husted
11f29361eb misc: chore: [ci skip] Log errors from TaskScheduler.UnobservedTaskException 2025-01-29 21:07:43 -06:00
Evan Husted
71d8cfd232 misc: chore: Pass rainbow color by reference in the event instead of passing around a packed int. 2025-01-29 20:51:55 -06:00
Evan Husted
023bd5f00f UI: Enable Rainbow cycling in the Settings window 2025-01-29 20:27:01 -06:00
Evan Husted
0ed7fd14ba misc: chore: [ci skip] Collapse CheckboxMenuItemStyle into the main Styles.xaml. 2025-01-29 18:59:17 -06:00
Evan Husted
a624fe64b9 UI: Scanning for mods on DLC content 2025-01-29 13:33:34 -06:00
Vladimir Sokolov
e02ef52069 Added --backend-threading arg for CommandLineState (#599)
Added the `--backend-threading` arg so that you can launch games via
a shortcut with modifications to this setting.
2025-01-29 12:49:36 -06:00
Evan Husted
707c9ef748 misc: chore: slightly improve PTC init log line 2025-01-28 22:25:01 -06:00
Evan Husted
2acc43e968 misc: chore: Use string.Empty in more places where it's snuck back 2025-01-28 22:17:11 -06:00
Evan Husted
191e158289 misc: chore: Use static instances of converters instead of using control resources 2025-01-28 22:11:48 -06:00
Evan Husted
a469f3d710 UI: Remove empty StackPanel in UserSelectorDialog 2025-01-28 21:47:29 -06:00
shinyoyo
1b3656bca9 LED Color & LED settings header (zh_CN) (#590) 2025-01-28 21:29:06 -06:00
Evan Husted
502ce98b3a UI: [ci skip] Make cheat window larger by default 2025-01-28 21:27:51 -06:00
LotP1
7085bafa60 PPTC Profiles (#370)
Added functionality that allows ExeFS mods to compile to their own PPTC
Profile and therefore store PTC data between sessions.
The feature calculates the hash of the currently loaded ExeFS mods and
stores the PPTC data in a profile that matches said hash, so you can
have multiple ExeFS loadouts without causing issues. This includes
different versions of the same mod as their hashes will be different.
Using this PR should be seamless as the JIT Sparse PR already laid the
groundwork for PPTC Profiles and this PR just allows ExeFS mods to load
and store their own profiles besides the `default` profile.

 **WARNING!** 
**This will update your PPTC profile version, which means the
PPTC profile will be invalidated if you try to run a PR/Build/Branch
that does not include this change!**
**This is only relevant for the default PPTC Profile, as any other profiles do not exist to older versions!**
2025-01-28 20:36:58 -06:00
196 changed files with 820 additions and 1297 deletions

View File

@@ -1,7 +1,6 @@
using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Linking;
using ARMeilleure.CodeGen.Unwinding; using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Translation.Cache; using ARMeilleure.Translation.Cache;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ARMeilleure.CodeGen namespace ARMeilleure.CodeGen

View File

@@ -1,4 +1,3 @@
using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -1,6 +1,5 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

View File

@@ -1,7 +1,6 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using Ryujinx.Common.Memory.PartialUnmaps; using Ryujinx.Common.Memory.PartialUnmaps;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

View File

@@ -1,5 +1,4 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System;
namespace ARMeilleure.State namespace ARMeilleure.State
{ {

View File

@@ -6,7 +6,6 @@ using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

View File

@@ -1,5 +1,4 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ARMeilleure.Translation.Cache namespace ARMeilleure.Translation.Cache

View File

@@ -1,5 +1,3 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
class DelegateInfo class DelegateInfo

View File

@@ -1,5 +1,3 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
delegate void DispatcherFunction(nint nativeContext, ulong startAddress); delegate void DispatcherFunction(nint nativeContext, ulong startAddress);

View File

@@ -1,5 +1,3 @@
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {
delegate ulong GuestFunction(nint nativeContextPtr); delegate ulong GuestFunction(nint nativeContextPtr);

View File

@@ -3,6 +3,8 @@ using ARMeilleure.CodeGen.Linking;
using ARMeilleure.CodeGen.Unwinding; using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.Common; using ARMeilleure.Common;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State;
using Humanizer;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
@@ -30,8 +32,8 @@ namespace ARMeilleure.Translation.PTC
{ {
private const string OuterHeaderMagicString = "PTCohd\0\0"; private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\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 = 7007; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";
@@ -184,6 +186,36 @@ namespace ARMeilleure.Translation.PTC
InitializeCarriers(); InitializeCarriers();
} }
private bool ContainsBlacklistedFunctions()
{
List<ulong> blacklist = Profiler.GetBlacklistedFunctions();
bool containsBlacklistedFunctions = false;
_infosStream.Seek(0L, SeekOrigin.Begin);
bool foundBadFunction = false;
for (int index = 0; index < GetEntriesCount(); index++)
{
InfoEntry infoEntry = DeserializeStructure<InfoEntry>(_infosStream);
foreach (ulong address in blacklist)
{
if (infoEntry.Address == address)
{
containsBlacklistedFunctions = true;
Logger.Warning?.Print(LogClass.Ptc, "PPTC cache invalidated: Found blacklisted functions in PPTC cache");
foundBadFunction = true;
break;
}
}
if (foundBadFunction)
{
break;
}
}
return containsBlacklistedFunctions;
}
private void PreLoad() private void PreLoad()
{ {
string fileNameActual = $"{CachePathActual}.cache"; string fileNameActual = $"{CachePathActual}.cache";
@@ -532,7 +564,7 @@ namespace ARMeilleure.Translation.PTC
public void LoadTranslations(Translator translator) public void LoadTranslations(Translator translator)
{ {
if (AreCarriersEmpty()) if (AreCarriersEmpty() || ContainsBlacklistedFunctions())
{ {
return; return;
} }
@@ -835,10 +867,18 @@ namespace ARMeilleure.Translation.PTC
while (profiledFuncsToTranslate.TryDequeue(out (ulong address, PtcProfiler.FuncProfile funcProfile) item)) while (profiledFuncsToTranslate.TryDequeue(out (ulong address, PtcProfiler.FuncProfile funcProfile) item))
{ {
ulong address = item.address; ulong address = item.address;
ExecutionMode executionMode = item.funcProfile.Mode;
bool highCq = item.funcProfile.HighCq;
Debug.Assert(Profiler.IsAddressInStaticCodeRange(address)); Debug.Assert(Profiler.IsAddressInStaticCodeRange(address));
TranslatedFunction func = translator.Translate(address, item.funcProfile.Mode, item.funcProfile.HighCq); TranslatedFunction func = translator.Translate(address, executionMode, highCq);
if (func == null)
{
Profiler.UpdateEntry(address, executionMode, true, true);
continue;
}
bool isAddressUnique = translator.Functions.TryAdd(address, func.GuestSize, func); bool isAddressUnique = translator.Functions.TryAdd(address, func.GuestSize, func);
@@ -884,8 +924,11 @@ namespace ARMeilleure.Translation.PTC
sw.Stop(); sw.Stop();
PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount); PtcStateChanged?.Invoke(PtcLoadingState.Loaded, _translateCount, _translateTotalCount);
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism} in {sw.Elapsed.TotalSeconds} s"); Logger.Info?.Print(LogClass.Ptc,
$"{_translateCount} of {_translateTotalCount} functions translated in {sw.Elapsed.TotalSeconds} seconds " +
$"| {"function".ToQuantity(_translateTotalCount - _translateCount)} blacklisted " +
$"| Thread count: {degreeOfParallelism}");
Thread preSaveThread = new(PreSave) Thread preSaveThread = new(PreSave)
{ {

View File

@@ -24,11 +24,12 @@ namespace ARMeilleure.Translation.PTC
{ {
private const string OuterHeaderMagicString = "Pohd\0\0\0\0"; private const string OuterHeaderMagicString = "Pohd\0\0\0\0";
private const uint InternalVersion = 5518; //! Not to be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 7007; //! Not to be incremented manually for each change to the ARMeilleure project.
private static readonly uint[] _migrateInternalVersions = private static readonly uint[] _migrateInternalVersions =
[ [
1866 1866,
5518,
]; ];
private const int SaveInterval = 30; // Seconds. private const int SaveInterval = 30; // Seconds.
@@ -77,20 +78,30 @@ namespace ARMeilleure.Translation.PTC
private void TimerElapsed(object _, ElapsedEventArgs __) private void TimerElapsed(object _, ElapsedEventArgs __)
=> new Thread(PreSave) { Name = "Ptc.DiskWriter" }.Start(); => new Thread(PreSave) { Name = "Ptc.DiskWriter" }.Start();
public void AddEntry(ulong address, ExecutionMode mode, bool highCq) public void AddEntry(ulong address, ExecutionMode mode, bool highCq, bool blacklist = false)
{ {
if (IsAddressInStaticCodeRange(address)) if (IsAddressInStaticCodeRange(address))
{ {
Debug.Assert(!highCq); Debug.Assert(!highCq);
lock (_lock) if (blacklist)
{ {
ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false)); lock (_lock)
{
ProfiledFuncs[address] = new FuncProfile(mode, highCq: false, true);
}
}
else
{
lock (_lock)
{
ProfiledFuncs.TryAdd(address, new FuncProfile(mode, highCq: false, false));
}
} }
} }
} }
public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq) public void UpdateEntry(ulong address, ExecutionMode mode, bool highCq, bool? blacklist = null)
{ {
if (IsAddressInStaticCodeRange(address)) if (IsAddressInStaticCodeRange(address))
{ {
@@ -100,7 +111,7 @@ namespace ARMeilleure.Translation.PTC
{ {
Debug.Assert(ProfiledFuncs.ContainsKey(address)); Debug.Assert(ProfiledFuncs.ContainsKey(address));
ProfiledFuncs[address] = new FuncProfile(mode, highCq: true); ProfiledFuncs[address] = new FuncProfile(mode, highCq: true, blacklist ?? ProfiledFuncs[address].Blacklist);
} }
} }
} }
@@ -116,7 +127,7 @@ namespace ARMeilleure.Translation.PTC
foreach (KeyValuePair<ulong, FuncProfile> profiledFunc in ProfiledFuncs) foreach (KeyValuePair<ulong, FuncProfile> profiledFunc in ProfiledFuncs)
{ {
if (!funcs.ContainsKey(profiledFunc.Key)) if (!funcs.ContainsKey(profiledFunc.Key) && !profiledFunc.Value.Blacklist)
{ {
profiledFuncsToTranslate.Enqueue((profiledFunc.Key, profiledFunc.Value)); profiledFuncsToTranslate.Enqueue((profiledFunc.Key, profiledFunc.Value));
} }
@@ -131,6 +142,24 @@ namespace ARMeilleure.Translation.PTC
ProfiledFuncs.TrimExcess(); ProfiledFuncs.TrimExcess();
} }
public List<ulong> GetBlacklistedFunctions()
{
List<ulong> funcs = new List<ulong>();
foreach (var profiledFunc in ProfiledFuncs)
{
if (profiledFunc.Value.Blacklist)
{
if (!funcs.Contains(profiledFunc.Key))
{
funcs.Add(profiledFunc.Key);
}
}
}
return funcs;
}
public void PreLoad() public void PreLoad()
{ {
_lastHash = default; _lastHash = default;
@@ -221,13 +250,18 @@ namespace ARMeilleure.Translation.PTC
return false; return false;
} }
Func<ulong, FuncProfile, (ulong, FuncProfile)> migrateEntryFunc = null;
switch (outerHeader.InfoFileVersion) switch (outerHeader.InfoFileVersion)
{ {
case InternalVersion: case InternalVersion:
ProfiledFuncs = Deserialize(stream); ProfiledFuncs = Deserialize(stream);
break; break;
case 1866: case 1866:
ProfiledFuncs = Deserialize(stream, (address, profile) => (address + 0x500000UL, profile)); migrateEntryFunc = (address, profile) => (address + 0x500000UL, profile);
goto case 5518;
case 5518:
ProfiledFuncs = DeserializeAddBlacklist(stream, migrateEntryFunc);
break; break;
default: default:
Logger.Error?.Print(LogClass.Ptc, $"No migration path for {nameof(outerHeader.InfoFileVersion)} '{outerHeader.InfoFileVersion}'. Discarding cache."); Logger.Error?.Print(LogClass.Ptc, $"No migration path for {nameof(outerHeader.InfoFileVersion)} '{outerHeader.InfoFileVersion}'. Discarding cache.");
@@ -257,6 +291,16 @@ namespace ARMeilleure.Translation.PTC
return DeserializeDictionary<ulong, FuncProfile>(stream, DeserializeStructure<FuncProfile>); return DeserializeDictionary<ulong, FuncProfile>(stream, DeserializeStructure<FuncProfile>);
} }
private static Dictionary<ulong, FuncProfile> DeserializeAddBlacklist(Stream stream, Func<ulong, FuncProfile, (ulong, FuncProfile)> migrateEntryFunc = null)
{
if (migrateEntryFunc != null)
{
return DeserializeAndUpdateDictionary(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure<FuncProfilePreBlacklist>(stream)); }, migrateEntryFunc);
}
return DeserializeDictionary<ulong, FuncProfile>(stream, (Stream stream) => { return new FuncProfile(DeserializeStructure<FuncProfilePreBlacklist>(stream)); });
}
private static ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream) private static ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
{ {
return new(memoryStream.GetBuffer(), (int)memoryStream.Position, (int)memoryStream.Length - (int)memoryStream.Position); return new(memoryStream.GetBuffer(), (int)memoryStream.Position, (int)memoryStream.Length - (int)memoryStream.Position);
@@ -388,13 +432,35 @@ namespace ARMeilleure.Translation.PTC
} }
} }
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)] [StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 6*/)]
public struct FuncProfile public struct FuncProfile
{ {
public ExecutionMode Mode; public ExecutionMode Mode;
public bool HighCq; public bool HighCq;
public bool Blacklist;
public FuncProfile(ExecutionMode mode, bool highCq) public FuncProfile(ExecutionMode mode, bool highCq, bool blacklist)
{
Mode = mode;
HighCq = highCq;
Blacklist = blacklist;
}
public FuncProfile(FuncProfilePreBlacklist fp)
{
Mode = fp.Mode;
HighCq = fp.HighCq;
Blacklist = false;
}
}
[StructLayout(LayoutKind.Sequential, Pack = 1/*, Size = 5*/)]
public struct FuncProfilePreBlacklist
{
public ExecutionMode Mode;
public bool HighCq;
public FuncProfilePreBlacklist(ExecutionMode mode, bool highCq)
{ {
Mode = mode; Mode = mode;
HighCq = highCq; HighCq = highCq;

View File

@@ -1,5 +1,4 @@
using ARMeilleure.Common; using ARMeilleure.Common;
using System;
namespace ARMeilleure.Translation namespace ARMeilleure.Translation
{ {

View File

@@ -5,7 +5,6 @@ using ARMeilleure.Diagnostics;
using ARMeilleure.Instructions; using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.Signal;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation.Cache; using ARMeilleure.Translation.Cache;
using ARMeilleure.Translation.PTC; using ARMeilleure.Translation.PTC;
@@ -249,6 +248,11 @@ namespace ARMeilleure.Translation
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter); ControlFlowGraph cfg = EmitAndGetCFG(context, blocks, out Range funcRange, out Counter<uint> counter);
if (cfg == null)
{
return null;
}
ulong funcSize = funcRange.End - funcRange.Start; ulong funcSize = funcRange.End - funcRange.Start;
Logger.EndPass(PassName.Translation, cfg); Logger.EndPass(PassName.Translation, cfg);
@@ -407,6 +411,11 @@ namespace ARMeilleure.Translation
if (opCode.Instruction.Emitter != null) if (opCode.Instruction.Emitter != null)
{ {
opCode.Instruction.Emitter(context); opCode.Instruction.Emitter(context);
if (opCode.Instruction.Name == InstName.Und && blkIndex == 0)
{
range = new Range(rangeStart, rangeEnd);
return null;
}
} }
else else
{ {

View File

@@ -4,7 +4,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation.Cache; using ARMeilleure.Translation.Cache;
using System; using System;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

View File

@@ -4,7 +4,6 @@ using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Threading; using System.Threading;

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using static Ryujinx.Audio.Backends.SoundIo.Native.SoundIo; using static Ryujinx.Audio.Backends.SoundIo.Native.SoundIo;

View File

@@ -4,7 +4,6 @@ using Ryujinx.Audio.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
using System.Buffers;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;

View File

@@ -1,7 +1,6 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System; using System;
using System.Buffers;
using System.Threading; using System.Threading;
namespace Ryujinx.Audio.Backends.Common namespace Ryujinx.Audio.Backends.Common

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using CpuAddress = System.UInt64; using CpuAddress = System.UInt64;
using DspAddress = System.UInt64; using DspAddress = System.UInt64;

View File

@@ -6,4 +6,16 @@ namespace Ryujinx.Common.Configuration
Unbounded, Unbounded,
Custom Custom
} }
public static class VSyncModeExtensions
{
public static VSyncMode Next(this VSyncMode vsync, bool customEnabled = false) =>
vsync switch
{
VSyncMode.Switch => customEnabled ? VSyncMode.Custom : VSyncMode.Unbounded,
VSyncMode.Unbounded => VSyncMode.Switch,
VSyncMode.Custom => VSyncMode.Unbounded,
_ => VSyncMode.Switch
};
}
} }

View File

@@ -1,5 +1,4 @@
using Microsoft.Win32; using Microsoft.Win32;
using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using System; using System;
using System.Diagnostics; using System.Diagnostics;

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -0,0 +1,58 @@
using Gommon;
using System.Collections.Generic;
using System.Threading;
namespace Ryujinx.Common.Helper
{
public class RefEvent<T>
{
public delegate void Handler(ref T arg);
private readonly Lock _subLock = new();
private readonly List<Handler> _subscriptions = [];
public bool HasSubscribers
{
get
{
lock (_subLock)
return _subscriptions.Count != 0;
}
}
public IReadOnlyList<Handler> Subscriptions
{
get
{
lock (_subLock)
return _subscriptions;
}
}
public void Add(Handler subscriber)
{
Guard.Require(subscriber, nameof(subscriber));
lock (_subLock)
_subscriptions.Add(subscriber);
}
public void Remove(Handler subscriber)
{
Guard.Require(subscriber, nameof(subscriber));
lock (_subLock)
_subscriptions.Remove(subscriber);
}
public void Clear()
{
lock (_subLock)
_subscriptions.Clear();
}
public void Call(ref T arg)
{
foreach (Handler subscription in Subscriptions)
subscription(ref arg);
}
}
}

View File

@@ -3,7 +3,6 @@ using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using System; using System;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices;
namespace Ryujinx.Common namespace Ryujinx.Common
{ {
@@ -30,10 +29,11 @@ namespace Ryujinx.Common
public static readonly string[] GreatMetalTitles = public static readonly string[] GreatMetalTitles =
[ [
"010076f0049a2000", // Bayonetta "01009b500007c000", // ARMS
"0100a5c00d162000", // Cuphead "0100a5c00d162000", // Cuphead
"010023800d64a000", // Deltarune "010023800d64a000", // Deltarune
"01003a30012c0000", // LEGO City Undercover "01003a30012c0000", // LEGO City Undercover
"010048701995e000", // Luigi's Manion 2 HD
"010028600EBDA000", // Mario 3D World "010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe "0100152000022000", // Mario Kart 8 Deluxe
"010075a016a3a000", // Persona 4 Arena Ultimax "010075a016a3a000", // Persona 4 Arena Ultimax
@@ -48,10 +48,14 @@ namespace Ryujinx.Common
"01009bf0072d4000", // Captain Toad: Treasure Tracker "01009bf0072d4000", // Captain Toad: Treasure Tracker
"01009510001ca000", // Fast RMX "01009510001ca000", // Fast RMX
"01005CA01580E000", // Persona 5 Royale "01005CA01580E000", // Persona 5 Royale
"010015100b514000", // Super Mario Bros. Wonder
"0100000000010000", // Super Mario Odyssey "0100000000010000", // Super Mario Odyssey
//Isaac claims it has a issue in level 2, but I am not able to replicate it on my M3. More testing would be appreciated: // Further testing is appreciated, I did not test the entire game:
"010015100b514000", // Super Mario Bros. Wonder "01007300020fa000", // Astral Chain
"010076f0049a2000", // Bayonetta
"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
"0100f4300bf2c000", // New Pokemon Snap
]; ];
public static string GetDiscordGameAsset(string titleId) public static string GetDiscordGameAsset(string titleId)

View File

@@ -1,4 +1,5 @@
using Gommon; using Gommon;
using Ryujinx.Common.Helper;
using System; using System;
using System.Drawing; using System.Drawing;
using System.Threading; using System.Threading;
@@ -55,7 +56,7 @@ namespace Ryujinx.Common.Utilities
{ {
_color = HsbToRgb((_color.GetHue() + Speed) / 360); _color = HsbToRgb((_color.GetHue() + Speed) / 360);
_updatedHandler.Call(_color.ToArgb()); _updatedHandler.Call(ref _color);
} }
} }
@@ -67,13 +68,13 @@ namespace Ryujinx.Common.Utilities
_color = Color.Blue; _color = Color.Blue;
} }
public static event Action<int> Updated public static event RefEvent<Color>.Handler Updated
{ {
add => _updatedHandler.Add(value); add => _updatedHandler.Add(value);
remove => _updatedHandler.Remove(value); remove => _updatedHandler.Remove(value);
} }
private static readonly Event<int> _updatedHandler = new(); private static readonly RefEvent<Color> _updatedHandler = new();
private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1) private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1)
{ {

View File

@@ -1,6 +1,5 @@
using ARMeilleure.State; using ARMeilleure.State;
using Ryujinx.Memory; using Ryujinx.Memory;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -5,7 +5,6 @@ using Ryujinx.Memory.Tracking;
using System; using System;
using System.Buffers; using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -1,5 +1,4 @@
using Ryujinx.Memory; using Ryujinx.Memory;
using System;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading; using System.Threading;

View File

@@ -2,7 +2,6 @@ using ARMeilleure.Common;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using Ryujinx.Cpu.Signal; using Ryujinx.Cpu.Signal;
using Ryujinx.Memory;
namespace Ryujinx.Cpu.Jit namespace Ryujinx.Cpu.Jit
{ {

View File

@@ -5,7 +5,6 @@ using Ryujinx.Memory.Tracking;
using System; using System;
using System.Buffers; using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;

View File

@@ -8,7 +8,6 @@ using Ryujinx.Memory.Tracking;
using System; using System;
using System.Buffers; using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace Ryujinx.Cpu.Jit namespace Ryujinx.Cpu.Jit

View File

@@ -3,7 +3,6 @@ using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.Arm32; using Ryujinx.Cpu.LightningJit.Arm32;
using Ryujinx.Cpu.LightningJit.Arm64; using Ryujinx.Cpu.LightningJit.Arm64;
using Ryujinx.Cpu.LightningJit.State; using Ryujinx.Cpu.LightningJit.State;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Cpu.LightningJit namespace Ryujinx.Cpu.LightningJit

View File

@@ -2,7 +2,6 @@ using ARMeilleure.Common;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.CodeGen; using Ryujinx.Cpu.LightningJit.CodeGen;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Numerics; using System.Numerics;

View File

@@ -1,5 +1,4 @@
using Ryujinx.Cpu.LightningJit.CodeGen; using Ryujinx.Cpu.LightningJit.CodeGen;
using System;
using System.Diagnostics; using System.Diagnostics;
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64

View File

@@ -1,5 +1,3 @@
using Ryujinx.Cpu.LightningJit.CodeGen;
namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64 namespace Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64
{ {
static class InstEmitVfpMove static class InstEmitVfpMove

View File

@@ -1,5 +1,3 @@
using System.Diagnostics;
namespace Ryujinx.Cpu.LightningJit.Arm64 namespace Ryujinx.Cpu.LightningJit.Arm64
{ {
static class SysUtils static class SysUtils

View File

@@ -3,7 +3,6 @@ using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.CodeGen; using Ryujinx.Cpu.LightningJit.CodeGen;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using Ryujinx.Cpu.LightningJit.Graph; using Ryujinx.Cpu.LightningJit.Graph;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Numerics; using System.Numerics;

View File

@@ -1,5 +1,4 @@
using ARMeilleure.Memory; using ARMeilleure.Memory;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Cpu.LightningJit.Cache namespace Ryujinx.Cpu.LightningJit.Cache

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Cpu.LightningJit namespace Ryujinx.Cpu.LightningJit

View File

@@ -1,5 +1,3 @@
using System;
namespace Ryujinx.Cpu.LightningJit namespace Ryujinx.Cpu.LightningJit
{ {
class TranslatedFunction class TranslatedFunction

View File

@@ -5,7 +5,6 @@ using Ryujinx.Cpu.LightningJit.Cache;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64; using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using Ryujinx.Cpu.LightningJit.State; using Ryujinx.Cpu.LightningJit.State;
using Ryujinx.Cpu.Signal; using Ryujinx.Cpu.Signal;
using Ryujinx.Memory;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Cpu.Signal namespace Ryujinx.Cpu.Signal

View File

@@ -1,6 +1,4 @@
using Ryujinx.Common.Logging;
using System; using System;
using System.Threading;
namespace Ryujinx.Graphics.Device namespace Ryujinx.Graphics.Device
{ {

View File

@@ -1,6 +1,5 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Graphics.Gpu.Engine.Threed.Blender namespace Ryujinx.Graphics.Gpu.Engine.Threed.Blender

View File

@@ -1,4 +1,3 @@
using Ryujinx.Graphics.Device;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;

View File

@@ -4,7 +4,6 @@ using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Image namespace Ryujinx.Graphics.Gpu.Image

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Memory; using Ryujinx.Memory;
using Ryujinx.Memory.Range; using Ryujinx.Memory.Range;
using System; using System;

View File

@@ -7,7 +7,6 @@ using Ryujinx.Memory;
using Ryujinx.Memory.Range; using Ryujinx.Memory.Range;
using Ryujinx.Memory.Tracking; using Ryujinx.Memory.Tracking;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@@ -1,6 +1,5 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@@ -2,7 +2,6 @@ using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine; using Ryujinx.Graphics.Gpu.Engine;
using Ryujinx.Graphics.Gpu.Image; using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using System;
using System.Linq; using System.Linq;
namespace Ryujinx.Graphics.Gpu.Shader namespace Ryujinx.Graphics.Gpu.Shader

View File

@@ -1,4 +1,3 @@
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;

View File

@@ -1,7 +1,6 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using SharpMetal.Metal; using SharpMetal.Metal;
using System;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.Graphics.Metal namespace Ryujinx.Graphics.Metal

View File

@@ -76,7 +76,7 @@ namespace Ryujinx.Graphics.Metal
return model; return model;
} }
return ""; return string.Empty;
} }
} }
} }

View File

@@ -1,5 +1,3 @@
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {
struct AVCodec struct AVCodec

View File

@@ -1,5 +1,3 @@
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {
struct AVCodec501 struct AVCodec501

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {

View File

@@ -1,5 +1,3 @@
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {
struct FFCodec<T> where T : struct struct FFCodec<T> where T : struct

View File

@@ -1,5 +1,3 @@
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native namespace Ryujinx.Graphics.Nvdec.FFmpeg.Native
{ {
struct FFCodecLegacy<T> where T : struct struct FFCodecLegacy<T> where T : struct

View File

@@ -1,6 +1,5 @@
using Ryujinx.Graphics.Nvdec.FFmpeg.Native; using Ryujinx.Graphics.Nvdec.FFmpeg.Native;
using Ryujinx.Graphics.Video; using Ryujinx.Graphics.Video;
using System;
namespace Ryujinx.Graphics.Nvdec.FFmpeg namespace Ryujinx.Graphics.Nvdec.FFmpeg
{ {

View File

@@ -1,6 +1,5 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Graphics.Video; using Ryujinx.Graphics.Video;
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Nvdec.Vp9.Types namespace Ryujinx.Graphics.Nvdec.Vp9.Types

View File

@@ -2,7 +2,6 @@ using OpenTK.Graphics.OpenGL;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image; using Ryujinx.Graphics.OpenGL.Image;
using System;
using static Ryujinx.Graphics.OpenGL.Effects.ShaderHelper; using static Ryujinx.Graphics.OpenGL.Effects.ShaderHelper;
namespace Ryujinx.Graphics.OpenGL.Effects namespace Ryujinx.Graphics.OpenGL.Effects

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;

View File

@@ -1,4 +1,3 @@
using Ryujinx.Graphics.OpenGL.Helper;
using System; using System;
namespace Ryujinx.Graphics.OpenGL namespace Ryujinx.Graphics.OpenGL

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.StructuredIr; using Ryujinx.Graphics.Shader.StructuredIr;
using Ryujinx.Graphics.Shader.Translation; using Ryujinx.Graphics.Shader.Translation;
@@ -218,7 +217,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
foreach (MemoryDefinition memory in memories) foreach (MemoryDefinition memory in memories)
{ {
string arraySize = ""; string arraySize = string.Empty;
if ((memory.Type & AggregateType.Array) != 0) if ((memory.Type & AggregateType.Array) != 0)
{ {
arraySize = $"[{memory.ArrayLength}]"; arraySize = $"[{memory.ArrayLength}]";
@@ -240,7 +239,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
BufferDefinition buffer = buffers[i]; BufferDefinition buffer = buffers[i];
bool needsPadding = buffer.Layout == BufferLayout.Std140; bool needsPadding = buffer.Layout == BufferLayout.Std140;
string fsiSuffix = !constant && fsi ? " [[raster_order_group(0)]]" : ""; string fsiSuffix = !constant && fsi ? " [[raster_order_group(0)]]" : string.Empty;
bufferDec[i] = $"{addressSpace} {Defaults.StructPrefix}_{buffer.Name}* {buffer.Name}{fsiSuffix};"; bufferDec[i] = $"{addressSpace} {Defaults.StructPrefix}_{buffer.Name}* {buffer.Name}{fsiSuffix};";
@@ -257,7 +256,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
type &= ~AggregateType.Array; type &= ~AggregateType.Array;
string typeName = GetVarTypeName(type); string typeName = GetVarTypeName(type);
string arraySuffix = ""; string arraySuffix = string.Empty;
if (field.Type.HasFlag(AggregateType.Array)) if (field.Type.HasFlag(AggregateType.Array))
{ {
@@ -353,7 +352,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
imageTypeName = $"array<{imageTypeName}, {image.ArrayLength}>"; imageTypeName = $"array<{imageTypeName}, {image.ArrayLength}>";
} }
string fsiSuffix = fsi ? " [[raster_order_group(0)]]" : ""; string fsiSuffix = fsi ? " [[raster_order_group(0)]]" : string.Empty;
imageDec[i] = $"{imageTypeName} {image.Name}{fsiSuffix};"; imageDec[i] = $"{imageTypeName} {image.Name}{fsiSuffix};";
} }
@@ -454,7 +453,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
IoVariable.VertexIndex => "[[vertex_id]]", IoVariable.VertexIndex => "[[vertex_id]]",
// IoVariable.PointCoord => "[[point_coord]]", // IoVariable.PointCoord => "[[point_coord]]",
IoVariable.UserDefined => context.Definitions.Stage == ShaderStage.Fragment ? $"[[user(loc{ioDefinition.Location})]]" : $"[[attribute({ioDefinition.Location})]]", IoVariable.UserDefined => context.Definitions.Stage == ShaderStage.Fragment ? $"[[user(loc{ioDefinition.Location})]]" : $"[[attribute({ioDefinition.Location})]]",
_ => "" _ => string.Empty
}; };
context.AppendLine($"{type} {name} {iq}{suffix};"); context.AppendLine($"{type} {name} {iq}{suffix};");
@@ -545,7 +544,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
IoVariable.FragmentOutputColor => $"[[color({ioDefinition.Location})]]", IoVariable.FragmentOutputColor => $"[[color({ioDefinition.Location})]]",
IoVariable.FragmentOutputDepth => "[[depth(any)]]", IoVariable.FragmentOutputDepth => "[[depth(any)]]",
IoVariable.ClipDistance => $"[[clip_distance]][{Defaults.TotalClipDistances}]", IoVariable.ClipDistance => $"[[clip_distance]][{Defaults.TotalClipDistances}]",
_ => "" _ => string.Empty
}; };
context.AppendLine($"{type} {name} {suffix};"); context.AppendLine($"{type} {name} {suffix};");

View File

@@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
inputsCount--; inputsCount--;
} }
string fieldName = ""; string fieldName = string.Empty;
switch (storageKind) switch (storageKind)
{ {
case StorageKind.ConstantBuffer: case StorageKind.ConstantBuffer:
@@ -140,7 +140,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
} }
} }
varName += fieldName; varName += fieldName;
varName += fieldHasPadding ? ".x" : ""; varName += fieldHasPadding ? ".x" : string.Empty;
if (isStore) if (isStore)
{ {
@@ -434,7 +434,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
string prefix = intCoords ? "uint" : "float"; string prefix = intCoords ? "uint" : "float";
return prefix + (count > 1 ? count : "") + "(" + coords + ")"; return prefix + (count > 1 ? count : string.Empty) + "(" + coords + ")";
} }
Append(AssemblePVector(pCount)); Append(AssemblePVector(pCount));
@@ -504,7 +504,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
} }
texCallBuilder.Append(')'); texCallBuilder.Append(')');
texCallBuilder.Append(colorIsVector ? GetMaskMultiDest(texOp.Index) : ""); texCallBuilder.Append(colorIsVector ? GetMaskMultiDest(texOp.Index) : string.Empty);
return texCallBuilder.ToString(); return texCallBuilder.ToString();
} }
@@ -558,7 +558,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
{ {
if (mask == 0x0) if (mask == 0x0)
{ {
return ""; return string.Empty;
} }
string swizzle = "."; string swizzle = ".";

View File

@@ -15,7 +15,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl
if (parameters.Definitions.Stage is not (ShaderStage.Vertex or ShaderStage.Fragment or ShaderStage.Compute)) if (parameters.Definitions.Stage is not (ShaderStage.Vertex or ShaderStage.Fragment or ShaderStage.Compute))
{ {
Logger.Warning?.Print(LogClass.Gpu, $"Attempted to generate unsupported shader type {parameters.Definitions.Stage}!"); Logger.Warning?.Print(LogClass.Gpu, $"Attempted to generate unsupported shader type {parameters.Definitions.Stage}!");
return ""; return string.Empty;
} }
CodeGenContext context = new(info, parameters); CodeGenContext context = new(info, parameters);

View File

@@ -4,7 +4,6 @@ using Ryujinx.Graphics.Shader.Translation;
using Spv.Generator; using Spv.Generator;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using static Spv.Specification;
using Instruction = Spv.Generator.Instruction; using Instruction = Spv.Generator.Instruction;
namespace Ryujinx.Graphics.Shader.CodeGen.Spirv namespace Ryujinx.Graphics.Shader.CodeGen.Spirv

View File

@@ -199,7 +199,7 @@ namespace Ryujinx.Graphics.Shader
_ => "float" _ => "float"
}; };
return $"{typeName}<{format}{(image ? ", access::read_write" : "")}>"; return $"{typeName}<{format}{(image ? ", access::read_write" : string.Empty)}>";
} }
} }
} }

View File

@@ -1,5 +1,4 @@
using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.IntermediateRepresentation;
using Ryujinx.Graphics.Shader.Translation;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@@ -1,5 +1,3 @@
using System;
namespace Ryujinx.Graphics.Video namespace Ryujinx.Graphics.Video
{ {
public readonly record struct Plane(nint Pointer, int Length); public readonly record struct Plane(nint Pointer, int Length);

View File

@@ -3,7 +3,6 @@ using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@@ -11,7 +11,6 @@ using System.Runtime.InteropServices;
using BlendOp = Silk.NET.Vulkan.BlendOp; using BlendOp = Silk.NET.Vulkan.BlendOp;
using Buffer = Silk.NET.Vulkan.Buffer; using Buffer = Silk.NET.Vulkan.Buffer;
using CompareOp = Ryujinx.Graphics.GAL.CompareOp; using CompareOp = Ryujinx.Graphics.GAL.CompareOp;
using Format = Ryujinx.Graphics.GAL.Format;
using FrontFace = Ryujinx.Graphics.GAL.FrontFace; using FrontFace = Ryujinx.Graphics.GAL.FrontFace;
using IndexType = Ryujinx.Graphics.GAL.IndexType; using IndexType = Ryujinx.Graphics.GAL.IndexType;
using PolygonMode = Ryujinx.Graphics.GAL.PolygonMode; using PolygonMode = Ryujinx.Graphics.GAL.PolygonMode;

View File

@@ -1,5 +1,4 @@
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using VkFormat = Silk.NET.Vulkan.Format;
namespace Ryujinx.Graphics.Vulkan namespace Ryujinx.Graphics.Vulkan
{ {

View File

@@ -1,7 +1,5 @@
using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
namespace Ryujinx.Graphics.Vulkan namespace Ryujinx.Graphics.Vulkan

View File

@@ -2,7 +2,6 @@ using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Threading; using System.Threading;
namespace Ryujinx.Graphics.Vulkan.Queries namespace Ryujinx.Graphics.Vulkan.Queries

View File

@@ -2,8 +2,6 @@ using Ryujinx.Common.Memory;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Collections.Generic;
using Format = Ryujinx.Graphics.GAL.Format;
using VkFormat = Silk.NET.Vulkan.Format; using VkFormat = Silk.NET.Vulkan.Format;
namespace Ryujinx.Graphics.Vulkan namespace Ryujinx.Graphics.Vulkan

View File

@@ -1,6 +1,5 @@
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.Runtime.Serialization;
namespace Ryujinx.Graphics.Vulkan namespace Ryujinx.Graphics.Vulkan
{ {

View File

@@ -7,7 +7,6 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.Serialization;
using System.Text; using System.Text;
namespace Ryujinx.HLE.Exceptions namespace Ryujinx.HLE.Exceptions

View File

@@ -4,8 +4,6 @@ using Ryujinx.HLE.HOS.Applets.Cabinet;
using Ryujinx.HLE.HOS.Applets.Dummy; using Ryujinx.HLE.HOS.Applets.Dummy;
using Ryujinx.HLE.HOS.Applets.Error; using Ryujinx.HLE.HOS.Applets.Error;
using Ryujinx.HLE.HOS.Services.Am.AppletAE; using Ryujinx.HLE.HOS.Services.Am.AppletAE;
using System;
using System.Collections.Generic;
namespace Ryujinx.HLE.HOS.Applets namespace Ryujinx.HLE.HOS.Applets
{ {

View File

@@ -1,10 +1,8 @@
using Ryujinx.Common.Logging;
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Services.Am.AppletAE; using Ryujinx.HLE.HOS.Services.Am.AppletAE;
using System; using System;
using System.IO; using System.IO;
using System.Runtime.InteropServices;
namespace Ryujinx.HLE.HOS.Applets.Dummy namespace Ryujinx.HLE.HOS.Applets.Dummy
{ {
internal class DummyApplet : IApplet internal class DummyApplet : IApplet

View File

@@ -5,7 +5,6 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard namespace Ryujinx.HLE.HOS.Applets.SoftwareKeyboard

View File

@@ -20,6 +20,7 @@ namespace Ryujinx.HLE.HOS
private readonly string _titleIdText; private readonly string _titleIdText;
private readonly string _displayVersion; private readonly string _displayVersion;
private readonly bool _diskCacheEnabled; private readonly bool _diskCacheEnabled;
private readonly string _diskCacheSelector;
private readonly ulong _codeAddress; private readonly ulong _codeAddress;
private readonly ulong _codeSize; private readonly ulong _codeSize;
@@ -31,6 +32,7 @@ namespace Ryujinx.HLE.HOS
string titleIdText, string titleIdText,
string displayVersion, string displayVersion,
bool diskCacheEnabled, bool diskCacheEnabled,
string diskCacheSelector,
ulong codeAddress, ulong codeAddress,
ulong codeSize) ulong codeSize)
{ {
@@ -39,6 +41,7 @@ namespace Ryujinx.HLE.HOS
_titleIdText = titleIdText; _titleIdText = titleIdText;
_displayVersion = displayVersion; _displayVersion = displayVersion;
_diskCacheEnabled = diskCacheEnabled; _diskCacheEnabled = diskCacheEnabled;
_diskCacheSelector = diskCacheSelector;
_codeAddress = codeAddress; _codeAddress = codeAddress;
_codeSize = codeSize; _codeSize = codeSize;
} }
@@ -114,7 +117,7 @@ namespace Ryujinx.HLE.HOS
} }
} }
DiskCacheLoadState = processContext.Initialize(_titleIdText, _displayVersion, _diskCacheEnabled, _codeAddress, _codeSize, "default"); //Ready for exefs profiles DiskCacheLoadState = processContext.Initialize(_titleIdText, _displayVersion, _diskCacheEnabled, _codeAddress, _codeSize, _diskCacheSelector ?? "default");
return processContext; return processContext;
} }

View File

@@ -2,7 +2,6 @@ using Ryujinx.Common;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
namespace Ryujinx.HLE.HOS.Kernel.Common namespace Ryujinx.HLE.HOS.Kernel.Common
{ {

View File

@@ -6,6 +6,7 @@ using LibHac.Loader;
using LibHac.Tools.Fs; using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.RomFs; using LibHac.Tools.FsSystem.RomFs;
using LibHac.Util;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
@@ -19,6 +20,7 @@ using System.Collections.Specialized;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Security.Cryptography;
using LazyFile = Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.LazyFile; using LazyFile = Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy.LazyFile;
using Path = System.IO.Path; using Path = System.IO.Path;
@@ -294,7 +296,7 @@ namespace Ryujinx.HLE.HOS
AddModsFromDirectory(mods, applicationDir, modMetadata); AddModsFromDirectory(mods, applicationDir, modMetadata);
} }
public static void QueryContentsDir(ModCache mods, DirectoryInfo contentsDir, ulong applicationId) public static void QueryContentsDir(ModCache mods, DirectoryInfo contentsDir, ulong applicationId, ulong[] installedDlcs)
{ {
if (!contentsDir.Exists) if (!contentsDir.Exists)
{ {
@@ -309,6 +311,16 @@ namespace Ryujinx.HLE.HOS
{ {
QueryApplicationDir(mods, applicationDir, applicationId); QueryApplicationDir(mods, applicationDir, applicationId);
} }
foreach (ulong installedDlcId in installedDlcs)
{
DirectoryInfo dlcModDir = FindApplicationDir(contentsDir, $"{installedDlcId:x16}");
if (dlcModDir != null)
{
QueryApplicationDir(mods, dlcModDir, applicationId);
}
}
} }
private static int QueryCheatsDir(ModCache mods, DirectoryInfo cheatsDir) private static int QueryCheatsDir(ModCache mods, DirectoryInfo cheatsDir)
@@ -415,7 +427,7 @@ namespace Ryujinx.HLE.HOS
{ {
foreach ((ulong applicationId, ModCache cache) in modCaches) foreach ((ulong applicationId, ModCache cache) in modCaches)
{ {
QueryContentsDir(cache, searchDir, applicationId); QueryContentsDir(cache, searchDir, applicationId, Array.Empty<ulong>());
} }
return true; return true;
@@ -581,6 +593,7 @@ namespace Ryujinx.HLE.HOS
public BitVector32 Stubs; public BitVector32 Stubs;
public BitVector32 Replaces; public BitVector32 Replaces;
public MetaLoader Npdm; public MetaLoader Npdm;
public string Hash;
public bool Modified => (Stubs.Data | Replaces.Data) != 0; public bool Modified => (Stubs.Data | Replaces.Data) != 0;
} }
@@ -591,8 +604,11 @@ namespace Ryujinx.HLE.HOS
{ {
Stubs = new BitVector32(), Stubs = new BitVector32(),
Replaces = new BitVector32(), Replaces = new BitVector32(),
Hash = null,
}; };
string tempHash = string.Empty;
if (!_appMods.TryGetValue(applicationId, out ModCache mods) || mods.ExefsDirs.Count == 0) if (!_appMods.TryGetValue(applicationId, out ModCache mods) || mods.ExefsDirs.Count == 0)
{ {
return modLoadResult; return modLoadResult;
@@ -628,8 +644,16 @@ namespace Ryujinx.HLE.HOS
modLoadResult.Replaces[1 << i] = true; modLoadResult.Replaces[1 << i] = true;
nsos[i] = new NsoExecutable(nsoFile.OpenRead().AsStorage(), nsoName); using (FileStream stream = nsoFile.OpenRead())
Logger.Info?.Print(LogClass.ModLoader, $"NSO '{nsoName}' replaced"); {
nsos[i] = new NsoExecutable(stream.AsStorage(), nsoName);
Logger.Info?.Print(LogClass.ModLoader, $"NSO '{nsoName}' replaced");
using (MD5 md5 = MD5.Create())
{
stream.Seek(0, SeekOrigin.Begin);
tempHash += BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLowerInvariant();
}
}
} }
modLoadResult.Stubs[1 << i] |= File.Exists(Path.Combine(mod.Path.FullName, nsoName + StubExtension)); modLoadResult.Stubs[1 << i] |= File.Exists(Path.Combine(mod.Path.FullName, nsoName + StubExtension));
@@ -661,6 +685,14 @@ namespace Ryujinx.HLE.HOS
} }
} }
if (!string.IsNullOrEmpty(tempHash))
{
using (MD5 md5 = MD5.Create())
{
modLoadResult.Hash += BitConverter.ToString(md5.ComputeHash(tempHash.ToBytes())).Replace("-", string.Empty).ToLowerInvariant();
}
}
return modLoadResult; return modLoadResult;
} }

View File

@@ -121,7 +121,7 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu
private void UpdatePassphraseIfNeeded() private void UpdatePassphraseIfNeeded()
{ {
string passphrase = _config.MultiplayerLdnPassphrase ?? ""; string passphrase = _config.MultiplayerLdnPassphrase ?? string.Empty;
if (passphrase != _passphrase) if (passphrase != _passphrase)
{ {
_passphrase = passphrase; _passphrase = passphrase;

View File

@@ -1,5 +1,4 @@
using Ryujinx.Common.Memory; using Ryujinx.Common.Memory;
using Ryujinx.Common.Utilities;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@@ -7,7 +7,6 @@ using Ryujinx.HLE.HOS.Services.Mii.Types;
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption; using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager; using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@@ -2,7 +2,6 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Ipc; using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel; using Ryujinx.HLE.HOS.Kernel;
using Ryujinx.HLE.HOS.Kernel.Ipc; using Ryujinx.HLE.HOS.Kernel.Ipc;
using Ryujinx.HLE.HOS.Services.Apm;
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@@ -3,7 +3,6 @@ using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Threading; using Ryujinx.HLE.HOS.Kernel.Threading;
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
using System; using System;
using System.Buffers;
namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
{ {

View File

@@ -4,7 +4,6 @@ using LibHac.Fs.Fsa;
using LibHac.Loader; using LibHac.Loader;
using LibHac.Ns; using LibHac.Ns;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
@@ -84,13 +83,6 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
// Apply Nsos patches. // Apply Nsos patches.
device.Configuration.VirtualFileSystem.ModLoader.ApplyNsoPatches(programId, nsoExecutables); device.Configuration.VirtualFileSystem.ModLoader.ApplyNsoPatches(programId, nsoExecutables);
// Don't use PTC if ExeFS files have been replaced.
bool enablePtc = device.System.EnablePtc && !modLoadResult.Modified;
if (!enablePtc)
{
Logger.Warning?.Print(LogClass.Ptc, "Detected unsupported ExeFs modifications. PTC disabled.");
}
string programName = string.Empty; string programName = string.Empty;
if (!isHomebrew && programId > 0x010000000000FFFF) if (!isHomebrew && programId > 0x010000000000FFFF)
@@ -117,7 +109,8 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
device.System.KernelContext, device.System.KernelContext,
metaLoader, metaLoader,
nacpData, nacpData,
enablePtc, device.System.EnablePtc,
modLoadResult.Hash,
true, true,
programName, programName,
metaLoader.GetProgramId(), metaLoader.GetProgramId(),

View File

@@ -235,6 +235,7 @@ namespace Ryujinx.HLE.Loaders.Processes
dummyExeFs.GetNpdm(), dummyExeFs.GetNpdm(),
nacpData, nacpData,
diskCacheEnabled: false, diskCacheEnabled: false,
diskCacheSelector: null,
allowCodeMemoryForJit: true, allowCodeMemoryForJit: true,
programName, programName,
programId, programId,

View File

@@ -21,7 +21,6 @@ using Ryujinx.HLE.Loaders.Processes.Extensions;
using Ryujinx.Horizon.Common; using Ryujinx.Horizon.Common;
using Ryujinx.Horizon.Sdk.Arp; using Ryujinx.Horizon.Sdk.Arp;
using System; using System;
using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using ApplicationId = LibHac.Ncm.ApplicationId; using ApplicationId = LibHac.Ncm.ApplicationId;
@@ -186,6 +185,7 @@ namespace Ryujinx.HLE.Loaders.Processes
string.Empty, string.Empty,
string.Empty, string.Empty,
false, false,
null,
codeAddress, codeAddress,
codeSize); codeSize);
@@ -226,6 +226,7 @@ namespace Ryujinx.HLE.Loaders.Processes
MetaLoader metaLoader, MetaLoader metaLoader,
BlitStruct<ApplicationControlProperty> applicationControlProperties, BlitStruct<ApplicationControlProperty> applicationControlProperties,
bool diskCacheEnabled, bool diskCacheEnabled,
string diskCacheSelector,
bool allowCodeMemoryForJit, bool allowCodeMemoryForJit,
string name, string name,
ulong programId, ulong programId,
@@ -379,6 +380,7 @@ namespace Ryujinx.HLE.Loaders.Processes
$"{programId:x16}", $"{programId:x16}",
displayVersion, displayVersion,
diskCacheEnabled, diskCacheEnabled,
diskCacheSelector,
codeStart, codeStart,
codeSize); codeSize);

View File

@@ -88,7 +88,7 @@ namespace Ryujinx.HLE.Loaders.Processes
bool isFirmwareApplication = ProgramId <= 0x0100000000007FFF; bool isFirmwareApplication = ProgramId <= 0x0100000000007FFF;
string name = !isFirmware string name = !isFirmware
? (isFirmwareApplication ? "Firmware Application " : "") + (!string.IsNullOrWhiteSpace(Name) ? Name : "<Unknown Name>") ? (isFirmwareApplication ? "Firmware Application " : string.Empty) + (!string.IsNullOrWhiteSpace(Name) ? Name : "<Unknown Name>")
: "Firmware"; : "Firmware";
// TODO: LibHac npdm currently doesn't support version field. // TODO: LibHac npdm currently doesn't support version field.

Some files were not shown because too many files have changed in this diff Show More