mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-04-14 18:22:55 +00:00
Compare commits
6 Commits
Canary-1.3
...
Canary-1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac5f9857e2 | ||
|
|
4b42087bd4 | ||
|
|
80cbf5d1fc | ||
|
|
cc6d2dc162 | ||
|
|
4ebc318da5 | ||
|
|
00dad0a5e2 |
@@ -41,7 +41,7 @@
|
||||
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies.AllArch" Version="6.1.2-build3" />
|
||||
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
|
||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.126" />
|
||||
<PackageVersion Include="Ryujinx.LibHac" Version="0.21.0-alpha.129" />
|
||||
<PackageVersion Include="Ryujinx.UpdateClient" Version="1.0.44" />
|
||||
<PackageVersion Include="Ryujinx.Systems.Update.Common" Version="1.0.44" />
|
||||
<PackageVersion Include="Gommon" Version="2.8.0.1" />
|
||||
@@ -56,7 +56,6 @@
|
||||
<PackageVersion Include="SkiaSharp.NativeAssets.Linux" Version="2.88.9" />
|
||||
<PackageVersion Include="SPB" Version="0.0.4-build32" />
|
||||
<PackageVersion Include="System.IO.Hashing" Version="9.0.2" />
|
||||
<PackageVersion Include="System.Management" Version="9.0.2" />
|
||||
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -11300,6 +11300,31 @@
|
||||
"zh_TW": "刪除"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "UserProfilesSave",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "Speichern",
|
||||
"el_GR": "",
|
||||
"en_US": "Save",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "UserProfilesClose",
|
||||
"Translations": {
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" />
|
||||
<PackageReference Include="MsgPack.Cli" />
|
||||
<PackageReference Include="System.Management" />
|
||||
<PackageReference Include="Humanizer" />
|
||||
<PackageReference Include="Gommon" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -184,6 +184,7 @@ namespace Ryujinx.Common
|
||||
"01001b300b9be000", // Diablo III: Eternal Collection
|
||||
"010027400cdc6000", // Divinity Original 2 - Definitive Edition
|
||||
"01008c8012920000", // Dying Light Platinum Edition
|
||||
"0100d11013e6a000", // Eschatos
|
||||
"01001cc01b2d4000", // Goat Simulator 3
|
||||
"01003620068ea000", // Hand of Fate 2
|
||||
"0100f7e00c70e000", // Hogwarts Legacy
|
||||
@@ -193,9 +194,15 @@ namespace Ryujinx.Common
|
||||
"0100d71004694000", // Minecraft
|
||||
"01007430037f6000", // Monopoly
|
||||
"0100853015e86000", // No Man's Sky
|
||||
"0100f85014ed0000", // No More Heroes
|
||||
"0100463014ed4000", // No More Heroes 2
|
||||
"0100e570094e8000", // Owlboy
|
||||
"01007bb017812000", // Portal
|
||||
"0100abd01785c000", // Portal 2
|
||||
"01009f100bc52000", // Psikyo Collection 1
|
||||
"01009d400c4a8000", // Psikyo Collection 2
|
||||
"01008e200c5c2000", // Muse Dash
|
||||
"01005ff002e2a000", // Rayman Legends
|
||||
"01007820196a6000", // Red Dead Redemption
|
||||
"0100e8300a67a000", // Risk
|
||||
"01002f7013224000", // Rune Factory 5
|
||||
|
||||
@@ -22,10 +22,11 @@ namespace Ryujinx.Common.Utilities
|
||||
}
|
||||
|
||||
// "dumpable" attribute of the calling process
|
||||
private const int PR_GET_DUMPABLE = 3;
|
||||
private const int PR_SET_DUMPABLE = 4;
|
||||
|
||||
[DllImport("libc", SetLastError = true)]
|
||||
private static extern int prctl(int option, int arg2);
|
||||
[LibraryImport("libc", SetLastError = true)]
|
||||
private static partial int prctl(int option, int arg2);
|
||||
|
||||
public static void SetCoreDumpable(bool dumpable)
|
||||
{
|
||||
@@ -36,5 +37,13 @@ namespace Ryujinx.Common.Utilities
|
||||
Debug.Assert(result == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the below line to display dumpable status in the console:
|
||||
// Console.WriteLine($"{OsUtils.IsCoreDumpable()}");
|
||||
public static bool IsCoreDumpable()
|
||||
{
|
||||
int result = prctl(PR_GET_DUMPABLE, 0);
|
||||
return result == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||
_activeCount = 0;
|
||||
|
||||
JoyHold = NpadJoyHoldType.Vertical;
|
||||
SixAxisActive = false;
|
||||
}
|
||||
|
||||
internal ref KEvent GetStyleSetUpdateEvent(PlayerIndex player)
|
||||
@@ -580,6 +581,24 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||
|
||||
return needUpdateRight;
|
||||
}
|
||||
|
||||
public bool isAtRest(int playerNumber)
|
||||
{
|
||||
|
||||
ref NpadInternalState currentNpad = ref _device.Hid.SharedMemory.Npads[playerNumber].InternalState;
|
||||
ref SixAxisSensorState storage = ref GetSixAxisSensorLifo(ref currentNpad, false).GetCurrentEntryRef();
|
||||
|
||||
float acceleration = Math.Abs(storage.Acceleration.X)
|
||||
+ Math.Abs(storage.Acceleration.Y)
|
||||
+ Math.Abs(storage.Acceleration.Z);
|
||||
|
||||
float angularVelocity = Math.Abs(storage.AngularVelocity.X)
|
||||
+ Math.Abs(storage.AngularVelocity.Y)
|
||||
+ Math.Abs(storage.AngularVelocity.Z);
|
||||
|
||||
// TODO: check against config deadzone and add sensitivity setting
|
||||
return ((acceleration <= 1.0F) && (angularVelocity <= 1.0F));
|
||||
}
|
||||
|
||||
private void UpdateDisconnectedInputSixAxis(PlayerIndex index)
|
||||
{
|
||||
|
||||
@@ -602,19 +602,33 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||
}
|
||||
|
||||
[CommandCmif(82)]
|
||||
// IsSixAxisSensorAtRest(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId) -> bool IsAsRest
|
||||
// IsSixAxisSensorAtRest(nn::hid::SixAxisSensorHandle, nn::applet::AppletResourceUserId) -> bool IsAtRest
|
||||
public ResultCode IsSixAxisSensorAtRest(ServiceCtx context)
|
||||
{
|
||||
int sixAxisSensorHandle = context.RequestData.ReadInt32();
|
||||
|
||||
// 4 byte struct w/ 4-byte alignment
|
||||
|
||||
// uint typeValue = (uint) sixAxisSensorHandle; // 0x0 0x4 TypeValue
|
||||
// uint npadStyleIndex = (uint) sixAxisSensorHandle & 0xff; // 0x0 0x1 NpadStyleIndex
|
||||
int playerNumber = (sixAxisSensorHandle << 8) & 0xff; // 0x1 0x1 PlayerNumber
|
||||
// uint deviceIdx= ((uint) sixAxisSensorHandle << 16) & 0xff; // 0x2 0x1 DeviceIdx
|
||||
// uint unknown = ((uint) sixAxisSensorHandle << 24) & 0xff;
|
||||
|
||||
// 32bit sign extension padding -> if = 0, + offset, else - offset
|
||||
|
||||
// npadStyleIndex = ((npadStyleIndex & 0x8000) == 0) ? npadStyleIndex | 0xFFFF0000 : npadStyleIndex & 0xFFFF0000;
|
||||
// playerNumber = ((playerNumber & 0x8000) == 0) ? playerNumber | 0xFFFF0000 : playerNumber & 0xFFFF0000;
|
||||
// deviceIdx = ((deviceIdx & 0x8000) == 0) ? deviceIdx | 0xFFFF0000 : deviceIdx & 0xFFFF0000;
|
||||
// unknown = ((unknown & 0x8000) == 0) ? unknown | 0xFFFF0000 : unknown & 0xFFFF0000;
|
||||
|
||||
context.RequestData.BaseStream.Position += 4; // Padding
|
||||
long appletResourceUserId = context.RequestData.ReadInt64();
|
||||
|
||||
bool isAtRest = true;
|
||||
|
||||
context.ResponseData.Write(isAtRest);
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle, isAtRest });
|
||||
|
||||
|
||||
// TODO: link to context.Device.Hid.Npads.SixAxisActive when properly implemented
|
||||
// We currently do not support stopping or starting SixAxisTracking.
|
||||
|
||||
context.ResponseData.Write(context.Device.Hid.Npads.isAtRest(playerNumber));
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
@@ -629,7 +643,7 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||
context.ResponseData.Write(_isFirmwareUpdateAvailableForSixAxisSensor);
|
||||
|
||||
Logger.Stub?.PrintStub(LogClass.ServiceHid, new { appletResourceUserId, sixAxisSensorHandle, _isFirmwareUpdateAvailableForSixAxisSensor });
|
||||
|
||||
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,5 +20,7 @@ namespace Ryujinx.HLE.HOS.SystemState
|
||||
SimplifiedChinese,
|
||||
TraditionalChinese,
|
||||
BrazilianPortuguese,
|
||||
Polish,
|
||||
Thai,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,9 @@ namespace Ryujinx.HLE.HOS.SystemState
|
||||
"es-419",
|
||||
"zh-Hans",
|
||||
"zh-Hant",
|
||||
"pt-BR"
|
||||
"pt-BR",
|
||||
"pl",
|
||||
"th"
|
||||
];
|
||||
|
||||
internal long DesiredKeyboardLayout { get; private set; }
|
||||
|
||||
@@ -18,5 +18,7 @@ namespace Ryujinx.HLE.HOS.SystemState
|
||||
TraditionalChinese,
|
||||
SimplifiedChinese,
|
||||
BrazilianPortuguese,
|
||||
Polish,
|
||||
Thai,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,19 @@
|
||||
using Ryujinx.Common.Memory;
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Ryujinx.Horizon.Sdk.Ns
|
||||
{
|
||||
public struct ApplicationControlProperty
|
||||
{
|
||||
public Array16<ApplicationTitle> Title;
|
||||
/// <summary>
|
||||
/// Use <see cref="Title"/> to access titles instead of accessing them directly.
|
||||
/// </summary>
|
||||
public Array16<ApplicationTitle> TitleBlock;
|
||||
public Array37<byte> Isbn;
|
||||
public StartupUserAccountValue StartupUserAccount;
|
||||
public UserAccountSwitchLockValue UserAccountSwitchLock;
|
||||
@@ -58,7 +65,10 @@ namespace Ryujinx.Horizon.Sdk.Ns
|
||||
public RepairFlagValue RepairFlag;
|
||||
public byte ProgramIndex;
|
||||
public RequiredNetworkServiceLicenseOnLaunchValue RequiredNetworkServiceLicenseOnLaunchFlag;
|
||||
public Array4<byte> Reserved3214;
|
||||
public byte ApplicationErrorCodePrefix;
|
||||
public TitleCompressionValue TitleCompression;
|
||||
public byte AcdIndex;
|
||||
public byte ApparentPlatform;
|
||||
public ApplicationNeighborDetectionClientConfiguration NeighborDetectionClientConfiguration;
|
||||
public ApplicationJitConfiguration JitConfiguration;
|
||||
public RequiredAddOnContentsSetBinaryDescriptor RequiredAddOnContentsSetBinaryDescriptors;
|
||||
@@ -74,6 +84,47 @@ namespace Ryujinx.Horizon.Sdk.Ns
|
||||
public readonly string DisplayVersionString => Encoding.UTF8.GetString(DisplayVersion.AsSpan()).TrimEnd('\0');
|
||||
public readonly string ApplicationErrorCodeCategoryString => Encoding.UTF8.GetString(ApplicationErrorCodeCategory.AsSpan()).TrimEnd('\0');
|
||||
public readonly string BcatPassphraseString => Encoding.UTF8.GetString(BcatPassphrase.AsSpan()).TrimEnd('\0');
|
||||
|
||||
private const int TitleCount = 32;
|
||||
private const int TitleEntrySize = 0x300;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the resolved title entries. When <see cref="TitleCompression"/> is
|
||||
/// <see cref="TitleCompressionValue.Enable"/>, the raw <see cref="TitleBlock"/> bytes are
|
||||
/// decompressed (raw deflate) from 0x3000 into 0x6000 bytes yielding up to 32 entries.
|
||||
/// Otherwise the 16 uncompressed entries from <see cref="TitleBlock"/> are returned directly.
|
||||
/// </summary>
|
||||
public readonly ApplicationTitle[] Title
|
||||
{
|
||||
get
|
||||
{
|
||||
var titles = new ApplicationTitle[TitleCount];
|
||||
|
||||
if (TitleCompression != TitleCompressionValue.Enable)
|
||||
{
|
||||
TitleBlock.AsSpan().CopyTo(titles);
|
||||
|
||||
return titles;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> titleBytes = MemoryMarshal.AsBytes(TitleBlock.AsSpan());
|
||||
ushort compressedBlobSize = BinaryPrimitives.ReadUInt16LittleEndian(titleBytes);
|
||||
ReadOnlySpan<byte> compressedBlob = titleBytes.Slice(2, compressedBlobSize);
|
||||
|
||||
byte[] decompressed = new byte[TitleCount * TitleEntrySize];
|
||||
|
||||
using (var compressedStream = new MemoryStream(compressedBlob.ToArray()))
|
||||
using (var deflateStream = new DeflateStream(compressedStream, CompressionMode.Decompress))
|
||||
{
|
||||
deflateStream.ReadExactly(decompressed, 0, decompressed.Length);
|
||||
}
|
||||
|
||||
MemoryMarshal.Cast<byte, ApplicationTitle>(decompressed).CopyTo(titles);
|
||||
|
||||
return titles;
|
||||
}
|
||||
}
|
||||
|
||||
public struct ApplicationTitle
|
||||
{
|
||||
@@ -130,6 +181,8 @@ namespace Ryujinx.Horizon.Sdk.Ns
|
||||
TraditionalChinese = 13,
|
||||
SimplifiedChinese = 14,
|
||||
BrazilianPortuguese = 15,
|
||||
Polish = 16,
|
||||
Thai = 17,
|
||||
}
|
||||
|
||||
public enum Organization
|
||||
@@ -302,5 +355,11 @@ namespace Ryujinx.Horizon.Sdk.Ns
|
||||
Deny = 0,
|
||||
Allow = 1,
|
||||
}
|
||||
|
||||
public enum TitleCompressionValue : byte
|
||||
{
|
||||
Disable = 0,
|
||||
Enable = 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace Ryujinx.Ava
|
||||
public static bool PreviewerDetached { get; private set; }
|
||||
public static bool UseHardwareAcceleration { get; private set; }
|
||||
public static string BackendThreadingArg { get; private set; }
|
||||
public static bool CoreDumpArg { get; private set; }
|
||||
|
||||
private const uint MbIconwarning = 0x30;
|
||||
|
||||
@@ -81,6 +82,8 @@ namespace Ryujinx.Ava
|
||||
bool noGuiArg = ConsumeCommandLineArgument(ref args, "--no-gui") || ConsumeCommandLineArgument(ref args, "nogui");
|
||||
bool coreDumpArg = ConsumeCommandLineArgument(ref args, "--core-dumps");
|
||||
|
||||
CoreDumpArg = coreDumpArg;
|
||||
|
||||
// TODO: Ryujinx causes core dumps on Linux when it exits "uncleanly", eg. through an unhandled exception.
|
||||
// This is undesirable and causes very odd behavior during development (the process stops responding,
|
||||
// the .NET debugger freezes or suddenly detaches, /tmp/ gets filled etc.), unless explicitly requested by the user.
|
||||
|
||||
@@ -28,11 +28,6 @@
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<TrimMode>partial</TrimMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)' == 'win-arm64'">
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishTrimmed>false</PublishTrimmed>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
FluentAvalonia, used in the Avalonia UI, requires a workaround for the json serializer used internally when using .NET 8+ System.Text.Json.
|
||||
|
||||
@@ -1404,7 +1404,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
||||
|
||||
if (string.IsNullOrWhiteSpace(data.Name))
|
||||
{
|
||||
foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title)
|
||||
foreach (ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title)
|
||||
{
|
||||
if (!controlTitle.NameString.IsEmpty())
|
||||
{
|
||||
@@ -1417,7 +1417,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
|
||||
|
||||
if (string.IsNullOrWhiteSpace(data.Developer))
|
||||
{
|
||||
foreach (ref readonly ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title)
|
||||
foreach (ApplicationControlProperty.ApplicationTitle controlTitle in controlData.Title)
|
||||
{
|
||||
if (!controlTitle.PublisherString.IsEmpty())
|
||||
{
|
||||
|
||||
@@ -24,6 +24,8 @@ namespace Ryujinx.Ava.Systems.Configuration.System
|
||||
SimplifiedChinese,
|
||||
TraditionalChinese,
|
||||
BrazilianPortuguese,
|
||||
Polish,
|
||||
Thai,
|
||||
}
|
||||
|
||||
public static class LanguageEnumHelper
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
<Button
|
||||
Name="SaveButton"
|
||||
Click="SaveButton_Click">
|
||||
<TextBlock Text="{ext:Locale UserProfilesSetProfileImage}" />
|
||||
<TextBlock Text="{ext:Locale UserProfilesSave}" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Avalonia.Platform.Storage;
|
||||
using Gommon;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -11,29 +13,42 @@ namespace Ryujinx.Ava.Utilities
|
||||
extension(IStorageProvider storageProvider)
|
||||
{
|
||||
public Task<Optional<IStorageFolder>> OpenSingleFolderPickerAsync(FolderPickerOpenOptions openOptions = null) =>
|
||||
storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, false))
|
||||
CoreDumpable(() => storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, false)))
|
||||
.Then(folders => folders.FindFirst());
|
||||
|
||||
|
||||
public Task<Optional<IStorageFile>> OpenSingleFilePickerAsync(FilePickerOpenOptions openOptions = null) =>
|
||||
storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, false))
|
||||
CoreDumpable(() => storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, false)))
|
||||
.Then(files => files.FindFirst());
|
||||
|
||||
|
||||
public Task<Optional<IReadOnlyList<IStorageFolder>>> OpenMultiFolderPickerAsync(FolderPickerOpenOptions openOptions = null) =>
|
||||
storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, true))
|
||||
CoreDumpable(() => storageProvider.OpenFolderPickerAsync(FixOpenOptions(openOptions, true)))
|
||||
.Then(folders => folders.Count > 0 ? Optional.Of(folders) : default);
|
||||
|
||||
|
||||
public Task<Optional<IReadOnlyList<IStorageFile>>> OpenMultiFilePickerAsync(FilePickerOpenOptions openOptions = null) =>
|
||||
storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, true))
|
||||
CoreDumpable(() => storageProvider.OpenFilePickerAsync(FixOpenOptions(openOptions, true)))
|
||||
.Then(files => files.Count > 0 ? Optional.Of(files) : default);
|
||||
}
|
||||
|
||||
private static async Task<T> CoreDumpable<T>(Func<Task<T>> picker)
|
||||
{
|
||||
OsUtils.SetCoreDumpable(true);
|
||||
try
|
||||
{
|
||||
return await picker();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!Program.CoreDumpArg)
|
||||
OsUtils.SetCoreDumpable(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static FilePickerOpenOptions FixOpenOptions(this FilePickerOpenOptions openOptions, bool allowMultiple)
|
||||
{
|
||||
if (openOptions is null)
|
||||
return new FilePickerOpenOptions { AllowMultiple = allowMultiple };
|
||||
|
||||
openOptions.AllowMultiple = allowMultiple;
|
||||
|
||||
return openOptions;
|
||||
}
|
||||
|
||||
@@ -43,7 +58,6 @@ namespace Ryujinx.Ava.Utilities
|
||||
return new FolderPickerOpenOptions { AllowMultiple = allowMultiple };
|
||||
|
||||
openOptions.AllowMultiple = allowMultiple;
|
||||
|
||||
return openOptions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Ryujinx.Common.Logging;
|
||||
using System;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Versioning;
|
||||
|
||||
@@ -11,7 +10,7 @@ namespace Ryujinx.Ava.Utilities.SystemInfo
|
||||
{
|
||||
internal WindowsSystemInfo()
|
||||
{
|
||||
CpuName = $"{GetCpuidCpuName() ?? GetCpuNameWMI()} ; {LogicalCoreCount} logical"; // WMI is very slow
|
||||
CpuName = $"{GetCpuidCpuName() ?? GetCpuNameFromRegistry()} ; {LogicalCoreCount} logical";
|
||||
(RamTotal, RamAvailable) = GetMemoryStats();
|
||||
}
|
||||
|
||||
@@ -28,25 +27,26 @@ namespace Ryujinx.Ava.Utilities.SystemInfo
|
||||
return (0, 0);
|
||||
}
|
||||
|
||||
private static string GetCpuNameWMI()
|
||||
private static string GetCpuNameFromRegistry()
|
||||
{
|
||||
ManagementObjectCollection cpuObjs = GetWMIObjects("root\\CIMV2", "SELECT * FROM Win32_Processor");
|
||||
|
||||
if (cpuObjs != null)
|
||||
try
|
||||
{
|
||||
foreach (ManagementBaseObject cpuObj in cpuObjs)
|
||||
{
|
||||
return cpuObj["Name"].ToString().Trim();
|
||||
}
|
||||
}
|
||||
using var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"HARDWARE\DESCRIPTION\System\CentralProcessor\0");
|
||||
|
||||
return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER")?.Trim();
|
||||
return key?.GetValue("ProcessorNameString")?.ToString()?.Trim();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Registry CPU name lookup failed: {ex.Message}");
|
||||
|
||||
return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER")?.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct MemoryStatusEx
|
||||
private struct MemoryStatusEx()
|
||||
{
|
||||
public uint Length;
|
||||
public uint Length = (uint)Marshal.SizeOf<MemoryStatusEx>();
|
||||
public uint MemoryLoad;
|
||||
public ulong TotalPhys;
|
||||
public ulong AvailPhys;
|
||||
@@ -55,33 +55,10 @@ namespace Ryujinx.Ava.Utilities.SystemInfo
|
||||
public ulong TotalVirtual;
|
||||
public ulong AvailVirtual;
|
||||
public ulong AvailExtendedVirtual;
|
||||
|
||||
public MemoryStatusEx()
|
||||
{
|
||||
Length = (uint)Marshal.SizeOf<MemoryStatusEx>();
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static partial bool GlobalMemoryStatusEx(ref MemoryStatusEx lpBuffer);
|
||||
|
||||
private static ManagementObjectCollection GetWMIObjects(string scope, string query)
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ManagementObjectSearcher(scope, query).Get();
|
||||
}
|
||||
catch (PlatformNotSupportedException ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}");
|
||||
}
|
||||
catch (COMException ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user