Compare commits

..

22 Commits

Author SHA1 Message Date
GreemDev
ebc775aeb5 update compiling document 2025-11-11 12:54:34 -06:00
GreemDev
e24eb13e07 more partial ObservableProperties 2025-11-11 12:43:34 -06:00
GreemDev
c7572b5d30 chore: change BufferHolder.GetHandle() to a getter for the handle instead 2025-11-11 12:43:34 -06:00
GreemDev
2ea829f17b chore: change MultiRegionHandle GetHandles to an accessor property 2025-11-11 12:43:34 -06:00
GreemDev
9c00ffa4b1 fix conflicts 2025-11-11 12:43:34 -06:00
GreemDev
84f26f7276 language feature: field keyword & partial properties for observable properties in the UI
partial properties are from C# 13 but weren't usable for these properties
2025-11-11 12:43:34 -06:00
GreemDev
f2105d6040 chore: converted BufferHandle ToInt32 extension to an implicit int operator on BufferHandle directly. 2025-11-11 12:43:34 -06:00
GreemDev
1f3e4674b5 chore: Split SoftFloat into multiple partial class parts 2025-11-11 12:43:34 -06:00
GreemDev
342c811aca chore: Split SoftFallback into multiple partial class parts 2025-11-11 12:43:34 -06:00
GreemDev
83502494d9 some more extension members 2025-11-11 12:43:34 -06:00
GreemDev
64238e6ec3 language feature: Extension Members: More converted 2025-11-11 12:43:34 -06:00
GreemDev
36bd919c53 use extension members for StorageProviderExtensions 2025-11-11 12:43:34 -06:00
GreemDev
f1df537e76 language feature: Extension Members: HLE <-> UI enum converters 2025-11-11 12:43:34 -06:00
GreemDev
f9e71a5908 Parse UI enum directly 2025-11-11 12:43:34 -06:00
GreemDev
f20291ddf2 language feature: Extension Members: Misc enum extensions methods converted to properties 2025-11-11 12:43:34 -06:00
GreemDev
cc80621a17 language feature: Extension Members: Ryujinx.Graphics.GAL.Format 2025-11-11 12:43:34 -06:00
GreemDev
6a1dec9f91 language feature: Extension Members: OperandType 2025-11-11 12:43:34 -06:00
GreemDev
274ec74856 language feature: Extension Members: HLE 2025-11-11 12:43:34 -06:00
GreemDev
ac98ade572 language feature: Extension Members: Graphics related, enums 2025-11-11 12:43:34 -06:00
GreemDev
e23213d290 language feature: Extension Members: CPU-related, enums 2025-11-11 12:43:34 -06:00
GreemDev
6467720c5c Add .NET Runtime version in About window under Ryujinx version. 2025-11-11 12:43:34 -06:00
GreemDev
010eab44ba feature: Initial .NET 10 Support
Works as of .NET 10.0.0-preview.3.25171.5
2025-11-11 12:43:34 -06:00
40 changed files with 273 additions and 537 deletions

2
.gitignore vendored
View File

@@ -18,8 +18,6 @@ build/
[Oo]bj/ [Oo]bj/
AppDir/ AppDir/
publish_appimage/ publish_appimage/
publish_ava/
publish_tmp_ava/
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
!packages/*/build/ !packages/*/build/

Binary file not shown.

View File

@@ -10,8 +10,6 @@
<string>Ryujinx</string> <string>Ryujinx</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>Ryujinx.icns</string> <string>Ryujinx.icns</string>
<key>CFBundleIconName</key>
<string>Ryujinx</string>
<key>CFBundleDocumentTypes</key> <key>CFBundleDocumentTypes</key>
<array> <array>
<dict> <dict>
@@ -42,7 +40,7 @@
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>1.3</string> <string>1.2</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>

View File

@@ -25,7 +25,6 @@ cp "$PUBLISH_DIRECTORY"/*.dylib "$APP_BUNDLE_DIRECTORY/Contents/Frameworks"
cp Info.plist "$APP_BUNDLE_DIRECTORY/Contents" cp Info.plist "$APP_BUNDLE_DIRECTORY/Contents"
cp Ryujinx.icns "$APP_BUNDLE_DIRECTORY/Contents/Resources/Ryujinx.icns" cp Ryujinx.icns "$APP_BUNDLE_DIRECTORY/Contents/Resources/Ryujinx.icns"
cp updater.sh "$APP_BUNDLE_DIRECTORY/Contents/Resources/updater.sh" cp updater.sh "$APP_BUNDLE_DIRECTORY/Contents/Resources/updater.sh"
cp Assets.car "$APP_BUNDLE_DIRECTORY/Contents/Resources/Assets.car"
cp -r "$PUBLISH_DIRECTORY/THIRDPARTY.md" "$APP_BUNDLE_DIRECTORY/Contents/Resources" cp -r "$PUBLISH_DIRECTORY/THIRDPARTY.md" "$APP_BUNDLE_DIRECTORY/Contents/Resources"
echo -n "APPL????" > "$APP_BUNDLE_DIRECTORY/Contents/PkgInfo" echo -n "APPL????" > "$APP_BUNDLE_DIRECTORY/Contents/PkgInfo"

View File

@@ -2275,12 +2275,12 @@
010018E011D92000,"Pokémon™ Shining Pearl",gpu;ldn-works,ingame,2024-08-28 13:26:35 010018E011D92000,"Pokémon™ Shining Pearl",gpu;ldn-works,ingame,2024-08-28 13:26:35
010015F008C54000,"Pokémon™ HOME",Needs Update;crash;services,menus,2020-12-06 06:01:51 010015F008C54000,"Pokémon™ HOME",Needs Update;crash;services,menus,2020-12-06 06:01:51
01001F5010DFA000,"Pokémon™ Legends: Arceus",gpu;Needs Update;ldn-works,ingame,2024-09-19 10:02:02 01001F5010DFA000,"Pokémon™ Legends: Arceus",gpu;Needs Update;ldn-works,ingame,2024-09-19 10:02:02
0100F43008C44000,"Pokémon™ Legends: Z-A",gpu;crash;ldn-works,ingame,2025-11-16 00:30:00
01005D100807A000,"Pokémon™ Quest",,playable,2022-02-22 16:12:32 01005D100807A000,"Pokémon™ Quest",,playable,2022-02-22 16:12:32
0100A3D008C5C000,"Pokémon™ Scarlet",gpu;nvdec;ldn-works;amd-vendor-bug,ingame,2023-12-14 13:18:29 0100A3D008C5C000,"Pokémon™ Scarlet",gpu;nvdec;ldn-works;amd-vendor-bug,ingame,2023-12-14 13:18:29
01008F6008C5E000,"Pokémon™ Violet",gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug,ingame,2024-07-30 02:51:48 01008F6008C5E000,"Pokémon™ Violet",gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug,ingame,2024-07-30 02:51:48
0100187003A36000,"Pokémon™: Lets Go, Eevee!",crash;nvdec;online-broken;ldn-broken,ingame,2024-06-01 15:03:04 0100187003A36000,"Pokémon™: Lets Go, Eevee!",crash;nvdec;online-broken;ldn-broken,ingame,2024-06-01 15:03:04
010003F003A34000,"Pokémon™: Lets Go, Pikachu!",crash;nvdec;online-broken;ldn-broken,ingame,2024-03-15 07:55:41 010003F003A34000,"Pokémon™: Lets Go, Pikachu!",crash;nvdec;online-broken;ldn-broken,ingame,2024-03-15 07:55:41
0100F43008C44000,"Pokémon Legends: Z-A",gpu;crash;ldn-broken,ingame,2025-10-16 19:13:00
0100B3F000BE2000,"Pokkén Tournament™ DX",nvdec;ldn-works;opengl-backend-bug;LAN;amd-vendor-bug;intel-vendor-bug,playable,2024-07-18 23:11:08 0100B3F000BE2000,"Pokkén Tournament™ DX",nvdec;ldn-works;opengl-backend-bug;LAN;amd-vendor-bug;intel-vendor-bug,playable,2024-07-18 23:11:08
010030D005AE6000,"Pokkén Tournament™ DX Demo",demo;opengl-backend-bug,playable,2022-08-10 12:03:19 010030D005AE6000,"Pokkén Tournament™ DX Demo",demo;opengl-backend-bug,playable,2022-08-10 12:03:19
0100A3500B4EC000,"Polandball: Can Into Space",,playable,2020-06-25 15:13:26 0100A3500B4EC000,"Polandball: Can Into Space",,playable,2020-06-25 15:13:26
1 title_id game_name labels status last_updated
2275 010018E011D92000 Pokémon™ Shining Pearl gpu;ldn-works ingame 2024-08-28 13:26:35
2276 010015F008C54000 Pokémon™ HOME Needs Update;crash;services menus 2020-12-06 06:01:51
2277 01001F5010DFA000 Pokémon™ Legends: Arceus gpu;Needs Update;ldn-works ingame 2024-09-19 10:02:02
0100F43008C44000 Pokémon™ Legends: Z-A gpu;crash;ldn-works ingame 2025-11-16 00:30:00
2278 01005D100807A000 Pokémon™ Quest playable 2022-02-22 16:12:32
2279 0100A3D008C5C000 Pokémon™ Scarlet gpu;nvdec;ldn-works;amd-vendor-bug ingame 2023-12-14 13:18:29
2280 01008F6008C5E000 Pokémon™ Violet gpu;nvdec;ldn-works;amd-vendor-bug;mac-bug ingame 2024-07-30 02:51:48
2281 0100187003A36000 Pokémon™: Let’s Go, Eevee! crash;nvdec;online-broken;ldn-broken ingame 2024-06-01 15:03:04
2282 010003F003A34000 Pokémon™: Let’s Go, Pikachu! crash;nvdec;online-broken;ldn-broken ingame 2024-03-15 07:55:41
2283 0100F43008C44000 Pokémon Legends: Z-A gpu;crash;ldn-broken ingame 2025-10-16 19:13:00
2284 0100B3F000BE2000 Pokkén Tournament™ DX nvdec;ldn-works;opengl-backend-bug;LAN;amd-vendor-bug;intel-vendor-bug playable 2024-07-18 23:11:08
2285 010030D005AE6000 Pokkén Tournament™ DX Demo demo;opengl-backend-bug playable 2022-08-10 12:03:19
2286 0100A3500B4EC000 Polandball: Can Into Space playable 2020-06-25 15:13:26

View File

@@ -361,7 +361,10 @@ namespace ARMeilleure.Translation
IntervalTreeNode<TK, TV> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode); IntervalTreeNode<TK, TV> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
tmp?.Parent = ParentOf(replacementNode); if (tmp != null)
{
tmp.Parent = ParentOf(replacementNode);
}
if (ParentOf(replacementNode) == null) if (ParentOf(replacementNode) == null)
{ {
@@ -579,7 +582,10 @@ namespace ARMeilleure.Translation
{ {
IntervalTreeNode<TK, TV> right = RightOf(node); IntervalTreeNode<TK, TV> right = RightOf(node);
node.Right = LeftOf(right); node.Right = LeftOf(right);
node.Right?.Parent = node; if (node.Right != null)
{
node.Right.Parent = node;
}
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node); IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
right.Parent = nodeParent; right.Parent = nodeParent;
@@ -609,7 +615,10 @@ namespace ARMeilleure.Translation
{ {
IntervalTreeNode<TK, TV> left = LeftOf(node); IntervalTreeNode<TK, TV> left = LeftOf(node);
node.Left = RightOf(left); node.Left = RightOf(left);
node.Left?.Parent = node; if (node.Left != null)
{
node.Left.Parent = node;
}
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node); IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
left.Parent = nodeParent; left.Parent = nodeParent;
@@ -658,7 +667,10 @@ namespace ARMeilleure.Translation
/// <param name="color">Color (Boolean)</param> /// <param name="color">Color (Boolean)</param>
private static void SetColor(IntervalTreeNode<TK, TV> node, bool color) private static void SetColor(IntervalTreeNode<TK, TV> node, bool color)
{ {
node?.Color = color; if (node != null)
{
node.Color = color;
}
} }
/// <summary> /// <summary>

View File

@@ -92,7 +92,6 @@ namespace Ryujinx.Audio.Renderer.Dsp.Command
} }
short[] outputBuffer = ArrayPool<short>.Shared.Rent((int)inputCount * SampleCount); short[] outputBuffer = ArrayPool<short>.Shared.Rent((int)inputCount * SampleCount);
Array.Fill(outputBuffer, (short)0, 0, (int)inputCount * SampleCount);
for (int i = 0; i < bufferCount; i++) for (int i = 0; i < bufferCount; i++)
{ {

View File

@@ -386,7 +386,10 @@ namespace Ryujinx.Common.Collections
IntervalTreeNode<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode); IntervalTreeNode<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
tmp?.Parent = ParentOf(replacementNode); if (tmp != null)
{
tmp.Parent = ParentOf(replacementNode);
}
if (ParentOf(replacementNode) == null) if (ParentOf(replacementNode) == null)
{ {

View File

@@ -235,7 +235,10 @@ namespace Ryujinx.Common.Collections
parent = ParentOf(element); parent = ParentOf(element);
color = ColorOf(element); color = ColorOf(element);
child?.Parent = parent; if (child != null)
{
child.Parent = parent;
}
if (parent == null) if (parent == null)
{ {
@@ -255,7 +258,8 @@ namespace Ryujinx.Common.Collections
element.Right = old.Right; element.Right = old.Right;
element.Parent = old.Parent; element.Parent = old.Parent;
element.Predecessor = old.Predecessor; element.Predecessor = old.Predecessor;
element.Predecessor?.Successor = element; if (element.Predecessor != null)
element.Predecessor.Successor = element;
if (ParentOf(old) == null) if (ParentOf(old) == null)
{ {
@@ -288,7 +292,10 @@ namespace Ryujinx.Common.Collections
parent = ParentOf(nodeToDelete); parent = ParentOf(nodeToDelete);
color = ColorOf(nodeToDelete); color = ColorOf(nodeToDelete);
child?.Parent = parent; if (child != null)
{
child.Parent = parent;
}
if (parent == null) if (parent == null)
{ {
@@ -307,9 +314,11 @@ namespace Ryujinx.Common.Collections
{ {
RestoreBalanceAfterRemoval(child); RestoreBalanceAfterRemoval(child);
} }
old.Successor?.Predecessor = old.Predecessor; if (old.Successor != null)
old.Predecessor?.Successor = old.Successor; old.Successor.Predecessor = old.Predecessor;
if (old.Predecessor != null)
old.Predecessor.Successor = old.Successor;
return old; return old;
} }

View File

@@ -250,7 +250,10 @@ namespace Ryujinx.Common.Collections
{ {
T right = RightOf(node); T right = RightOf(node);
node.Right = LeftOf(right); node.Right = LeftOf(right);
node.Right?.Parent = node; if (node.Right != null)
{
node.Right.Parent = node;
}
T nodeParent = ParentOf(node); T nodeParent = ParentOf(node);
right.Parent = nodeParent; right.Parent = nodeParent;
@@ -278,7 +281,10 @@ namespace Ryujinx.Common.Collections
{ {
T left = LeftOf(node); T left = LeftOf(node);
node.Left = RightOf(left); node.Left = RightOf(left);
node.Left?.Parent = node; if (node.Left != null)
{
node.Left.Parent = node;
}
T nodeParent = ParentOf(node); T nodeParent = ParentOf(node);
left.Parent = nodeParent; left.Parent = nodeParent;
@@ -323,7 +329,10 @@ namespace Ryujinx.Common.Collections
/// <param name="color">Color (Boolean)</param> /// <param name="color">Color (Boolean)</param>
protected static void SetColor(T node, bool color) protected static void SetColor(T node, bool color)
{ {
node?.Color = color; if (node != null)
{
node.Color = color;
}
} }
/// <summary> /// <summary>

View File

@@ -328,7 +328,10 @@ namespace Ryujinx.Common.Collections
Node<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode); Node<TKey, TValue> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
tmp?.Parent = ParentOf(replacementNode); if (tmp != null)
{
tmp.Parent = ParentOf(replacementNode);
}
if (ParentOf(replacementNode) == null) if (ParentOf(replacementNode) == null)
{ {

View File

@@ -35,7 +35,6 @@ namespace Ryujinx.Common.Logging
ServiceBsd, ServiceBsd,
ServiceBtm, ServiceBtm,
ServiceCaps, ServiceCaps,
ServiceEctx,
ServiceFatal, ServiceFatal,
ServiceFriend, ServiceFriend,
ServiceFs, ServiceFs,

View File

@@ -84,7 +84,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
ICounterEvent evt = _items[index + i].Event; ICounterEvent evt = _items[index + i].Event;
evt?.Invalid = true; if (evt != null)
{
evt.Invalid = true;
}
} }
_items.RemoveRange(index, count); _items.RemoveRange(index, count);

View File

@@ -26,8 +26,12 @@ namespace Ryujinx.Graphics.Shader.Translation.Optimizations
// - Both branches are jumping to the same location. // - Both branches are jumping to the same location.
// In this case, the branch on the current block can be removed, // In this case, the branch on the current block can be removed,
// as the next block is going to jump to the same place anyway. // as the next block is going to jump to the same place anyway.
if (nextBlock == null)
{
return false;
}
if (nextBlock?.Operations.First?.Value is not Operation next) if (nextBlock.Operations.First?.Value is not Operation next)
{ {
return false; return false;
} }

View File

@@ -891,7 +891,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
result = new NestedName(name, prev); result = new NestedName(name, prev);
} }
context?.FinishWithTemplateArguments = false; if (context != null)
{
context.FinishWithTemplateArguments = false;
}
return result; return result;
} }
@@ -1071,7 +1074,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
return null; return null;
} }
context?.CtorDtorConversion = true; if (context != null)
{
context.CtorDtorConversion = true;
}
return new ConversionOperatorType(type); return new ConversionOperatorType(type);
default: default:
@@ -1343,7 +1349,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
_position++; _position++;
context?.CtorDtorConversion = true; if (context != null)
{
context.CtorDtorConversion = true;
}
if (isInherited && ParseName(context) == null) if (isInherited && ParseName(context) == null)
{ {
@@ -1363,7 +1372,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
_position++; _position++;
context?.CtorDtorConversion = true; if (context != null)
{
context.CtorDtorConversion = true;
}
return new CtorDtorNameType(prev, true); return new CtorDtorNameType(prev, true);
} }
@@ -2993,10 +3005,16 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
BaseNode result = null; BaseNode result = null;
CvType cv = new(ParseCvQualifiers(), null); CvType cv = new(ParseCvQualifiers(), null);
context?.Cv = cv; if (context != null)
{
context.Cv = cv;
}
SimpleReferenceType Ref = ParseRefQualifiers(); SimpleReferenceType Ref = ParseRefQualifiers();
context?.Ref = Ref; if (context != null)
{
context.Ref = Ref;
}
if (ConsumeIf("St")) if (ConsumeIf("St"))
{ {
@@ -3042,7 +3060,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
} }
result = new NameTypeWithTemplateArguments(result, templateArgument); result = new NameTypeWithTemplateArguments(result, templateArgument);
context?.FinishWithTemplateArguments = true; if (context != null)
{
context.FinishWithTemplateArguments = true;
}
_substitutionList.Add(result); _substitutionList.Add(result);
continue; continue;
@@ -3235,7 +3256,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
return null; return null;
} }
context?.FinishWithTemplateArguments = true; if (context != null)
{
context.FinishWithTemplateArguments = true;
}
return new NameTypeWithTemplateArguments(substitution, templateArguments); return new NameTypeWithTemplateArguments(substitution, templateArguments);
} }
@@ -3255,7 +3279,10 @@ namespace Ryujinx.HLE.HOS.Diagnostics.Demangler
return null; return null;
} }
context?.FinishWithTemplateArguments = true; if (context != null)
{
context.FinishWithTemplateArguments = true;
}
return new NameTypeWithTemplateArguments(result, templateArguments); return new NameTypeWithTemplateArguments(result, templateArguments);
} }

View File

@@ -174,7 +174,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
if (previousThread != nextThread) if (previousThread != nextThread)
{ {
previousThread?.LastScheduledTime = PerformanceCounter.ElapsedTicks; if (previousThread != null)
{
previousThread.LastScheduledTime = PerformanceCounter.ElapsedTicks;
}
_state.SelectedThread = nextThread; _state.SelectedThread = nextThread;
_state.NeedsScheduling = true; _state.NeedsScheduling = true;

View File

@@ -1,32 +0,0 @@
using System;
using Ryujinx.Common.Logging;
using Ryujinx.Horizon.Common;
namespace Ryujinx.HLE.HOS.Services.Ectx
{
class IContextRegistrar : DisposableIpcService
{
public IContextRegistrar(ServiceCtx context) { }
[CommandCmif(0)] // 11.0.0+
// Complete(nn::Result result, buffer<bytes, 5> raw_context) -> (i32 context_descriptor)
public ResultCode Complete(ServiceCtx context)
{
Result result = new(context.RequestData.ReadInt32());
ulong rawContextPosition = context.Request.SendBuff[0].Position;
ulong rawContextSize = context.Request.SendBuff[0].Size;
byte[] rawContext = new byte[rawContextSize];
context.Memory.Read(rawContextPosition, rawContext);
context.ResponseData.Write(0); // TODO: return context_descriptor
Logger.Stub?.PrintStub(LogClass.ServiceEctx, $"Result: {result}, rawContext: {Convert.ToHexString(rawContext)}" );
return ResultCode.Success;
}
protected override void Dispose(bool isDisposing) { }
}
}

View File

@@ -4,14 +4,5 @@ namespace Ryujinx.HLE.HOS.Services.Ectx
class IWriterForApplication : IpcService class IWriterForApplication : IpcService
{ {
public IWriterForApplication(ServiceCtx context) { } public IWriterForApplication(ServiceCtx context) { }
[CommandCmif(0)]
// CreateContextRegistrar() -> object<nn::err::context::IContextRegistrar>
public ResultCode CreateContextRegistrar(ServiceCtx context)
{
MakeObject(context, new IContextRegistrar(context));
return ResultCode.Success;
}
} }
} }

View File

@@ -1169,7 +1169,9 @@ namespace Ryujinx.HLE.HOS.Services.Sockets.Bsd
public override void DestroyAtExit() public override void DestroyAtExit()
{ {
_context?.Dispose(); if (_context != null) {
_context.Dispose();
}
} }
} }
} }

View File

@@ -22,7 +22,7 @@ namespace Ryujinx.Input.SDL3
private StandardControllerInputConfig _configuration; private StandardControllerInputConfig _configuration;
private readonly SDL_GamepadButton[] _buttonsDriverMapping = private static readonly SDL_GamepadButton[] _buttonsDriverMapping =
[ [
// Unbound, ignored. // Unbound, ignored.
SDL_GamepadButton.SDL_GAMEPAD_BUTTON_INVALID, SDL_GamepadButton.SDL_GAMEPAD_BUTTON_INVALID,
@@ -88,20 +88,6 @@ namespace Ryujinx.Input.SDL3
Features = GetFeaturesFlag(); Features = GetFeaturesFlag();
_triggerThreshold = 0.0f; _triggerThreshold = 0.0f;
// Face button mapping
SDL_GamepadButton[] faceButtons = _buttonsDriverMapping[1..5];
foreach (SDL_GamepadButton btn in faceButtons) {
int mapId = SDL_GetGamepadButtonLabel(_gamepadHandle, btn) switch {
SDL_GamepadButtonLabel.SDL_GAMEPAD_BUTTON_LABEL_A or SDL_GamepadButtonLabel.SDL_GAMEPAD_BUTTON_LABEL_CROSS => 1,
SDL_GamepadButtonLabel.SDL_GAMEPAD_BUTTON_LABEL_B or SDL_GamepadButtonLabel.SDL_GAMEPAD_BUTTON_LABEL_CIRCLE => 2,
SDL_GamepadButtonLabel.SDL_GAMEPAD_BUTTON_LABEL_X or SDL_GamepadButtonLabel.SDL_GAMEPAD_BUTTON_LABEL_SQUARE => 3,
SDL_GamepadButtonLabel.SDL_GAMEPAD_BUTTON_LABEL_Y or SDL_GamepadButtonLabel.SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE => 4,
_ => -1
};
if (mapId == -1) { continue; }
_buttonsDriverMapping[mapId] = btn;
}
// Enable motion tracking // Enable motion tracking
if ((Features & GamepadFeaturesFlag.Motion) != 0) if ((Features & GamepadFeaturesFlag.Motion) != 0)
{ {

View File

@@ -65,7 +65,7 @@ namespace Ryujinx.Input.SDL3
string strGuid = new(guidBytes); string strGuid = new(guidBytes);
return $"{strGuid[4..6]}{strGuid[6..8]}{strGuid[2..4]}{strGuid[0..2]}-{strGuid[10..12]}{strGuid[8..10]}-{strGuid[12..16]}-{strGuid[16..20]}-{strGuid[20..32]}"; return $"{strGuid[0..8]}-{strGuid[8..12]}-{strGuid[12..16]}-{strGuid[16..20]}-{strGuid[20..32]}";
} }

View File

@@ -330,7 +330,6 @@ namespace Ryujinx.Input.HLE
_device.TamperMachine.UpdateInput(hleInputStates); _device.TamperMachine.UpdateInput(hleInputStates);
hleMotionStates.Clear();
_hleMotionStatesPool.Release(hleMotionStates); _hleMotionStatesPool.Release(hleMotionStates);
} }
} }

View File

@@ -58,7 +58,10 @@ namespace Ryujinx.Memory.Tracking
{ {
foreach (RegionHandle handle in _handles) foreach (RegionHandle handle in _handles)
{ {
handle?.RegisterAction((address, size) => action(handle.Address, handle.Size)); if (handle != null)
{
handle?.RegisterAction((address, size) => action(handle.Address, handle.Size));
}
} }
} }
@@ -66,7 +69,10 @@ namespace Ryujinx.Memory.Tracking
{ {
foreach (RegionHandle handle in _handles) foreach (RegionHandle handle in _handles)
{ {
handle?.RegisterPreciseAction((address, size, write) => action(handle.Address, handle.Size, write)); if (handle != null)
{
handle?.RegisterPreciseAction((address, size, write) => action(handle.Address, handle.Size, write));
}
} }
} }

View File

@@ -233,8 +233,6 @@ namespace Ryujinx.Ava
{ {
Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location: {ConfigurationPath}"); Logger.Warning?.PrintMsg(LogClass.Application, $"Failed to load config! Loading the default config instead.\nFailed config location: {ConfigurationPath}");
ConfigurationFileFormat.RenameInvalidConfigFile(ConfigurationPath);
ConfigurationState.Instance.LoadDefault(); ConfigurationState.Instance.LoadDefault();
} }
} }

View File

@@ -501,12 +501,18 @@ namespace Ryujinx.Ava.Systems
private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs<bool> args) private void UpdateIgnoreMissingServicesState(object sender, ReactiveEventArgs<bool> args)
{ {
Device?.Configuration.IgnoreMissingServices = args.NewValue; if (Device != null)
{
Device.Configuration.IgnoreMissingServices = args.NewValue;
}
} }
private void UpdateAspectRatioState(object sender, ReactiveEventArgs<AspectRatio> args) private void UpdateAspectRatioState(object sender, ReactiveEventArgs<AspectRatio> args)
{ {
Device?.Configuration.AspectRatio = args.NewValue; if (Device != null)
{
Device.Configuration.AspectRatio = args.NewValue;
}
} }
private void UpdateAntiAliasing(object sender, ReactiveEventArgs<AntiAliasing> e) private void UpdateAntiAliasing(object sender, ReactiveEventArgs<AntiAliasing> e)

View File

@@ -6,9 +6,7 @@ using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE; using Ryujinx.HLE;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
namespace Ryujinx.Ava.Systems.Configuration namespace Ryujinx.Ava.Systems.Configuration
{ {
@@ -512,43 +510,6 @@ namespace Ryujinx.Ava.Systems.Configuration
} }
} }
/// <summary>
/// Renames the configuration file when it is deemed invalid
/// </summary>
/// <param name="path">The path to the invalid JSON configuration file</param>
/// <returns>The path of the renamed invalid JSON configuration file, or null if the rename failed</returns>
public static string RenameInvalidConfigFile(string path)
{
if (string.IsNullOrWhiteSpace(path) || !File.Exists(path))
{
return null;
}
try
{
string directory = Path.GetDirectoryName(path) ?? string.Empty;
string originalFileName = Path.GetFileName(path);
if (string.IsNullOrWhiteSpace(originalFileName))
{
return null;
}
string renamedFileName = $"{originalFileName}.{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.invalid";
string renamedPath = string.IsNullOrEmpty(directory) ? renamedFileName : Path.Combine(directory, renamedFileName);
File.Move(path, renamedPath, overwrite: false);
Logger.Warning?.PrintMsg(LogClass.Application, $"Invalid configuration renamed to: {renamedPath}");
return renamedPath;
}
catch (Exception ex)
{
Logger.Error?.PrintMsg(LogClass.Application, $"Failed to rename invalid configuration file \"{path}\": {ex}");
return null;
}
}
/// <summary> /// <summary>
/// Save a configuration file to disk /// Save a configuration file to disk
/// </summary> /// </summary>

View File

@@ -28,8 +28,6 @@ namespace Ryujinx.Ava.Systems.Configuration
{ {
RyuLogger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {cff.Version}, loading default."); RyuLogger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {cff.Version}, loading default.");
ConfigurationFileFormat.RenameInvalidConfigFile(configurationFilePath);
LoadDefault(); LoadDefault();
return; return;
} }

View File

@@ -88,10 +88,14 @@ namespace Ryujinx.Ava.Systems
{ {
if (showVersionUpToDate) if (showVersionUpToDate)
{ {
await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog( UserResult userResult = await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog(
LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage],
string.Empty, string.Empty);
_versionResponse.ReleaseUrlFormat.Format(currentVersion));
if (userResult is UserResult.Ok)
{
OpenHelper.OpenUrl(_versionResponse.ReleaseUrlFormat.Format(currentVersion));
}
} }
Logger.Info?.Print(LogClass.Application, "Up to date."); Logger.Info?.Print(LogClass.Application, "Up to date.");

View File

@@ -60,10 +60,14 @@ namespace Ryujinx.Ava.Systems
{ {
if (showVersionUpToDate) if (showVersionUpToDate)
{ {
await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog( UserResult userResult = await ContentDialogHelper.CreateUpdaterUpToDateInfoDialog(
LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage],
string.Empty, string.Empty);
changelogUrl: _versionResponse.ReleaseUrlFormat.Format(currentVersion));
if (userResult is UserResult.Ok)
{
OpenHelper.OpenUrl(_versionResponse.ReleaseUrlFormat.Format(currentVersion));
}
} }
Logger.Info?.Print(LogClass.Application, "Up to date."); Logger.Info?.Print(LogClass.Application, "Up to date.");
@@ -102,18 +106,22 @@ namespace Ryujinx.Ava.Systems
Logger.Info?.Print(LogClass.Application, $"Version found: {newVersionString.Replace("", "->")}"); Logger.Info?.Print(LogClass.Application, $"Version found: {newVersionString.Replace("", "->")}");
RequestUserToUpdate:
// Show a message asking the user if they want to update // Show a message asking the user if they want to update
UserResult shouldUpdate = await ContentDialogHelper.CreateUpdaterChoiceDialog( UserResult shouldUpdate = await ContentDialogHelper.CreateUpdaterChoiceDialog(
LocaleManager.Instance[LocaleKeys.RyujinxUpdater], LocaleManager.Instance[LocaleKeys.RyujinxUpdater],
LocaleManager.Instance[LocaleKeys.RyujinxUpdaterMessage], LocaleManager.Instance[LocaleKeys.RyujinxUpdaterMessage],
newVersionString, newVersionString);
ReleaseInformation.GetChangelogUrl(currentVersion, newVersion));
switch (shouldUpdate) switch (shouldUpdate)
{ {
case UserResult.Yes: case UserResult.Yes:
await UpdateRyujinx(_versionResponse.ArtifactUrl); await UpdateRyujinx(_versionResponse.ArtifactUrl);
break; break;
// Secondary button maps to no, which in this case is the show changelog button.
case UserResult.No:
OpenHelper.OpenUrl(ReleaseInformation.GetChangelogUrl(currentVersion, newVersion));
goto RequestUserToUpdate;
default: default:
_running = false; _running = false;
break; break;

View File

@@ -167,7 +167,10 @@ namespace Ryujinx.Ava.UI.Controls
private void Message_TextInput(object sender, TextInputEventArgs e) private void Message_TextInput(object sender, TextInputEventArgs e)
{ {
_host?.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message); if (_host != null)
{
_host.IsPrimaryButtonEnabled = _checkLength(Message.Length) && _checkInput(Message);
}
} }
private void Message_KeyUp(object sender, KeyEventArgs e) private void Message_KeyUp(object sender, KeyEventArgs e)

View File

@@ -10,7 +10,6 @@ using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using System; using System;
using System.Threading; using System.Threading;
@@ -103,25 +102,6 @@ namespace Ryujinx.Ava.UI.Helpers
return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, deferCloseAction); return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, deferCloseAction);
} }
public async static Task<UserResult> ShowTextDialogWithButton(
string title,
string primaryText,
string secondaryText,
string primaryButton,
string secondaryButton,
string closeButton,
int iconSymbol,
string buttonText,
Action onClick,
UserResult primaryButtonResult = UserResult.Ok,
ManualResetEvent deferResetEvent = null,
TypedEventHandler<ContentDialog, ContentDialogButtonClickEventArgs> deferCloseAction = null)
{
Grid content = CreateTextDialogContentWithButton(primaryText, secondaryText, iconSymbol, buttonText, onClick);
return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, deferCloseAction);
}
public static async Task<UserResult> ShowDeferredContentDialog( public static async Task<UserResult> ShowDeferredContentDialog(
Window window, Window window,
@@ -193,109 +173,43 @@ namespace Ryujinx.Ava.UI.Helpers
MinHeight = 80, MinHeight = 80,
}; };
content.Children.Add(new SymbolIcon SymbolIcon icon = new()
{ {
Symbol = (Symbol)symbol, Symbol = (Symbol)symbol,
Margin = new Thickness(10), Margin = new Thickness(10),
FontSize = 40, FontSize = 40,
FlowDirection = FlowDirection.LeftToRight, FlowDirection = FlowDirection.LeftToRight,
VerticalAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center,
GridColumn = 0, };
GridRow = 0,
GridRowSpan = 2
});
content.Children.Add(new TextBlock Grid.SetColumn(icon, 0);
Grid.SetRowSpan(icon, 2);
Grid.SetRow(icon, 0);
TextBlock primaryLabel = new()
{ {
Text = primaryText, Text = primaryText,
Margin = new Thickness(5), Margin = new Thickness(5),
TextWrapping = TextWrapping.Wrap, TextWrapping = TextWrapping.Wrap,
MaxWidth = 450, MaxWidth = 450,
GridColumn = 1, };
GridRow = 0
});
content.Children.Add(new TextBlock TextBlock secondaryLabel = new()
{ {
Text = secondaryText, Text = secondaryText,
Margin = new Thickness(5), Margin = new Thickness(5),
TextWrapping = TextWrapping.Wrap, TextWrapping = TextWrapping.Wrap,
MaxWidth = 450, MaxWidth = 450,
GridColumn = 1,
GridRow = 1
});
return content;
}
private static Grid CreateTextDialogContentWithButton(string primaryText, string secondaryText, int symbol, string buttonName, Action onClick)
{
Grid content = new()
{
RowDefinitions = [new(), new(), new(GridLength.Star), new()],
ColumnDefinitions = [new(GridLength.Auto), new()],
MinHeight = 80,
}; };
content.Children.Add(new SymbolIcon Grid.SetColumn(primaryLabel, 1);
{ Grid.SetColumn(secondaryLabel, 1);
Symbol = (Symbol)symbol, Grid.SetRow(primaryLabel, 0);
Margin = new Thickness(10), Grid.SetRow(secondaryLabel, 1);
FontSize = 40,
FlowDirection = FlowDirection.LeftToRight,
VerticalAlignment = VerticalAlignment.Center,
GridColumn = 0,
GridRow = 0,
GridRowSpan = 2
});
StackPanel buttonContent = new() content.Children.Add(icon);
{ content.Children.Add(primaryLabel);
Orientation = Orientation.Horizontal, content.Children.Add(secondaryLabel);
Spacing = 2
};
buttonContent.Children.Add(new TextBlock
{
Text = buttonName,
Margin = new Thickness(2)
});
buttonContent.Children.Add(new SymbolIcon
{
FlowDirection = FlowDirection.LeftToRight,
Symbol = Symbol.Open
});
content.Children.Add(new TextBlock
{
Text = primaryText,
Margin = new Thickness(5),
TextWrapping = TextWrapping.Wrap,
MaxWidth = 450,
GridColumn = 1,
GridRow = 0
});
content.Children.Add(new TextBlock
{
Text = secondaryText,
Margin = new Thickness(5),
TextWrapping = TextWrapping.Wrap,
MaxWidth = 450,
GridColumn = 1,
GridRow = 1
});
content.Children.Add(new Button
{
Content = buttonContent,
HorizontalAlignment = HorizontalAlignment.Center,
Command = Commands.Create(onClick),
GridRow = 2,
GridColumnSpan = 2,
});
return content; return content;
} }
@@ -368,20 +282,15 @@ namespace Ryujinx.Ava.UI.Helpers
LocaleManager.Instance[LocaleKeys.InputDialogOk], LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Important); (int)Symbol.Important);
internal static async Task CreateUpdaterUpToDateInfoDialog(string primary, string secondaryText, internal static async Task<UserResult> CreateUpdaterUpToDateInfoDialog(string primary, string secondaryText)
string changelogUrl) => await ShowTextDialog(
{
await ShowTextDialogWithButton(
LocaleManager.Instance[LocaleKeys.DialogUpdaterTitle], LocaleManager.Instance[LocaleKeys.DialogUpdaterTitle],
primary, primary,
secondaryText, secondaryText,
string.Empty, LocaleManager.Instance[LocaleKeys.DialogUpdaterShowChangelogMessage],
string.Empty, string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk], LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Important, (int)Symbol.Important);
LocaleManager.Instance[LocaleKeys.DialogUpdaterShowChangelogMessage],
() => OpenHelper.OpenUrl(changelogUrl));
}
internal static async Task CreateWarningDialog(string primary, string secondaryText) internal static async Task CreateWarningDialog(string primary, string secondaryText)
=> await ShowTextDialog( => await ShowTextDialog(
@@ -431,7 +340,7 @@ namespace Ryujinx.Ava.UI.Helpers
return response == UserResult.Yes; return response == UserResult.Yes;
} }
internal static async Task<UserResult> CreateUpdaterChoiceDialog(string title, string primary, string secondaryText, string changelogUrl) internal static async Task<UserResult> CreateUpdaterChoiceDialog(string title, string primary, string secondaryText)
{ {
if (_isChoiceDialogOpen) if (_isChoiceDialogOpen)
{ {
@@ -440,16 +349,14 @@ namespace Ryujinx.Ava.UI.Helpers
_isChoiceDialogOpen = true; _isChoiceDialogOpen = true;
UserResult response = await ShowTextDialogWithButton( UserResult response = await ShowTextDialog(
title, title,
primary, primary,
secondaryText, secondaryText,
LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance[LocaleKeys.InputDialogYes],
string.Empty, LocaleManager.Instance[LocaleKeys.DialogUpdaterShowChangelogMessage],
LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.InputDialogNo],
(int)Symbol.Help, (int)Symbol.Help,
LocaleManager.Instance[LocaleKeys.DialogUpdaterShowChangelogMessage],
() => OpenHelper.OpenUrl(changelogUrl),
UserResult.Yes); UserResult.Yes);
_isChoiceDialogOpen = false; _isChoiceDialogOpen = false;

View File

@@ -1,40 +0,0 @@
using Avalonia.Controls;
namespace Ryujinx.Ava.UI.Helpers
{
public static class ControlExtensions
{
extension(Control ctrl)
{
public int GridRow
{
get => Grid.GetRow(ctrl);
set => Grid.SetRow(ctrl, value);
}
public int GridColumn
{
get => Grid.GetColumn(ctrl);
set => Grid.SetColumn(ctrl, value);
}
public int GridRowSpan
{
get => Grid.GetRowSpan(ctrl);
set => Grid.SetRowSpan(ctrl, value);
}
public int GridColumnSpan
{
get => Grid.GetColumnSpan(ctrl);
set => Grid.SetColumnSpan(ctrl, value);
}
public bool GridIsSharedSizeScope
{
get => Grid.GetIsSharedSizeScope(ctrl);
set => Grid.SetIsSharedSizeScope(ctrl, value);
}
}
}
}

View File

@@ -27,136 +27,82 @@ namespace Ryujinx.Ava.UI.Models.Input
public ControllerType ControllerType { get; set; } public ControllerType ControllerType { get; set; }
public PlayerIndex PlayerIndex { get; set; } public PlayerIndex PlayerIndex { get; set; }
[ObservableProperty] [ObservableProperty] private StickInputId _leftJoystick;
public partial StickInputId LeftJoystick { get; set; } [ObservableProperty] private bool _leftInvertStickX;
[ObservableProperty] private bool _leftInvertStickY;
[ObservableProperty] private bool _leftRotate90;
[ObservableProperty] private GamepadInputId _leftStickButton;
[ObservableProperty] [ObservableProperty] private StickInputId _rightJoystick;
public partial bool LeftInvertStickX { get; set; } [ObservableProperty] private bool _rightInvertStickX;
[ObservableProperty] private bool _rightInvertStickY;
[ObservableProperty] private bool _rightRotate90;
[ObservableProperty] private GamepadInputId _rightStickButton;
[ObservableProperty] [ObservableProperty] private GamepadInputId _dpadUp;
public partial bool LeftInvertStickY { get; set; } [ObservableProperty] private GamepadInputId _dpadDown;
[ObservableProperty] private GamepadInputId _dpadLeft;
[ObservableProperty] private GamepadInputId _dpadRight;
[ObservableProperty] [ObservableProperty] private GamepadInputId _buttonMinus;
public partial bool LeftRotate90 { get; set; } [ObservableProperty] private GamepadInputId _buttonPlus;
[ObservableProperty] [ObservableProperty] private GamepadInputId _buttonA;
public partial GamepadInputId LeftStickButton { get; set; } [ObservableProperty] private GamepadInputId _buttonB;
[ObservableProperty] private GamepadInputId _buttonX;
[ObservableProperty] private GamepadInputId _buttonY;
[ObservableProperty] [ObservableProperty] private GamepadInputId _buttonZl;
public partial StickInputId RightJoystick { get; set; } [ObservableProperty] private GamepadInputId _buttonZr;
[ObservableProperty] [ObservableProperty] private GamepadInputId _buttonL;
public partial bool RightInvertStickX { get; set; } [ObservableProperty] private GamepadInputId _buttonR;
[ObservableProperty] [ObservableProperty] private GamepadInputId _leftButtonSl;
public partial bool RightInvertStickY { get; set; } [ObservableProperty] private GamepadInputId _leftButtonSr;
[ObservableProperty] [ObservableProperty] private GamepadInputId _rightButtonSl;
public partial bool RightRotate90 { get; set; } [ObservableProperty] private GamepadInputId _rightButtonSr;
[ObservableProperty] [ObservableProperty] private float _deadzoneLeft;
public partial GamepadInputId RightStickButton { get; set; } [ObservableProperty] private float _deadzoneRight;
[ObservableProperty] [ObservableProperty] private float _rangeLeft;
public partial GamepadInputId DpadUp { get; set; } [ObservableProperty] private float _rangeRight;
[ObservableProperty] [ObservableProperty] private float _triggerThreshold;
public partial GamepadInputId DpadDown { get; set; }
[ObservableProperty] [ObservableProperty] private bool _enableMotion;
public partial GamepadInputId DpadLeft { get; set; }
[ObservableProperty] [ObservableProperty] private bool _enableRumble;
public partial GamepadInputId DpadRight { get; set; }
[ObservableProperty] [ObservableProperty] private bool _enableLedChanging;
public partial GamepadInputId ButtonMinus { get; set; }
[ObservableProperty] [ObservableProperty] private Color _ledColor;
public partial GamepadInputId ButtonPlus { get; set; }
[ObservableProperty]
public partial GamepadInputId ButtonA { get; set; }
[ObservableProperty]
public partial GamepadInputId ButtonB { get; set; }
[ObservableProperty]
public partial GamepadInputId ButtonX { get; set; }
[ObservableProperty]
public partial GamepadInputId ButtonY { get; set; }
[ObservableProperty]
public partial GamepadInputId ButtonZl { get; set; }
[ObservableProperty]
public partial GamepadInputId ButtonZr { get; set; }
[ObservableProperty]
public partial GamepadInputId ButtonL { get; set; }
[ObservableProperty]
public partial GamepadInputId ButtonR { get; set; }
[ObservableProperty]
public partial GamepadInputId LeftButtonSl { get; set; }
[ObservableProperty]
public partial GamepadInputId LeftButtonSr { get; set; }
[ObservableProperty]
public partial GamepadInputId RightButtonSl { get; set; }
[ObservableProperty]
public partial GamepadInputId RightButtonSr { get; set; }
[ObservableProperty]
public partial float DeadzoneLeft { get; set; }
[ObservableProperty]
public partial float DeadzoneRight { get; set; }
[ObservableProperty]
public partial float RangeLeft { get; set; }
[ObservableProperty]
public partial float RangeRight { get; set; }
[ObservableProperty]
public partial float TriggerThreshold { get; set; }
[ObservableProperty]
public partial bool EnableMotion { get; set; }
[ObservableProperty]
public partial bool EnableRumble { get; set; }
[ObservableProperty]
public partial bool EnableLedChanging { get; set; }
[ObservableProperty]
public partial Color LedColor { get; set; }
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed; public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
private bool _turnOffLed;
public bool TurnOffLed public bool TurnOffLed
{ {
get; get => _turnOffLed;
set set
{ {
field = value; _turnOffLed = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(ShowLedColorPicker)); OnPropertyChanged(nameof(ShowLedColorPicker));
} }
} }
private bool _useRainbowLed;
public bool UseRainbowLed public bool UseRainbowLed
{ {
get; get => _useRainbowLed;
set set
{ {
field = value; _useRainbowLed = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(ShowLedColorPicker)); OnPropertyChanged(nameof(ShowLedColorPicker));
} }

View File

@@ -6,44 +6,31 @@ namespace Ryujinx.Ava.UI.Models.Input
{ {
public partial class HotkeyConfig : BaseModel public partial class HotkeyConfig : BaseModel
{ {
[ObservableProperty] [ObservableProperty] private Key _toggleVSyncMode;
public partial Key ToggleVSyncMode { get; set; }
[ObservableProperty] [ObservableProperty] private Key _screenshot;
public partial Key Screenshot { get; set; }
[ObservableProperty] [ObservableProperty] private Key _showUI;
public partial Key ShowUI { get; set; }
[ObservableProperty] [ObservableProperty] private Key _pause;
public partial Key Pause { get; set; }
[ObservableProperty] [ObservableProperty] private Key _toggleMute;
public partial Key ToggleMute { get; set; }
[ObservableProperty] [ObservableProperty] private Key _resScaleUp;
public partial Key ResScaleUp { get; set; }
[ObservableProperty] [ObservableProperty] private Key _resScaleDown;
public partial Key ResScaleDown { get; set; }
[ObservableProperty] [ObservableProperty] private Key _volumeUp;
public partial Key VolumeUp { get; set; }
[ObservableProperty] [ObservableProperty] private Key _volumeDown;
public partial Key VolumeDown { get; set; }
[ObservableProperty] [ObservableProperty] private Key _customVSyncIntervalIncrement;
public partial Key CustomVSyncIntervalIncrement { get; set; }
[ObservableProperty] [ObservableProperty] private Key _customVSyncIntervalDecrement;
public partial Key CustomVSyncIntervalDecrement { get; set; }
[ObservableProperty] [ObservableProperty] private Key _turboMode;
public partial Key TurboMode { get; set; }
[ObservableProperty] [ObservableProperty] private bool _turboModeWhileHeld;
public partial bool TurboModeWhileHeld { get; set; }
public HotkeyConfig(KeyboardHotkeys config) public HotkeyConfig(KeyboardHotkeys config)
{ {

View File

@@ -12,89 +12,42 @@ namespace Ryujinx.Ava.UI.Models.Input
public ControllerType ControllerType { get; set; } public ControllerType ControllerType { get; set; }
public PlayerIndex PlayerIndex { get; set; } public PlayerIndex PlayerIndex { get; set; }
[ObservableProperty] [ObservableProperty] private Key _leftStickUp;
public partial Key LeftStickUp { get; set; } [ObservableProperty] private Key _leftStickDown;
[ObservableProperty] private Key _leftStickLeft;
[ObservableProperty] private Key _leftStickRight;
[ObservableProperty] private Key _leftStickButton;
[ObservableProperty] [ObservableProperty] private Key _rightStickUp;
public partial Key LeftStickDown { get; set; } [ObservableProperty] private Key _rightStickDown;
[ObservableProperty] private Key _rightStickLeft;
[ObservableProperty] private Key _rightStickRight;
[ObservableProperty] private Key _rightStickButton;
[ObservableProperty] [ObservableProperty] private Key _dpadUp;
public partial Key LeftStickLeft { get; set; } [ObservableProperty] private Key _dpadDown;
[ObservableProperty] private Key _dpadLeft;
[ObservableProperty] private Key _dpadRight;
[ObservableProperty] [ObservableProperty] private Key _buttonMinus;
public partial Key LeftStickRight { get; set; } [ObservableProperty] private Key _buttonPlus;
[ObservableProperty] [ObservableProperty] private Key _buttonA;
public partial Key LeftStickButton { get; set; } [ObservableProperty] private Key _buttonB;
[ObservableProperty] private Key _buttonX;
[ObservableProperty] private Key _buttonY;
[ObservableProperty] [ObservableProperty] private Key _buttonL;
public partial Key RightStickUp { get; set; } [ObservableProperty] private Key _buttonR;
[ObservableProperty] [ObservableProperty] private Key _buttonZl;
public partial Key RightStickDown { get; set; } [ObservableProperty] private Key _buttonZr;
[ObservableProperty] [ObservableProperty] private Key _leftButtonSl;
public partial Key RightStickLeft { get; set; } [ObservableProperty] private Key _leftButtonSr;
[ObservableProperty] [ObservableProperty] private Key _rightButtonSl;
public partial Key RightStickRight { get; set; } [ObservableProperty] private Key _rightButtonSr;
[ObservableProperty]
public partial Key RightStickButton { get; set; }
[ObservableProperty]
public partial Key DpadUp { get; set; }
[ObservableProperty]
public partial Key DpadDown { get; set; }
[ObservableProperty]
public partial Key DpadLeft { get; set; }
[ObservableProperty]
public partial Key DpadRight { get; set; }
[ObservableProperty]
public partial Key ButtonMinus { get; set; }
[ObservableProperty]
public partial Key ButtonPlus { get; set; }
[ObservableProperty]
public partial Key ButtonA { get; set; }
[ObservableProperty]
public partial Key ButtonB { get; set; }
[ObservableProperty]
public partial Key ButtonX { get; set; }
[ObservableProperty]
public partial Key ButtonY { get; set; }
[ObservableProperty]
public partial Key ButtonL { get; set; }
[ObservableProperty]
public partial Key ButtonR { get; set; }
[ObservableProperty]
public partial Key ButtonZl { get; set; }
[ObservableProperty]
public partial Key ButtonZr { get; set; }
[ObservableProperty]
public partial Key LeftButtonSl { get; set; }
[ObservableProperty]
public partial Key LeftButtonSr { get; set; }
[ObservableProperty]
public partial Key RightButtonSl { get; set; }
[ObservableProperty]
public partial Key RightButtonSr { get; set; }
public KeyboardInputConfig(InputConfig config) public KeyboardInputConfig(InputConfig config)
{ {

View File

@@ -6,8 +6,8 @@ namespace Ryujinx.Ava.UI.Models
{ {
public partial class ModModel : BaseModel public partial class ModModel : BaseModel
{ {
[ObservableProperty] [ObservableProperty] private bool _enabled;
public partial bool Enabled { get; set; }
public bool InSd { get; } public bool InSd { get; }
public string Path { get; } public string Path { get; }
public string Name { get; } public string Name { get; }

View File

@@ -15,7 +15,6 @@ namespace Ryujinx.Ava.UI.Models
public string Name { get; set; } public string Name { get; set; }
public byte[] Data { get; set; } public byte[] Data { get; set; }
[ObservableProperty] [ObservableProperty] private SolidColorBrush _backgroundColor = new(Colors.White);
public partial SolidColorBrush BackgroundColor { get; set; } = new(Colors.White);
} }
} }

View File

@@ -7,26 +7,24 @@ namespace Ryujinx.Ava.UI.Models
{ {
public partial class TempProfile : BaseModel public partial class TempProfile : BaseModel
{ {
[ObservableProperty] [ObservableProperty] private byte[] _image;
public partial byte[] Image { get; set; } [ObservableProperty] private string _name = String.Empty;
private UserId _userId;
[ObservableProperty]
public partial string Name { get; set; } = string.Empty;
public static uint MaxProfileNameLength => 0x20; public static uint MaxProfileNameLength => 0x20;
public UserId UserId public UserId UserId
{ {
get; get => _userId;
set set
{ {
field = value; _userId = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(UserIdString)); OnPropertyChanged(nameof(UserIdString));
} }
} }
public string UserIdString => UserId.ToString(); public string UserIdString => _userId.ToString();
public TempProfile(UserProfile profile) public TempProfile(UserProfile profile)
{ {

View File

@@ -13,20 +13,11 @@ namespace Ryujinx.Ava.UI.Models
{ {
private readonly Profile _profile; private readonly Profile _profile;
private readonly NavigationDialogHost _owner; private readonly NavigationDialogHost _owner;
[ObservableProperty] [ObservableProperty] private byte[] _image;
public partial byte[] Image { get; set; } [ObservableProperty] private string _name;
[ObservableProperty] private UserId _userId;
[ObservableProperty] [ObservableProperty] private bool _isPointerOver;
public partial string Name { get; set; } [ObservableProperty] private IBrush _backgroundColor;
[ObservableProperty]
public partial UserId UserId { get; set; }
[ObservableProperty]
public partial bool IsPointerOver { get; set; }
[ObservableProperty]
public partial IBrush BackgroundColor { get; set; }
public UserProfile(Profile profile, NavigationDialogHost owner) public UserProfile(Profile profile, NavigationDialogHost owner)
{ {
@@ -48,7 +39,7 @@ namespace Ryujinx.Ava.UI.Models
private void UpdateBackground() private void UpdateBackground()
{ {
Application currentApplication = Application.Current; Application currentApplication = Avalonia.Application.Current;
currentApplication.Styles.TryGetResource("ControlFillColorSecondary", currentApplication.ActualThemeVariant, out object color); currentApplication.Styles.TryGetResource("ControlFillColorSecondary", currentApplication.ActualThemeVariant, out object color);
if (color is not null) if (color is not null)

View File

@@ -359,9 +359,8 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
[ObservableProperty] [ObservableProperty] private bool _matchSystemTime;
public partial bool MatchSystemTime { get; set; }
public DateTimeOffset CurrentDate { get; set; } public DateTimeOffset CurrentDate { get; set; }
public TimeSpan CurrentTime { get; set; } public TimeSpan CurrentTime { get; set; }