add a keyboard shortcut for opening amiibo .bin files #461

Merged
jozz024 merged 2 commits from master into master 2025-01-01 04:45:52 +00:00
152 changed files with 826 additions and 543 deletions
Showing only changes of commit 4de53ada43 - Show all commits

View File

@ -61,8 +61,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmp
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.Common", "src\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj", "{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
@ -219,10 +217,6 @@ Global
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU {7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA161CA0-CD65-4E6E-B644-51C8D1E542DC}.Release|Any CPU.Build.0 = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU {6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@ -13,7 +13,7 @@ mkdir -p AppDir/usr/bin
cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop cp distribution/linux/Ryujinx.desktop AppDir/Ryujinx.desktop
cp distribution/linux/appimage/AppRun AppDir/AppRun cp distribution/linux/appimage/AppRun AppDir/AppRun
cp src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png AppDir/Ryujinx.svg cp distribution/misc/Logo.svg AppDir/Ryujinx.svg
cp -r "$BUILDDIR"/* AppDir/usr/bin/ cp -r "$BUILDDIR"/* AppDir/usr/bin/

View File

@ -9,20 +9,12 @@ namespace Ryujinx.Audio.Backends.Dummy
{ {
public class DummyHardwareDeviceDriver : IHardwareDeviceDriver public class DummyHardwareDeviceDriver : IHardwareDeviceDriver
{ {
private readonly ManualResetEvent _updateRequiredEvent; private readonly ManualResetEvent _updateRequiredEvent = new(false);
private readonly ManualResetEvent _pauseEvent; private readonly ManualResetEvent _pauseEvent = new(true);
public static bool IsSupported => true; public static bool IsSupported => true;
public float Volume { get; set; } public float Volume { get; set; } = 1f;
public DummyHardwareDeviceDriver()
{
_updateRequiredEvent = new ManualResetEvent(false);
_pauseEvent = new ManualResetEvent(true);
Volume = 1f;
}
public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount) public IHardwareDeviceSession OpenDeviceSession(Direction direction, IVirtualMemoryManager memoryManager, SampleFormat sampleFormat, uint sampleRate, uint channelCount)
{ {
@ -60,7 +52,7 @@ namespace Ryujinx.Audio.Backends.Dummy
Dispose(true); Dispose(true);
} }
protected virtual void Dispose(bool disposing) private void Dispose(bool disposing)
{ {
if (disposing) if (disposing)
{ {

View File

@ -0,0 +1,35 @@
namespace Ryujinx.Common
{
public class BitTricks
{
// Never actually written bit packing logic before, so I looked it up.
// This code is from https://gist.github.com/Alan-FGR/04938e93e2bffdf5802ceb218a37c195
public static ulong PackBitFields(uint[] values, byte[] bitFields)
{
ulong retVal = values[0]; //we set the first value right away
for (int f = 1; f < values.Length; f++)
{
retVal <<= bitFields[f]; // we shift the previous value
retVal += values[f];// and add our current value
}
return retVal;
}
public static uint[] UnpackBitFields(ulong packed, byte[] bitFields)
{
int fields = bitFields.Length - 1; // number of fields to unpack
uint[] retArr = new uint[fields + 1]; // init return array
int curPos = 0; // current field bit position (start)
int lastEnd; // position where last field ended
for (int f = fields; f >= 0; f--) // loop from last
{
lastEnd = curPos; // we store where the last value ended
curPos += bitFields[f]; // we get where the current value starts
int leftShift = 64 - curPos; // we figure how much left shift we gotta apply for the other numbers to overflow into oblivion
retArr[f] = (uint)((packed << leftShift) >> leftShift + lastEnd); // we do magic
}
return retArr;
}
}
}

View File

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Common.Configuration
{
[Flags]
public enum DirtyHacks : byte
{
Xc2MenuSoftlockFix = 1,
ShaderCompilationThreadSleep = 2
}
public record EnabledDirtyHack(DirtyHacks Hack, int Value)
{
public static readonly byte[] PackedFormat = [8, 32];
public ulong Pack() => BitTricks.PackBitFields([(uint)Hack, (uint)Value], PackedFormat);
public static EnabledDirtyHack Unpack(ulong packedHack)
{
var unpackedFields = BitTricks.UnpackBitFields(packedHack, PackedFormat);
if (unpackedFields is not [var hack, var value])
throw new ArgumentException(nameof(packedHack));
return new EnabledDirtyHack((DirtyHacks)hack, (int)value);
}
}
public class DirtyHackCollection : Dictionary<DirtyHacks, int>
{
public DirtyHackCollection(EnabledDirtyHack[] hacks)
{
foreach ((DirtyHacks dirtyHacks, int value) in hacks)
{
Add(dirtyHacks, value);
}
}
public DirtyHackCollection(ulong[] packedHacks)
{
foreach ((DirtyHacks dirtyHacks, int value) in packedHacks.Select(EnabledDirtyHack.Unpack))
{
Add(dirtyHacks, value);
}
}
public ulong[] PackEntries() =>
this
.Select(it =>
BitTricks.PackBitFields([(uint)it.Key, (uint)it.Value], EnabledDirtyHack.PackedFormat))
.ToArray();
public static implicit operator DirtyHackCollection(EnabledDirtyHack[] hacks) => new(hacks);
public static implicit operator DirtyHackCollection(ulong[] packedHacks) => new(packedHacks);
public new int this[DirtyHacks hack] => TryGetValue(hack, out var value) ? value : -1;
public bool IsEnabled(DirtyHacks hack) => ContainsKey(hack);
}
}

View File

@ -8,10 +8,10 @@ namespace Ryujinx.Common
public static class StreamExtensions public static class StreamExtensions
{ {
/// <summary> /// <summary>
/// Writes a <see cref="ReadOnlySpan{int}" /> to this stream. /// Writes an int span to this stream.
/// ///
/// This default implementation converts each buffer value to a stack-allocated /// This default implementation converts each buffer value to a stack-allocated
/// byte array, then writes it to the Stream using <cref="System.Stream.Write(byte[])" />. /// byte array, then writes it to the Stream using <see cref="Stream.Write(ReadOnlySpan{byte})" />.
/// </summary> /// </summary>
/// <param name="stream">The stream to be written to</param> /// <param name="stream">The stream to be written to</param>
/// <param name="buffer">The buffer of values to be written</param> /// <param name="buffer">The buffer of values to be written</param>

View File

@ -3,7 +3,7 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.UI.Common.Helper namespace Ryujinx.Common.Helper
{ {
public static partial class ConsoleHelper public static partial class ConsoleHelper
{ {

View File

@ -8,7 +8,7 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.UI.Common.Helper namespace Ryujinx.Common.Helper
{ {
public static partial class FileAssociationHelper public static partial class FileAssociationHelper
{ {

View File

@ -3,7 +3,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.UI.Common.Helper namespace Ryujinx.Common.Helper
{ {
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
public static class LinuxHelper public static class LinuxHelper

View File

@ -2,7 +2,7 @@ using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Versioning; using System.Runtime.Versioning;
namespace Ryujinx.UI.Common.Helper namespace Ryujinx.Common.Helper
{ {
[SupportedOSPlatform("macos")] [SupportedOSPlatform("macos")]
public static partial class ObjectiveC public static partial class ObjectiveC

View File

@ -5,7 +5,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace Ryujinx.UI.Common.Helper namespace Ryujinx.Common.Helper
{ {
public static partial class OpenHelper public static partial class OpenHelper
{ {

View File

@ -8,6 +8,8 @@ namespace Ryujinx.Common
{ {
public static class TitleIDs public static class TitleIDs
{ {
public static ReactiveObject<Optional<string>> CurrentApplication { get; set; } = new();
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend) public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
{ {
switch (currentBackend) switch (currentBackend)
@ -33,6 +35,7 @@ namespace Ryujinx.Common
"010028600EBDA000", // Mario 3D World "010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe "0100152000022000", // Mario Kart 8 Deluxe
"01005CA01580E000", // Persona 5 "01005CA01580E000", // Persona 5
"01001f5010dfa000", // Pokemon Legends Arceus
"01008C0016544000", // Sea of Stars "01008C0016544000", // Sea of Stars
"01006A800016E000", // Smash Ultimate "01006A800016E000", // Smash Ultimate
"0100000000010000", // Super Mario Odyessy "0100000000010000", // Super Mario Odyessy

View File

@ -1,4 +1,4 @@
namespace Ryujinx.UI.Common namespace Ryujinx.Common.UI
{ {
/// <summary> /// <summary>
/// Represent a common error that could be reported to the user by the emulator. /// Represent a common error that could be reported to the user by the emulator.

View File

@ -1,4 +1,5 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.Device; using Ryujinx.Graphics.Device;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu.Engine.GPFifo; using Ryujinx.Graphics.Gpu.Engine.GPFifo;
@ -91,6 +92,9 @@ namespace Ryujinx.Graphics.Gpu
/// </summary> /// </summary>
internal SupportBufferUpdater SupportBufferUpdater { get; } internal SupportBufferUpdater SupportBufferUpdater { get; }
internal DirtyHackCollection DirtyHacks { get; }
/// <summary> /// <summary>
/// Host hardware capabilities. /// Host hardware capabilities.
/// </summary> /// </summary>
@ -113,7 +117,7 @@ namespace Ryujinx.Graphics.Gpu
/// Creates a new instance of the GPU emulation context. /// Creates a new instance of the GPU emulation context.
/// </summary> /// </summary>
/// <param name="renderer">Host renderer</param> /// <param name="renderer">Host renderer</param>
public GpuContext(IRenderer renderer) public GpuContext(IRenderer renderer, DirtyHackCollection hackCollection)
{ {
Renderer = renderer; Renderer = renderer;
@ -136,6 +140,8 @@ namespace Ryujinx.Graphics.Gpu
SupportBufferUpdater = new SupportBufferUpdater(renderer); SupportBufferUpdater = new SupportBufferUpdater(renderer);
DirtyHacks = hackCollection;
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds); _firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
} }

View File

@ -1,3 +1,4 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
@ -366,6 +367,9 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
{ {
try try
{ {
if (_context.DirtyHacks.IsEnabled(DirtyHacks.ShaderCompilationThreadSleep))
Thread.Sleep(_context.DirtyHacks[DirtyHacks.ShaderCompilationThreadSleep]);
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute); AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken); _asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);
} }

View File

@ -1,3 +1,4 @@
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

@ -23,12 +23,14 @@ namespace Ryujinx.Graphics.Metal
private int _requestedWidth; private int _requestedWidth;
private int _requestedHeight; private int _requestedHeight;
// private bool _vsyncEnabled;
private AntiAliasing _currentAntiAliasing; private AntiAliasing _currentAntiAliasing;
private bool _updateEffect; private bool _updateEffect;
private IPostProcessingEffect _effect; private IPostProcessingEffect _effect;
private IScalingFilter _scalingFilter; private IScalingFilter _scalingFilter;
private bool _isLinear; private bool _isLinear;
public bool IsVSyncEnabled => _metalLayer.DisplaySyncEnabled;
// private float _scalingFilterLevel; // private float _scalingFilterLevel;
private bool _updateScalingFilter; private bool _updateScalingFilter;
private ScalingFilter _currentScalingFilter; private ScalingFilter _currentScalingFilter;
@ -40,7 +42,7 @@ namespace Ryujinx.Graphics.Metal
_metalLayer = metalLayer; _metalLayer = metalLayer;
} }
private unsafe void ResizeIfNeeded() private void ResizeIfNeeded()
{ {
if (_requestedWidth != 0 && _requestedHeight != 0) if (_requestedWidth != 0 && _requestedHeight != 0)
{ {
@ -54,7 +56,7 @@ namespace Ryujinx.Graphics.Metal
} }
} }
public unsafe void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback) public void Present(ITexture texture, ImageCrop crop, Action swapBuffersCallback)
{ {
if (_renderer.Pipeline is Pipeline pipeline && texture is Texture tex) if (_renderer.Pipeline is Pipeline pipeline && texture is Texture tex)
{ {
@ -141,15 +143,7 @@ namespace Ryujinx.Graphics.Metal
public void ChangeVSyncMode(VSyncMode vSyncMode) public void ChangeVSyncMode(VSyncMode vSyncMode)
{ {
switch (vSyncMode) _metalLayer.DisplaySyncEnabled = vSyncMode is VSyncMode.Switch;
{
case VSyncMode.Unbounded:
_metalLayer.DisplaySyncEnabled = false;
break;
case VSyncMode.Switch:
_metalLayer.DisplaySyncEnabled = true;
break;
}
} }
public void SetAntiAliasing(AntiAliasing effect) public void SetAntiAliasing(AntiAliasing effect)

View File

@ -2,8 +2,8 @@ namespace Ryujinx.Graphics.Nvdec.Vp9
{ {
internal enum BitDepth internal enum BitDepth
{ {
Bits8 = 8, /**< 8 bits */ Bits8 = 8, // < 8 bits
Bits10 = 10, /**< 10 bits */ Bits10 = 10, // < 10 bits
Bits12 = 12, /**< 12 bits */ Bits12 = 12, // < 12 bits
} }
} }

View File

@ -1,3 +1,4 @@
using Gommon;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
@ -890,7 +891,12 @@ namespace Ryujinx.Graphics.Vulkan
private void PrintGpuInformation() private void PrintGpuInformation()
{ {
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})"); string gpuInfoMessage = $"{GpuRenderer} ({GpuVersion})";
if (!GpuRenderer.StartsWithIgnoreCase(GpuVendor))
gpuInfoMessage = gpuInfoMessage.Prepend(GpuVendor);
Logger.Notice.Print(LogClass.Gpu, gpuInfoMessage);
Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB"); Logger.Notice.Print(LogClass.Gpu, $"GPU Memory: {GetTotalGPUMemory() / (1024 * 1024)} MiB");
} }

View File

@ -189,6 +189,11 @@ namespace Ryujinx.HLE
/// </summary> /// </summary>
public Action RefreshInputConfig { internal get; set; } public Action RefreshInputConfig { internal get; set; }
/// <summary>
/// The desired hacky workarounds.
/// </summary>
public EnabledDirtyHack[] Hacks { internal get; set; }
public HLEConfiguration(VirtualFileSystem virtualFileSystem, public HLEConfiguration(VirtualFileSystem virtualFileSystem,
LibHacHorizonManager libHacHorizonManager, LibHacHorizonManager libHacHorizonManager,
ContentManager contentManager, ContentManager contentManager,
@ -218,7 +223,8 @@ namespace Ryujinx.HLE
bool multiplayerDisableP2p, bool multiplayerDisableP2p,
string multiplayerLdnPassphrase, string multiplayerLdnPassphrase,
string multiplayerLdnServer, string multiplayerLdnServer,
int customVSyncInterval) int customVSyncInterval,
EnabledDirtyHack[] dirtyHacks = null)
{ {
VirtualFileSystem = virtualFileSystem; VirtualFileSystem = virtualFileSystem;
LibHacHorizonManager = libHacHorizonManager; LibHacHorizonManager = libHacHorizonManager;
@ -250,6 +256,7 @@ namespace Ryujinx.HLE
MultiplayerDisableP2p = multiplayerDisableP2p; MultiplayerDisableP2p = multiplayerDisableP2p;
MultiplayerLdnPassphrase = multiplayerLdnPassphrase; MultiplayerLdnPassphrase = multiplayerLdnPassphrase;
MultiplayerLdnServer = multiplayerLdnServer; MultiplayerLdnServer = multiplayerLdnServer;
Hacks = dirtyHacks ?? [];
} }
} }
} }

View File

@ -1,6 +1,9 @@
using LibHac; using LibHac;
using LibHac.Common; using LibHac.Common;
using LibHac.Sf; using LibHac.Sf;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using System.Threading;
namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
{ {
@ -13,6 +16,8 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
_baseStorage = SharedRef<LibHac.FsSrv.Sf.IStorage>.CreateMove(ref baseStorage); _baseStorage = SharedRef<LibHac.FsSrv.Sf.IStorage>.CreateMove(ref baseStorage);
} }
private const string Xc2TitleId = "0100e95004038000";
[CommandCmif(0)] [CommandCmif(0)]
// Read(u64 offset, u64 length) -> buffer<u8, 0x46, 0> buffer // Read(u64 offset, u64 length) -> buffer<u8, 0x46, 0> buffer
public ResultCode Read(ServiceCtx context) public ResultCode Read(ServiceCtx context)
@ -34,6 +39,13 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true); using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true);
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size); Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size);
if (context.Device.DirtyHacks.IsEnabled(DirtyHacks.Xc2MenuSoftlockFix) && TitleIDs.CurrentApplication.Value == Xc2TitleId)
{
// Add a load-bearing sleep to avoid XC2 softlock
// https://web.archive.org/web/20240728045136/https://github.com/Ryujinx/Ryujinx/issues/2357
Thread.Sleep(2);
}
return (ResultCode)result.Value; return (ResultCode)result.Value;
} }

View File

@ -114,10 +114,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
} }
} }
string usedCharacterStr = BitConverter.ToString(usedCharacter).Replace("-", ""); string usedCharacterStr = Convert.ToHexString(usedCharacter);
string variationStr = BitConverter.ToString(variation).Replace("-", ""); string variationStr = Convert.ToHexString(variation);
string amiiboIDStr = BitConverter.ToString(amiiboID).Replace("-", ""); string amiiboIDStr = Convert.ToHexString(amiiboID);
string setIDStr = BitConverter.ToString(setID).Replace("-", ""); string setIDStr = Convert.ToHexString(setID);
string head = usedCharacterStr + variationStr; string head = usedCharacterStr + variationStr;
string tail = amiiboIDStr + setIDStr + "02"; string tail = amiiboIDStr + setIDStr + "02";
string finalID = head + tail; string finalID = head + tail;
@ -289,8 +289,8 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
private static void LogFinalData(byte[] titleId, byte[] appId, string head, string tail, string finalID, string nickName, DateTime initDateTime, DateTime writeDateTime, ushort settingsValue, ushort writeCounterValue, byte[] applicationAreas) private static void LogFinalData(byte[] titleId, byte[] appId, string head, string tail, string finalID, string nickName, DateTime initDateTime, DateTime writeDateTime, ushort settingsValue, ushort writeCounterValue, byte[] applicationAreas)
{ {
Logger.Debug?.Print(LogClass.ServiceNfp, $"Title ID: 0x{BitConverter.ToString(titleId).Replace("-", "")}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Title ID: 0x{Convert.ToHexString(titleId)}");
Logger.Debug?.Print(LogClass.ServiceNfp, $"Application Program ID: 0x{BitConverter.ToString(appId).Replace("-", "")}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Application Program ID: 0x{Convert.ToHexString(appId)}");
Logger.Debug?.Print(LogClass.ServiceNfp, $"Head: {head}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Head: {head}");
Logger.Debug?.Print(LogClass.ServiceNfp, $"Tail: {tail}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Tail: {tail}");
Logger.Debug?.Print(LogClass.ServiceNfp, $"Final ID: {finalID}"); Logger.Debug?.Print(LogClass.ServiceNfp, $"Final ID: {finalID}");

View File

@ -4,8 +4,10 @@ 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.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.Memory; using Ryujinx.Memory;
using System; using System;
@ -102,7 +104,7 @@ namespace Ryujinx.HLE.Loaders.Processes.Extensions
} }
// Initialize GPU. // Initialize GPU.
Graphics.Gpu.GraphicsConfig.TitleId = programId.ToString("X16"); GraphicsConfig.TitleId = programId.ToString("X16");
device.Gpu.HostInitalized.Set(); device.Gpu.HostInitalized.Set();
if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible)) if (!MemoryBlock.SupportsFlags(MemoryAllocationFlags.ViewCompatible))

View File

@ -6,7 +6,9 @@ using LibHac.Ns;
using LibHac.Tools.Fs; using LibHac.Tools.Fs;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using LibHac.Tools.FsSystem.NcaUtils; using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Loaders.Processes.Extensions;
using System; using System;
@ -59,6 +61,8 @@ namespace Ryujinx.HLE.Loaders.Processes
{ {
_latestPid = processResult.ProcessId; _latestPid = processResult.ProcessId;
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
return true; return true;
} }
} }
@ -86,6 +90,8 @@ namespace Ryujinx.HLE.Loaders.Processes
{ {
_latestPid = processResult.ProcessId; _latestPid = processResult.ProcessId;
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
return true; return true;
} }
} }
@ -113,6 +119,8 @@ namespace Ryujinx.HLE.Loaders.Processes
if (processResult.ProgramId > 0x01000000000007FF) if (processResult.ProgramId > 0x01000000000007FF)
{ {
_latestPid = processResult.ProcessId; _latestPid = processResult.ProcessId;
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
} }
return true; return true;
@ -132,6 +140,8 @@ namespace Ryujinx.HLE.Loaders.Processes
{ {
_latestPid = processResult.ProcessId; _latestPid = processResult.ProcessId;
TitleIDs.CurrentApplication.Value = processResult.ProgramIdText;
return true; return true;
} }
} }
@ -183,14 +193,17 @@ namespace Ryujinx.HLE.Loaders.Processes
if (nacpData.Value.PresenceGroupId != 0) if (nacpData.Value.PresenceGroupId != 0)
{ {
programId = nacpData.Value.PresenceGroupId; programId = nacpData.Value.PresenceGroupId;
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
} }
else if (nacpData.Value.SaveDataOwnerId != 0) else if (nacpData.Value.SaveDataOwnerId != 0)
{ {
programId = nacpData.Value.SaveDataOwnerId; programId = nacpData.Value.SaveDataOwnerId;
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
} }
else if (nacpData.Value.AddOnContentBaseId != 0) else if (nacpData.Value.AddOnContentBaseId != 0)
{ {
programId = nacpData.Value.AddOnContentBaseId - 0x1000; programId = nacpData.Value.AddOnContentBaseId - 0x1000;
TitleIDs.CurrentApplication.Value = programId.ToString("X16");
} }
} }
@ -204,7 +217,7 @@ namespace Ryujinx.HLE.Loaders.Processes
} }
// Explicitly null TitleId to disable the shader cache. // Explicitly null TitleId to disable the shader cache.
Graphics.Gpu.GraphicsConfig.TitleId = null; GraphicsConfig.TitleId = null;
_device.Gpu.HostInitalized.Set(); _device.Gpu.HostInitalized.Set();
ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device, ProcessResult processResult = ProcessLoaderHelper.LoadNsos(_device,

View File

@ -2,6 +2,7 @@ using LibHac.Common;
using LibHac.Ns; using LibHac.Ns;
using Ryujinx.Audio.Backends.CompatLayer; using Ryujinx.Audio.Backends.CompatLayer;
using Ryujinx.Audio.Integration; using Ryujinx.Audio.Integration;
using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
@ -17,6 +18,8 @@ namespace Ryujinx.HLE
{ {
public class Switch : IDisposable public class Switch : IDisposable
{ {
public static Switch Shared { get; private set; }
public HLEConfiguration Configuration { get; } public HLEConfiguration Configuration { get; }
public IHardwareDeviceDriver AudioDeviceDriver { get; } public IHardwareDeviceDriver AudioDeviceDriver { get; }
public MemoryBlock Memory { get; } public MemoryBlock Memory { get; }
@ -37,6 +40,8 @@ namespace Ryujinx.HLE
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable; public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
public DirtyHackCollection DirtyHacks { get; }
public Switch(HLEConfiguration configuration) public Switch(HLEConfiguration configuration)
{ {
ArgumentNullException.ThrowIfNull(configuration.GpuRenderer); ArgumentNullException.ThrowIfNull(configuration.GpuRenderer);
@ -52,9 +57,10 @@ namespace Ryujinx.HLE
: MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable; : MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable;
#pragma warning disable IDE0055 // Disable formatting #pragma warning disable IDE0055 // Disable formatting
DirtyHacks = new DirtyHackCollection(Configuration.Hacks);
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver); AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags); Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
Gpu = new GpuContext(Configuration.GpuRenderer); Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks);
System = new HOS.Horizon(this); System = new HOS.Horizon(this);
Statistics = new PerformanceStatistics(); Statistics = new PerformanceStatistics();
Hid = new Hid(this, System.HidStorage); Hid = new Hid(this, System.HidStorage);
@ -72,8 +78,11 @@ namespace Ryujinx.HLE
System.EnablePtc = Configuration.EnablePtc; System.EnablePtc = Configuration.EnablePtc;
System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel; System.FsIntegrityCheckLevel = Configuration.FsIntegrityCheckLevel;
System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode; System.GlobalAccessLogMode = Configuration.FsGlobalAccessLogMode;
UpdateVSyncInterval(); UpdateVSyncInterval();
#pragma warning restore IDE0055 #pragma warning restore IDE0055
Shared = this;
} }
public void ProcessFrame() public void ProcessFrame()
@ -142,6 +151,9 @@ namespace Ryujinx.HLE
AudioDeviceDriver.Dispose(); AudioDeviceDriver.Dispose();
FileSystem.Dispose(); FileSystem.Dispose();
Memory.Dispose(); Memory.Dispose();
TitleIDs.CurrentApplication.Value = null;
Shared = null;
} }
} }
} }

View File

@ -1,12 +0,0 @@
namespace Ryujinx.UI.Common
{
public enum FileTypes
{
NSP,
PFS0,
XCI,
NCA,
NRO,
NSO
}
}

View File

@ -1,64 +0,0 @@
using LibHac.Common;
using LibHac.Ncm;
using LibHac.Ns;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem;
using Ryujinx.UI.App.Common;
namespace Ryujinx.UI.Common.Helper
{
public readonly struct AppletMetadata
{
private readonly ContentManager _contentManager;
public string Name { get; }
public ulong ProgramId { get; }
public string Version { get; }
public AppletMetadata(ContentManager contentManager, string name, ulong programId, string version = "1.0.0")
: this(name, programId, version)
{
_contentManager = contentManager;
}
public AppletMetadata(string name, ulong programId, string version = "1.0.0")
{
Name = name;
ProgramId = programId;
Version = version;
}
public string GetContentPath(ContentManager contentManager)
=> (contentManager ?? _contentManager)
.GetInstalledContentPath(ProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
public bool CanStart(ContentManager contentManager, out ApplicationData appData, out BlitStruct<ApplicationControlProperty> appControl)
{
contentManager ??= _contentManager;
if (contentManager == null)
{
appData = null;
appControl = new BlitStruct<ApplicationControlProperty>(0);
return false;
}
appData = new()
{
Name = Name,
Id = ProgramId,
Path = GetContentPath(contentManager)
};
if (string.IsNullOrEmpty(appData.Path))
{
appControl = new BlitStruct<ApplicationControlProperty>(0);
return false;
}
appControl = StructHelpers.CreateCustomNacpData(Name, Version);
return true;
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,132 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1050 1050.5"
style="enable-background:new 0 0 1050 1050.5;" xml:space="preserve">
<style type="text/css">
.st0{fill:#20221F;}
.st1{fill:#3B3B3B;}
.st2{fill:#121212;}
.st3{fill:#444542;}
.st4{fill:#FFFFFF;}
.st5{fill:#444542;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
.st6{fill:#454644;}
.st7{fill:#454644;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;}
.st8{fill:#3B3C3A;}
.st9{font-family:'Helvetica-Bold';}
.st10{font-size:40px;}
.st11{fill:#0D0D0A;}
</style>
<g id="Front">
<path id="Right_Grip_00000028282943321285403220000008369785803052272051_" class="st0" d="M766,850.5
c34,28.2,27.6,35.9,68.5,108.5c36.7,74.7,64.4,104.4,125.1,84.1v0c95.3-57.9,59.3-145.3,43.6-275.2c-10-60.6-35.6-190.3-35.6-190.3
L766,850.5z"/>
<path id="Left_Grip" class="st0" d="M82.3,577.6c0,0-25.6,129.7-35.6,190.3C31,897.8-5,985.1,90.3,1043v0
c60.8,20.3,88.4-9.4,125.1-84.1c40.9-72.7,34.5-80.3,68.5-108.5L82.3,577.6z"/>
<path id="Right_Bumper_00000006710349871522532470000011078040965381267594_" class="st1" d="M676.3,378.4
c10.1-4.3,39.7-22.5,58.7-19.7c59.5,0.9,166.7,17.7,172.6,81.2"/>
<path id="Left_Bumper_00000024680414077879639570000011759596763560342154_" class="st1" d="M142.4,439.9
c5.9-63.4,113-80.2,172.6-81.2c19-2.8,48.6,15.4,58.7,19.7"/>
<path id="Background_00000141418846164053065470000016150094984198570163_" class="st2" d="M766,850.5
c35.5-30.8,68.5-74.7,96-113.5c26.9-36.3,94.7-136.7,105.6-159.3c0-2.4-6.3-30.1-12.8-56.2C919.1,361.9,702.2,378.1,525,378.1
c-177.4,0-394.1-16.2-429.9,143.3c-6.5,26-12.8,53.8-12.8,56.2c10.9,22.6,78.8,123,105.6,159.3c27.5,38.8,60.5,82.8,96,113.5"/>
<g id="Directional_Pad">
<path id="Background_00000032628022449190479560000015279211462520783249_" class="st3" d="M466.2,683.5h-40c-2.8,0-5-2.2-5-5v-40
c0-2.8-2.2-5-5-5h-30c-2.8,0-5,2.2-5,5v40c0,2.8-2.2,5-5,5h-40c-2.8,0-5,2.2-5,5v30c0,2.8,2.2,5,5,5h40c2.8,0,5,2.2,5,5v40
c0,2.8,2.2,5,5,5h30c2.8,0,5-2.2,5-5v-40c0-2.8,2.2-5,5-5h40c2.8,0,5-2.2,5-5v-30C471.2,685.8,469,683.5,466.2,683.5z"/>
<g id="Arrows">
<g>
<polygon class="st4" points="393.7,746 408.7,746 401.2,761 "/>
</g>
<g>
<polygon class="st4" points="358.7,696 358.7,711 343.7,703.5 "/>
</g>
<g>
<polygon class="st4" points="408.7,661 393.7,661 401.2,646 "/>
</g>
<g>
<polygon class="st4" points="443.7,711 443.7,696 458.7,703.5 "/>
</g>
</g>
</g>
<g id="R_Thumbstick_00000152226188525111835500000011838297421350334865_">
<circle id="Background_00000035532849542660068350000006517224202948159422_" class="st0" cx="650.6" cy="703.5" r="55"/>
<circle id="Stick" class="st5" cx="650.6" cy="703.5" r="45"/>
</g>
<g id="L_Thumbstick_00000047032468231999382210000005512347386782594484_">
<circle id="Background_00000182502673988292164000000007125719133096369561_" class="st0" cx="240.2" cy="564.8" r="55"/>
<circle id="Stick_00000075121990265259598900000000214370239054002365_" class="st5" cx="240.2" cy="564.8" r="45"/>
</g>
<g id="Minus_Button">
<circle id="_Background_00000120554951013892796430000015877571645746699662_" class="st6" cx="401" cy="489.3" r="22.5"/>
<polyline id="Plus_00000039131319101621183460000006196023733899658629_" class="st4" points="386.2,491.8 386.2,486.8
416.2,486.8 416.2,491.8 "/>
</g>
<g id="Plus_Button">
<circle id="_Background" class="st6" cx="650.4" cy="489.6" r="22.5"/>
<polygon id="Plus" class="st4" points="665.6,487.1 653.1,487.1 653.1,474.4 648.1,474.4 648.1,487.1 635.6,487.1 635.6,492.1
648.1,492.1 648.1,504.4 653.1,504.4 653.1,492.1 665.6,492.1 "/>
</g>
<g id="Home_Button_00000029758737660217614780000001403165237001195407_">
<circle id="_Background_00000132788487854287834010000009548421243227981499_" class="st6" cx="605.4" cy="564.8" r="22.5"/>
<path id="Home" class="st4" d="M605.4,549.8l-15,15h5v15h20v-15h5L605.4,549.8z M610.4,574.8h-10v-10h10V574.8z"/>
</g>
<g id="Capture_Button_00000105394663133565750060000017455731898661404072_">
<path class="st6" d="M468.6,586.5h-30c-2.8,0-5-2.2-5-5v-29.5c0-2.8,2.2-5,5-5h30c2.8,0,5,2.2,5,5v29.5
C473.6,584.2,471.4,586.5,468.6,586.5z"/>
<circle class="st7" cx="453.6" cy="566.7" r="15"/>
</g>
<g id="Buttons_00000023239109225132251950000005218343074279628213_">
<g id="A_Button">
<circle id="Background_00000006699118933065716380000004636085088820886913_" class="st8" cx="863.9" cy="564.8" r="35"/>
<text transform="matrix(1 0 0 1 849.4224 578.6607)" class="st4 st9 st10">A</text>
</g>
<g id="X_Button">
<circle id="Background_00000083074713085756701790000016893839312974798515_" class="st8" cx="793.9" cy="494.8" r="35"/>
<text transform="matrix(1 0 0 1 780.5266 508.6604)" class="st4 st9 st10">X</text>
</g>
<g id="Y_Button_00000100344340438574137780000014238704828967683973_">
<circle id="Background_00000137100455694543496620000011124722786613194377_" class="st8" cx="723.9" cy="564.8" r="35"/>
<text transform="matrix(1 0 0 1 710.5263 578.661)" class="st4 st9 st10">Y</text>
</g>
<g id="B_Button_00000041994261956088037220000013468634544777304733_">
<circle id="Background_00000096038108578846046800000001873940014252420514_" class="st8" cx="793.9" cy="634.8" r="35"/>
<text transform="matrix(1 0 0 1 780.9706 648.6605)" class="st4 st9 st10">B</text>
</g>
</g>
</g>
<g id="Top_Down">
<path id="Left_Grip_00000026131988385328425370000016677941743356253314_" class="st0" d="M219.2,78.5
c-12.5-17.6-25.9-42.3-45.6-58.6C153.5,3.3,112.1-4.7,87.1,5.8c-13.9,5.8-33.4,33.1-42.7,52.8C33.9,80.9,30.4,109.9,32,141.4
c1.2,25.1,5.3,51.7,14.2,78.6c0,0,14.3,53.8,42.8,80.8c11.2,10.6,35,26.6,35,26.6l116-217.5C240,109.9,224.6,86.2,219.2,78.5z"/>
<path id="Right_Grip_00000016782759094708820330000002450847065936193693_" class="st0" d="M828.6,78.5
c12.5-17.6,25.9-42.3,45.6-58.6c20.1-16.6,61.4-24.5,86.5-14.1c13.9,5.8,33.4,33.1,42.7,52.8c10.5,22.3,13.9,51.3,12.4,82.8
c-1.2,25.1-5.3,51.7-14.2,78.6c0,0-14.3,53.8-42.8,80.8c-11.2,10.6-35,26.6-35,26.6l-116-217.5C807.8,109.9,823.2,86.2,828.6,78.5z
"/>
<path id="Background_00000169534857628063347190000007586592143875928969_" class="st11" d="M866,122.2
c66.3,18.7,85.1,128.8,69,186c-2.5,54.2-148.9,15.3-265.1,31.2c-41.1,1.7-91.8,2.4-145.9,2.3c-54.1,0-104.8-0.6-145.9-2.3
c-116.2-15.9-262.6,23.1-265.1-31.2c-16.1-57.1,2.6-167.3,69-186l60.5-18.8l38.9-1.9c40.2,0.1,142.8,0,242.7,0
c99.9,0,202.4,0.1,242.7,0l38.9,1.9L866,122.2z"/>
<g id="ZL_Trigger_00000005254517714433203260000014117442438696169895_">
<path id="Background_00000111870097528015387240000017384507710402295183_" class="st1" d="M145.9,239.2
c15.2-97.4,38.1-147.2,141.7-137c8.2,16.4,43.3,83,50.6,105.7C280.6,227.2,204.7,225.6,145.9,239.2z"/>
<text id="ZL_Trigger" transform="matrix(1.0139 0 0 1 218.3906 179.3992)" class="st4 st9 st10">ZL</text>
</g>
<g id="ZR_Trigger">
<path id="Background_00000133526766189752063450000016781240006605114763_" class="st1" d="M716.2,207.9
c7.4-22.7,42.5-89.3,50.6-105.7c103.7-10.2,126.5,39.6,141.7,137C849.8,225.6,773.8,227.2,716.2,207.9z"/>
<text id="ZL_Trigger_00000000206350378518266660000001315160307759857328_" transform="matrix(1.0139 0 0 1 784.2356 179.3992)" class="st4 st9 st10">ZR</text>
</g>
<g id="R_Trigger_00000085939413106284991650000014018840000393673094_">
<path id="Background" class="st1" d="M664,318.5c7-10.1,27.8-78.4,45.4-78.7C1040.8,243.7,897.1,334,664,318.5z"/>
<text id="R_Trigger" transform="matrix(1 0 0 1 769.6461 292.8947)" class="st4 st9 st10">R</text>
</g>
<g id="L_Trigger">
<path id="Background_00000043427985111927735300000011910735497762731703_" class="st1" d="M340.6,238.6
c17.6,0.3,38.4,68.6,45.4,78.7C152.9,332.8,9.2,242.6,340.6,238.6z"/>
<text id="R_Trigger_00000092444210070373642420000009814634285137007748_" transform="matrix(1 0 0 1 253.7327 291.7279)" class="st4 st9 st10">L</text>
</g>
</g>
</svg>

View File

@ -21,34 +21,6 @@
<None Remove="Resources\Logo_Ryujinx.png" /> <None Remove="Resources\Logo_Ryujinx.png" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\Controller_JoyConLeft.svg" />
<EmbeddedResource Include="Resources\Controller_JoyConPair.svg" />
<EmbeddedResource Include="Resources\Controller_JoyConRight.svg" />
<EmbeddedResource Include="Resources\Controller_ProCon.svg" />
<EmbeddedResource Include="Resources\Icon_NCA.png" />
<EmbeddedResource Include="Resources\Icon_NRO.png" />
<EmbeddedResource Include="Resources\Icon_NSO.png" />
<EmbeddedResource Include="Resources\Icon_NSP.png" />
<EmbeddedResource Include="Resources\Icon_XCI.png" />
<EmbeddedResource Include="Resources\Logo_Amiibo.png" />
<EmbeddedResource Include="Resources\Logo_Ryujinx.png" />
<EmbeddedResource Include="Resources\Logo_Ryujinx_AntiAlias.png" />
<EmbeddedResource Include="Resources\Logo_Discord_Dark.png" />
<EmbeddedResource Include="Resources\Logo_Discord_Light.png" />
<EmbeddedResource Include="Resources\Logo_GitHub_Dark.png" />
<EmbeddedResource Include="Resources\Logo_GitHub_Light.png" />
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR '$(RuntimeIdentifier)' == ''">
<EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop" />
</ItemGroup>
<ItemGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64' OR '$(RuntimeIdentifier)' == ''">
<EmbeddedResource Include="..\..\distribution\macos\shortcut-template.plist" />
<EmbeddedResource Include="..\..\distribution\macos\shortcut-launch-script.sh" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DiscordRichPresence" /> <PackageReference Include="DiscordRichPresence" />
<PackageReference Include="DynamicData" /> <PackageReference Include="DynamicData" />

View File

@ -20,11 +20,15 @@ using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.Renderer; using Ryujinx.Ava.UI.Renderer;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.SystemInterop; using Ryujinx.Common.SystemInterop;
using Ryujinx.Common.UI;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.GAL.Multithreading; using Ryujinx.Graphics.GAL.Multithreading;
@ -39,10 +43,6 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.Input; using Ryujinx.Input;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Helper;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using SkiaSharp; using SkiaSharp;
using SPB.Graphics.Vulkan; using SPB.Graphics.Vulkan;
@ -311,6 +311,7 @@ namespace Ryujinx.Ava
Device.VSyncMode = e.NewValue; Device.VSyncMode = e.NewValue;
Device.UpdateVSyncInterval(); Device.UpdateVSyncInterval();
} }
_renderer.Window?.ChangeVSyncMode(e.NewValue); _renderer.Window?.ChangeVSyncMode(e.NewValue);
_viewModel.ShowCustomVSyncIntervalPicker = (e.NewValue == VSyncMode.Custom); _viewModel.ShowCustomVSyncIntervalPicker = (e.NewValue == VSyncMode.Custom);
@ -577,7 +578,6 @@ namespace Ryujinx.Ava
public void Stop() public void Stop()
{ {
_isActive = false; _isActive = false;
DiscordIntegrationModule.SwitchToMainState();
} }
private void Exit() private void Exit()
@ -862,12 +862,10 @@ namespace Ryujinx.Ava
return false; return false;
} }
ApplicationMetadata appMeta = ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText, ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
appMetadata => appMetadata.UpdatePreGame() appMetadata => appMetadata.UpdatePreGame()
); );
DiscordIntegrationModule.SwitchToPlayingState(appMeta, Device.Processes.ActiveApplication);
return true; return true;
} }
@ -923,7 +921,7 @@ namespace Ryujinx.Ava
// Initialize Configuration. // Initialize Configuration.
var memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value; var memoryConfiguration = ConfigurationState.Instance.System.DramSize.Value;
Device = new HLE.Switch(new HLEConfiguration( Device = new Switch(new HLEConfiguration(
VirtualFileSystem, VirtualFileSystem,
_viewModel.LibHacHorizonManager, _viewModel.LibHacHorizonManager,
ContentManager, ContentManager,
@ -953,7 +951,8 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Multiplayer.DisableP2p, ConfigurationState.Instance.Multiplayer.DisableP2p,
ConfigurationState.Instance.Multiplayer.LdnPassphrase, ConfigurationState.Instance.Multiplayer.LdnPassphrase,
ConfigurationState.Instance.Multiplayer.LdnServer, ConfigurationState.Instance.Multiplayer.LdnServer,
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value)); ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
} }
private static IHardwareDeviceDriver InitializeAudio() private static IHardwareDeviceDriver InitializeAudio()

View File

@ -17426,25 +17426,25 @@
"ID": "TitleUpdateVersionLabel", "ID": "TitleUpdateVersionLabel",
"Translations": { "Translations": {
"ar_SA": "الإصدار: {0}", "ar_SA": "الإصدار: {0}",
"de_DE": "Version {0} - {1}", "de_DE": "",
"el_GR": "Version {0} - {1}", "el_GR": "",
"en_US": "Version {0} - {1}", "en_US": "Version {0}",
"es_ES": "Versión {0} - {1}", "es_ES": "Versión {0}",
"fr_FR": "", "fr_FR": "",
"he_IL": "גרסה {0} - {1}", "he_IL": "גרסה: {0}",
"it_IT": "Versione {0} - {1}", "it_IT": "Versione {0}",
"ja_JP": "バージョン {0} - {1}", "ja_JP": "バージョン {0}",
"ko_KR": "버전 {0} - {1}", "ko_KR": "버전 {0}",
"no_NO": "Versjon {0} - {1}", "no_NO": "Versjon {0}",
"pl_PL": "Wersja {0} - {1}", "pl_PL": "Wersja {0}",
"pt_BR": "Versão {0} - {1}", "pt_BR": "Versão {0}",
"ru_RU": "Версия {0} - {1}", "ru_RU": "Версия {0}",
"sv_SE": "Version {0} - {1}", "sv_SE": "Version {0}",
"th_TH": "เวอร์ชั่น {0} - {1}", "th_TH": "เวอร์ชั่น {0}",
"tr_TR": "Sürüm {0} - {1}", "tr_TR": "Sürüm {0}",
"uk_UA": "Версія {0} - {1}", "uk_UA": "Версія {0}",
"zh_CN": "游戏更新的版本 {0} - {1}", "zh_CN": "游戏更新的版本 {0}",
"zh_TW": "版本 {0} - {1}" "zh_TW": "版本 {0}"
} }
}, },
{ {

View File

@ -15,12 +15,12 @@ using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Loaders.Processes.Extensions;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Helper;
using System; using System;
using System.Buffers; using System.Buffers;
using System.IO; using System.IO;

View File

@ -1,8 +1,8 @@
using Gommon; using Gommon;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.UI.Common.Configuration;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.UI.Common.Models.Amiibo namespace Ryujinx.Ava.Common.Models.Amiibo
{ {
public struct AmiiboApi : IEquatable<AmiiboApi> public struct AmiiboApi : IEquatable<AmiiboApi>
{ {

View File

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.UI.Common.Models.Amiibo namespace Ryujinx.Ava.Common.Models.Amiibo
{ {
public class AmiiboApiGamesSwitch public class AmiiboApiGamesSwitch
{ {

View File

@ -1,6 +1,6 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.UI.Common.Models.Amiibo namespace Ryujinx.Ava.Common.Models.Amiibo
{ {
public class AmiiboApiUsage public class AmiiboApiUsage
{ {

View File

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.UI.Common.Models.Amiibo namespace Ryujinx.Ava.Common.Models.Amiibo
{ {
public struct AmiiboJson public struct AmiiboJson
{ {

View File

@ -1,9 +1,7 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.UI.Common.Models.Amiibo namespace Ryujinx.Ava.Common.Models.Amiibo
{ {
[JsonSerializable(typeof(AmiiboJson))] [JsonSerializable(typeof(AmiiboJson))]
public partial class AmiiboJsonSerializerContext : JsonSerializerContext public partial class AmiiboJsonSerializerContext : JsonSerializerContext;
{
}
} }

View File

@ -1,4 +1,4 @@
namespace Ryujinx.UI.Common.Models namespace Ryujinx.Ava.Common.Models
{ {
// NOTE: most consuming code relies on this model being value-comparable // NOTE: most consuming code relies on this model being value-comparable
public record DownloadableContentModel(ulong TitleId, string ContainerPath, string FullPath) public record DownloadableContentModel(ulong TitleId, string ContainerPath, string FullPath)

View File

@ -1,4 +1,4 @@
namespace Ryujinx.UI.Common.Models.Github namespace Ryujinx.Ava.Common.Models.Github
{ {
public class GithubReleaseAssetJsonResponse public class GithubReleaseAssetJsonResponse
{ {

View File

@ -1,6 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.UI.Common.Models.Github namespace Ryujinx.Ava.Common.Models.Github
{ {
public class GithubReleasesJsonResponse public class GithubReleasesJsonResponse
{ {

View File

@ -1,9 +1,7 @@
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
namespace Ryujinx.UI.Common.Models.Github namespace Ryujinx.Ava.Common.Models.Github
{ {
[JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)]
public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext;
{
}
} }

View File

@ -1,4 +1,4 @@
namespace Ryujinx.UI.Common.Models namespace Ryujinx.Ava.Common.Models
{ {
// NOTE: most consuming code relies on this model being value-comparable // NOTE: most consuming code relies on this model being value-comparable
public record TitleUpdateModel(ulong TitleId, ulong Version, string DisplayVersion, string Path) public record TitleUpdateModel(ulong TitleId, ulong Version, string DisplayVersion, string Path)

View File

@ -1,8 +1,8 @@
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.UI.App.Common;
namespace Ryujinx.UI.Common.Models namespace Ryujinx.Ava.Common.Models
{ {
public record XCITrimmerFileModel( public record XCITrimmerFileModel(
string Name, string Name,

View File

@ -1,13 +1,14 @@
using DiscordRPC; using DiscordRPC;
using Humanizer; using Humanizer;
using Humanizer.Localisation; using Humanizer.Localisation;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.HLE;
using Ryujinx.HLE.Loaders.Processes; using Ryujinx.HLE.Loaders.Processes;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Configuration;
using System.Text; using System.Text;
namespace Ryujinx.UI.Common namespace Ryujinx.Ava
{ {
public static class DiscordIntegrationModule public static class DiscordIntegrationModule
{ {
@ -44,6 +45,16 @@ namespace Ryujinx.UI.Common
}; };
ConfigurationState.Instance.EnableDiscordIntegration.Event += Update; ConfigurationState.Instance.EnableDiscordIntegration.Event += Update;
TitleIDs.CurrentApplication.Event += (_, e) =>
{
if (e.NewValue)
SwitchToPlayingState(
ApplicationLibrary.LoadAndSaveMetaData(e.NewValue),
Switch.Shared.Processes.ActiveApplication
);
else
SwitchToMainState();
};
} }
private static void Update(object sender, ReactiveEventArgs<bool> evnt) private static void Update(object sender, ReactiveEventArgs<bool> evnt)
@ -69,7 +80,7 @@ namespace Ryujinx.UI.Common
} }
} }
public static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes) private static void SwitchToPlayingState(ApplicationMetadata appMeta, ProcessResult procRes)
{ {
_discordClient?.SetPresence(new RichPresence _discordClient?.SetPresence(new RichPresence
{ {
@ -88,7 +99,7 @@ namespace Ryujinx.UI.Common
}); });
} }
public static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain); private static void SwitchToMainState() => _discordClient?.SetPresence(_discordPresenceMain);
private static string TruncateToByteLength(string input) private static string TruncateToByteLength(string input)
{ {

View File

@ -2,6 +2,7 @@
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Ava; using Ryujinx.Ava;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller; using Ryujinx.Common.Configuration.Hid.Controller;
@ -16,8 +17,6 @@ using Ryujinx.Graphics.OpenGL;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.Input; using Ryujinx.Input;
using Ryujinx.UI.Common;
using Ryujinx.UI.Common.Configuration;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
using System.IO; using System.IO;

View File

@ -1,6 +1,7 @@
using CommandLine; using CommandLine;
using Gommon; using Gommon;
using Ryujinx.Ava; using Ryujinx.Ava;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
@ -13,9 +14,6 @@ using Ryujinx.Cpu;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.Graphics.Gpu.Shader; using Ryujinx.Graphics.Gpu.Shader;
using Ryujinx.Graphics.Metal;
using Ryujinx.Graphics.OpenGL;
using Ryujinx.Graphics.Vulkan;
using Ryujinx.Graphics.Vulkan.MoltenVK; using Ryujinx.Graphics.Vulkan.MoltenVK;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
@ -25,7 +23,6 @@ using Ryujinx.Input;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
using Ryujinx.Input.SDL2; using Ryujinx.Input.SDL2;
using Ryujinx.SDL2.Common; using Ryujinx.SDL2.Common;
using Ryujinx.UI.Common.Configuration;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View File

@ -1,11 +1,11 @@
using CommandLine; using CommandLine;
using Gommon; using Gommon;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.UI.Common.Configuration;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -8,6 +8,10 @@ using Projektanker.Icons.Avalonia.MaterialDesign;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Ava.Utilities.SystemInfo;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.GraphicsDriver;
@ -16,11 +20,6 @@ using Ryujinx.Common.SystemInterop;
using Ryujinx.Graphics.Vulkan.MoltenVK; using Ryujinx.Graphics.Vulkan.MoltenVK;
using Ryujinx.Headless; using Ryujinx.Headless;
using Ryujinx.SDL2.Common; using Ryujinx.SDL2.Common;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Helper;
using Ryujinx.UI.Common.SystemInfo;
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -117,9 +116,6 @@ namespace Ryujinx.Ava
// Setup base data directory. // Setup base data directory.
AppDataManager.Initialize(CommandLineState.BaseDirPathArg); AppDataManager.Initialize(CommandLineState.BaseDirPathArg);
// Set the delegate for localizing the word "never" in the UI
ApplicationData.LocalizedNever = () => LocaleManager.Instance[LocaleKeys.Never];
// Initialize the configuration. // Initialize the configuration.
ConfigurationState.Initialize(); ConfigurationState.Initialize();

View File

@ -48,6 +48,7 @@
<PackageReference Include="Avalonia.Svg" /> <PackageReference Include="Avalonia.Svg" />
<PackageReference Include="Avalonia.Svg.Skia" /> <PackageReference Include="Avalonia.Svg.Skia" />
<PackageReference Include="CommandLineParser" /> <PackageReference Include="CommandLineParser" />
<PackageReference Include="DiscordRichPresence" />
<PackageReference Include="DynamicData" /> <PackageReference Include="DynamicData" />
<PackageReference Include="FluentAvaloniaUI" /> <PackageReference Include="FluentAvaloniaUI" />
<PackageReference Include="Projektanker.Icons.Avalonia" /> <PackageReference Include="Projektanker.Icons.Avalonia" />
@ -57,6 +58,7 @@
<PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" /> <PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'osx-x64' AND '$(RuntimeIdentifier)' != 'osx-arm64'" />
<PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" /> <PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" />
<PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" /> <PackageReference Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'linux-arm64' AND '$(RuntimeIdentifier)' != 'win-x64'" />
<PackageReference Include="securifybv.ShellLink" />
<PackageReference Include="Silk.NET.Vulkan" /> <PackageReference Include="Silk.NET.Vulkan" />
<PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" /> <PackageReference Include="Silk.NET.Vulkan.Extensions.EXT" />
<PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" /> <PackageReference Include="Silk.NET.Vulkan.Extensions.KHR" />
@ -77,7 +79,6 @@
<ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" /> <ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" />
<ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" /> <ProjectReference Include="..\ARMeilleure\ARMeilleure.csproj" />
<ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" /> <ProjectReference Include="..\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
<ProjectReference Include="..\Ryujinx.UI.Common\Ryujinx.UI.Common.csproj" />
<ProjectReference Include="..\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" /> <ProjectReference Include="..\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup> </ItemGroup>
@ -128,12 +129,33 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop">
<Link>Assets\ShortcutFiles\shortcut-template.desktop</Link>
</EmbeddedResource>
<EmbeddedResource Include="..\..\distribution\macos\shortcut-launch-script.sh">
<Link>Assets\ShortcutFiles\shortcut-launch-script.sh</Link>
</EmbeddedResource>
<EmbeddedResource Include="..\..\distribution\macos\shortcut-template.plist">
<Link>Assets\ShortcutFiles\shortcut-template.plist</Link>
</EmbeddedResource>
<EmbeddedResource Include="Assets\locales.json" /> <EmbeddedResource Include="Assets\locales.json" />
<EmbeddedResource Include="Assets\Styles\Styles.xaml" /> <EmbeddedResource Include="Assets\Styles\Styles.xaml" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_ProCon.svg" /> <EmbeddedResource Include="Assets\Icons\Controller_ProCon.svg" />
<EmbeddedResource Include="Assets\UIImages\Icon_NCA.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NRO.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NSO.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_NSP.png" />
<EmbeddedResource Include="Assets\UIImages\Icon_XCI.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Amiibo.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Discord_Dark.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Discord_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Dark.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_GitHub_Light.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx.png" />
<EmbeddedResource Include="Assets\UIImages\Logo_Ryujinx_AntiAlias.png" />
<EmbeddedResource Include="Headless\Ryujinx.bmp" LogicalName="HeadlessLogo" /> <EmbeddedResource Include="Headless\Ryujinx.bmp" LogicalName="HeadlessLogo" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -11,10 +11,10 @@ using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Helper;
using System; using System;
using System.Diagnostics; using System.Diagnostics;

View File

@ -5,12 +5,12 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.HOS.Applets; using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard; using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard;
using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types; using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationProxy.Types;
using Ryujinx.HLE.UI; using Ryujinx.HLE.UI;
using Ryujinx.UI.Common.Configuration;
using System; using System;
using System.Threading; using System.Threading;

View File

@ -25,7 +25,7 @@
Height="80" Height="80"
MinWidth="50" MinWidth="50"
Margin="5,10,20,10" Margin="5,10,20,10"
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" /> Source="resm:Ryujinx.Assets.UIImages.Logo_Ryujinx.png?assembly=Ryujinx" />
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"

View File

@ -20,7 +20,7 @@
MinWidth="50" MinWidth="50"
Margin="5,10,20,10" Margin="5,10,20,10"
VerticalAlignment="Center" VerticalAlignment="Center"
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" /> Source="resm:Ryujinx.Assets.UIImages.Logo_Ryujinx.png?assembly=Ryujinx" />
<TextBlock <TextBlock
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"

View File

@ -10,10 +10,11 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Helper;
using SkiaSharp; using SkiaSharp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -3,7 +3,7 @@ using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.UI.App.Common; using Ryujinx.Ava.Utilities.AppLibrary;
using System; using System;
namespace Ryujinx.Ava.UI.Controls namespace Ryujinx.Ava.UI.Controls

View File

@ -5,7 +5,7 @@ using Avalonia.Interactivity;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.UI.App.Common; using Ryujinx.Ava.Utilities.AppLibrary;
using System; using System;
using System.Linq; using System.Linq;

View File

@ -26,7 +26,7 @@
Height="70" Height="70"
MinWidth="50" MinWidth="50"
Margin="5,10,20,10" Margin="5,10,20,10"
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.UI.Common" /> Source="resm:Ryujinx.Assets.UIImages.Logo_Ryujinx.png?assembly=Ryujinx" />
<StackPanel <StackPanel
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"

View File

@ -1,5 +1,5 @@
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Ryujinx.UI.App.Common; using Ryujinx.Ava.Utilities.AppLibrary;
namespace Ryujinx.Ava.UI.Helpers namespace Ryujinx.Ava.UI.Helpers
{ {

View File

@ -1,8 +1,7 @@
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.UI.App.Common; using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.UI.Common.Helper;
using System; using System;
using System.Globalization; using System.Globalization;

View File

@ -1,5 +1,5 @@
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.UI.Common; using Ryujinx.Common.UI;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Helpers namespace Ryujinx.Ava.UI.Helpers

View File

@ -3,7 +3,7 @@ using Avalonia.Data;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Gommon; using Gommon;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.UI.Common.Models; using Ryujinx.Ava.Common.Models;
using System; using System;
using System.Globalization; using System.Globalization;

View File

@ -2,7 +2,7 @@ using Avalonia;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.UI.Common.Models; using Ryujinx.Ava.Common.Models;
using System; using System;
using System.Globalization; using System.Globalization;
using static Ryujinx.Common.Utilities.XCIFileTrimmer; using static Ryujinx.Common.Utilities.XCIFileTrimmer;

View File

@ -1,7 +1,7 @@
using Avalonia; using Avalonia;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Ryujinx.UI.Common.Models; using Ryujinx.Ava.Common.Models;
using System; using System;
using System.Globalization; using System.Globalization;
using static Ryujinx.Common.Utilities.XCIFileTrimmer; using static Ryujinx.Common.Utilities.XCIFileTrimmer;

View File

@ -1,4 +1,4 @@
using Ryujinx.UI.App.Common; using Ryujinx.Ava.Utilities.AppLibrary;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,4 +1,4 @@
using Ryujinx.UI.App.Common; using Ryujinx.Ava.Utilities.AppLibrary;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -3,9 +3,9 @@ using LibHac.Fs;
using LibHac.Ncm; using LibHac.Ncm;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Helper;
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@ -2,9 +2,9 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Platform; using Avalonia.Platform;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.UI.Common.Configuration; using Ryujinx.Common.Helper;
using Ryujinx.UI.Common.Helper;
using SPB.Graphics; using SPB.Graphics;
using SPB.Platform; using SPB.Platform;
using SPB.Platform.GLX; using SPB.Platform.GLX;

View File

@ -1,9 +1,9 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.OpenGL;
using Ryujinx.UI.Common.Configuration;
using SPB.Graphics; using SPB.Graphics;
using SPB.Graphics.Exceptions; using SPB.Graphics.Exceptions;
using SPB.Graphics.OpenGL; using SPB.Graphics.OpenGL;

View File

@ -1,10 +1,10 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Gommon; using Gommon;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.UI.Common.Configuration;
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;

View File

@ -3,7 +3,7 @@ using Avalonia.Styling;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.UI.Common.Configuration; using Ryujinx.Ava.Utilities.Configuration;
using System; using System;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
@ -66,11 +66,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark); bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
string basePath = "resm:Ryujinx.UI.Common.Resources."; string basePath = "resm:Ryujinx.Assets.UIImages.";
string themeSuffix = isDarkTheme ? "Dark.png" : "Light.png"; string themeSuffix = isDarkTheme ? "Dark.png" : "Light.png";
GithubLogo = LoadBitmap($"{basePath}Logo_GitHub_{themeSuffix}?assembly=Ryujinx.UI.Common"); GithubLogo = LoadBitmap($"{basePath}Logo_GitHub_{themeSuffix}?assembly=Ryujinx");
DiscordLogo = LoadBitmap($"{basePath}Logo_Discord_{themeSuffix}?assembly=Ryujinx.UI.Common"); DiscordLogo = LoadBitmap($"{basePath}Logo_Discord_{themeSuffix}?assembly=Ryujinx");
} }
private static Bitmap LoadBitmap(string uri) => new(Avalonia.Platform.AssetLoader.Open(new Uri(uri))); private static Bitmap LoadBitmap(string uri) => new(Avalonia.Platform.AssetLoader.Open(new Uri(uri)));

View File

@ -3,13 +3,13 @@ using Avalonia.Collections;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models.Amiibo;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.UI.Common.Models.Amiibo;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -68,7 +68,7 @@ namespace Ryujinx.Ava.UI.ViewModels
_amiiboSeries = new ObservableCollection<string>(); _amiiboSeries = new ObservableCollection<string>();
_amiibos = new AvaloniaList<AmiiboApi>(); _amiibos = new AvaloniaList<AmiiboApi>();
_amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.UI.Common/Resources/Logo_Amiibo.png"); _amiiboLogoBytes = EmbeddedResources.Read("Ryujinx/Assets/UIImages/Logo_Amiibo.png");
_ = LoadContentAsync(); _ = LoadContentAsync();
} }

View File

@ -1,4 +1,4 @@
using Ryujinx.UI.App.Common; using Ryujinx.Ava.Utilities.AppLibrary;
using System; using System;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels

View File

@ -13,8 +13,9 @@ namespace Ryujinx.Ava.UI.ViewModels
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
protected void OnPropertiesChanged(params ReadOnlySpan<string> propertyNames) protected void OnPropertiesChanged(string firstPropertyName, params ReadOnlySpan<string> propertyNames)
{ {
OnPropertyChanged(firstPropertyName);
foreach (var propertyName in propertyNames) foreach (var propertyName in propertyNames)
{ {
OnPropertyChanged(propertyName); OnPropertyChanged(propertyName);

View File

@ -5,10 +5,10 @@ using Avalonia.Threading;
using DynamicData; using DynamicData;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Models;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@ -10,6 +10,7 @@ using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
@ -19,7 +20,6 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.Input; using Ryujinx.Input;
using Ryujinx.UI.Common.Configuration;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -35,10 +35,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public class InputViewModel : BaseModel, IDisposable public class InputViewModel : BaseModel, IDisposable
{ {
private const string Disabled = "disabled"; private const string Disabled = "disabled";
private const string ProControllerResource = "Ryujinx.UI.Common/Resources/Controller_ProCon.svg"; private const string ProControllerResource = "Ryujinx/Assets/Icons/Controller_ProCon.svg";
private const string JoyConPairResource = "Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg"; private const string JoyConPairResource = "Ryujinx/Assets/Icons/Controller_JoyConPair.svg";
private const string JoyConLeftResource = "Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg"; private const string JoyConLeftResource = "Ryujinx/Assets/Icons/Controller_JoyConLeft.svg";
private const string JoyConRightResource = "Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg"; private const string JoyConRightResource = "Ryujinx/Assets/Icons/Controller_JoyConRight.svg";
private const string KeyboardString = "keyboard"; private const string KeyboardString = "keyboard";
private const string ControllerString = "controller"; private const string ControllerString = "controller";
private readonly MainWindow _mainWindow; private readonly MainWindow _mainWindow;

View File

@ -21,9 +21,13 @@ using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.Models.Generic; using Ryujinx.Ava.UI.Models.Generic;
using Ryujinx.Ava.UI.Renderer; using Ryujinx.Ava.UI.Renderer;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.UI;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.Cpu; using Ryujinx.Cpu;
using Ryujinx.HLE; using Ryujinx.HLE;
@ -33,10 +37,6 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption; using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
using Ryujinx.HLE.UI; using Ryujinx.HLE.UI;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Helper;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using SkiaSharp; using SkiaSharp;
using System; using System;
@ -133,7 +133,7 @@ namespace Ryujinx.Ava.UI.ViewModels
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left. // For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
// The border gets reduced to colored pixels in the 4 corners. // The border gets reduced to colored pixels in the 4 corners.
public static readonly Bitmap IconBitmap = public static readonly Bitmap IconBitmap =
new(Assembly.GetAssembly(typeof(ConfigurationState))!.GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Ryujinx_AntiAlias.png")!); new(Assembly.GetAssembly(typeof(MainWindowViewModel))!.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
public MainWindow Window { get; init; } public MainWindow Window { get; init; }

View File

@ -0,0 +1,77 @@
using Gommon;
using Ryujinx.Ava.Utilities.Configuration;
namespace Ryujinx.Ava.UI.ViewModels
{
public class SettingsHacksViewModel : BaseModel
{
private readonly SettingsViewModel _baseViewModel;
public SettingsHacksViewModel() {}
public SettingsHacksViewModel(SettingsViewModel settingsVm)
{
_baseViewModel = settingsVm;
}
private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
private bool _shaderTranslationThreadSleep = ConfigurationState.Instance.Hacks.EnableShaderTranslationDelay;
private int _shaderTranslationSleepDelay = ConfigurationState.Instance.Hacks.ShaderTranslationDelay;
public bool Xc2MenuSoftlockFixEnabled
{
get => _xc2MenuSoftlockFix;
set
{
_xc2MenuSoftlockFix = value;
OnPropertyChanged();
}
}
public bool ShaderTranslationDelayEnabled
{
get => _shaderTranslationThreadSleep;
set
{
_shaderTranslationThreadSleep = value;
OnPropertyChanged();
}
}
public string ShaderTranslationDelayTooltipText => $"Current value: {ShaderTranslationDelay}";
public int ShaderTranslationDelay
{
get => _shaderTranslationSleepDelay;
set
{
_shaderTranslationSleepDelay = value;
OnPropertiesChanged(nameof(ShaderTranslationDelay), nameof(ShaderTranslationDelayTooltipText));
}
}
public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
{
sb.AppendLine(
"This fix applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.")
.AppendLine();
sb.AppendLine("From the issue on GitHub:").AppendLine();
sb.Append(
"When clicking very fast from game main menu to 2nd submenu, " +
"there is a low chance that the game will softlock, " +
"the submenu won't show up, while background music is still there.");
});
public static string ShaderTranslationDelayTooltip { get; } = Lambda.String(sb =>
{
sb.AppendLine("This hack applies the delay you specify every time shaders are attempted to be translated.")
.AppendLine();
sb.Append("Configurable via slider, only when this option is enabled.");
});
}
}

View File

@ -1,6 +1,7 @@
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Threading; using Avalonia.Threading;
using Gommon;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL2;
@ -9,6 +10,8 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.GraphicsDriver;
@ -17,8 +20,6 @@ using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.Services.Time.TimeZone; using Ryujinx.HLE.HOS.Services.Time.TimeZone;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Configuration.System;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
@ -62,7 +63,9 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _networkInterfaceIndex; private int _networkInterfaceIndex;
private int _multiplayerModeIndex; private int _multiplayerModeIndex;
private string _ldnPassphrase; private string _ldnPassphrase;
private string _LdnServer; private string _ldnServer;
public SettingsHacksViewModel DirtyHacks { get; }
public int ResolutionScale public int ResolutionScale
{ {
@ -162,9 +165,7 @@ namespace Ryujinx.Ava.UI.ViewModels
get => _vSyncMode; get => _vSyncMode;
set set
{ {
if (value == VSyncMode.Custom || if (value is VSyncMode.Custom or VSyncMode.Switch or VSyncMode.Unbounded)
value == VSyncMode.Switch ||
value == VSyncMode.Unbounded)
{ {
_vSyncMode = value; _vSyncMode = value;
OnPropertyChanged(); OnPropertyChanged();
@ -258,6 +259,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool UseHypervisor { get; set; } public bool UseHypervisor { get; set; }
public bool DisableP2P { get; set; } public bool DisableP2P { get; set; }
public bool ShowDirtyHacks => ConfigurationState.Instance.Hacks.ShowDirtyHacks;
public string TimeZone { get; set; } public string TimeZone { get; set; }
public string ShaderDumpPath { get; set; } public string ShaderDumpPath { get; set; }
@ -374,10 +377,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public string LdnServer public string LdnServer
{ {
get => _LdnServer; get => _ldnServer;
set set
{ {
_LdnServer = value; _ldnServer = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
@ -386,9 +389,12 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
_virtualFileSystem = virtualFileSystem; _virtualFileSystem = virtualFileSystem;
_contentManager = contentManager; _contentManager = contentManager;
if (Program.PreviewerDetached) if (Program.PreviewerDetached)
{ {
Task.Run(LoadTimeZones); Task.Run(LoadTimeZones);
DirtyHacks = new SettingsHacksViewModel(this);
} }
} }
@ -408,6 +414,8 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
Task.Run(LoadAvailableGpus); Task.Run(LoadAvailableGpus);
LoadCurrentConfiguration(); LoadCurrentConfiguration();
DirtyHacks = new SettingsHacksViewModel(this);
} }
} }
@ -622,9 +630,9 @@ namespace Ryujinx.Ava.UI.ViewModels
OpenglDebugLevel = (int)config.Logger.GraphicsDebugLevel.Value; OpenglDebugLevel = (int)config.Logger.GraphicsDebugLevel.Value;
MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value; MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value;
DisableP2P = config.Multiplayer.DisableP2p.Value; DisableP2P = config.Multiplayer.DisableP2p;
LdnPassphrase = config.Multiplayer.LdnPassphrase.Value; LdnPassphrase = config.Multiplayer.LdnPassphrase;
LdnServer = config.Multiplayer.LdnServer.Value; LdnServer = config.Multiplayer.LdnServer;
} }
public void SaveSettings() public void SaveSettings()
@ -747,6 +755,11 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Multiplayer.LdnPassphrase.Value = LdnPassphrase; config.Multiplayer.LdnPassphrase.Value = LdnPassphrase;
config.Multiplayer.LdnServer.Value = LdnServer; config.Multiplayer.LdnServer.Value = LdnServer;
// Dirty Hacks
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFixEnabled;
config.Hacks.EnableShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelayEnabled;
config.Hacks.ShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelay;
config.ToFileFormat().SaveConfig(Program.ConfigurationPath); config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
MainWindow.UpdateGraphicsConfig(); MainWindow.UpdateGraphicsConfig();

View File

@ -4,10 +4,10 @@ using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Models;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;

View File

@ -4,10 +4,10 @@ using Gommon;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Models;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@ -371,6 +371,16 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public XCITrimmerFileModel NullableProcessingApplication
{
get => _processingApplication.OrDefault();
set
{
_processingApplication = value;
OnPropertyChanged();
}
}
public bool Processing public bool Processing
{ {
get => _cancellationTokenSource != null; get => _cancellationTokenSource != null;

View File

@ -7,12 +7,12 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption; using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
using Ryujinx.UI.Common;
using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Helper;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -5,10 +5,10 @@ using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.UI.Common.Configuration;
using System; using System;
namespace Ryujinx.Ava.UI.Views.Main namespace Ryujinx.Ava.UI.Views.Main

View File

@ -0,0 +1,76 @@
<UserControl
x:Class="Ryujinx.Ava.UI.Views.Settings.SettingsHacksView"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
mc:Ignorable="d"
x:DataType="viewModels:SettingsViewModel">
<Design.DataContext>
<viewModels:SettingsViewModel />
</Design.DataContext>
<ScrollViewer
Name="HacksPage"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<Border Classes="settings">
<StackPanel
Margin="10"
HorizontalAlignment="Center"
Orientation="Vertical"
Spacing="5">
<TextBlock
HorizontalAlignment="Center"
Classes="h1"
Text="Dirty Hacks" />
<TextBlock
Foreground="{DynamicResource SecondaryTextColor}"
TextDecorations="Underline"
Text="Game-specific hacks &amp; tricks to alleviate performance issues or crashing. Will cause issues." />
<StackPanel
Margin="0,10,0,0"
Orientation="Horizontal"
HorizontalAlignment="Center"
ToolTip.Tip="{Binding DirtyHacks.Xc2MenuFixTooltip}">
<CheckBox
Margin="0"
IsChecked="{Binding DirtyHacks.Xc2MenuSoftlockFixEnabled}"/>
<TextBlock
VerticalAlignment="Center"
Text="Xenoblade Chronicles 2 Menu Softlock Fix" />
</StackPanel>
<Separator/>
<StackPanel
Margin="0,10,0,0"
Orientation="Horizontal"
HorizontalAlignment="Center"
ToolTip.Tip="{Binding DirtyHacks.ShaderTranslationDelayTooltip}">
<CheckBox
Margin="0"
IsChecked="{Binding DirtyHacks.ShaderTranslationDelayEnabled}"/>
<TextBlock VerticalAlignment="Center"
Text="Arbitrary Delay on Shader Translation"/>
</StackPanel>
<Slider IsVisible="{Binding DirtyHacks.ShaderTranslationDelayEnabled}"
HorizontalAlignment="Center"
Value="{Binding DirtyHacks.ShaderTranslationDelay}"
ToolTip.Tip="{Binding DirtyHacks.ShaderTranslationDelayTooltipText}"
Width="175"
Margin="0,-3,0,0"
Height="32"
Padding="0,-5"
TickFrequency="1"
IsSnapToTickEnabled="True"
LargeChange="10"
SmallChange="1"
VerticalAlignment="Center"
Minimum="1"
Maximum="1000" />
<Separator/>
</StackPanel>
</Border>
</ScrollViewer>
</UserControl>

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