Compare commits

..

7 Commits

Author SHA1 Message Date
TSRBerry
4505a7f162 Fix opening the wrong log directory (#6220) 2024-01-30 17:52:45 +01:00
gdkchan
ccbbaddbcb Fix exception when trying to read output pointer buffer size (#6221)
* Fix exception when trying to read output pointer buffer size

* Better name
2024-01-29 21:19:39 -03:00
Ac_K
8bf102d2cd Cpu: Implement Vpadal and Vrintr instructions (#6185)
* Cpu: Implement Vpadal and Vrintr instructions

This PR superseed last instructions left in #2242.
Since I'm not a CPU guy I've just ported the code and nothing more.
Please be precise during review if there are some changes to be done.

It should fixes #1781

Co-Authored-By: Piyachet Kanda <piyachetk@gmail.com>

* Addresses gdkchan's feedback

* Addresses gdkchan's feedback 2

* Apply suggestions from code review

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

* another fix

* Update InstEmitSimdHelper32.cs

* Correct fix

* Addresses gdkchan's feedback

* Update CpuTestSimdCvt32.cs

---------

Co-authored-by: Piyachet Kanda <piyachetk@gmail.com>
Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2024-01-30 00:51:05 +01:00
Ac_K
2adf031830 deps: Update Avalonia.Svg (#6218)
Updates `Avalonia.Svg` from 11.0.0.10 to 11.0.0.13
Updates `Avalonia.Svg.Skia` from 11.0.0.10 to 11.0.0.13

And reflect update changes as dependabot can't do it.

Superseed #6209
2024-01-29 23:22:42 +01:00
Isaac Marovitz
bb4a28b525 Ava UI: Mod Manager Fixes (Again) (#6187)
* Fix typo + Fix deleting from old dir

* Avoid double enumeration

* Break when parentDir is found

* Fix deleting non subdirectory mods

* Typo
2024-01-29 23:14:19 +01:00
merry
a8fbcdae9f UI: Clarify Create Application Shortcut tooltip text (#6217) 2024-01-29 23:08:24 +01:00
TSRBerry
4e81ab4229 Avalonia: Fix dialog issues caused by 1.1.1105 (#6211)
* Set _contentDialogOverlayWindow to null

* Make CheckLaunchState async
2024-01-29 22:57:20 +01:00
25 changed files with 210 additions and 56 deletions

View File

@@ -8,8 +8,8 @@
<PackageVersion Include="Avalonia.Desktop" Version="11.0.7" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.7" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.7" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.10" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.10" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.13" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.13" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="1.1.7" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />

View File

@@ -875,6 +875,7 @@ namespace ARMeilleure.Decoders
SetVfp("<<<<11100x10xxxxxxxx101xx1x0xxxx", InstName.Vnmul, InstEmit32.Vnmul_S, OpCode32SimdRegS.Create, OpCode32SimdRegS.CreateT32);
SetVfp("111111101x1110xxxxxx101x01x0xxxx", InstName.Vrint, InstEmit32.Vrint_RM, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("<<<<11101x110110xxxx101x11x0xxxx", InstName.Vrint, InstEmit32.Vrint_Z, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("<<<<11101x110110xxxx101x01x0xxxx", InstName.Vrintr, InstEmit32.Vrintr_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("<<<<11101x110111xxxx101x01x0xxxx", InstName.Vrintx, InstEmit32.Vrintx_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("<<<<11101x110001xxxx101x11x0xxxx", InstName.Vsqrt, InstEmit32.Vsqrt_S, OpCode32SimdS.Create, OpCode32SimdS.CreateT32);
SetVfp("111111100xxxxxxxxxxx101xx0x0xxxx", InstName.Vsel, InstEmit32.Vsel, OpCode32SimdSel.Create, OpCode32SimdSel.CreateT32);
@@ -995,6 +996,7 @@ namespace ARMeilleure.Decoders
SetAsimd("1111001x1x000xxxxxxx<<x10x01xxxx", InstName.Vorr, InstEmit32.Vorr_II, OpCode32SimdImm.Create, OpCode32SimdImm.CreateT32);
SetAsimd("111100100x<<xxxxxxxx1011x0x1xxxx", InstName.Vpadd, InstEmit32.Vpadd_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x00xxxxxxxx1101x0x0xxxx", InstName.Vpadd, InstEmit32.Vpadd_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100111x11<<00xxxx0110xxx0xxxx", InstName.Vpadal, InstEmit32.Vpadal, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("111100111x11<<00xxxx0010xxx0xxxx", InstName.Vpaddl, InstEmit32.Vpaddl, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
SetAsimd("1111001x0x<<xxxxxxxx1010x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_I, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
SetAsimd("111100110x00xxxxxxxx1111x0x0xxxx", InstName.Vpmax, InstEmit32.Vpmax_V, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);

View File

@@ -1115,6 +1115,13 @@ namespace ARMeilleure.Instructions
}
}
public static void Vpadal(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
EmitVectorPairwiseTernaryLongOpI32(context, (op1, op2, op3) => context.Add(context.Add(op1, op2), op3), op.Opc != 1);
}
public static void Vpaddl(ArmEmitterContext context)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;

View File

@@ -578,6 +578,22 @@ namespace ARMeilleure.Instructions
}
}
// VRINTR (floating-point).
public static void Vrintr_S(ArmEmitterContext context)
{
if (Optimizations.UseAdvSimd)
{
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, Intrinsic.Arm64FrintiS);
}
else
{
EmitScalarUnaryOpF32(context, (op1) =>
{
return EmitRoundByRMode(context, op1);
});
}
}
// VRINTZ (floating-point).
public static void Vrint_Z(ArmEmitterContext context)
{

View File

@@ -673,6 +673,35 @@ namespace ARMeilleure.Instructions
context.Copy(GetVecA32(op.Qd), res);
}
public static void EmitVectorPairwiseTernaryLongOpI32(ArmEmitterContext context, Func3I emit, bool signed)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
int elems = op.GetBytesCount() >> op.Size;
int pairs = elems >> 1;
Operand res = GetVecA32(op.Qd);
for (int index = 0; index < pairs; index++)
{
int pairIndex = index * 2;
Operand m1 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex, op.Size, signed);
Operand m2 = EmitVectorExtract32(context, op.Qm, op.Im + pairIndex + 1, op.Size, signed);
if (op.Size == 2)
{
m1 = signed ? context.SignExtend32(OperandType.I64, m1) : context.ZeroExtend32(OperandType.I64, m1);
m2 = signed ? context.SignExtend32(OperandType.I64, m2) : context.ZeroExtend32(OperandType.I64, m2);
}
Operand d1 = EmitVectorExtract32(context, op.Qd, op.Id + index, op.Size + 1, signed);
res = EmitVectorInsert(context, res, emit(m1, m2, d1), op.Id + index, op.Size + 1);
}
context.Copy(GetVecA32(op.Qd), res);
}
// Narrow
public static void EmitVectorUnaryNarrowOp32(ArmEmitterContext context, Func1I emit, bool signed = false)

View File

@@ -637,6 +637,7 @@ namespace ARMeilleure.Instructions
Vorn,
Vorr,
Vpadd,
Vpadal,
Vpaddl,
Vpmax,
Vpmin,
@@ -656,6 +657,7 @@ namespace ARMeilleure.Instructions
Vrintm,
Vrintn,
Vrintp,
Vrintr,
Vrintx,
Vrshr,
Vrshrn,

View File

@@ -72,6 +72,7 @@
"GameListContextMenuExtractDataLogoToolTip": "Extract the Logo section from Application's current config (including updates)",
"GameListContextMenuCreateShortcut": "Create Application Shortcut",
"GameListContextMenuCreateShortcutToolTip": "Create a Desktop Shortcut that launches the selected Application",
"GameListContextMenuCreateShortcutToolTipMacOS": "Create a shortcut in macOS's Applications folder that launches the selected Application",
"StatusBarGamesLoaded": "{0}/{1} Games Loaded",
"StatusBarSystemVersion": "System Version: {0}",
"LinuxVmMaxMapCountDialogTitle": "Low limit for memory mappings detected",

View File

@@ -9,6 +9,7 @@ using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common;
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Services.Hid;
using System;
using System.Linq;
using System.Threading.Tasks;
@@ -103,7 +104,7 @@ namespace Ryujinx.Ava.UI.Applet
if (!string.IsNullOrWhiteSpace(path))
{
SvgSource source = new();
SvgSource source = new(default(Uri));
source.Load(EmbeddedResources.GetStream(path));

View File

@@ -16,7 +16,7 @@
Click="CreateApplicationShortcut_Click"
Header="{locale:Locale GameListContextMenuCreateShortcut}"
IsEnabled="{Binding CreateShortcutEnabled}"
ToolTip.Tip="{locale:Locale GameListContextMenuCreateShortcutToolTip}" />
ToolTip.Tip="{OnPlatform Default={locale:Locale GameListContextMenuCreateShortcutToolTip}, macOS={locale:Locale GameListContextMenuCreateShortcutToolTipMacOS}}" />
<Separator />
<MenuItem
Click="OpenUserSaveDirectory_Click"

View File

@@ -388,6 +388,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
_contentDialogOverlayWindow.Content = null;
_contentDialogOverlayWindow.Close();
_contentDialogOverlayWindow = null;
}
return result;

View File

@@ -17,14 +17,16 @@ namespace Ryujinx.Ava.UI.Models
}
}
public bool InSd { get; }
public string Path { get; }
public string Name { get; }
public ModModel(string path, string name, bool enabled)
public ModModel(string path, string name, bool enabled, bool inSd)
{
Path = path;
Name = name;
Enabled = enabled;
InSd = inSd;
}
}
}

View File

@@ -180,7 +180,7 @@ namespace Ryujinx.Ava.UI.ViewModels
if (!string.IsNullOrWhiteSpace(_controllerImage))
{
SvgSource source = new();
SvgSource source = new(default(Uri));
source.Load(EmbeddedResources.GetStream(_controllerImage));

View File

@@ -1352,9 +1352,9 @@ namespace Ryujinx.Ava.UI.ViewModels
{
string logPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
if (ReleaseInformation.IsValid)
if (LoggerModule.LogDirectoryPath != null)
{
logPath = Path.Combine(AppDataManager.BaseDirPath, "Logs");
logPath = LoggerModule.LogDirectoryPath;
}
new DirectoryInfo(logPath).Create();

View File

@@ -102,13 +102,14 @@ namespace Ryujinx.Ava.UI.ViewModels
foreach (var path in modsBasePaths)
{
var inSd = path == ModLoader.GetSdModsBasePath();
var modCache = new ModLoader.ModCache();
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId);
foreach (var mod in modCache.RomfsDirs)
{
var modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled);
var modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
if (Mods.All(x => x.Path != mod.Path.Parent.FullName))
{
Mods.Add(modModel);
@@ -117,12 +118,12 @@ namespace Ryujinx.Ava.UI.ViewModels
foreach (var mod in modCache.RomfsContainers)
{
Mods.Add(new ModModel(mod.Path.FullName, mod.Name, mod.Enabled));
Mods.Add(new ModModel(mod.Path.FullName, mod.Name, mod.Enabled, inSd));
}
foreach (var mod in modCache.ExefsDirs)
{
var modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled);
var modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
if (Mods.All(x => x.Path != mod.Path.Parent.FullName))
{
Mods.Add(modModel);
@@ -131,7 +132,7 @@ namespace Ryujinx.Ava.UI.ViewModels
foreach (var mod in modCache.ExefsContainers)
{
Mods.Add(new ModModel(mod.Path.FullName, mod.Name, mod.Enabled));
Mods.Add(new ModModel(mod.Path.FullName, mod.Name, mod.Enabled, inSd));
}
}
@@ -183,30 +184,43 @@ namespace Ryujinx.Ava.UI.ViewModels
public void Delete(ModModel model)
{
var modsDir = ModLoader.GetApplicationDir(ModLoader.GetSdModsBasePath(), _applicationId.ToString("x16"));
var parentDir = String.Empty;
var isSubdir = true;
var pathToDelete = model.Path;
var basePath = model.InSd ? ModLoader.GetSdModsBasePath() : ModLoader.GetModsBasePath();
var modsDir = ModLoader.GetApplicationDir(basePath, _applicationId.ToString("x16"));
foreach (var dir in Directory.GetDirectories(modsDir, "*", SearchOption.TopDirectoryOnly))
if (new DirectoryInfo(model.Path).Parent?.FullName == modsDir)
{
if (Directory.GetDirectories(dir, "*", SearchOption.AllDirectories).Contains(model.Path))
isSubdir = false;
}
if (isSubdir)
{
var parentDir = String.Empty;
foreach (var dir in Directory.GetDirectories(modsDir, "*", SearchOption.TopDirectoryOnly))
{
parentDir = dir;
if (Directory.GetDirectories(dir, "*", SearchOption.AllDirectories).Contains(model.Path))
{
parentDir = dir;
break;
}
}
if (parentDir == String.Empty)
{
Dispatcher.UIThread.Post(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(
LocaleKeys.DialogModDeleteNoParentMessage,
model.Path));
});
return;
}
}
if (parentDir == String.Empty)
{
Dispatcher.UIThread.Post(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(
LocaleKeys.DialogModDeleteNoParentMessage,
parentDir));
});
return;
}
Logger.Info?.Print(LogClass.Application, $"Deleting mod at \"{model.Path}\"");
Directory.Delete(parentDir, true);
Logger.Info?.Print(LogClass.Application, $"Deleting mod at \"{pathToDelete}\"");
Directory.Delete(pathToDelete, true);
Mods.Remove(model);
OnPropertyChanged(nameof(ModCount));

View File

@@ -263,7 +263,7 @@ namespace Ryujinx.Ava.UI.Windows
}
}
private void CheckLaunchState()
private async Task CheckLaunchState()
{
if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount)
{
@@ -271,23 +271,11 @@ namespace Ryujinx.Ava.UI.Windows
if (LinuxHelper.PkExecPath is not null)
{
Dispatcher.UIThread.Post(async () =>
{
if (OperatingSystem.IsLinux())
{
await ShowVmMaxMapCountDialog();
}
});
await Dispatcher.UIThread.InvokeAsync(ShowVmMaxMapCountDialog);
}
else
{
Dispatcher.UIThread.Post(async () =>
{
if (OperatingSystem.IsLinux())
{
await ShowVmMaxMapCountWarning();
}
});
await Dispatcher.UIThread.InvokeAsync(ShowVmMaxMapCountWarning);
}
}
@@ -304,12 +292,12 @@ namespace Ryujinx.Ava.UI.Windows
{
ShowKeyErrorOnLoad = false;
Dispatcher.UIThread.Post(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys));
await Dispatcher.UIThread.InvokeAsync(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys));
}
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))
{
Updater.BeginParse(this, false).ContinueWith(task =>
await Updater.BeginParse(this, false).ContinueWith(task =>
{
Logger.Error?.Print(LogClass.Application, $"Updater Error: {task.Exception}");
}, TaskContinuationOptions.OnlyOnFaulted);
@@ -404,7 +392,9 @@ namespace Ryujinx.Ava.UI.Windows
LoadApplications();
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
CheckLaunchState();
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
private void SetMainContent(Control content = null)

View File

@@ -23,7 +23,7 @@ namespace Ryujinx.Common.Logging.Targets
public static FileStream PrepareLogFile(string path)
{
// Ensure directory is present
DirectoryInfo logDir = new(Path.Combine(path, "Logs"));
DirectoryInfo logDir = new(path);
try
{
logDir.Create();

View File

@@ -427,11 +427,11 @@ namespace Ryujinx.Headless.SDL2
if (!option.DisableFileLog)
{
FileStream logFile = FileLogTarget.PrepareLogFile(AppDomain.CurrentDomain.BaseDirectory);
FileStream logFile = FileLogTarget.PrepareLogFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs"));
if (logFile == null)
{
logFile = FileLogTarget.PrepareLogFile(AppDataManager.BaseDirPath);
logFile = FileLogTarget.PrepareLogFile(Path.Combine(AppDataManager.BaseDirPath, "Logs"));
if (logFile == null)
{

View File

@@ -181,6 +181,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
}
Span<uint> dataWords = Span<uint>.Empty;
Span<uint> dataWordsPadded = Span<uint>.Empty;
if (meta.DataWordsCount != 0)
{
@@ -189,6 +190,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
int padding = (dataOffsetAligned - dataOffset) / sizeof(uint);
dataWords = MemoryMarshal.Cast<byte, uint>(data)[padding..meta.DataWordsCount];
dataWordsPadded = MemoryMarshal.Cast<byte, uint>(data)[..meta.DataWordsCount];
data = data[(meta.DataWordsCount * sizeof(uint))..];
}
@@ -209,6 +211,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
ReceiveBuffers = receiveBuffers,
ExchangeBuffers = exchangeBuffers,
DataWords = dataWords,
DataWordsPadded = dataWordsPadded,
ReceiveList = receiveList,
CopyHandles = copyHandles,
MoveHandles = moveHandles,

View File

@@ -9,6 +9,7 @@ namespace Ryujinx.Horizon.Sdk.Sf.Hipc
public Span<HipcBufferDescriptor> ReceiveBuffers;
public Span<HipcBufferDescriptor> ExchangeBuffers;
public Span<uint> DataWords;
public Span<uint> DataWordsPadded;
public Span<HipcReceiveListEntry> ReceiveList;
public Span<int> CopyHandles;
public Span<int> MoveHandles;

View File

@@ -206,7 +206,7 @@ namespace Ryujinx.Horizon.Sdk.Sf
}
else
{
var data = MemoryMarshal.Cast<uint, byte>(context.Request.Data.DataWords);
var data = MemoryMarshal.Cast<uint, byte>(context.Request.Data.DataWordsPadded);
var recvPointerSizes = MemoryMarshal.Cast<byte, ushort>(data[runtimeMetadata.UnfixedOutPointerSizeOffset..]);
size = recvPointerSizes[unfixedRecvPointerIndex++];

View File

@@ -511,6 +511,45 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise, Description("VRINTR.F<size> <Sd>, <Sm>")]
[Platform(Exclude = "Linux,MacOsX")] // Instruction isn't testable due to Unicorn.
public void Vrintr([Values(0u, 1u)] uint rd,
[Values(0u, 1u)] uint rm,
[Values(2u, 3u)] uint size,
[ValueSource(nameof(_1D_F_))] ulong s0,
[ValueSource(nameof(_1D_F_))] ulong s1,
[ValueSource(nameof(_1D_F_))] ulong s2,
[Values(RMode.Rn, RMode.Rm, RMode.Rp)] RMode rMode)
{
uint opcode = 0xEEB60A40;
V128 v0, v1, v2;
if (size == 2)
{
opcode |= ((rm & 0x1e) >> 1) | ((rm & 0x1) << 5);
opcode |= ((rd & 0x1e) << 11) | ((rd & 0x1) << 22);
v0 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s0), (uint)BitConverter.SingleToInt32Bits(s0));
v1 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s1), (uint)BitConverter.SingleToInt32Bits(s0));
v2 = MakeVectorE0E1((uint)BitConverter.SingleToInt32Bits(s2), (uint)BitConverter.SingleToInt32Bits(s1));
}
else
{
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
v0 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s0), (uint)BitConverter.DoubleToInt64Bits(s0));
v1 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s1), (uint)BitConverter.DoubleToInt64Bits(s0));
v2 = MakeVectorE0E1((uint)BitConverter.DoubleToInt64Bits(s2), (uint)BitConverter.DoubleToInt64Bits(s1));
}
opcode |= ((size & 3) << 8);
int fpscr = (int)rMode << (int)Fpcr.RMode;
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2, fpscr: fpscr);
CompareAgainstUnicorn();
}
#endif
}
}

View File

@@ -908,6 +908,44 @@ namespace Ryujinx.Tests.Cpu
CompareAgainstUnicorn();
}
[Test, Pairwise]
public void Vp_Add_Long_Accumulate([Values(0u, 2u, 4u, 8u)] uint rd,
[Values(0u, 2u, 4u, 8u)] uint rm,
[Values(0u, 1u, 2u)] uint size,
[Random(RndCnt)] ulong z,
[Random(RndCnt)] ulong a,
[Random(RndCnt)] ulong b,
[Values] bool q,
[Values] bool unsigned)
{
uint opcode = 0xF3B00600; // VPADAL.S8 D0, Q0
if (q)
{
opcode |= 1 << 6;
rm <<= 1;
rd <<= 1;
}
if (unsigned)
{
opcode |= 1 << 7;
}
opcode |= ((rm & 0xf) << 0) | ((rm & 0x10) << 1);
opcode |= ((rd & 0xf) << 12) | ((rd & 0x10) << 18);
opcode |= size << 18;
V128 v0 = MakeVectorE0E1(z, z);
V128 v1 = MakeVectorE0E1(a, z);
V128 v2 = MakeVectorE0E1(b, z);
SingleOpcode(opcode, v0: v0, v1: v1, v2: v2);
CompareAgainstUnicorn();
}
#endif
}
}

View File

@@ -9,6 +9,8 @@ namespace Ryujinx.Ui.Common.Configuration
{
public static class LoggerModule
{
public static string LogDirectoryPath { get; private set; }
public static void Initialize()
{
ConfigurationState.Instance.Logger.EnableDebug.Event += ReloadEnableDebug;
@@ -82,21 +84,26 @@ namespace Ryujinx.Ui.Common.Configuration
{
if (e.NewValue)
{
FileStream logFile = FileLogTarget.PrepareLogFile(AppDomain.CurrentDomain.BaseDirectory);
string logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
FileStream logFile = FileLogTarget.PrepareLogFile(logDir);
if (logFile == null)
{
logFile = FileLogTarget.PrepareLogFile(AppDataManager.BaseDirPath);
logDir = Path.Combine(AppDataManager.BaseDirPath, "Logs");
logFile = FileLogTarget.PrepareLogFile(logDir);
if (logFile == null)
{
Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the application directory or the Ryujinx directory is writable.");
LogDirectoryPath = null;
Logger.RemoveTarget("file");
return;
}
}
LogDirectoryPath = logDir;
Logger.AddTarget(new AsyncLogTargetWrapper(
new FileLogTarget("file", logFile),
1000,

View File

@@ -1378,9 +1378,9 @@ namespace Ryujinx.Ui
{
string logPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
if (ReleaseInformation.IsValid)
if (LoggerModule.LogDirectoryPath != null)
{
logPath = System.IO.Path.Combine(AppDataManager.BaseDirPath, "Logs");
logPath = LoggerModule.LogDirectoryPath;
}
new DirectoryInfo(logPath).Create();

View File

@@ -1,4 +1,5 @@
using Gtk;
using System;
namespace Ryujinx.Ui.Widgets
{
@@ -193,7 +194,7 @@ namespace Ryujinx.Ui.Widgets
//
_createShortcutMenuItem = new MenuItem("Create Application Shortcut")
{
TooltipText = "Create a Desktop Shortcut that launches the selected Application."
TooltipText = OperatingSystem.IsMacOS() ? "Create a shortcut in macOS's Applications folder that launches the selected Application" : "Create a Desktop Shortcut that launches the selected Application."
};
_createShortcutMenuItem.Activated += CreateShortcut_Clicked;