Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 208e685e27 | |||
| 9227cbe5a7 | |||
| 332bcdfaf1 | |||
| 1c8276197f | |||
| a3596ba858 | |||
| 38ed71ddfe | |||
| 3ffcc72117 | |||
| 80d619f010 | |||
| fe1617ffea | |||
| eb6b0e9adc | |||
| 9631bdfe16 | |||
| 2a84656ffc | |||
| 6c6580ddcc | |||
| c47448628c | |||
| d0ac83b493 | |||
| e0ddbe55c0 | |||
| 4a4078865f | |||
| 3f59bade94 | |||
| c2ed0fd5fd |
@@ -42,7 +42,7 @@
|
|||||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
|
||||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||||
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
|
||||||
<PackageVersion Include="Gommon" Version="2.7.1" />
|
<PackageVersion Include="Gommon" Version="2.7.1.1" />
|
||||||
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
|
||||||
<PackageVersion Include="Sep" Version="0.6.0" />
|
<PackageVersion Include="Sep" Version="0.6.0" />
|
||||||
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
<PackageVersion Include="shaderc.net" Version="0.1.0" />
|
||||||
|
|||||||
@@ -1436,7 +1436,7 @@
|
|||||||
010083A018262000,"Hitman: Blood Money — Reprisal",deadlock,ingame,2024-09-28 16:28:50
|
010083A018262000,"Hitman: Blood Money — Reprisal",deadlock,ingame,2024-09-28 16:28:50
|
||||||
01004B100A5CC000,"Hob: The Definitive Edition",,playable,2021-01-13 09:39:19
|
01004B100A5CC000,"Hob: The Definitive Edition",,playable,2021-01-13 09:39:19
|
||||||
0100F7300ED2C000,"Hoggy2",,playable,2022-10-10 13:53:35
|
0100F7300ED2C000,"Hoggy2",,playable,2022-10-10 13:53:35
|
||||||
0100F7E00C70E000,"Hogwarts Legacy",slow,ingame,2024-09-03 19:53:58
|
0100F7E00C70E000,"Hogwarts Legacy",UE4;slow,ingame,2024-09-03 19:53:58
|
||||||
0100633007D48000,"Hollow Knight",nvdec,playable,2023-01-16 15:44:56
|
0100633007D48000,"Hollow Knight",nvdec,playable,2023-01-16 15:44:56
|
||||||
0100F2100061E800,"Hollow0",UE4;gpu,ingame,2021-03-03 23:42:56
|
0100F2100061E800,"Hollow0",UE4;gpu,ingame,2021-03-03 23:42:56
|
||||||
0100342009E16000,"Holy Potatoes! What The Hell?!",,playable,2020-07-03 10:48:56
|
0100342009E16000,"Holy Potatoes! What The Hell?!",,playable,2020-07-03 10:48:56
|
||||||
@@ -1800,6 +1800,7 @@
|
|||||||
010005A00B312000,"Megaton Rainfall",gpu;opengl,boots,2022-08-04 18:29:43
|
010005A00B312000,"Megaton Rainfall",gpu;opengl,boots,2022-08-04 18:29:43
|
||||||
0100EA100DF92000,"Meiji Katsugeki Haikara Ryuuseigumi - Seibai Shimaseu, Yonaoshi Kagyou",32-bit;nvdec,playable,2022-12-05 13:19:12
|
0100EA100DF92000,"Meiji Katsugeki Haikara Ryuuseigumi - Seibai Shimaseu, Yonaoshi Kagyou",32-bit;nvdec,playable,2022-12-05 13:19:12
|
||||||
0100B360068B2000,"Mekorama",gpu,boots,2021-06-17 16:37:21
|
0100B360068B2000,"Mekorama",gpu,boots,2021-06-17 16:37:21
|
||||||
|
010012301932A000,"Melatonin",,playable,2025-02-16 04:08:17
|
||||||
01000FA010340000,"Melbits World",nvdec;online,menus,2021-11-26 13:51:22
|
01000FA010340000,"Melbits World",nvdec;online,menus,2021-11-26 13:51:22
|
||||||
0100F68019636000,"Melon Journey",,playable,2023-04-23 21:20:01
|
0100F68019636000,"Melon Journey",,playable,2023-04-23 21:20:01
|
||||||
010079C012896000,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
|
010079C012896000,"Memories Off -Innocent Fille- for Dearest",,playable,2020-08-04 07:31:22
|
||||||
|
|||||||
|
@@ -24,7 +24,7 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
private static JitCacheInvalidation _jitCacheInvalidator;
|
private static JitCacheInvalidation _jitCacheInvalidator;
|
||||||
|
|
||||||
private static CacheMemoryAllocator _cacheAllocator;
|
private static List<CacheMemoryAllocator> _cacheAllocators = [];
|
||||||
|
|
||||||
private static readonly List<CacheEntry> _cacheEntries = [];
|
private static readonly List<CacheEntry> _cacheEntries = [];
|
||||||
|
|
||||||
@@ -40,37 +40,48 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
public static void Initialize(IJitMemoryAllocator allocator)
|
public static void Initialize(IJitMemoryAllocator allocator)
|
||||||
{
|
{
|
||||||
if (_initialized)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
lock (_lock)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
if (_initialized)
|
if (_initialized)
|
||||||
{
|
{
|
||||||
return;
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
JitUnwindWindows.RemoveFunctionTableHandler(
|
||||||
|
_jitRegions[0].Pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < _jitRegions.Count; i++)
|
||||||
|
{
|
||||||
|
_jitRegions[i].Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
_jitRegions.Clear();
|
||||||
|
_cacheAllocators.Clear();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_activeRegionIndex = 0;
|
||||||
|
|
||||||
ReservedRegion firstRegion = new(allocator, CacheSize);
|
ReservedRegion firstRegion = new(allocator, CacheSize);
|
||||||
_jitRegions.Add(firstRegion);
|
_jitRegions.Add(firstRegion);
|
||||||
_activeRegionIndex = 0;
|
|
||||||
|
CacheMemoryAllocator firstCacheAllocator = new(CacheSize);
|
||||||
|
_cacheAllocators.Add(firstCacheAllocator);
|
||||||
|
|
||||||
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
if (!OperatingSystem.IsWindows() && !OperatingSystem.IsMacOS())
|
||||||
{
|
{
|
||||||
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
_jitCacheInvalidator = new JitCacheInvalidation(allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
|
||||||
|
|
||||||
if (OperatingSystem.IsWindows())
|
if (OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
JitUnwindWindows.InstallFunctionTableHandler(
|
JitUnwindWindows.InstallFunctionTableHandler(
|
||||||
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
firstRegion.Pointer, CacheSize, firstRegion.Pointer + Allocate(_pageSize)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_initialized = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +147,7 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
|
|
||||||
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
if (TryFind(funcOffset, out CacheEntry entry, out int entryIndex) && entry.Offset == funcOffset)
|
||||||
{
|
{
|
||||||
_cacheAllocator.Free(funcOffset, AlignCodeSize(entry.Size));
|
_cacheAllocators[_activeRegionIndex].Free(funcOffset, AlignCodeSize(entry.Size));
|
||||||
_cacheEntries.RemoveAt(entryIndex);
|
_cacheEntries.RemoveAt(entryIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,30 +178,24 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
{
|
{
|
||||||
codeSize = AlignCodeSize(codeSize);
|
codeSize = AlignCodeSize(codeSize);
|
||||||
|
|
||||||
for (int i = _activeRegionIndex; i < _jitRegions.Count; i++)
|
int allocOffset = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
||||||
|
|
||||||
|
if (allocOffset >= 0)
|
||||||
{
|
{
|
||||||
int allocOffset = _cacheAllocator.Allocate(codeSize);
|
_jitRegions[_activeRegionIndex].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
||||||
|
return allocOffset;
|
||||||
if (allocOffset >= 0)
|
|
||||||
{
|
|
||||||
_jitRegions[i].ExpandIfNeeded((ulong)allocOffset + (ulong)codeSize);
|
|
||||||
_activeRegionIndex = i;
|
|
||||||
return allocOffset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int exhaustedRegion = _activeRegionIndex;
|
int exhaustedRegion = _activeRegionIndex;
|
||||||
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
ReservedRegion newRegion = new(_jitRegions[0].Allocator, CacheSize);
|
||||||
_jitRegions.Add(newRegion);
|
_jitRegions.Add(newRegion);
|
||||||
_activeRegionIndex = _jitRegions.Count - 1;
|
_activeRegionIndex = _jitRegions.Count - 1;
|
||||||
|
|
||||||
int newRegionNumber = _activeRegionIndex;
|
|
||||||
|
|
||||||
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {newRegionNumber} ({((long)(newRegionNumber + 1) * CacheSize).Bytes()} Total Allocation).");
|
Logger.Warning?.Print(LogClass.Cpu, $"JIT Cache Region {exhaustedRegion} exhausted, creating new Cache Region {_activeRegionIndex} ({((long)(_activeRegionIndex + 1) * CacheSize).Bytes()} Total Allocation).");
|
||||||
|
|
||||||
_cacheAllocator = new CacheMemoryAllocator(CacheSize);
|
|
||||||
|
|
||||||
int allocOffsetNew = _cacheAllocator.Allocate(codeSize);
|
_cacheAllocators.Add(new CacheMemoryAllocator(CacheSize));
|
||||||
|
|
||||||
|
int allocOffsetNew = _cacheAllocators[_activeRegionIndex].Allocate(codeSize);
|
||||||
if (allocOffsetNew < 0)
|
if (allocOffsetNew < 0)
|
||||||
{
|
{
|
||||||
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
throw new OutOfMemoryException("Failed to allocate in new Cache Region!");
|
||||||
|
|||||||
@@ -52,6 +52,11 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
nint context,
|
nint context,
|
||||||
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
[MarshalAs(UnmanagedType.LPWStr)] string outOfProcessCallbackDll);
|
||||||
|
|
||||||
|
[LibraryImport("kernel32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
private static unsafe partial bool RtlDeleteFunctionTable(
|
||||||
|
ulong tableIdentifier);
|
||||||
|
|
||||||
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
private static GetRuntimeFunctionCallback _getRuntimeFunctionCallback;
|
||||||
|
|
||||||
private static int _sizeOfRuntimeFunction;
|
private static int _sizeOfRuntimeFunction;
|
||||||
@@ -91,6 +96,23 @@ namespace ARMeilleure.Translation.Cache
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void RemoveFunctionTableHandler(nint codeCachePointer)
|
||||||
|
{
|
||||||
|
ulong codeCachePtr = (ulong)codeCachePointer.ToInt64();
|
||||||
|
|
||||||
|
bool result;
|
||||||
|
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
result = RtlDeleteFunctionTable(codeCachePtr | 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Failure removing function table callback.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
private static unsafe RuntimeFunction* FunctionTableHandler(ulong controlPc, nint context)
|
||||||
{
|
{
|
||||||
int offset = (int)((long)controlPc - context.ToInt64());
|
int offset = (int)((long)controlPc - context.ToInt64());
|
||||||
|
|||||||
@@ -5,15 +5,34 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace Ryujinx.Common.Helper
|
namespace Ryujinx.Common.Helper
|
||||||
{
|
{
|
||||||
|
public enum OperatingSystemType
|
||||||
|
{
|
||||||
|
MacOS,
|
||||||
|
Linux,
|
||||||
|
Windows
|
||||||
|
}
|
||||||
|
|
||||||
public static class RunningPlatform
|
public static class RunningPlatform
|
||||||
{
|
{
|
||||||
|
public static readonly OperatingSystemType CurrentOS
|
||||||
|
= IsMacOS
|
||||||
|
? OperatingSystemType.MacOS
|
||||||
|
: IsWindows
|
||||||
|
? OperatingSystemType.Windows
|
||||||
|
: IsLinux
|
||||||
|
? OperatingSystemType.Linux
|
||||||
|
: throw new PlatformNotSupportedException();
|
||||||
|
|
||||||
|
public static Architecture Architecture => RuntimeInformation.OSArchitecture;
|
||||||
|
public static Architecture CurrentProcessArchitecture => RuntimeInformation.ProcessArchitecture;
|
||||||
|
|
||||||
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
public static bool IsMacOS => OperatingSystem.IsMacOS();
|
||||||
public static bool IsWindows => OperatingSystem.IsWindows();
|
public static bool IsWindows => OperatingSystem.IsWindows();
|
||||||
public static bool IsLinux => OperatingSystem.IsLinux();
|
public static bool IsLinux => OperatingSystem.IsLinux();
|
||||||
|
|
||||||
public static bool IsArm => RuntimeInformation.OSArchitecture is Architecture.Arm64;
|
public static bool IsArm => Architecture is Architecture.Arm64;
|
||||||
|
|
||||||
public static bool IsX64 => RuntimeInformation.OSArchitecture is Architecture.X64;
|
public static bool IsX64 => Architecture is Architecture.X64;
|
||||||
|
|
||||||
public static bool IsIntelMac => IsMacOS && IsX64;
|
public static bool IsIntelMac => IsMacOS && IsX64;
|
||||||
public static bool IsArmMac => IsMacOS && IsArm;
|
public static bool IsArmMac => IsMacOS && IsArm;
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Ryujinx.Common
|
||||||
|
{
|
||||||
|
public static class SharedConstants
|
||||||
|
{
|
||||||
|
public const string DefaultLanPlayHost = "ryuldn.vudjun.com";
|
||||||
|
public const short LanPlayPort = 30456;
|
||||||
|
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
-10
@@ -23,9 +23,6 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
{
|
{
|
||||||
class IUserLocalCommunicationService : IpcService, IDisposable
|
class IUserLocalCommunicationService : IpcService, IDisposable
|
||||||
{
|
{
|
||||||
public static string DefaultLanPlayHost = "ryuldn.vudjun.com";
|
|
||||||
public static short LanPlayPort = 30456;
|
|
||||||
|
|
||||||
public INetworkClient NetworkClient { get; private set; }
|
public INetworkClient NetworkClient { get; private set; }
|
||||||
|
|
||||||
private const int NifmRequestID = 90;
|
private const int NifmRequestID = 90;
|
||||||
@@ -1092,20 +1089,18 @@ namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator
|
|||||||
case MultiplayerMode.LdnRyu:
|
case MultiplayerMode.LdnRyu:
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string ldnServer = context.Device.Configuration.MultiplayerLdnServer;
|
string ldnServer = context.Device.Configuration.MultiplayerLdnServer
|
||||||
if (string.IsNullOrEmpty(ldnServer))
|
?? throw new InvalidOperationException("Cannot initialize RyuLDN with a null Multiplayer server.");
|
||||||
{
|
|
||||||
ldnServer = DefaultLanPlayHost;
|
|
||||||
}
|
|
||||||
if (!IPAddress.TryParse(ldnServer, out IPAddress ipAddress))
|
if (!IPAddress.TryParse(ldnServer, out IPAddress ipAddress))
|
||||||
{
|
{
|
||||||
ipAddress = Dns.GetHostEntry(ldnServer).AddressList[0];
|
ipAddress = Dns.GetHostEntry(ldnServer).AddressList[0];
|
||||||
}
|
}
|
||||||
NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), LanPlayPort, context.Device.Configuration);
|
NetworkClient = new LdnMasterProxyClient(ipAddress.ToString(), SharedConstants.LanPlayPort, context.Device.Configuration);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.ServiceLdn, "Could not locate LdnRyu server. Defaulting to stubbed wireless.");
|
Logger.Error?.Print(LogClass.ServiceLdn, "Could not locate RyuLDN server. Defaulting to stubbed wireless.");
|
||||||
Logger.Error?.Print(LogClass.ServiceLdn, ex.Message);
|
Logger.Error?.Print(LogClass.ServiceLdn, ex.Message);
|
||||||
NetworkClient = new LdnDisabledClient();
|
NetworkClient = new LdnDisabledClient();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ namespace Ryujinx.Input.SDL2
|
|||||||
byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0;
|
byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0;
|
||||||
|
|
||||||
if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0)
|
if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0)
|
||||||
Logger.Error?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting.");
|
Logger.Debug?.Print(LogClass.Hid, "LED setting failed; probably in the middle of disconnecting.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private GamepadFeaturesFlag GetFeaturesFlag()
|
private GamepadFeaturesFlag GetFeaturesFlag()
|
||||||
|
|||||||
@@ -951,7 +951,7 @@ namespace Ryujinx.Ava
|
|||||||
ConfigurationState.Instance.Multiplayer.Mode,
|
ConfigurationState.Instance.Multiplayer.Mode,
|
||||||
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
ConfigurationState.Instance.Multiplayer.DisableP2p,
|
||||||
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
ConfigurationState.Instance.Multiplayer.LdnPassphrase,
|
||||||
ConfigurationState.Instance.Multiplayer.LdnServer,
|
ConfigurationState.Instance.Multiplayer.GetLdnServer(),
|
||||||
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
|
ConfigurationState.Instance.Graphics.CustomVSyncInterval.Value,
|
||||||
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
|
ConfigurationState.Instance.Hacks.ShowDirtyHacks ? ConfigurationState.Instance.Hacks.EnabledHacks : null));
|
||||||
}
|
}
|
||||||
|
|||||||
+169
-169
File diff suppressed because it is too large
Load Diff
@@ -200,7 +200,7 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
if (backupDir.Exists)
|
if (backupDir.Exists)
|
||||||
{
|
{
|
||||||
cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
|
cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
|
||||||
cacheFiles.AddRange(mainDir.EnumerateFiles("*.info"));
|
cacheFiles.AddRange(backupDir.EnumerateFiles("*.info"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cacheFiles.Count > 0)
|
if (cacheFiles.Count > 0)
|
||||||
|
|||||||
@@ -793,7 +793,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleFirmwareInstallation(string filename)
|
public async Task HandleFirmwareInstallation(string filename)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -139,8 +139,24 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
base.OnApplyTemplate(e);
|
base.OnApplyTemplate(e);
|
||||||
|
|
||||||
NotificationHelper.SetNotificationManager(this);
|
NotificationHelper.SetNotificationManager(this);
|
||||||
|
|
||||||
Executor.ExecuteBackgroundAsync(ShowIntelMacWarningAsync);
|
Executor.ExecuteBackgroundAsync(async () =>
|
||||||
|
{
|
||||||
|
await ShowIntelMacWarningAsync();
|
||||||
|
FilePath firmwarePath = CommandLineState.FirmwareToInstallPathArg;
|
||||||
|
if (firmwarePath is not null)
|
||||||
|
{
|
||||||
|
if ((firmwarePath.ExistsAsFile && firmwarePath.Extension is "xci" or "zip") ||
|
||||||
|
firmwarePath.ExistsAsDirectory)
|
||||||
|
{
|
||||||
|
await Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
|
ViewModel.HandleFirmwareInstallation(firmwarePath));
|
||||||
|
CommandLineState.FirmwareToInstallPathArg = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Logger.Notice.Print(LogClass.UI, "Invalid firmware type provided. Path must be a directory, or a .zip or .xci file.");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnScalingChanged(object sender, EventArgs e)
|
private void OnScalingChanged(object sender, EventArgs e)
|
||||||
@@ -173,17 +189,12 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(() =>
|
Dispatcher.UIThread.Post(() =>
|
||||||
{
|
{
|
||||||
List<LdnGameData> ldnGameDataArray = e.LdnData.ToList();
|
|
||||||
ViewModel.LdnData.Clear();
|
ViewModel.LdnData.Clear();
|
||||||
foreach (ApplicationData application in ViewModel.Applications.Where(it => it.HasControlHolder))
|
foreach (ApplicationData application in ViewModel.Applications.Where(it => it.HasControlHolder))
|
||||||
{
|
{
|
||||||
ref ApplicationControlProperty controlHolder = ref application.ControlHolder.Value;
|
ref ApplicationControlProperty controlHolder = ref application.ControlHolder.Value;
|
||||||
|
|
||||||
ViewModel.LdnData[application.IdString] =
|
ViewModel.LdnData[application.IdString] = e.LdnData.Where(ref controlHolder);
|
||||||
LdnGameData.GetArrayForApp(
|
|
||||||
ldnGameDataArray,
|
|
||||||
ref controlHolder
|
|
||||||
);
|
|
||||||
|
|
||||||
UpdateApplicationWithLdnData(application);
|
UpdateApplicationWithLdnData(application);
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-10
@@ -43,17 +43,9 @@ namespace Ryujinx.Ava
|
|||||||
private const int ConnectionCount = 4;
|
private const int ConnectionCount = 4;
|
||||||
|
|
||||||
private static string _buildVer;
|
private static string _buildVer;
|
||||||
|
|
||||||
|
|
||||||
private static readonly string _platformExt =
|
private static readonly string _platformExt = BuildPlatformExtension();
|
||||||
RunningPlatform.IsMacOS
|
|
||||||
? "macos_universal.app.tar.gz"
|
|
||||||
: RunningPlatform.IsWindows
|
|
||||||
? "win_x64.zip"
|
|
||||||
: RunningPlatform.IsX64Linux
|
|
||||||
? "linux_x64.tar.gz"
|
|
||||||
: RunningPlatform.IsArmLinux
|
|
||||||
? "linux_arm64.tar.gz"
|
|
||||||
: throw new PlatformNotSupportedException();
|
|
||||||
|
|
||||||
private static string _buildUrl;
|
private static string _buildUrl;
|
||||||
private static long _buildSize;
|
private static long _buildSize;
|
||||||
@@ -780,5 +772,34 @@ namespace Ryujinx.Ava
|
|||||||
public static void CleanupUpdate() =>
|
public static void CleanupUpdate() =>
|
||||||
Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories)
|
Directory.GetFiles(_homeDir, "*.ryuold", SearchOption.AllDirectories)
|
||||||
.ForEach(File.Delete);
|
.ForEach(File.Delete);
|
||||||
|
|
||||||
|
private static string BuildPlatformExtension()
|
||||||
|
{
|
||||||
|
if (RunningPlatform.IsMacOS)
|
||||||
|
return "macos_universal.app.tar.gz";
|
||||||
|
|
||||||
|
#pragma warning disable CS8509 // It is exhaustive for any values this can contain.
|
||||||
|
string osPrefix = RunningPlatform.CurrentOS switch
|
||||||
|
{
|
||||||
|
OperatingSystemType.Linux => "linux",
|
||||||
|
OperatingSystemType.Windows => "win"
|
||||||
|
};
|
||||||
|
|
||||||
|
string archSuffix = RunningPlatform.Architecture switch
|
||||||
|
{
|
||||||
|
Architecture.Arm64 => "arm64",
|
||||||
|
Architecture.X64 => "x64",
|
||||||
|
_ => throw new PlatformNotSupportedException($"Unknown architecture {Enum.GetName(RunningPlatform.Architecture)}."),
|
||||||
|
};
|
||||||
|
|
||||||
|
string fileExtension = RunningPlatform.CurrentOS switch
|
||||||
|
#pragma warning restore CS8509
|
||||||
|
{
|
||||||
|
OperatingSystemType.Linux => "tar.gz",
|
||||||
|
OperatingSystemType.Windows => "zip"
|
||||||
|
};
|
||||||
|
|
||||||
|
return $"{osPrefix}_{archSuffix}.{fileExtension}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
{
|
{
|
||||||
public class ApplicationLibrary
|
public class ApplicationLibrary
|
||||||
{
|
{
|
||||||
public const string DefaultLanPlayWebHost = "ryuldnweb.vudjun.com";
|
|
||||||
public Language DesiredLanguage { get; set; }
|
public Language DesiredLanguage { get; set; }
|
||||||
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated;
|
||||||
public event Action<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
public event Action<LdnGameDataReceivedEventArgs> LdnGameDataReceived;
|
||||||
@@ -826,7 +825,6 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
|
|
||||||
public async Task RefreshLdn()
|
public async Task RefreshLdn()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (ConfigurationState.Instance.Multiplayer.Mode == MultiplayerMode.LdnRyu)
|
if (ConfigurationState.Instance.Multiplayer.Mode == MultiplayerMode.LdnRyu)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -834,33 +832,22 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
string ldnWebHost = ConfigurationState.Instance.Multiplayer.LdnServer;
|
string ldnWebHost = ConfigurationState.Instance.Multiplayer.LdnServer;
|
||||||
if (string.IsNullOrEmpty(ldnWebHost))
|
if (string.IsNullOrEmpty(ldnWebHost))
|
||||||
{
|
{
|
||||||
ldnWebHost = DefaultLanPlayWebHost;
|
ldnWebHost = SharedConstants.DefaultLanPlayWebHost;
|
||||||
}
|
}
|
||||||
IEnumerable<LdnGameData> ldnGameDataArray = Array.Empty<LdnGameData>();
|
|
||||||
using HttpClient httpClient = new();
|
using HttpClient httpClient = new();
|
||||||
string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games");
|
string ldnGameDataArrayString = await httpClient.GetStringAsync($"https://{ldnWebHost}/api/public_games");
|
||||||
ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData);
|
LdnGameData[] ldnGameDataArray = JsonHelper.Deserialize(ldnGameDataArrayString, _ldnDataSerializerContext.IEnumerableLdnGameData).ToArray();
|
||||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs(ldnGameDataArray));
|
||||||
{
|
return;
|
||||||
LdnData = ldnGameDataArray
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}");
|
Logger.Warning?.Print(LogClass.Application, $"Failed to fetch the public games JSON from the API. Player and game count in the game list will be unavailable.\n{ex.Message}");
|
||||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
|
||||||
{
|
|
||||||
LdnData = Array.Empty<LdnGameData>()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
LdnGameDataReceived?.Invoke(LdnGameDataReceivedEventArgs.Empty);
|
||||||
LdnGameDataReceived?.Invoke(new LdnGameDataReceivedEventArgs
|
|
||||||
{
|
|
||||||
LdnData = Array.Empty<LdnGameData>()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace the currently stored DLC state for the game with the provided DLC state.
|
// Replace the currently stored DLC state for the game with the provided DLC state.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
public IEnumerable<string> Players { get; set; }
|
public IEnumerable<string> Players { get; set; }
|
||||||
|
|
||||||
public static Array GetArrayForApp(
|
public static Array GetArrayForApp(
|
||||||
IEnumerable<LdnGameData> receivedData, ref ApplicationControlProperty acp)
|
LdnGameData[] receivedData, ref ApplicationControlProperty acp)
|
||||||
{
|
{
|
||||||
LibHac.Common.FixedArrays.Array8<ulong> communicationId = acp.LocalCommunicationId;
|
LibHac.Common.FixedArrays.Array8<ulong> communicationId = acp.LocalCommunicationId;
|
||||||
|
|
||||||
@@ -40,4 +40,10 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
public int GameCount => _ldnDatas.Length;
|
public int GameCount => _ldnDatas.Length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class LdnGameDataHelper
|
||||||
|
{
|
||||||
|
public static LdnGameData.Array Where(this LdnGameData[] unfilteredDatas, ref ApplicationControlProperty acp)
|
||||||
|
=> LdnGameData.GetArrayForApp(unfilteredDatas, ref acp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
|
|||||||
{
|
{
|
||||||
public class LdnGameDataReceivedEventArgs : EventArgs
|
public class LdnGameDataReceivedEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
public IEnumerable<LdnGameData> LdnData { get; set; }
|
public static new readonly LdnGameDataReceivedEventArgs Empty = new(null);
|
||||||
|
|
||||||
|
public LdnGameDataReceivedEventArgs(LdnGameData[] ldnData)
|
||||||
|
{
|
||||||
|
LdnData = ldnData ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public LdnGameData[] LdnData { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Gommon;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ namespace Ryujinx.Ava.Utilities
|
|||||||
public static string OverrideBackendThreading { get; private set; }
|
public static string OverrideBackendThreading { get; private set; }
|
||||||
public static string OverrideHideCursor { get; private set; }
|
public static string OverrideHideCursor { get; private set; }
|
||||||
public static string BaseDirPathArg { get; private set; }
|
public static string BaseDirPathArg { get; private set; }
|
||||||
|
public static FilePath FirmwareToInstallPathArg { get; set; }
|
||||||
public static string Profile { get; private set; }
|
public static string Profile { get; private set; }
|
||||||
public static string LaunchPathArg { get; private set; }
|
public static string LaunchPathArg { get; private set; }
|
||||||
public static string LaunchApplicationId { get; private set; }
|
public static string LaunchApplicationId { get; private set; }
|
||||||
@@ -41,6 +43,19 @@ namespace Ryujinx.Ava.Utilities
|
|||||||
|
|
||||||
BaseDirPathArg = args[++i];
|
BaseDirPathArg = args[++i];
|
||||||
|
|
||||||
|
arguments.Add(arg);
|
||||||
|
arguments.Add(args[i]);
|
||||||
|
break;
|
||||||
|
case "--install-firmware":
|
||||||
|
if (i + 1 >= args.Length)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'");
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FirmwareToInstallPathArg = new FilePath(args[++i]);
|
||||||
|
|
||||||
arguments.Add(arg);
|
arguments.Add(arg);
|
||||||
arguments.Add(args[i]);
|
arguments.Add(args[i]);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using ARMeilleure;
|
using ARMeilleure;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
|
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
using Ryujinx.Ava.Utilities.Configuration.System;
|
||||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
using Ryujinx.Ava.Utilities.Configuration.UI;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
@@ -647,6 +648,14 @@ namespace Ryujinx.Ava.Utilities.Configuration
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public ReactiveObject<string> LdnServer { get; private set; }
|
public ReactiveObject<string> LdnServer { get; private set; }
|
||||||
|
|
||||||
|
public string GetLdnServer()
|
||||||
|
{
|
||||||
|
string ldnServer = LdnServer;
|
||||||
|
return string.IsNullOrEmpty(ldnServer)
|
||||||
|
? SharedConstants.DefaultLanPlayHost
|
||||||
|
: ldnServer;
|
||||||
|
}
|
||||||
|
|
||||||
public MultiplayerSection()
|
public MultiplayerSection()
|
||||||
{
|
{
|
||||||
LanInterfaceId = new ReactiveObject<string>();
|
LanInterfaceId = new ReactiveObject<string>();
|
||||||
|
|||||||
@@ -59,12 +59,13 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
"Race" => "Racing",
|
"Race" => "Racing",
|
||||||
_ => FormattedValue.ForceReset
|
_ => FormattedValue.ForceReset
|
||||||
};
|
};
|
||||||
|
|
||||||
private static FormattedValue PokemonSVUnionCircle(SingleValue value)
|
private static FormattedValue PokemonSV(MultiValue values)
|
||||||
=> value.Matched.BoxedValue is 0 ? "Playing Alone" : "Playing in a group";
|
{
|
||||||
|
|
||||||
private static FormattedValue PokemonSVArea(SingleValue value)
|
string playStatus = values.Matched[0].BoxedValue is 0 ? "Playing Alone" : "Playing in a group";
|
||||||
=> value.Matched.StringValue switch
|
|
||||||
|
FormattedValue locations = values.Matched[1].ToString() switch
|
||||||
{
|
{
|
||||||
// Base Game Locations
|
// Base Game Locations
|
||||||
"a_w01" => "South Area One",
|
"a_w01" => "South Area One",
|
||||||
@@ -92,10 +93,13 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
"a_w24" => "South Paldean Sea",
|
"a_w24" => "South Paldean Sea",
|
||||||
"a_w25" => "West Paldean Sea",
|
"a_w25" => "West Paldean Sea",
|
||||||
"a_w26" => "East Paldean Sea",
|
"a_w26" => "East Paldean Sea",
|
||||||
"a_w27" => "Nouth Paldean Sea",
|
"a_w27" => "North Paldean Sea",
|
||||||
//TODO DLC Locations
|
//TODO DLC Locations
|
||||||
_ => FormattedValue.ForceReset
|
_ => FormattedValue.ForceReset
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return$"{playStatus} in {locations}";
|
||||||
|
}
|
||||||
|
|
||||||
private static FormattedValue SuperSmashBrosUltimate_Mode(SparseMultiValue values)
|
private static FormattedValue SuperSmashBrosUltimate_Mode(SparseMultiValue values)
|
||||||
{
|
{
|
||||||
@@ -115,6 +119,11 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
return $"Achievement Unlocked - ID: {anniversary}";
|
return $"Achievement Unlocked - ID: {anniversary}";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (values.Matched.ContainsKey("is_created"))
|
||||||
|
{
|
||||||
|
return "Edited a Custom Stage!";
|
||||||
|
}
|
||||||
|
|
||||||
if (values.Matched.ContainsKey("adv_slot"))
|
if (values.Matched.ContainsKey("adv_slot"))
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -59,9 +59,8 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
.AddSpec(
|
.AddSpec(
|
||||||
["0100a3d008c5c000", "01008f6008c5e000"],
|
["0100a3d008c5c000", "01008f6008c5e000"],
|
||||||
spec => spec
|
spec => spec
|
||||||
.WithDescription("based on what area of Paldea you're exploring.")
|
.WithDescription("based on if you're playing alone or in a group and what area of Paldea you're exploring.")
|
||||||
.AddValueFormatter("area_no", PokemonSVArea)
|
.AddMultiValueFormatter(["team_circle", "area_no"], PokemonSV)
|
||||||
.AddValueFormatter("team_circle", PokemonSVUnionCircle)
|
|
||||||
)
|
)
|
||||||
.AddSpec(
|
.AddSpec(
|
||||||
"01006a800016e000",
|
"01006a800016e000",
|
||||||
@@ -71,7 +70,7 @@ namespace Ryujinx.Ava.Utilities.PlayReport
|
|||||||
[
|
[
|
||||||
// Metadata to figure out what PlayReport we have.
|
// Metadata to figure out what PlayReport we have.
|
||||||
"match_mode", "match_submode", "anniversary", "fighter", "reason", "challenge_count",
|
"match_mode", "match_submode", "anniversary", "fighter", "reason", "challenge_count",
|
||||||
"adv_slot",
|
"adv_slot", "is_created",
|
||||||
// List of Fighters
|
// List of Fighters
|
||||||
"player_1_fighter", "player_2_fighter", "player_3_fighter", "player_4_fighter",
|
"player_1_fighter", "player_2_fighter", "player_3_fighter", "player_4_fighter",
|
||||||
"player_5_fighter", "player_6_fighter", "player_7_fighter", "player_8_fighter",
|
"player_5_fighter", "player_6_fighter", "player_7_fighter", "player_8_fighter",
|
||||||
|
|||||||
Reference in New Issue
Block a user