Compare commits

...

32 Commits

Author SHA1 Message Date
Evan Husted
391f57bdd2 misc: Headless: Inherit main input config 2025-01-01 01:55:10 -06:00
Evan Husted
fd2b5a7fc1 misc: Remove RendererHost AXAML 2025-01-01 01:55:10 -06:00
Otozinclus
37c165e9fc Only delay shader translation on Metal (#480)
This way the Arbitrary Shader Translation Delay hack will no longer
affect shader loading when using Vulkan.
2025-01-01 00:18:17 -06:00
Daenorth
003a6d322b Update to no_NO Norwegian Translation (#475)
Updated for time resync & auto graphics backend
2025-01-01 00:15:21 -06:00
jozz024
978d2c132b add a keyboard shortcut for opening amiibo .bin files (#461) 2024-12-31 22:45:52 -06:00
Evan Husted
5d63706cea misc: Bake in ValueEqual logic into ReactiveEventArgs
[ci skip]
2024-12-31 22:34:14 -06:00
Evan Husted
732aafd3bb misc: Prevent value change logging when the value is changed to the same thing it was before the value change. 2024-12-31 22:23:08 -06:00
Evan Husted
3fa714bb72 misc: DateTimeOffset Extract extension from Gommon 2024-12-31 21:21:54 -06:00
Evan Husted
7c01633f13 UI: Show the path of the mod on the folder button 2024-12-31 21:15:50 -06:00
Evan Husted
27c5cba10b misc: More Mvvm usage instead of writing out the observable properties 2024-12-31 21:11:57 -06:00
Evan Husted
3525d5ecd4 UI: clean up slider UI for shader translation delay 2024-12-31 20:11:49 -06:00
Evan Husted
6286501550 misc: do not log dirty hack changes if ShowDirtyHacks is disabled 2024-12-31 20:11:44 -06:00
Evan Husted
61ae427a4d misc: Add CommunityToolkit.Mvvm for observable property generation; apply it to MainWindowViewModel for now. 2024-12-31 03:29:08 -06:00
Evan Husted
19d2883a35 UI: Store config migrations in a dictionary and loop through it to do migrations. 2024-12-31 02:51:14 -06:00
Evan Husted
617c03119f misc: clean vsync toggle log 2024-12-31 00:52:39 -06:00
Evan Husted
e43d899e1d misc: Use a few static helpers for Avalonia objects 2024-12-31 00:19:23 -06:00
Evan Husted
0cd09ea0c5 misc: Simplify ControlHolder checks in MainWindowViewModel 2024-12-31 00:04:23 -06:00
Evan Husted
4135d74e4d UI: Only allow right click to create a context menu if a game is selected. 2024-12-30 23:50:55 -06:00
Evan Husted
bd29f658b1 misc: Forgot about OfType [ci skip] 2024-12-30 23:28:32 -06:00
Evan Husted
df150f0788 misc: Significantly reduce duplicated code in ConfigurationState migration logic. 300 lines removed; functionally identical. 2024-12-30 23:14:05 -06:00
Evan Husted
e50198b37d Clarify DramSize XMLdoc 2024-12-30 23:11:59 -06:00
Evan Husted
f426945fec misc: Rename DirtyHacks to DirtyHack
Rename DirtyHack.ShaderCompilationThreadSleep to ShaderTranslationDelay
Changed EnabledDirtyHack to a struct
rename DirtyHackCollection to DirtyHacks
2024-12-30 22:18:35 -06:00
Evan Husted
172869bfba misc: cleanup applying the current dirty hacks to the config upon loading the json 2024-12-30 22:11:16 -06:00
Evan Husted
b6f88514f9 misc: Move BitTricks methods into BitUtils
Cleanup DirtyHackCollection
2024-12-30 22:11:16 -06:00
Hack茶ん
e92f52e56c Korean translations for new locale keys (#465) 2024-12-30 21:13:43 -06:00
Evan Husted
318498eab0 misc: prefix ValidationTask with I, it's an interface
Mention in PR comment script that you now need to be logged into GitHub to download artifacts.
2024-12-30 20:57:18 -06:00
Evan Husted
a5cde8e006 misc: Update Gommon, apply new extension 2024-12-30 20:37:02 -06:00
Evan Husted
d0a344d632 Validation Project v2 (#471)
Original PR had issues in the CI when building.

> Refactor of the Validation System for more ease of use in the future.
The project now builds a standalone executable and executes it before
the main project is built or published.
Since it is now a standalone executable we are also able to use .NET
Core features as we are no longer locked to netstandard.

> The project currently includes 1 task, LocalesValidationTask, that
will check if the locales.json file has any of the following issues:
>   - The json is invalid.
>   - The json has locales with missing languages.
> - The json has locales with langauges that are just duplicates of the
en_US field.

> If the project is built or published locally it will also fix any
missing languages or duplicate fields.

---------

Co-authored-by: LotP1 <68976644+LotP1@users.noreply.github.com>
2024-12-30 20:31:27 -06:00
Otozinclus
ca66298817 Update Metal Games list (#472)
I tested let's go in most locations and did some battles and it runs
perfectly

Legends Arceus will freeze occasionally on Metal, so it was removed.
2024-12-30 20:28:35 -06:00
Evan Husted
9ae1c4380d UI: Fix crashing when opening an Applet or application with no existing icon 2024-12-30 02:32:44 -06:00
Evan Husted
c88518bce2 Revert "Validation Project v2" (#470)
Reverts Ryubing/Ryujinx#444
2024-12-30 02:06:24 -06:00
Evan Husted
a3888ed7cf Revert "misc: New Solution Format (.SLNX)"
This reverts commit 7cbbd02973.
2024-12-30 02:05:40 -06:00
53 changed files with 1106 additions and 1897 deletions

View File

@@ -37,7 +37,7 @@ jobs:
if (!artifacts.length) {
return core.error(`No artifacts found`);
}
let body = `Download the artifacts for this pull request:\n`;
let body = `*You need to be logged into GitHub to download these files.*\n\nDownload the artifacts for this pull request:\n`;
let hidden_debug_artifacts = `\n\n <details><summary>Only for Developers</summary>\n`;
for (const art of artifacts) {
const url = `https://github.com/Ryubing/Ryujinx/actions/runs/${run_id}/artifacts/${art.id}`;

View File

@@ -17,6 +17,7 @@
<PackageVersion Include="Projektanker.Icons.Avalonia.FontAwesome" Version="9.4.0"/>
<PackageVersion Include="Projektanker.Icons.Avalonia.MaterialDesign" Version="9.4.0"/>
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0"/>
<PackageVersion Include="Concentus" Version="2.2.0" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageVersion Include="DynamicData" Version="9.0.4" />
@@ -41,7 +42,7 @@
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.3-build14" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
<PackageVersion Include="Ryujinx.SDL2-CS" Version="2.30.0-build32" />
<PackageVersion Include="Gommon" Version="2.6.8" />
<PackageVersion Include="Gommon" Version="2.7.0.1" />
<PackageVersion Include="securifybv.ShellLink" Version="0.1.0" />
<PackageVersion Include="shaderc.net" Version="0.1.0" />
<PackageVersion Include="SharpMetal" Version="1.0.0-preview21" />

269
Ryujinx.sln Normal file
View File

@@ -0,0 +1,269 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32228.430
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests", "src\Ryujinx.Tests\Ryujinx.Tests.csproj", "{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Unicorn", "src\Ryujinx.Tests.Unicorn\Ryujinx.Tests.Unicorn.csproj", "{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE", "src\Ryujinx.HLE\Ryujinx.HLE.csproj", "{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.ShaderTools", "src\Ryujinx.ShaderTools\Ryujinx.ShaderTools.csproj", "{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Common", "src\Ryujinx.Common\Ryujinx.Common.csproj", "{5FD4E4F6-8928-4B3C-BE07-28A675C17226}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ARMeilleure", "src\ARMeilleure\ARMeilleure.csproj", "{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Gpu", "src\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj", "{ADA7EA87-0D63-4D97-9433-922A2124401F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.GAL", "src\Ryujinx.Graphics.GAL\Ryujinx.Graphics.GAL.csproj", "{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.OpenGL", "src\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj", "{9558FB96-075D-4219-8FFF-401979DC0B69}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Texture", "src\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj", "{E1B1AD28-289D-47B7-A106-326972240207}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Shader", "src\Ryujinx.Graphics.Shader\Ryujinx.Graphics.Shader.csproj", "{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec", "src\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj", "{85A0FA56-DC01-4A42-8808-70DAC76BD66D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio", "src\Ryujinx.Audio\Ryujinx.Audio.csproj", "{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Memory", "src\Ryujinx.Memory\Ryujinx.Memory.csproj", "{A5E6C691-9E22-4263-8F40-42F002CE66BE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Tests.Memory", "src\Ryujinx.Tests.Memory\Ryujinx.Tests.Memory.csproj", "{D1CC5322-7325-4F6B-9625-194B30BE1296}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Cpu", "src\Ryujinx.Cpu\Ryujinx.Cpu.csproj", "{3DF35E3D-D844-4399-A9A1-A9E923264C17}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Device", "src\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj", "{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Host1x", "src\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj", "{C35F1536-7DE5-4F9D-9604-B5B4E1561947}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.Vp9", "src\Ryujinx.Graphics.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj", "{B9AECA11-E248-4886-A10B-81B631CAAF29}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vic", "src\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj", "{81BB2C11-9408-4EA3-822E-42987AF54429}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Video", "src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj", "{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.OpenAL", "src\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj", "{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SoundIo", "src\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj", "{716364DE-B988-41A6-BAB4-327964266ECC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input", "src\Ryujinx.Input\Ryujinx.Input.csproj", "{C16F112F-38C3-40BC-9F5F-4791112063D6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Input.SDL2", "src\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj", "{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.SDL2.Common", "src\Ryujinx.SDL2.Common\Ryujinx.SDL2.Common.csproj", "{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Audio.Backends.SDL2", "src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj", "{D99A395A-8569-4DB0-B336-900647890052}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Nvdec.FFmpeg", "src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj", "{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx", "src\Ryujinx\Ryujinx.csproj", "{7C1B2721-13DA-4B62-B046-C626605ECCE6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Generators", "src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj", "{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Graphics.Vulkan", "src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj", "{D4D09B08-D580-4D69-B886-C35D2853F6C8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Spv.Generator", "src\Spv.Generator\Spv.Generator.csproj", "{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.UI.LocaleGenerator", "src\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj", "{77D01AD9-2C98-478E-AE1D-8F7100738FB4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Common", "src\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj", "{77F96ECE-4952-42DB-A528-DED25572A573}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon", "src\Ryujinx.Horizon\Ryujinx.Horizon.csproj", "{AF34127A-3A92-43E5-8496-14960A50B1F1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.Horizon.Kernel.Generators", "src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj", "{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal", "src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj", "{C08931FA-1191-417A-864F-3882D93E683B}"
ProjectSection(ProjectDependencies) = postProject
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} = {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.BuildValidationTasks", "src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj", "{4A89A234-4F19-497D-A576-DDE8CDFC5B22}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ryujinx.Graphics.Metal.SharpMetalExtensions", "src/Ryujinx.Graphics.Metal.SharpMetalExtensions\Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj", "{81EA598C-DBA1-40B0-8DA4-4796B78F2037}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36F870C1-3E5F-485F-B426-F0645AF78751}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.github\workflows\build.yml = .github\workflows\build.yml
.github\workflows\canary.yml = .github\workflows\canary.yml
Directory.Packages.props = Directory.Packages.props
.github\workflows\release.yml = .github\workflows\release.yml
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBB55AEA-C7D7-4DEB-BF96-FA1789E225E9}.Release|Any CPU.Build.0 = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D8F72938-78EF-4E8C-BAFE-531C9C3C8F15}.Release|Any CPU.Build.0 = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CB92CFF9-1D62-4D4F-9E88-8130EF61E351}.Release|Any CPU.Build.0 = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3AB294D0-2230-468F-9EB3-BDFCAEAE99A5}.Release|Any CPU.Build.0 = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FD4E4F6-8928-4B3C-BE07-28A675C17226}.Release|Any CPU.Build.0 = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ABF09A5E-2D8B-4B6F-A51D-5CE414DDB15A}.Release|Any CPU.Build.0 = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADA7EA87-0D63-4D97-9433-922A2124401F}.Release|Any CPU.Build.0 = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}.Release|Any CPU.Build.0 = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9558FB96-075D-4219-8FFF-401979DC0B69}.Release|Any CPU.Build.0 = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1B1AD28-289D-47B7-A106-326972240207}.Release|Any CPU.Build.0 = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{03B955CD-AD84-4B93-AAA7-BF17923BBAA5}.Release|Any CPU.Build.0 = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{85A0FA56-DC01-4A42-8808-70DAC76BD66D}.Release|Any CPU.Build.0 = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Debug|Any CPU.Build.0 = Debug|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.ActiveCfg = Release|Any CPU
{806ACF6D-90B0-45D0-A1AC-5F220F3B3985}.Release|Any CPU.Build.0 = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5E6C691-9E22-4263-8F40-42F002CE66BE}.Release|Any CPU.Build.0 = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1CC5322-7325-4F6B-9625-194B30BE1296}.Release|Any CPU.Build.0 = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3DF35E3D-D844-4399-A9A1-A9E923264C17}.Release|Any CPU.Build.0 = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3002C3C-7B09-4FE7-894A-372EDA22FC6E}.Release|Any CPU.Build.0 = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C35F1536-7DE5-4F9D-9604-B5B4E1561947}.Release|Any CPU.Build.0 = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B9AECA11-E248-4886-A10B-81B631CAAF29}.Release|Any CPU.Build.0 = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81BB2C11-9408-4EA3-822E-42987AF54429}.Release|Any CPU.Build.0 = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD4A2C14-8E3D-4957-ABBE-3C38897B3E2D}.Release|Any CPU.Build.0 = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0BE11899-DF2D-4BDE-B9EE-2489E8D35E7D}.Release|Any CPU.Build.0 = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{716364DE-B988-41A6-BAB4-327964266ECC}.Release|Any CPU.Build.0 = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C16F112F-38C3-40BC-9F5F-4791112063D6}.Release|Any CPU.Build.0 = Release|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DFAB6F2D-B9BF-4AFF-B22B-7684A328EBA3}.Release|Any CPU.Build.0 = Release|Any CPU
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2D5D3A1D-5730-4648-B0AB-06C53CB910C0}.Release|Any CPU.Build.0 = Release|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D99A395A-8569-4DB0-B336-900647890052}.Release|Any CPU.Build.0 = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BEE1C184-C9A4-410B-8DFC-FB74D5C93AEB}.Release|Any CPU.Build.0 = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7C1B2721-13DA-4B62-B046-C626605ECCE6}.Release|Any CPU.Build.0 = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6AE2A5E8-4C5A-48B9-997B-E1455C0355C6}.Release|Any CPU.Build.0 = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4D09B08-D580-4D69-B886-C35D2853F6C8}.Release|Any CPU.Build.0 = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2BCB3D7A-38C0-4FE7-8FDA-374C6AD56D0E}.Release|Any CPU.Build.0 = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77D01AD9-2C98-478E-AE1D-8F7100738FB4}.Release|Any CPU.Build.0 = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77F96ECE-4952-42DB-A528-DED25572A573}.Release|Any CPU.Build.0 = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF34127A-3A92-43E5-8496-14960A50B1F1}.Release|Any CPU.Build.0 = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F55A45D-4E1D-4A36-ADD3-87F29A285AA2}.Release|Any CPU.Build.0 = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = Release|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81EA598C-DBA1-40B0-8DA4-4796B78F2037}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {110169B3-3328-4730-8AB0-BA05BEF75C1A}
EndGlobalSection
EndGlobal

View File

@@ -1,52 +0,0 @@
<Solution>
<Folder Name="/Solution Items/">
<File Path=".editorconfig" />
<File Path=".github\workflows\build.yml" />
<File Path=".github\workflows\canary.yml" />
<File Path="Directory.Packages.props" />
<File Path=".github\workflows\release.yml" />
</Folder>
<Project Path="src/Ryujinx.Graphics.Metal.SharpMetalExtensions\Ryujinx.Graphics.Metal.SharpMetalExtensions.csproj" Type="Classic C#" />
<Project Path="src\ARMeilleure\ARMeilleure.csproj" />
<Project Path="src\Ryujinx.Audio.Backends.OpenAL\Ryujinx.Audio.Backends.OpenAL.csproj" />
<Project Path="src\Ryujinx.Audio.Backends.SDL2\Ryujinx.Audio.Backends.SDL2.csproj" />
<Project Path="src\Ryujinx.Audio.Backends.SoundIo\Ryujinx.Audio.Backends.SoundIo.csproj" />
<Project Path="src\Ryujinx.Audio\Ryujinx.Audio.csproj" />
<Project Path="src\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj" Type="Classic C#">
<Configuration Solution="Debug|Any CPU" Project="Debug|Any CPU|NoBuild" />
<Configuration Solution="Release|Any CPU" Project="Release|Any CPU|NoBuild" />
</Project>
<Project Path="src\Ryujinx.Common\Ryujinx.Common.csproj" />
<Project Path="src\Ryujinx.Cpu\Ryujinx.Cpu.csproj" />
<Project Path="src\Ryujinx.Graphics.Device\Ryujinx.Graphics.Device.csproj" />
<Project Path="src\Ryujinx.Graphics.GAL\Ryujinx.Graphics.GAL.csproj" />
<Project Path="src\Ryujinx.Graphics.Gpu\Ryujinx.Graphics.Gpu.csproj" />
<Project Path="src\Ryujinx.Graphics.Host1x\Ryujinx.Graphics.Host1x.csproj" />
<Project Path="src\Ryujinx.Graphics.Metal\Ryujinx.Graphics.Metal.csproj" />
<Project Path="src\Ryujinx.Graphics.Nvdec.FFmpeg\Ryujinx.Graphics.Nvdec.FFmpeg.csproj" />
<Project Path="src\Ryujinx.Graphics.Nvdec.Vp9\Ryujinx.Graphics.Nvdec.Vp9.csproj" />
<Project Path="src\Ryujinx.Graphics.Nvdec\Ryujinx.Graphics.Nvdec.csproj" />
<Project Path="src\Ryujinx.Graphics.OpenGL\Ryujinx.Graphics.OpenGL.csproj" />
<Project Path="src\Ryujinx.Graphics.Shader\Ryujinx.Graphics.Shader.csproj" />
<Project Path="src\Ryujinx.Graphics.Texture\Ryujinx.Graphics.Texture.csproj" />
<Project Path="src\Ryujinx.Graphics.Vic\Ryujinx.Graphics.Vic.csproj" />
<Project Path="src\Ryujinx.Graphics.Video\Ryujinx.Graphics.Video.csproj" />
<Project Path="src\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" />
<Project Path="src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj" />
<Project Path="src\Ryujinx.HLE\Ryujinx.HLE.csproj" />
<Project Path="src\Ryujinx.Horizon.Common\Ryujinx.Horizon.Common.csproj" />
<Project Path="src\Ryujinx.Horizon.Generators\Ryujinx.Horizon.Generators.csproj" />
<Project Path="src\Ryujinx.Horizon.Kernel.Generators\Ryujinx.Horizon.Kernel.Generators.csproj" />
<Project Path="src\Ryujinx.Horizon\Ryujinx.Horizon.csproj" />
<Project Path="src\Ryujinx.Input.SDL2\Ryujinx.Input.SDL2.csproj" />
<Project Path="src\Ryujinx.Input\Ryujinx.Input.csproj" />
<Project Path="src\Ryujinx.Memory\Ryujinx.Memory.csproj" />
<Project Path="src\Ryujinx.SDL2.Common\Ryujinx.SDL2.Common.csproj" />
<Project Path="src\Ryujinx.ShaderTools\Ryujinx.ShaderTools.csproj" />
<Project Path="src\Ryujinx.Tests.Memory\Ryujinx.Tests.Memory.csproj" />
<Project Path="src\Ryujinx.Tests.Unicorn\Ryujinx.Tests.Unicorn.csproj" />
<Project Path="src\Ryujinx.Tests\Ryujinx.Tests.csproj" />
<Project Path="src\Ryujinx.UI.LocaleGenerator\Ryujinx.UI.LocaleGenerator.csproj" />
<Project Path="src\Ryujinx\Ryujinx.csproj" />
<Project Path="src\Spv.Generator\Spv.Generator.csproj" />
</Solution>

View File

@@ -1,6 +1,6 @@
namespace Ryujinx.BuildValidationTasks
{
public interface ValidationTask
public interface IValidationTask
{
public bool Execute(string projectPath, bool isGitRunner);
}

View File

@@ -7,7 +7,7 @@ using System.Text.Encodings.Web;
namespace Ryujinx.BuildValidationTasks
{
public class LocalesValidationTask : ValidationTask
public class LocalesValidationTask : IValidationTask
{
public LocalesValidationTask() { }

View File

@@ -10,6 +10,7 @@
<Exec WorkingDirectory="$(ProjectDir)bin\Debug\$(TargetFramework)\"
Command="dotnet Ryujinx.BuildValidationTasks.dll &quot;$(ProjectDir)..\..\\&quot;"
ConsoleToMsBuild="true"
Condition="'$(RuntimeIdentifier)' == ''"
/>
</Target>

View File

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

View File

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

View File

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

View File

@@ -53,6 +53,9 @@ namespace Ryujinx.Common
{
public static void LogValueChange<T>(LogClass logClass, ReactiveEventArgs<T> eventArgs, string valueName)
{
if (eventArgs.AreValuesEqual)
return;
string message = string.Create(CultureInfo.InvariantCulture, $"{valueName} set to: {eventArgs.NewValue}");
Logger.Info?.Print(logClass, message);
@@ -65,5 +68,22 @@ namespace Ryujinx.Common
{
public T OldValue { get; } = oldValue;
public T NewValue { get; } = newValue;
public bool AreValuesEqual
{
get
{
if (OldValue == null && NewValue == null)
return true;
if (OldValue == null && NewValue != null)
return false;
if (OldValue != null && NewValue == null)
return false;
return OldValue!.Equals(NewValue);
}
}
}
}

View File

@@ -35,7 +35,8 @@ namespace Ryujinx.Common
"010028600EBDA000", // Mario 3D World
"0100152000022000", // Mario Kart 8 Deluxe
"01005CA01580E000", // Persona 5
"01001f5010dfa000", // Pokemon Legends Arceus
"0100187003A36000", // Pokémon: Let's Go, Evoli!
"010003f003a34000", // Pokémon: Let's Go, Pikachu!
"01008C0016544000", // Sea of Stars
"01006A800016E000", // Smash Ultimate
"0100000000010000", // Super Mario Odyessy

View File

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

View File

@@ -92,7 +92,11 @@ namespace Ryujinx.Graphics.Gpu
/// </summary>
internal SupportBufferUpdater SupportBufferUpdater { get; }
internal DirtyHackCollection DirtyHacks { get; }
/// <summary>
/// Enabled dirty hacks.
/// Used for workarounds to emulator bugs we can't fix/don't know how to fix yet.
/// </summary>
internal DirtyHacks DirtyHacks { get; }
/// <summary>
@@ -117,7 +121,7 @@ namespace Ryujinx.Graphics.Gpu
/// Creates a new instance of the GPU emulation context.
/// </summary>
/// <param name="renderer">Host renderer</param>
public GpuContext(IRenderer renderer, DirtyHackCollection hackCollection)
public GpuContext(IRenderer renderer, DirtyHacks hacks)
{
Renderer = renderer;
@@ -140,7 +144,7 @@ namespace Ryujinx.Graphics.Gpu
SupportBufferUpdater = new SupportBufferUpdater(renderer);
DirtyHacks = hackCollection;
DirtyHacks = hacks;
_firstTimestamp = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
}

View File

@@ -367,8 +367,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
{
try
{
if (_context.DirtyHacks.IsEnabled(DirtyHacks.ShaderCompilationThreadSleep))
Thread.Sleep(_context.DirtyHacks[DirtyHacks.ShaderCompilationThreadSleep]);
if (_context.Capabilities.Api == TargetApi.Metal && _context.DirtyHacks.IsEnabled(DirtyHack.ShaderTranslationDelay))
Thread.Sleep(_context.DirtyHacks[DirtyHack.ShaderTranslationDelay]);
AsyncProgramTranslation asyncTranslation = new(guestShaders, specState, programIndex, isCompute);
_asyncTranslationQueue.Add(asyncTranslation, _cancellationToken);

View File

@@ -39,7 +39,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy
using var region = context.Memory.GetWritableRegion(bufferAddress, (int)bufferLen, true);
Result result = _baseStorage.Get.Read((long)offset, new OutBuffer(region.Memory.Span), (long)size);
if (context.Device.DirtyHacks.IsEnabled(DirtyHacks.Xc2MenuSoftlockFix) && TitleIDs.CurrentApplication.Value == Xc2TitleId)
if (context.Device.DirtyHacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix) && TitleIDs.CurrentApplication.Value == Xc2TitleId)
{
// Add a load-bearing sleep to avoid XC2 softlock
// https://web.archive.org/web/20240728045136/https://github.com/Ryujinx/Ryujinx/issues/2357

View File

@@ -40,7 +40,7 @@ namespace Ryujinx.HLE
public bool IsFrameAvailable => Gpu.Window.IsFrameAvailable;
public DirtyHackCollection DirtyHacks { get; }
public DirtyHacks DirtyHacks { get; }
public Switch(HLEConfiguration configuration)
{
@@ -57,7 +57,7 @@ namespace Ryujinx.HLE
: MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Mirrorable;
#pragma warning disable IDE0055 // Disable formatting
DirtyHacks = new DirtyHackCollection(Configuration.Hacks);
DirtyHacks = new DirtyHacks(Configuration.Hacks);
AudioDeviceDriver = new CompatLayerHardwareDeviceDriver(Configuration.AudioDeviceDriver);
Memory = new MemoryBlock(Configuration.MemoryConfiguration.ToDramSize(), memoryAllocationFlags);
Gpu = new GpuContext(Configuration.GpuRenderer, DirtyHacks);

View File

@@ -314,7 +314,7 @@ namespace Ryujinx.Ava
_renderer.Window?.ChangeVSyncMode(e.NewValue);
_viewModel.ShowCustomVSyncIntervalPicker = (e.NewValue == VSyncMode.Custom);
_viewModel.UpdateVSyncIntervalPicker();
}
public void VSyncModeToggle()

View File

@@ -1234,8 +1234,8 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"ko_KR": "자주 묻는 질문(FAQ) 및 안내",
"no_NO": "Vanlige spørsmål og veiledninger",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "FAQ и Руководства",
@@ -1460,7 +1460,7 @@
"it_IT": "Preferito",
"ja_JP": "お気に入り",
"ko_KR": "즐겨찾기",
"no_NO": "",
"no_NO": "Favoritter",
"pl_PL": "Ulubione",
"pt_BR": "Favorito",
"ru_RU": "Избранное",
@@ -2609,8 +2609,8 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"ko_KR": "펌웨어 버전 : {0}",
"no_NO": "Fastvareversjon: {0}",
"pl_PL": "",
"pt_BR": "Versão do firmware: {0}",
"ru_RU": "Версия прошивки: {0}",
@@ -3460,7 +3460,7 @@
"it_IT": "Corea",
"ja_JP": "韓国",
"ko_KR": "한국",
"no_NO": "",
"no_NO": "Koreansk",
"pl_PL": "",
"pt_BR": "Coreia",
"ru_RU": "Корея",
@@ -4009,8 +4009,8 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"ko_KR": "PC 날짜와 시간에 동기화",
"no_NO": "Resynkroniser til PC-dato og -klokkeslett",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Повторная синхронизация с датой и временем на компьютере",
@@ -15259,8 +15259,8 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"ko_KR": "시스템 시간을 PC의 현재 날짜 및 시간과 일치하도록 다시 동기화합니다.\n\n이 설정은 활성 설정이 아니므로 여전히 동기화되지 않을 수 있으며, 이 경우 이 버튼을 다시 클릭하면 됩니다.",
"no_NO": "Resynkroniser systemtiden slik at den samsvarer med PC-ens gjeldende dato og klokkeslett. \\Dette er ikke en aktiv innstilling, men den kan likevel komme ut av synkronisering; i så fall er det bare å klikke på denne knappen igjen.",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Повторно синхронизирует системное время, чтобы оно соответствовало текущей дате и времени вашего компьютера.\n\nЭто не активная настройка, она все еще может рассинхронизироваться; в этом случае просто нажмите эту кнопку еще раз.",
@@ -20509,7 +20509,7 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"ko_KR": "자동",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
@@ -20534,8 +20534,8 @@
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"ko_KR": "Vulkan을 사용합니다.\nARM 맥에서 해당 플랫폼에서 잘 실행되는 게임을 플레이하는 경우 Metal 후단부를 사용합니다.",
"no_NO": "Bruker Vulkan \nPå en ARM Mac, og når du spiller et spill som kjører bra under den, bruker du Metal-backend.",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "Использует Vulkan.\nНа Mac с ARM процессорами используется Metal, если игра с ним совместима и хорошо работает.",

View File

@@ -163,6 +163,11 @@ namespace Ryujinx.Headless
ReloadConfig();
if (option.InheritConfig)
{
option.InheritMainConfigInput(originalArgs, ConfigurationState.Instance);
}
_virtualFileSystem = VirtualFileSystem.CreateInstance();
_libHacHorizonManager = new LibHacHorizonManager();
@@ -224,15 +229,7 @@ namespace Ryujinx.Headless
_enableKeyboard = option.EnableKeyboard;
_enableMouse = option.EnableMouse;
static void LoadPlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
{
InputConfig inputConfig = HandlePlayerConfiguration(inputProfileName, inputId, index);
if (inputConfig != null)
{
_inputConfiguration.Add(inputConfig);
}
}
LoadPlayerConfiguration(option.InputProfile1Name, option.InputId1, PlayerIndex.Player1);
LoadPlayerConfiguration(option.InputProfile2Name, option.InputId2, PlayerIndex.Player2);
@@ -244,7 +241,6 @@ namespace Ryujinx.Headless
LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8);
LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld);
if (_inputConfiguration.Count == 0)
{
return;
@@ -306,6 +302,24 @@ namespace Ryujinx.Headless
}
_inputManager.Dispose();
return;
void LoadPlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
{
if (index == PlayerIndex.Handheld && _inputConfiguration.Count > 0)
{
Logger.Info?.Print(LogClass.Configuration, "Skipping handheld configuration as there are already other players configured.");
return;
}
InputConfig inputConfig = option.InheritedInputConfigs[index] ?? HandlePlayerConfiguration(inputProfileName, inputId, index);
if (inputConfig != null)
{
_inputConfiguration.Add(inputConfig);
}
}
}
private static void SetupProgressHandler()

View File

@@ -154,11 +154,40 @@ namespace Ryujinx.Headless
return;
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
string OptionName(string propertyName) =>
typeof(Options)!.GetProperty(propertyName)!.GetCustomAttribute<OptionAttribute>()!.LongName;
}
public void InheritMainConfigInput(string[] originalArgs, ConfigurationState configurationState)
{
Dictionary<PlayerIndex, (string InputId, string InputProfileName)> indicesToProperties = new()
{
{ PlayerIndex.Handheld, (nameof(InputIdHandheld), nameof(InputProfileHandheldName)) },
{ PlayerIndex.Player1, (nameof(InputId1), nameof(InputProfile1Name)) },
{ PlayerIndex.Player2, (nameof(InputId2), nameof(InputProfile2Name)) },
{ PlayerIndex.Player3, (nameof(InputId3), nameof(InputProfile3Name)) },
{ PlayerIndex.Player4, (nameof(InputId4), nameof(InputProfile4Name)) },
{ PlayerIndex.Player5, (nameof(InputId5), nameof(InputProfile5Name)) },
{ PlayerIndex.Player6, (nameof(InputId6), nameof(InputProfile6Name)) },
{ PlayerIndex.Player7, (nameof(InputId7), nameof(InputProfile7Name)) },
{ PlayerIndex.Player8, (nameof(InputId8), nameof(InputProfile8Name)) }
};
foreach ((PlayerIndex playerIndex, (string id, string profile)) in indicesToProperties)
{
if (NeedsOverride(id) && NeedsOverride(profile))
{
configurationState.Hid.InputConfig.Value.FindFirst(x => x.PlayerIndex == playerIndex)
.IfPresent(ic => InheritedInputConfigs[playerIndex] = ic);
}
}
return;
bool NeedsOverride(string argKey) => originalArgs.None(arg => arg.TrimStart('-').EqualsIgnoreCase(OptionName(argKey)));
}
private static string OptionName(string propertyName) =>
typeof(Options)!.GetProperty(propertyName)!.GetCustomAttribute<OptionAttribute>()!.LongName;
// General
[Option("use-main-config", Required = false, Default = false, HelpText = "Use the settings from what was configured via the UI.")]
@@ -391,5 +420,7 @@ namespace Ryujinx.Headless
[Value(0, MetaName = "input", HelpText = "Input to load.", Required = true)]
public string InputPath { get; set; }
public SafeDictionary<PlayerIndex, InputConfig> InheritedInputConfigs = new();
}
}

View File

@@ -15,10 +15,7 @@
<Target Name="BuildValidationProj" BeforeTargets="BeforeBuild">
<Message Text="Building Validation Project for $(TargetFramework)" Importance="high" Condition="'$(RuntimeIdentifier)' == ''" />
<Message Text="Building Validation Project for $(TargetFramework) with runtime $(RuntimeIdentifier)" Importance="high" Condition="'$(RuntimeIdentifier)' != ''" />
<Exec WorkingDirectory="..\Ryujinx.BuildValidationTasks\" Command="dotnet restore Ryujinx.BuildValidationTasks.csproj --force --ucr true" Condition="'$(RuntimeIdentifier)' == ''" />
<Exec WorkingDirectory="..\Ryujinx.BuildValidationTasks\" Command="dotnet restore Ryujinx.BuildValidationTasks.csproj --force --runtime $(RuntimeIdentifier)" Condition="'$(RuntimeIdentifier)' != ''" />
<MSBuild Projects="..\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj" Properties="Configuration=Debug" />
<Exec WorkingDirectory="..\Ryujinx.BuildValidationTasks\" Command="dotnet build -c Debug /clp:NoSummary" />
</Target>
@@ -52,6 +49,7 @@
<PackageReference Include="Avalonia.Svg" />
<PackageReference Include="Avalonia.Svg.Skia" />
<PackageReference Include="CommandLineParser" />
<PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="DiscordRichPresence" />
<PackageReference Include="DynamicData" />
<PackageReference Include="FluentAvaloniaUI" />

View File

@@ -15,7 +15,6 @@
x:DataType="viewModels:MainWindowViewModel">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
<controls:ApplicationContextMenu x:Key="ApplicationContextMenu" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
@@ -26,10 +25,10 @@
Padding="8"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ContextFlyout="{StaticResource ApplicationContextMenu}"
SelectedItem="{Binding GridSelectedApplication}"
ContextFlyout="{Binding GridAppContextMenu}"
DoubleTapped="GameList_DoubleTapped"
ItemsSource="{Binding AppsObservableList}"
SelectionChanged="GameList_SelectionChanged">
ItemsSource="{Binding AppsObservableList}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel

View File

@@ -26,11 +26,5 @@ namespace Ryujinx.Ava.UI.Controls
if (sender is ListBox { SelectedItem: ApplicationData selected })
RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent));
}
public void GameList_SelectionChanged(object sender, SelectionChangedEventArgs args)
{
if (DataContext is MainWindowViewModel viewModel && sender is ListBox { SelectedItem: ApplicationData selected })
viewModel.GridSelectedApplication = selected;
}
}
}

View File

@@ -7,7 +7,6 @@
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
xmlns:converters="clr-namespace:Avalonia.Data.Converters;assembly=Avalonia.Base"
d:DesignHeight="450"
d:DesignWidth="800"
Focusable="True"
@@ -16,7 +15,6 @@
x:DataType="viewModels:MainWindowViewModel">
<UserControl.Resources>
<helpers:BitmapArrayValueConverter x:Key="ByteImage" />
<controls:ApplicationContextMenu x:Key="ApplicationContextMenu" />
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
@@ -28,10 +26,10 @@
Padding="8"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ContextFlyout="{StaticResource ApplicationContextMenu}"
SelectedItem="{Binding ListSelectedApplication}"
ContextFlyout="{Binding ListAppContextMenu}"
DoubleTapped="GameList_DoubleTapped"
ItemsSource="{Binding AppsObservableList}"
SelectionChanged="GameList_SelectionChanged">
ItemsSource="{Binding AppsObservableList}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel

View File

@@ -30,12 +30,6 @@ namespace Ryujinx.Ava.UI.Controls
RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent));
}
public void GameList_SelectionChanged(object sender, SelectionChangedEventArgs args)
{
if (DataContext is MainWindowViewModel viewModel && sender is ListBox { SelectedItem: ApplicationData selected })
viewModel.ListSelectedApplication = selected;
}
private async void IdString_OnClick(object sender, RoutedEventArgs e)
{
if (DataContext is not MainWindowViewModel mwvm)

View File

@@ -1,12 +0,0 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignWidth="800"
d:DesignHeight="450"
x:Class="Ryujinx.Ava.UI.Renderer.RendererHost"
FlowDirection="LeftToRight"
Focusable="True">
</UserControl>

View File

@@ -1,16 +1,15 @@
using Avalonia;
using Avalonia;
using Avalonia.Controls;
using Gommon;
using Avalonia.Media;
using Ryujinx.Ava.Utilities.Configuration;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Ava.UI.Renderer
{
public partial class RendererHost : UserControl, IDisposable
public class RendererHost : UserControl, IDisposable
{
public readonly EmbeddedWindow EmbeddedWindow;
@@ -19,7 +18,8 @@ namespace Ryujinx.Ava.UI.Renderer
public RendererHost()
{
InitializeComponent();
Focusable = true;
FlowDirection = FlowDirection.LeftToRight;
EmbeddedWindow = ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
{
@@ -43,8 +43,6 @@ namespace Ryujinx.Ava.UI.Renderer
public RendererHost(string titleId)
{
InitializeComponent();
switch (TitleIDs.SelectGraphicsBackend(titleId, ConfigurationState.Instance.Graphics.GraphicsBackend))
{
case GraphicsBackend.OpenGl:
@@ -109,3 +107,4 @@ namespace Ryujinx.Ava.UI.Renderer
}
}
}

View File

@@ -1,6 +1,7 @@
using Avalonia.Media.Imaging;
using Avalonia.Styling;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Utilities.Configuration;
@@ -8,42 +9,11 @@ using System;
namespace Ryujinx.Ava.UI.ViewModels
{
public class AboutWindowViewModel : BaseModel, IDisposable
public partial class AboutWindowViewModel : BaseModel, IDisposable
{
private Bitmap _githubLogo;
private Bitmap _discordLogo;
private string _version;
public Bitmap GithubLogo
{
get => _githubLogo;
set
{
_githubLogo = value;
OnPropertyChanged();
}
}
public Bitmap DiscordLogo
{
get => _discordLogo;
set
{
_discordLogo = value;
OnPropertyChanged();
}
}
public string Version
{
get => _version;
set
{
_version = value;
OnPropertyChanged();
}
}
[ObservableProperty] private Bitmap _githubLogo;
[ObservableProperty] private Bitmap _discordLogo;
[ObservableProperty] private string _version;
public string Developers => "GreemDev";

View File

@@ -1,18 +1,10 @@
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Ryujinx.Ava.UI.ViewModels
{
public class BaseModel : INotifyPropertyChanged
public class BaseModel : ObservableObject
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void OnPropertiesChanged(string firstPropertyName, params ReadOnlySpan<string> propertyNames)
{
OnPropertyChanged(firstPropertyName);

View File

@@ -2,6 +2,7 @@ using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
@@ -17,13 +18,13 @@ using Application = Avalonia.Application;
namespace Ryujinx.Ava.UI.ViewModels
{
public class DownloadableContentManagerViewModel : BaseModel
public partial class DownloadableContentManagerViewModel : BaseModel
{
private readonly ApplicationLibrary _applicationLibrary;
private AvaloniaList<DownloadableContentModel> _downloadableContents = new();
private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new();
private AvaloniaList<DownloadableContentModel> _views = new();
private bool _showBundledContentNotice = false;
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new();
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _views = new();
[ObservableProperty] private bool _showBundledContentNotice = false;
private string _search;
private readonly ApplicationData _applicationData;
@@ -41,26 +42,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public AvaloniaList<DownloadableContentModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public AvaloniaList<DownloadableContentModel> SelectedDownloadableContents
{
get => _selectedDownloadableContents;
set
{
_selectedDownloadableContents = value;
OnPropertyChanged();
}
}
public string Search
{
get => _search;
@@ -77,26 +58,13 @@ namespace Ryujinx.Ava.UI.ViewModels
get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count);
}
public bool ShowBundledContentNotice
{
get => _showBundledContentNotice;
set
{
_showBundledContentNotice = value;
OnPropertyChanged();
}
}
public DownloadableContentManagerViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
{
_applicationLibrary = applicationLibrary;
_applicationData = applicationData;
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
_storageProvider = desktop.MainWindow.StorageProvider;
}
_storageProvider = RyujinxApp.MainWindow.StorageProvider;
LoadDownloadableContents();
}

View File

@@ -245,9 +245,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{
if (Program.PreviewerDetached)
{
_mainWindow =
(MainWindow)((IClassicDesktopStyleApplicationLifetime)Application.Current
.ApplicationLifetime).MainWindow;
_mainWindow = RyujinxApp.MainWindow;
AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);

View File

@@ -6,6 +6,7 @@ using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData;
using DynamicData.Binding;
using FluentAvalonia.UI.Controls;
@@ -54,77 +55,112 @@ using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
namespace Ryujinx.Ava.UI.ViewModels
{
public class MainWindowViewModel : BaseModel
public partial class MainWindowViewModel : BaseModel
{
private const int HotKeyPressDelayMs = 500;
private delegate int LoadContentFromFolderDelegate(List<string> dirs, out int numRemoved);
private ObservableCollectionExtended<ApplicationData> _applications;
private string _aspectStatusText;
[ObservableProperty] private ObservableCollectionExtended<ApplicationData> _applications;
[ObservableProperty] private string _aspectRatioStatusText;
[ObservableProperty] private string _loadHeading;
[ObservableProperty] private string _cacheLoadStatus;
[ObservableProperty] private string _dockedStatusText;
[ObservableProperty] private string _fifoStatusText;
[ObservableProperty] private string _gameStatusText;
[ObservableProperty] private string _volumeStatusText;
[ObservableProperty] private string _gpuNameText;
[ObservableProperty] private string _backendText;
[ObservableProperty] private string _shaderCountText;
[ObservableProperty] private bool _showShaderCompilationHint;
[ObservableProperty] private bool _isFullScreen;
[ObservableProperty] private int _progressMaximum;
[ObservableProperty] private int _progressValue;
[ObservableProperty] private bool _showMenuAndStatusBar = true;
[ObservableProperty] private bool _showStatusSeparator;
[ObservableProperty] private Brush _progressBarForegroundColor;
[ObservableProperty] private Brush _progressBarBackgroundColor;
[ObservableProperty] private Brush _vSyncModeColor;
[ObservableProperty] private byte[] _selectedIcon;
[ObservableProperty] private int _statusBarProgressMaximum;
[ObservableProperty] private int _statusBarProgressValue;
[ObservableProperty] private string _statusBarProgressStatusText;
[ObservableProperty] private bool _statusBarProgressStatusVisible;
[ObservableProperty] private bool _isPaused;
[ObservableProperty] private bool _isLoadingIndeterminate = true;
[ObservableProperty] private bool _showAll;
[ObservableProperty] private string _lastScannedAmiiboId;
[ObservableProperty] private ReadOnlyObservableCollection<ApplicationData> _appsObservableList;
[ObservableProperty] private long _lastFullscreenToggle = Environment.TickCount64;
[ObservableProperty] private bool _showContent = true;
[ObservableProperty] private float _volumeBeforeMute;
[ObservableProperty] private bool _areMimeTypesRegistered = FileAssociationHelper.AreMimeTypesRegistered;
[ObservableProperty] private Cursor _cursor;
[ObservableProperty] private string _title;
[ObservableProperty] private WindowState _windowState;
[ObservableProperty] private double _windowWidth;
[ObservableProperty] private double _windowHeight;
[ObservableProperty] private bool _isActive;
[ObservableProperty] private bool _isSubMenuOpen;
[ObservableProperty] private ApplicationContextMenu _listAppContextMenu;
[ObservableProperty] private ApplicationContextMenu _gridAppContextMenu;
private string _loadHeading;
private string _cacheLoadStatus;
private string _searchText;
private Timer _searchTimer;
private string _dockedStatusText;
private string _vSyncModeText;
private string _fifoStatusText;
private string _gameStatusText;
private string _volumeStatusText;
private string _gpuStatusText;
private string _shaderCountText;
private bool _showLoadProgress;
private bool _isGameRunning;
private bool _isAmiiboRequested;
private bool _isAmiiboBinRequested;
private bool _showShaderCompilationHint;
private bool _isGameRunning;
private bool _isFullScreen;
private int _progressMaximum;
private int _progressValue;
private long _lastFullscreenToggle = Environment.TickCount64;
private bool _showLoadProgress;
private bool _showMenuAndStatusBar = true;
private bool _showStatusSeparator;
private Brush _progressBarForegroundColor;
private Brush _progressBarBackgroundColor;
private Brush _vSyncModeColor;
private byte[] _selectedIcon;
private bool _isAppletMenuActive;
private int _statusBarProgressMaximum;
private int _statusBarProgressValue;
private string _statusBarProgressStatusText;
private bool _statusBarProgressStatusVisible;
private bool _isPaused;
private bool _showContent = true;
private bool _isLoadingIndeterminate = true;
private bool _showAll;
private string _lastScannedAmiiboId;
private bool _statusBarVisible;
private ReadOnlyObservableCollection<ApplicationData> _appsObservableList;
private string _searchText;
private Timer _searchTimer;
private string _vSyncModeText;
private string _showUiKey = "F4";
private string _pauseKey = "F5";
private string _screenshotKey = "F8";
private float _volume;
private float _volumeBeforeMute;
private string _backendText;
private bool _areMimeTypesRegistered = FileAssociationHelper.AreMimeTypesRegistered;
private bool _isAppletMenuActive;
private bool _statusBarVisible;
private bool _canUpdate = true;
private Cursor _cursor;
private string _title;
private ApplicationData _currentApplicationData;
private readonly AutoResetEvent _rendererWaitEvent;
private WindowState _windowState;
private double _windowWidth;
private double _windowHeight;
private int _customVSyncInterval;
private int _customVSyncIntervalPercentageProxy;
private ApplicationData _listSelectedApplication;
private ApplicationData _gridSelectedApplication;
private bool _isActive;
private bool _isSubMenuOpen;
public ApplicationData ListSelectedApplication
{
get => _listSelectedApplication;
set
{
_listSelectedApplication = value;
public ApplicationData ListSelectedApplication;
public ApplicationData GridSelectedApplication;
#pragma warning disable MVVMTK0034
if (_listSelectedApplication != null && _listAppContextMenu == null)
ListAppContextMenu = new ApplicationContextMenu();
else if (_listSelectedApplication == null && _listAppContextMenu != null)
ListAppContextMenu = null!;
#pragma warning restore MVVMTK0034
OnPropertyChanged();
}
}
public ApplicationData GridSelectedApplication
{
get => _gridSelectedApplication;
set
{
_gridSelectedApplication = value;
#pragma warning disable MVVMTK0034
if (_gridSelectedApplication != null && _gridAppContextMenu == null)
GridAppContextMenu = new ApplicationContextMenu();
else if (_gridSelectedApplication == null && _gridAppContextMenu != null)
GridAppContextMenu = null!;
#pragma warning restore MVVMTK0034
OnPropertyChanged();
}
}
// Key is Title ID
public SafeDictionary<string, LdnGameData.Array> LdnData = [];
@@ -218,7 +254,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool CanUpdate
{
get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(false);
get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate();
set
{
_canUpdate = value;
@@ -226,49 +262,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public Cursor Cursor
{
get => _cursor;
set
{
_cursor = value;
OnPropertyChanged();
}
}
public ReadOnlyObservableCollection<ApplicationData> AppsObservableList
{
get => _appsObservableList;
set
{
_appsObservableList = value;
OnPropertyChanged();
}
}
public bool IsPaused
{
get => _isPaused;
set
{
_isPaused = value;
OnPropertyChanged();
}
}
public long LastFullscreenToggle
{
get => _lastFullscreenToggle;
set
{
_lastFullscreenToggle = value;
OnPropertyChanged();
}
}
public bool StatusBarVisible
{
get => _statusBarVisible && EnableNonGameRunningControls;
@@ -284,17 +277,6 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool ShowFirmwareStatus => !ShowLoadProgress;
public bool ShowShaderCompilationHint
{
get => _showShaderCompilationHint;
set
{
_showShaderCompilationHint = value;
OnPropertyChanged();
}
}
public bool IsGameRunning
{
get => _isGameRunning;
@@ -350,61 +332,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public string GameStatusText
{
get => _gameStatusText;
set
{
_gameStatusText = value;
OnPropertyChanged();
}
}
public bool IsFullScreen
{
get => _isFullScreen;
set
{
_isFullScreen = value;
OnPropertyChanged();
}
}
public bool IsSubMenuOpen
{
get => _isSubMenuOpen;
set
{
_isSubMenuOpen = value;
OnPropertyChanged();
}
}
public bool ShowAll
{
get => _showAll;
set
{
_showAll = value;
OnPropertyChanged();
}
}
public string LastScannedAmiiboId
{
get => _lastScannedAmiiboId;
set
{
_lastScannedAmiiboId = value;
OnPropertyChanged();
}
}
public ApplicationData SelectedApplication
{
get
@@ -418,87 +345,20 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public bool OpenUserSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0;
public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0;
public bool OpenDeviceSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
public bool OpenDeviceSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
public bool TrimXCIEnabled => XCIFileTrimmer.CanTrim(SelectedApplication.Path, new XCITrimmerLog.MainWindow(this));
public bool OpenBcatSaveDirectoryEnabled => !SelectedApplication.ControlHolder.ByteSpan.IsZeros() && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
public string LoadHeading
{
get => _loadHeading;
set
{
_loadHeading = value;
OnPropertyChanged();
}
}
public string CacheLoadStatus
{
get => _cacheLoadStatus;
set
{
_cacheLoadStatus = value;
OnPropertyChanged();
}
}
public Brush ProgressBarBackgroundColor
{
get => _progressBarBackgroundColor;
set
{
_progressBarBackgroundColor = value;
OnPropertyChanged();
}
}
public Brush ProgressBarForegroundColor
{
get => _progressBarForegroundColor;
set
{
_progressBarForegroundColor = value;
OnPropertyChanged();
}
}
public Brush VSyncModeColor
{
get => _vSyncModeColor;
set
{
_vSyncModeColor = value;
OnPropertyChanged();
}
}
public bool OpenBcatSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
public bool ShowCustomVSyncIntervalPicker
=> _isGameRunning && AppHost.Device.VSyncMode == VSyncMode.Custom;
public void UpdateVSyncIntervalPicker()
{
get
{
if (_isGameRunning)
{
return AppHost.Device.VSyncMode ==
VSyncMode.Custom;
}
else
{
return false;
}
}
set
{
OnPropertyChanged();
}
OnPropertyChanged(nameof(ShowCustomVSyncIntervalPicker));
}
public int CustomVSyncIntervalPercentageProxy
@@ -551,126 +411,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public byte[] SelectedIcon
{
get => _selectedIcon;
set
{
_selectedIcon = value;
OnPropertyChanged();
}
}
public int ProgressMaximum
{
get => _progressMaximum;
set
{
_progressMaximum = value;
OnPropertyChanged();
}
}
public int ProgressValue
{
get => _progressValue;
set
{
_progressValue = value;
OnPropertyChanged();
}
}
public int StatusBarProgressMaximum
{
get => _statusBarProgressMaximum;
set
{
_statusBarProgressMaximum = value;
OnPropertyChanged();
}
}
public int StatusBarProgressValue
{
get => _statusBarProgressValue;
set
{
_statusBarProgressValue = value;
OnPropertyChanged();
}
}
public bool StatusBarProgressStatusVisible
{
get => _statusBarProgressStatusVisible;
set
{
_statusBarProgressStatusVisible = value;
OnPropertyChanged();
}
}
public string StatusBarProgressStatusText
{
get => _statusBarProgressStatusText;
set
{
_statusBarProgressStatusText = value;
OnPropertyChanged();
}
}
public string FifoStatusText
{
get => _fifoStatusText;
set
{
_fifoStatusText = value;
OnPropertyChanged();
}
}
public string GpuNameText
{
get => _gpuStatusText;
set
{
_gpuStatusText = value;
OnPropertyChanged();
}
}
public string ShaderCountText
{
get => _shaderCountText;
set
{
_shaderCountText = value;
OnPropertyChanged();
}
}
public string BackendText
{
get => _backendText;
set
{
_backendText = value;
OnPropertyChanged();
}
}
public string VSyncModeText
{
get => _vSyncModeText;
@@ -679,39 +419,7 @@ namespace Ryujinx.Ava.UI.ViewModels
_vSyncModeText = value;
OnPropertyChanged();
}
}
public string DockedStatusText
{
get => _dockedStatusText;
set
{
_dockedStatusText = value;
OnPropertyChanged();
}
}
public string AspectRatioStatusText
{
get => _aspectStatusText;
set
{
_aspectStatusText = value;
OnPropertyChanged();
}
}
public string VolumeStatusText
{
get => _volumeStatusText;
set
{
_volumeStatusText = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ShowCustomVSyncIntervalPicker));
}
}
@@ -735,73 +443,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public float VolumeBeforeMute
{
get => _volumeBeforeMute;
set
{
_volumeBeforeMute = value;
OnPropertyChanged();
}
}
public bool ShowStatusSeparator
{
get => _showStatusSeparator;
set
{
_showStatusSeparator = value;
OnPropertyChanged();
}
}
public bool ShowMenuAndStatusBar
{
get => _showMenuAndStatusBar;
set
{
_showMenuAndStatusBar = value;
OnPropertyChanged();
}
}
public bool IsLoadingIndeterminate
{
get => _isLoadingIndeterminate;
set
{
_isLoadingIndeterminate = value;
OnPropertyChanged();
}
}
public bool IsActive
{
get => _isActive;
set
{
_isActive = value;
OnPropertyChanged();
}
}
public bool ShowContent
{
get => _showContent;
set
{
_showContent = value;
OnPropertyChanged();
}
}
public bool IsAppletMenuActive
{
get => _isAppletMenuActive && EnableNonGameRunningControls;
@@ -813,39 +454,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public WindowState WindowState
{
get => _windowState;
internal set
{
_windowState = value;
OnPropertyChanged();
}
}
public double WindowWidth
{
get => _windowWidth;
set
{
_windowWidth = value;
OnPropertyChanged();
}
}
public double WindowHeight
{
get => _windowHeight;
set
{
_windowHeight = value;
OnPropertyChanged();
}
}
public bool IsGrid => Glyph == Glyph.Grid;
public bool IsList => Glyph == Glyph.List;
@@ -889,17 +497,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public string Title
{
get => _title;
set
{
_title = value;
OnPropertyChanged();
}
}
public bool ShowConsoleVisible
{
get => ConsoleHelper.SetConsoleWindowStateSupported;
@@ -910,27 +507,6 @@ namespace Ryujinx.Ava.UI.ViewModels
get => FileAssociationHelper.IsTypeAssociationSupported;
}
public bool AreMimeTypesRegistered
{
get => _areMimeTypesRegistered;
set {
_areMimeTypesRegistered = value;
OnPropertyChanged();
}
}
public ObservableCollectionExtended<ApplicationData> Applications
{
get => _applications;
set
{
_applications = value;
OnPropertyChanged();
}
}
public Glyph Glyph
{
get => (Glyph)ConfigurationState.Instance.UI.GameListViewMode.Value;
@@ -948,7 +524,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool ShowNames
{
get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1; set
get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1;
set
{
ConfigurationState.Instance.UI.ShowNames.Value = value;
@@ -1508,8 +1085,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
VSyncModeText = args.VSyncMode == "Custom" ? "Custom" : "VSync";
ShowCustomVSyncIntervalPicker =
args.VSyncMode == VSyncMode.Custom.ToString();
DockedStatusText = args.DockedMode;
AspectRatioStatusText = args.AspectRatio;
GameStatusText = args.GameStatus;

View File

@@ -1,8 +1,7 @@
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData;
using Gommon;
using Ryujinx.Ava.Common.Locale;
@@ -18,13 +17,13 @@ using System.Linq;
namespace Ryujinx.Ava.UI.ViewModels
{
public class ModManagerViewModel : BaseModel
public partial class ModManagerViewModel : BaseModel
{
private readonly string _modJsonPath;
private AvaloniaList<ModModel> _mods = new();
private AvaloniaList<ModModel> _views = new();
private AvaloniaList<ModModel> _selectedMods = new();
[ObservableProperty] private AvaloniaList<ModModel> _views = new();
[ObservableProperty] private AvaloniaList<ModModel> _selectedMods = new();
private string _search;
private readonly ulong _applicationId;
@@ -44,26 +43,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public AvaloniaList<ModModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public AvaloniaList<ModModel> SelectedMods
{
get => _selectedMods;
set
{
_selectedMods = value;
OnPropertyChanged();
}
}
public string Search
{
get => _search;
@@ -86,10 +65,7 @@ namespace Ryujinx.Ava.UI.ViewModels
_modJsonPath = Path.Combine(AppDataManager.GamesDirPath, applicationId.ToString("x16"), "mods.json");
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
_storageProvider = desktop.MainWindow.StorageProvider;
}
_storageProvider = RyujinxApp.MainWindow.StorageProvider;
LoadMods(applicationId);
}
@@ -146,8 +122,10 @@ namespace Ryujinx.Ava.UI.ViewModels
.Filter(Filter)
.Bind(out var view).AsObservableList();
#pragma warning disable MVVMTK0034 // Event to update is fired below
_views.Clear();
_views.AddRange(view);
#pragma warning restore MVVMTK0034
SelectedMods = new(Views.Where(x => x.Enabled));

View File

@@ -1,9 +1,10 @@
using Gommon;
using CommunityToolkit.Mvvm.ComponentModel;
using Gommon;
using Ryujinx.Ava.Utilities.Configuration;
namespace Ryujinx.Ava.UI.ViewModels
{
public class SettingsHacksViewModel : BaseModel
public partial class SettingsHacksViewModel : BaseModel
{
private readonly SettingsViewModel _baseViewModel;
@@ -14,33 +15,11 @@ namespace Ryujinx.Ava.UI.ViewModels
_baseViewModel = settingsVm;
}
private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
private bool _shaderTranslationThreadSleep = ConfigurationState.Instance.Hacks.EnableShaderTranslationDelay;
[ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
[ObservableProperty] private bool _shaderTranslationDelayEnabled = ConfigurationState.Instance.Hacks.EnableShaderTranslationDelay;
private int _shaderTranslationSleepDelay = ConfigurationState.Instance.Hacks.ShaderTranslationDelay;
public bool Xc2MenuSoftlockFixEnabled
{
get => _xc2MenuSoftlockFix;
set
{
_xc2MenuSoftlockFix = value;
OnPropertyChanged();
}
}
public bool ShaderTranslationDelayEnabled
{
get => _shaderTranslationThreadSleep;
set
{
_shaderTranslationThreadSleep = value;
OnPropertyChanged();
}
}
public string ShaderTranslationDelayTooltipText => $"Current value: {ShaderTranslationDelay}";
public string ShaderTranslationDelayValueText => $"{ShaderTranslationDelay}ms";
public int ShaderTranslationDelay
{
@@ -49,7 +28,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{
_shaderTranslationSleepDelay = value;
OnPropertiesChanged(nameof(ShaderTranslationDelay), nameof(ShaderTranslationDelayTooltipText));
OnPropertiesChanged(nameof(ShaderTranslationDelay), nameof(ShaderTranslationDelayValueText));
}
}

View File

@@ -1,6 +1,7 @@
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Gommon;
using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.OpenAL;
@@ -46,9 +47,9 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _resolutionScale;
private int _graphicsBackendMultithreadingIndex;
private float _volume;
private bool _isVulkanAvailable = true;
private bool _gameDirectoryChanged;
private bool _autoloadDirectoryChanged;
[ObservableProperty] private bool _isVulkanAvailable = true;
[ObservableProperty] private bool _gameDirectoryChanged;
[ObservableProperty] private bool _autoloadDirectoryChanged;
private readonly List<string> _gpuIds = new();
private int _graphicsBackendIndex;
private int _scalingFilter;
@@ -63,7 +64,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _networkInterfaceIndex;
private int _multiplayerModeIndex;
private string _ldnPassphrase;
private string _ldnServer;
[ObservableProperty] private string _ldnServer;
public SettingsHacksViewModel DirtyHacks { get; }
@@ -111,43 +112,10 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public bool IsVulkanAvailable
{
get => _isVulkanAvailable;
set
{
_isVulkanAvailable = value;
OnPropertyChanged();
}
}
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
public bool IsAppleSiliconMac => OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
public bool GameDirectoryChanged
{
get => _gameDirectoryChanged;
set
{
_gameDirectoryChanged = value;
OnPropertyChanged();
}
}
public bool AutoloadDirectoryChanged
{
get => _autoloadDirectoryChanged;
set
{
_autoloadDirectoryChanged = value;
OnPropertyChanged();
}
}
public bool IsMacOS => OperatingSystem.IsMacOS();
public bool EnableDiscordIntegration { get; set; }
@@ -187,14 +155,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public string CustomVSyncIntervalPercentageText
{
get
{
string text = CustomVSyncIntervalPercentageProxy + "%";
return text;
}
}
public string CustomVSyncIntervalPercentageText => CustomVSyncIntervalPercentageProxy + "%";
public bool EnableCustomVSyncInterval
{
@@ -356,7 +317,6 @@ namespace Ryujinx.Ava.UI.ViewModels
set
{
_networkInterfaceIndex = value != -1 ? value : 0;
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value = _networkInterfaces[NetworkInterfaceList[_networkInterfaceIndex]];
}
}
@@ -366,7 +326,6 @@ namespace Ryujinx.Ava.UI.ViewModels
set
{
_multiplayerModeIndex = value;
ConfigurationState.Instance.Multiplayer.Mode.Value = (MultiplayerMode)_multiplayerModeIndex;
}
}
@@ -375,16 +334,6 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsInvalidLdnPassphraseVisible { get; set; }
public string LdnServer
{
get => _ldnServer;
set
{
_ldnServer = value;
OnPropertyChanged();
}
}
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
{
_virtualFileSystem = virtualFileSystem;
@@ -466,11 +415,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public void MatchSystemTime()
{
var dto = DateTimeOffset.Now;
(DateTimeOffset dto, TimeSpan timeOfDay) = DateTimeOffset.Now.Extract();
CurrentDate = new DateTimeOffset(dto.Year, dto.Month, dto.Day, 0, 0, 0, dto.Offset);
CurrentTime = dto.TimeOfDay;
CurrentDate = dto;
CurrentTime = timeOfDay;
OnPropertyChanged(nameof(CurrentDate));
OnPropertyChanged(nameof(CurrentTime));
@@ -648,16 +596,14 @@ namespace Ryujinx.Ava.UI.ViewModels
config.ShowTitleBar.Value = ShowTitleBar;
config.HideCursor.Value = (HideCursorMode)HideCursor;
if (_gameDirectoryChanged)
if (GameDirectoryChanged)
{
List<string> gameDirs = new(GameDirectories);
config.UI.GameDirs.Value = gameDirs;
config.UI.GameDirs.Value = [..GameDirectories];
}
if (_autoloadDirectoryChanged)
if (AutoloadDirectoryChanged)
{
List<string> autoloadDirs = new(AutoloadDirectories);
config.UI.AutoloadDirs.Value = autoloadDirs;
config.UI.AutoloadDirs.Value = [..AutoloadDirectories];
}
config.UI.BaseStyle.Value = BaseStyleIndex switch
@@ -756,7 +702,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Multiplayer.LdnServer.Value = LdnServer;
// Dirty Hacks
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFixEnabled;
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix;
config.Hacks.EnableShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelayEnabled;
config.Hacks.ShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelay;
@@ -767,8 +713,8 @@ namespace Ryujinx.Ava.UI.ViewModels
SaveSettingsEvent?.Invoke();
_gameDirectoryChanged = false;
_autoloadDirectoryChanged = false;
GameDirectoryChanged = false;
AutoloadDirectoryChanged = false;
}
private static void RevertIfNotSaved()

View File

@@ -1,74 +1,32 @@
using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.HLE.FileSystem;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Application = Avalonia.Application;
namespace Ryujinx.Ava.UI.ViewModels
{
public record TitleUpdateViewNoUpdateSentinal();
public record TitleUpdateViewModelNoUpdate;
public class TitleUpdateViewModel : BaseModel
public partial class TitleUpdateViewModel : BaseModel
{
private ApplicationLibrary ApplicationLibrary { get; }
private ApplicationData ApplicationData { get; }
private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
private AvaloniaList<object> _views = new();
private object _selectedUpdate = new TitleUpdateViewNoUpdateSentinal();
private bool _showBundledContentNotice = false;
[ObservableProperty] private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
[ObservableProperty] private AvaloniaList<object> _views = new();
[ObservableProperty] private object _selectedUpdate = new TitleUpdateViewModelNoUpdate();
[ObservableProperty] private bool _showBundledContentNotice;
public AvaloniaList<TitleUpdateModel> TitleUpdates
{
get => _titleUpdates;
set
{
_titleUpdates = value;
OnPropertyChanged();
}
}
public AvaloniaList<object> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public object SelectedUpdate
{
get => _selectedUpdate;
set
{
_selectedUpdate = value;
OnPropertyChanged();
}
}
public bool ShowBundledContentNotice
{
get => _showBundledContentNotice;
set
{
_showBundledContentNotice = value;
OnPropertyChanged();
}
}
public IStorageProvider StorageProvider;
private readonly IStorageProvider _storageProvider;
public TitleUpdateViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
{
@@ -76,10 +34,7 @@ namespace Ryujinx.Ava.UI.ViewModels
ApplicationData = applicationData;
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
StorageProvider = desktop.MainWindow.StorageProvider;
}
_storageProvider = RyujinxApp.MainWindow.StorageProvider;
LoadUpdates();
}
@@ -90,7 +45,7 @@ namespace Ryujinx.Ava.UI.ViewModels
.Where(it => it.TitleUpdate.TitleIdBase == ApplicationData.IdBase);
bool hasBundledContent = false;
SelectedUpdate = new TitleUpdateViewNoUpdateSentinal();
SelectedUpdate = new TitleUpdateViewModelNoUpdate();
foreach ((TitleUpdateModel update, bool isSelected) in updates)
{
TitleUpdates.Add(update);
@@ -116,12 +71,12 @@ namespace Ryujinx.Ava.UI.ViewModels
var selected = SelectedUpdate;
Views.Clear();
Views.Add(new TitleUpdateViewNoUpdateSentinal());
Views.Add(new TitleUpdateViewModelNoUpdate());
Views.AddRange(sortedUpdates);
SelectedUpdate = selected;
if (SelectedUpdate is TitleUpdateViewNoUpdateSentinal)
if (SelectedUpdate is TitleUpdateViewModelNoUpdate)
{
SelectedUpdate = Views[0];
}
@@ -179,7 +134,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}
else if (update == SelectedUpdate as TitleUpdateModel)
{
SelectedUpdate = new TitleUpdateViewNoUpdateSentinal();
SelectedUpdate = new TitleUpdateViewModelNoUpdate();
}
SortUpdates();
@@ -187,7 +142,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public async Task Add()
{
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
var result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
AllowMultiple = true,
FileTypeFilter = new List<FilePickerFileType>

View File

@@ -1,4 +1,5 @@
using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Fsa;
@@ -20,12 +21,12 @@ using Image = SkiaSharp.SKImage;
namespace Ryujinx.Ava.UI.ViewModels
{
internal class UserFirmwareAvatarSelectorViewModel : BaseModel
internal partial class UserFirmwareAvatarSelectorViewModel : BaseModel
{
private static readonly Dictionary<string, byte[]> _avatarStore = new();
private ObservableCollection<ProfileImageModel> _images;
private Color _backgroundColor = Colors.White;
[ObservableProperty] private ObservableCollection<ProfileImageModel> _images;
[ObservableProperty] private Color _backgroundColor = Colors.White;
private int _selectedIndex;
@@ -34,27 +35,11 @@ namespace Ryujinx.Ava.UI.ViewModels
_images = new ObservableCollection<ProfileImageModel>();
LoadImagesFromStore();
}
public Color BackgroundColor
PropertyChanged += (_, args) =>
{
get => _backgroundColor;
set
{
_backgroundColor = value;
OnPropertyChanged();
if (args.PropertyName == nameof(BackgroundColor))
ChangeImageBackground();
}
}
public ObservableCollection<ProfileImageModel> Images
{
get => _images;
set
{
_images = value;
OnPropertyChanged();
}
};
}
public int SelectedIndex
@@ -70,7 +55,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}
else
{
SelectedImage = _images[_selectedIndex].Data;
SelectedImage = Images[_selectedIndex].Data;
}
OnPropertyChanged();

View File

@@ -1,18 +1,9 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Ryujinx.Ava.UI.ViewModels
{
internal class UserProfileImageSelectorViewModel : BaseModel
internal partial class UserProfileImageSelectorViewModel : BaseModel
{
private bool _firmwareFound;
public bool FirmwareFound
{
get => _firmwareFound;
set
{
_firmwareFound = value;
OnPropertyChanged();
}
}
[ObservableProperty] private bool _firmwareFound;
}
}

View File

@@ -1,3 +1,4 @@
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData;
using DynamicData.Binding;
using Ryujinx.Ava.Common.Locale;
@@ -8,74 +9,31 @@ using System.Collections.ObjectModel;
namespace Ryujinx.Ava.UI.ViewModels
{
public class UserSaveManagerViewModel : BaseModel
public partial class UserSaveManagerViewModel : BaseModel
{
private int _sortIndex;
private int _orderIndex;
private string _search;
private ObservableCollection<SaveModel> _saves = new();
private ObservableCollection<SaveModel> _views = new();
[ObservableProperty] private int _sortIndex;
[ObservableProperty] private int _orderIndex;
[ObservableProperty] private string _search;
[ObservableProperty] private ObservableCollection<SaveModel> _saves = new();
[ObservableProperty] private ObservableCollection<SaveModel> _views = new();
private readonly AccountManager _accountManager;
public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId);
public int SortIndex
{
get => _sortIndex;
set
{
_sortIndex = value;
OnPropertyChanged();
Sort();
}
}
public int OrderIndex
{
get => _orderIndex;
set
{
_orderIndex = value;
OnPropertyChanged();
Sort();
}
}
public string Search
{
get => _search;
set
{
_search = value;
OnPropertyChanged();
Sort();
}
}
public ObservableCollection<SaveModel> Saves
{
get => _saves;
set
{
_saves = value;
OnPropertyChanged();
Sort();
}
}
public ObservableCollection<SaveModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public UserSaveManagerViewModel(AccountManager accountManager)
{
_accountManager = accountManager;
PropertyChanged += (_, evt) =>
{
if (evt.PropertyName is
nameof(SortIndex) or
nameof(OrderIndex) or
nameof(Search) or
nameof(Saves))
{
Sort();
}
};
}
public void Sort()
@@ -85,8 +43,10 @@ namespace Ryujinx.Ava.UI.ViewModels
.Sort(GetComparer())
.Bind(out var view).AsObservableList();
#pragma warning disable MVVMTK0034
_views.Clear();
_views.AddRange(view);
#pragma warning restore MVVMTK0034
OnPropertyChanged(nameof(Views));
}
@@ -94,7 +54,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{
if (arg is SaveModel save)
{
return string.IsNullOrWhiteSpace(_search) || save.Title.ToLower().Contains(_search.ToLower());
return string.IsNullOrWhiteSpace(Search) || save.Title.ToLower().Contains(Search.ToLower());
}
return false;

View File

@@ -247,6 +247,7 @@
Header="{ext:Locale MenuBarActionsScanAmiiboBin}"
Icon="{ext:Icon mdi-cube-scan}"
IsVisible="{Binding CanScanAmiiboBinaries}"
InputGesture="Ctrl + B"
IsEnabled="{Binding IsAmiiboBinRequested}" />
<MenuItem
Command="{Binding TakeScreenshot}"

View File

@@ -41,7 +41,7 @@ namespace Ryujinx.Ava.UI.Views.Main
private void VSyncMode_PointerReleased(object sender, PointerReleasedEventArgs e)
{
Window.ViewModel.ToggleVSyncMode();
Logger.Info?.Print(LogClass.Application, $"VSync Mode toggled to: {Window.ViewModel.AppHost.Device.VSyncMode}");
Logger.Info?.PrintMsg(LogClass.Application, $"VSync Mode toggled to: {Window.ViewModel.AppHost.Device.VSyncMode}");
}
private void DockedStatus_PointerReleased(object sender, PointerReleasedEventArgs e)

View File

@@ -26,7 +26,6 @@ namespace Ryujinx.Ava.UI.Views.Main
{
DataContext = ViewModel = window.ViewModel;
}
}
public void Sort_Checked(object sender, RoutedEventArgs args)

View File

@@ -37,7 +37,7 @@
ToolTip.Tip="{Binding DirtyHacks.Xc2MenuFixTooltip}">
<CheckBox
Margin="0"
IsChecked="{Binding DirtyHacks.Xc2MenuSoftlockFixEnabled}"/>
IsChecked="{Binding DirtyHacks.Xc2MenuSoftlockFix}"/>
<TextBlock
VerticalAlignment="Center"
Text="Xenoblade Chronicles 2 Menu Softlock Fix" />
@@ -54,10 +54,13 @@
<TextBlock VerticalAlignment="Center"
Text="Arbitrary Delay on Shader Translation"/>
</StackPanel>
<Slider IsVisible="{Binding DirtyHacks.ShaderTranslationDelayEnabled}"
HorizontalAlignment="Center"
<StackPanel
IsVisible="{Binding DirtyHacks.ShaderTranslationDelayEnabled}"
Margin="0,10,0,0"
Orientation="Horizontal"
HorizontalAlignment="Center">
<Slider HorizontalAlignment="Center"
Value="{Binding DirtyHacks.ShaderTranslationDelay}"
ToolTip.Tip="{Binding DirtyHacks.ShaderTranslationDelayTooltipText}"
Width="175"
Margin="0,-3,0,0"
Height="32"
@@ -69,6 +72,9 @@
VerticalAlignment="Center"
Minimum="1"
Maximum="1000" />
<TextBlock Margin="5,0"
Text="{Binding DirtyHacks.ShaderTranslationDelayValueText}"/>
</StackPanel>
<Separator/>
</StackPanel>
</Border>

View File

@@ -40,6 +40,7 @@
<KeyBinding Gesture="F9" Command="{Binding ToggleDockMode}" />
<KeyBinding Gesture="Escape" Command="{Binding ExitCurrentState}" />
<KeyBinding Gesture="Ctrl+A" Command="{Binding OpenAmiiboWindow}" />
<KeyBinding Gesture="Ctrl+B" Command="{Binding OpenBinFile}" />
</Window.KeyBindings>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RowDefinitions="*">
<helpers:OffscreenTextBox IsEnabled="False" Opacity="0" Name="HiddenTextBox" IsHitTestVisible="False" IsTabStop="False" />

View File

@@ -93,6 +93,7 @@
Padding="10"
MinWidth="0"
MinHeight="0"
ToolTip.Tip="{Binding Path}"
Click="OpenLocation">
<ui:SymbolIcon
Symbol="OpenFolder"

View File

@@ -95,7 +95,7 @@
</Panel>
</DataTemplate>
<DataTemplate
DataType="viewModels:TitleUpdateViewNoUpdateSentinal">
DataType="viewModels:TitleUpdateViewModelNoUpdate">
<Panel
Height="33"
Margin="10">

View File

@@ -33,7 +33,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
public string Path { get; set; }
public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; }
public bool HasControlHolder => ControlHolder.ByteSpan.Length > 0;
public bool HasControlHolder => ControlHolder.ByteSpan.Length > 0 && !ControlHolder.ByteSpan.IsZeros();
public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed);

View File

@@ -75,11 +75,11 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
TitleUpdates = _titleUpdates.AsObservableCache();
DownloadableContents = _downloadableContents.AsObservableCache();
_nspIcon = EmbeddedResources.Read("Ryujinx.Assets.UIImages.Icon_NSP.png");
_xciIcon = EmbeddedResources.Read("Ryujinx.Assets.UIImages.Icon_XCI.png");
_ncaIcon = EmbeddedResources.Read("Ryujinx.Assets.UIImages.Icon_NCA.png");
_nroIcon = EmbeddedResources.Read("Ryujinx.Assets.UIImages.Icon_NRO.png");
_nsoIcon = EmbeddedResources.Read("Ryujinx.Assets.UIImages.Icon_NSO.png");
_nspIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_NSP.png");
_xciIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_XCI.png");
_ncaIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_NCA.png");
_nroIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_NRO.png");
_nsoIcon = EmbeddedResources.Read("Ryujinx/Assets.UIImages.Icon_NSO.png");
}
/// <exception cref="Ryujinx.HLE.Exceptions.InvalidNpdmException">The npdm file doesn't contain valid data.</exception>

View File

@@ -1,3 +1,4 @@
using Gommon;
using LibHac.Ns;
using System;
using System.Collections.Generic;
@@ -22,7 +23,7 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
LibHac.Common.FixedArrays.Array8<ulong> communicationId = acp.LocalCommunicationId;
return new Array(receivedData.Where(game =>
communicationId.Items.Contains(Convert.ToUInt64(game.TitleId, 16))
communicationId.Items.Contains(game.TitleId.ToULong())
));
}

View File

@@ -272,7 +272,7 @@ namespace Ryujinx.Ava.Utilities.Configuration
public MemoryManagerMode MemoryManagerMode { get; set; }
/// <summary>
/// Expands the RAM amount on the emulated system from 4GiB to 8GiB
/// Expands the RAM amount on the emulated system
/// </summary>
public MemoryConfiguration DramSize { get; set; }

View File

@@ -1,3 +1,4 @@
using Gommon;
using Ryujinx.Ava.Utilities.Configuration.System;
using Ryujinx.Ava.Utilities.Configuration.UI;
using Ryujinx.Common.Configuration;
@@ -10,189 +11,197 @@ using Ryujinx.HLE;
using System;
using System.Collections.Generic;
using System.Linq;
using RyuLogger = Ryujinx.Common.Logging.Logger;
namespace Ryujinx.Ava.Utilities.Configuration
{
public partial class ConfigurationState
{
public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath)
public void Load(ConfigurationFileFormat cff, string configurationFilePath)
{
bool configurationFileUpdated = false;
if (configurationFileFormat.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
if (cff.Version is < 0 or > ConfigurationFileFormat.CurrentVersion)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default.");
RyuLogger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {cff.Version}, loading default.");
LoadDefault();
}
if (configurationFileFormat.Version < 2)
foreach ((int newVersion, Action<ConfigurationFileFormat> migratorFunction)
in _migrations.OrderBy(x => x.Key))
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2.");
if (cff.Version >= newVersion)
continue;
configurationFileFormat.SystemRegion = Region.USA;
RyuLogger.Warning?.Print(LogClass.Application,
$"Outdated configuration version {cff.Version}, migrating to version {newVersion}.");
migratorFunction(cff);
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 3)
EnableDiscordIntegration.Value = cff.EnableDiscordIntegration;
CheckUpdatesOnStart.Value = cff.CheckUpdatesOnStart;
ShowConfirmExit.Value = cff.ShowConfirmExit;
IgnoreApplet.Value = cff.IgnoreApplet;
RememberWindowState.Value = cff.RememberWindowState;
ShowTitleBar.Value = cff.ShowTitleBar;
EnableHardwareAcceleration.Value = cff.EnableHardwareAcceleration;
HideCursor.Value = cff.HideCursor;
Logger.EnableFileLog.Value = cff.EnableFileLog;
Logger.EnableDebug.Value = cff.LoggingEnableDebug;
Logger.EnableStub.Value = cff.LoggingEnableStub;
Logger.EnableInfo.Value = cff.LoggingEnableInfo;
Logger.EnableWarn.Value = cff.LoggingEnableWarn;
Logger.EnableError.Value = cff.LoggingEnableError;
Logger.EnableTrace.Value = cff.LoggingEnableTrace;
Logger.EnableGuest.Value = cff.LoggingEnableGuest;
Logger.EnableFsAccessLog.Value = cff.LoggingEnableFsAccessLog;
Logger.FilteredClasses.Value = cff.LoggingFilteredClasses;
Logger.GraphicsDebugLevel.Value = cff.LoggingGraphicsDebugLevel;
Graphics.ResScale.Value = cff.ResScale;
Graphics.ResScaleCustom.Value = cff.ResScaleCustom;
Graphics.MaxAnisotropy.Value = cff.MaxAnisotropy;
Graphics.AspectRatio.Value = cff.AspectRatio;
Graphics.ShadersDumpPath.Value = cff.GraphicsShadersDumpPath;
Graphics.BackendThreading.Value = cff.BackendThreading;
Graphics.GraphicsBackend.Value = cff.GraphicsBackend;
Graphics.PreferredGpu.Value = cff.PreferredGpu;
Graphics.AntiAliasing.Value = cff.AntiAliasing;
Graphics.ScalingFilter.Value = cff.ScalingFilter;
Graphics.ScalingFilterLevel.Value = cff.ScalingFilterLevel;
Graphics.VSyncMode.Value = cff.VSyncMode;
Graphics.EnableCustomVSyncInterval.Value = cff.EnableCustomVSyncInterval;
Graphics.CustomVSyncInterval.Value = cff.CustomVSyncInterval;
Graphics.EnableShaderCache.Value = cff.EnableShaderCache;
Graphics.EnableTextureRecompression.Value = cff.EnableTextureRecompression;
Graphics.EnableMacroHLE.Value = cff.EnableMacroHLE;
Graphics.EnableColorSpacePassthrough.Value = cff.EnableColorSpacePassthrough;
System.Language.Value = cff.SystemLanguage;
System.Region.Value = cff.SystemRegion;
System.TimeZone.Value = cff.SystemTimeZone;
System.SystemTimeOffset.Value = cff.SystemTimeOffset;
System.EnableDockedMode.Value = cff.DockedMode;
System.EnablePtc.Value = cff.EnablePtc;
System.EnableLowPowerPtc.Value = cff.EnableLowPowerPtc;
System.EnableInternetAccess.Value = cff.EnableInternetAccess;
System.EnableFsIntegrityChecks.Value = cff.EnableFsIntegrityChecks;
System.FsGlobalAccessLogMode.Value = cff.FsGlobalAccessLogMode;
System.AudioBackend.Value = cff.AudioBackend;
System.AudioVolume.Value = cff.AudioVolume;
System.MemoryManagerMode.Value = cff.MemoryManagerMode;
System.DramSize.Value = cff.DramSize;
System.IgnoreMissingServices.Value = cff.IgnoreMissingServices;
System.UseHypervisor.Value = cff.UseHypervisor;
UI.GuiColumns.FavColumn.Value = cff.GuiColumns.FavColumn;
UI.GuiColumns.IconColumn.Value = cff.GuiColumns.IconColumn;
UI.GuiColumns.AppColumn.Value = cff.GuiColumns.AppColumn;
UI.GuiColumns.DevColumn.Value = cff.GuiColumns.DevColumn;
UI.GuiColumns.VersionColumn.Value = cff.GuiColumns.VersionColumn;
UI.GuiColumns.TimePlayedColumn.Value = cff.GuiColumns.TimePlayedColumn;
UI.GuiColumns.LastPlayedColumn.Value = cff.GuiColumns.LastPlayedColumn;
UI.GuiColumns.FileExtColumn.Value = cff.GuiColumns.FileExtColumn;
UI.GuiColumns.FileSizeColumn.Value = cff.GuiColumns.FileSizeColumn;
UI.GuiColumns.PathColumn.Value = cff.GuiColumns.PathColumn;
UI.ColumnSort.SortColumnId.Value = cff.ColumnSort.SortColumnId;
UI.ColumnSort.SortAscending.Value = cff.ColumnSort.SortAscending;
UI.GameDirs.Value = cff.GameDirs;
UI.AutoloadDirs.Value = cff.AutoloadDirs ?? [];
UI.ShownFileTypes.NSP.Value = cff.ShownFileTypes.NSP;
UI.ShownFileTypes.PFS0.Value = cff.ShownFileTypes.PFS0;
UI.ShownFileTypes.XCI.Value = cff.ShownFileTypes.XCI;
UI.ShownFileTypes.NCA.Value = cff.ShownFileTypes.NCA;
UI.ShownFileTypes.NRO.Value = cff.ShownFileTypes.NRO;
UI.ShownFileTypes.NSO.Value = cff.ShownFileTypes.NSO;
UI.LanguageCode.Value = cff.LanguageCode;
UI.BaseStyle.Value = cff.BaseStyle;
UI.GameListViewMode.Value = cff.GameListViewMode;
UI.ShowNames.Value = cff.ShowNames;
UI.IsAscendingOrder.Value = cff.IsAscendingOrder;
UI.GridSize.Value = cff.GridSize;
UI.ApplicationSort.Value = cff.ApplicationSort;
UI.StartFullscreen.Value = cff.StartFullscreen;
UI.ShowConsole.Value = cff.ShowConsole;
UI.WindowStartup.WindowSizeWidth.Value = cff.WindowStartup.WindowSizeWidth;
UI.WindowStartup.WindowSizeHeight.Value = cff.WindowStartup.WindowSizeHeight;
UI.WindowStartup.WindowPositionX.Value = cff.WindowStartup.WindowPositionX;
UI.WindowStartup.WindowPositionY.Value = cff.WindowStartup.WindowPositionY;
UI.WindowStartup.WindowMaximized.Value = cff.WindowStartup.WindowMaximized;
Hid.EnableKeyboard.Value = cff.EnableKeyboard;
Hid.EnableMouse.Value = cff.EnableMouse;
Hid.Hotkeys.Value = cff.Hotkeys;
Hid.InputConfig.Value = cff.InputConfig ?? [];
Multiplayer.LanInterfaceId.Value = cff.MultiplayerLanInterfaceId;
Multiplayer.Mode.Value = cff.MultiplayerMode;
Multiplayer.DisableP2p.Value = cff.MultiplayerDisableP2p;
Multiplayer.LdnPassphrase.Value = cff.MultiplayerLdnPassphrase;
Multiplayer.LdnServer.Value = cff.LdnServer;
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3.");
Hacks.ShowDirtyHacks.Value = cff.ShowDirtyHacks;
configurationFileFormat.SystemTimeZone = "UTC";
DirtyHacks hacks = new (cff.DirtyHacks ?? []);
configurationFileUpdated = true;
Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix);
Hacks.EnableShaderTranslationDelay.Value = hacks.IsEnabled(DirtyHack.ShaderTranslationDelay);
Hacks.ShaderTranslationDelay.Value = hacks[DirtyHack.ShaderTranslationDelay].CoerceAtLeast(0);
}
if (configurationFileFormat.Version < 4)
if (configurationFileUpdated)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4.");
ToFileFormat().SaveConfig(configurationFilePath);
configurationFileFormat.MaxAnisotropy = -1;
configurationFileUpdated = true;
RyuLogger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
}
}
if (configurationFileFormat.Version < 5)
private static readonly Dictionary<int, Action<ConfigurationFileFormat>> _migrations =
Collections.NewDictionary<int, Action<ConfigurationFileFormat>>(
(2, static cff => cff.SystemRegion = Region.USA),
(3, static cff => cff.SystemTimeZone = "UTC"),
(4, static cff => cff.MaxAnisotropy = -1),
(5, static cff => cff.SystemTimeOffset = 0),
(8, static cff => cff.EnablePtc = true),
(9, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5.");
configurationFileFormat.SystemTimeOffset = 0;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 8)
cff.ColumnSort = new ColumnSort { SortColumnId = 0, SortAscending = false };
cff.Hotkeys = new KeyboardHotkeys { ToggleVSyncMode = Key.F1 };
}),
(10, static cff => cff.AudioBackend = AudioBackend.OpenAl),
(11, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8.");
configurationFileFormat.EnablePtc = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 9)
cff.ResScale = 1;
cff.ResScaleCustom = 1.0f;
}),
(12, static cff => cff.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None),
// 13 -> LDN1
(14, static cff => cff.CheckUpdatesOnStart = true),
(16, static cff => cff.EnableShaderCache = true),
(17, static cff => cff.StartFullscreen = false),
(18, static cff => cff.AspectRatio = AspectRatio.Fixed16x9),
// 19 -> LDN2
(20, static cff => cff.ShowConfirmExit = true),
(21, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9.");
configurationFileFormat.ColumnSort = new ColumnSort
{
SortColumnId = 0,
SortAscending = false,
};
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = Key.F1,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 10)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10.");
configurationFileFormat.AudioBackend = AudioBackend.OpenAl;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 11)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11.");
configurationFileFormat.ResScale = 1;
configurationFileFormat.ResScaleCustom = 1.0f;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 12)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12.");
configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None;
configurationFileUpdated = true;
}
// configurationFileFormat.Version == 13 -> LDN1
if (configurationFileFormat.Version < 14)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14.");
configurationFileFormat.CheckUpdatesOnStart = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 16)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16.");
configurationFileFormat.EnableShaderCache = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 17)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17.");
configurationFileFormat.StartFullscreen = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 18)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18.");
configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9;
configurationFileUpdated = true;
}
// configurationFileFormat.Version == 19 -> LDN2
if (configurationFileFormat.Version < 20)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20.");
configurationFileFormat.ShowConfirmExit = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 21)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 21.");
// Initialize network config.
configurationFileFormat.MultiplayerMode = MultiplayerMode.Disabled;
configurationFileFormat.MultiplayerLanInterfaceId = "0";
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 22)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22.");
configurationFileFormat.HideCursor = HideCursorMode.Never;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 24)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24.");
configurationFileFormat.InputConfig = new List<InputConfig>
cff.MultiplayerMode = MultiplayerMode.Disabled;
cff.MultiplayerLanInterfaceId = "0";
}),
(22, static cff => cff.HideCursor = HideCursorMode.Never),
(24, static cff =>
{
cff.InputConfig =
[
new StandardKeyboardInputConfig
{
Version = InputConfig.CurrentVersion,
@@ -240,534 +249,172 @@ namespace Ryujinx.Ava.Utilities.Configuration
StickRight = Key.L,
StickButton = Key.H,
},
},
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 25)
];
}),
(26, static cff => cff.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe),
(27, static cff => cff.EnableMouse = false),
(29,
static cff =>
cff.Hotkeys = new KeyboardHotkeys
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25.");
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 26)
ToggleVSyncMode = Key.F1, Screenshot = Key.F8, ShowUI = Key.F4
}),
(30, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 26.");
configurationFileFormat.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 27)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 27.");
configurationFileFormat.EnableMouse = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 28)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 28.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = Key.F1,
Screenshot = Key.F8,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 29)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = Key.F1,
Screenshot = Key.F8,
ShowUI = Key.F4,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 30)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 30.");
foreach (InputConfig config in configurationFileFormat.InputConfig)
foreach (InputConfig config in cff.InputConfig)
{
if (config is StandardControllerInputConfig controllerConfig)
{
controllerConfig.Rumble = new RumbleConfigController
{
EnableRumble = false,
StrongRumble = 1f,
WeakRumble = 1f,
EnableRumble = false, StrongRumble = 1f, WeakRumble = 1f,
};
}
}
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 31)
}),
(31, static cff => cff.BackendThreading = BackendThreading.Auto),
(32, static cff => cff.Hotkeys = new KeyboardHotkeys
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 31.");
configurationFileFormat.BackendThreading = BackendThreading.Auto;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 32)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 32.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI,
Pause = Key.F5,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 33)
}),
(33, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 33.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
cff.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI,
Pause = cff.Hotkeys.Pause,
ToggleMute = Key.F2,
};
configurationFileFormat.AudioVolume = 1;
configurationFileUpdated = true;
cff.AudioVolume = 1;
}),
(34, static cff => cff.EnableInternetAccess = false),
(35, static cff =>
{
foreach (StandardControllerInputConfig config in cff.InputConfig
.OfType<StandardControllerInputConfig>())
{
config.RangeLeft = 1.0f;
config.RangeRight = 1.0f;
}
}),
if (configurationFileFormat.Version < 34)
(36, static cff => cff.LoggingEnableTrace = false),
(37, static cff => cff.ShowConsole = true),
(38, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 34.");
configurationFileFormat.EnableInternetAccess = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 35)
cff.BaseStyle = "Dark";
cff.GameListViewMode = 0;
cff.ShowNames = true;
cff.GridSize = 2;
cff.LanguageCode = "en_US";
}),
(39,
static cff => cff.Hotkeys = new KeyboardHotkeys
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 35.");
foreach (InputConfig config in configurationFileFormat.InputConfig)
{
if (config is StandardControllerInputConfig controllerConfig)
{
controllerConfig.RangeLeft = 1.0f;
controllerConfig.RangeRight = 1.0f;
}
}
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 36)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 36.");
configurationFileFormat.LoggingEnableTrace = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 37)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37.");
configurationFileFormat.ShowConsole = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 38)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 38.");
configurationFileFormat.BaseStyle = "Dark";
configurationFileFormat.GameListViewMode = 0;
configurationFileFormat.ShowNames = true;
configurationFileFormat.GridSize = 2;
configurationFileFormat.LanguageCode = "en_US";
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 39)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 39.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI,
Pause = cff.Hotkeys.Pause,
ToggleMute = cff.Hotkeys.ToggleMute,
ResScaleUp = Key.Unbound,
ResScaleDown = Key.Unbound,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 40)
ResScaleDown = Key.Unbound
}),
(40, static cff => cff.GraphicsBackend = GraphicsBackend.OpenGl),
(41,
static cff => cff.Hotkeys = new KeyboardHotkeys
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 40.");
configurationFileFormat.GraphicsBackend = GraphicsBackend.OpenGl;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 41)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 41.");
configurationFileFormat.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = configurationFileFormat.Hotkeys.ToggleVSyncMode,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
ToggleVSyncMode = cff.Hotkeys.ToggleVSyncMode,
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI,
Pause = cff.Hotkeys.Pause,
ToggleMute = cff.Hotkeys.ToggleMute,
ResScaleUp = cff.Hotkeys.ResScaleUp,
ResScaleDown = cff.Hotkeys.ResScaleDown,
VolumeUp = Key.Unbound,
VolumeDown = Key.Unbound,
};
}
if (configurationFileFormat.Version < 42)
VolumeDown = Key.Unbound
}),
(42, static cff => cff.EnableMacroHLE = true),
(43, static cff => cff.UseHypervisor = true),
(44, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 42.");
configurationFileFormat.EnableMacroHLE = true;
}
if (configurationFileFormat.Version < 43)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 43.");
configurationFileFormat.UseHypervisor = true;
}
if (configurationFileFormat.Version < 44)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 44.");
configurationFileFormat.AntiAliasing = AntiAliasing.None;
configurationFileFormat.ScalingFilter = ScalingFilter.Bilinear;
configurationFileFormat.ScalingFilterLevel = 80;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 45)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 45.");
configurationFileFormat.ShownFileTypes = new ShownFileTypes
cff.AntiAliasing = AntiAliasing.None;
cff.ScalingFilter = ScalingFilter.Bilinear;
cff.ScalingFilterLevel = 80;
}),
(45,
static cff => cff.ShownFileTypes = new ShownFileTypes
{
NSP = true,
PFS0 = true,
XCI = true,
NCA = true,
NRO = true,
NSO = true,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 46)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 46.");
configurationFileFormat.MultiplayerLanInterfaceId = "0";
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 47)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 47.");
configurationFileFormat.WindowStartup = new WindowStartup
NSO = true
}),
(46, static cff => cff.UseHypervisor = OperatingSystem.IsMacOS()),
(47,
static cff => cff.WindowStartup = new WindowStartup
{
WindowPositionX = 0,
WindowPositionY = 0,
WindowSizeHeight = 760,
WindowSizeWidth = 1280,
WindowMaximized = false,
};
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 48)
WindowMaximized = false
}),
(48, static cff => cff.EnableColorSpacePassthrough = false),
(49, static _ =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 48.");
configurationFileFormat.EnableColorSpacePassthrough = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 49)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 49.");
if (OperatingSystem.IsMacOS())
{
AppDataManager.FixMacOSConfigurationFolders();
}
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 50)
}),
(50, static cff => cff.EnableHardwareAcceleration = true),
(51, static cff => cff.RememberWindowState = true),
(52, static cff => cff.AutoloadDirs = []),
(53, static cff => cff.EnableLowPowerPtc = false),
(54, static cff => cff.DramSize = MemoryConfiguration.MemoryConfiguration4GiB),
(55, static cff => cff.IgnoreApplet = false),
(56, static cff => cff.ShowTitleBar = !OperatingSystem.IsWindows()),
(57, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 50.");
cff.VSyncMode = VSyncMode.Switch;
cff.EnableCustomVSyncInterval = false;
configurationFileFormat.EnableHardwareAcceleration = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 51)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 51.");
configurationFileFormat.RememberWindowState = true;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 52)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 52.");
configurationFileFormat.AutoloadDirs = [];
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 53)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 53.");
configurationFileFormat.EnableLowPowerPtc = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 54)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 54.");
configurationFileFormat.DramSize = MemoryConfiguration.MemoryConfiguration4GiB;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 55)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 55.");
configurationFileFormat.IgnoreApplet = false;
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 56)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 56.");
configurationFileFormat.ShowTitleBar = !OperatingSystem.IsWindows();
configurationFileUpdated = true;
}
if (configurationFileFormat.Version < 57)
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 57.");
configurationFileFormat.VSyncMode = VSyncMode.Switch;
configurationFileFormat.EnableCustomVSyncInterval = false;
configurationFileFormat.Hotkeys = new KeyboardHotkeys
cff.Hotkeys = new KeyboardHotkeys
{
ToggleVSyncMode = Key.F1,
Screenshot = configurationFileFormat.Hotkeys.Screenshot,
ShowUI = configurationFileFormat.Hotkeys.ShowUI,
Pause = configurationFileFormat.Hotkeys.Pause,
ToggleMute = configurationFileFormat.Hotkeys.ToggleMute,
ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp,
ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown,
VolumeUp = configurationFileFormat.Hotkeys.VolumeUp,
VolumeDown = configurationFileFormat.Hotkeys.VolumeDown,
Screenshot = cff.Hotkeys.Screenshot,
ShowUI = cff.Hotkeys.ShowUI,
Pause = cff.Hotkeys.Pause,
ToggleMute = cff.Hotkeys.ToggleMute,
ResScaleUp = cff.Hotkeys.ResScaleUp,
ResScaleDown = cff.Hotkeys.ResScaleDown,
VolumeUp = cff.Hotkeys.VolumeUp,
VolumeDown = cff.Hotkeys.VolumeDown,
CustomVSyncIntervalIncrement = Key.Unbound,
CustomVSyncIntervalDecrement = Key.Unbound,
};
configurationFileFormat.CustomVSyncInterval = 120;
configurationFileUpdated = true;
}
// 58 migration accidentally got skipped but it worked with no issues somehow lol
if (configurationFileFormat.Version < 59)
cff.CustomVSyncInterval = 120;
}),
// 58 migration accidentally got skipped, but it worked with no issues somehow lol
(59, static cff =>
{
Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 59.");
cff.ShowDirtyHacks = false;
cff.DirtyHacks = [];
configurationFileFormat.ShowDirtyHacks = false;
configurationFileFormat.DirtyHacks = [];
configurationFileUpdated = true;
}
Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog;
Graphics.ResScale.Value = configurationFileFormat.ResScale;
Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom;
Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy;
Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio;
Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath;
Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading;
Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend;
Graphics.PreferredGpu.Value = configurationFileFormat.PreferredGpu;
Graphics.AntiAliasing.Value = configurationFileFormat.AntiAliasing;
Graphics.ScalingFilter.Value = configurationFileFormat.ScalingFilter;
Graphics.ScalingFilterLevel.Value = configurationFileFormat.ScalingFilterLevel;
Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug;
Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub;
Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo;
Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn;
Logger.EnableError.Value = configurationFileFormat.LoggingEnableError;
Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace;
Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest;
Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog;
Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses;
Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel;
System.Language.Value = configurationFileFormat.SystemLanguage;
System.Region.Value = configurationFileFormat.SystemRegion;
System.TimeZone.Value = configurationFileFormat.SystemTimeZone;
System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset;
System.EnableDockedMode.Value = configurationFileFormat.DockedMode;
EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration;
CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart;
ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit;
IgnoreApplet.Value = configurationFileFormat.IgnoreApplet;
RememberWindowState.Value = configurationFileFormat.RememberWindowState;
ShowTitleBar.Value = configurationFileFormat.ShowTitleBar;
EnableHardwareAcceleration.Value = configurationFileFormat.EnableHardwareAcceleration;
HideCursor.Value = configurationFileFormat.HideCursor;
Graphics.VSyncMode.Value = configurationFileFormat.VSyncMode;
Graphics.EnableCustomVSyncInterval.Value = configurationFileFormat.EnableCustomVSyncInterval;
Graphics.CustomVSyncInterval.Value = configurationFileFormat.CustomVSyncInterval;
Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache;
Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression;
Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE;
Graphics.EnableColorSpacePassthrough.Value = configurationFileFormat.EnableColorSpacePassthrough;
System.EnablePtc.Value = configurationFileFormat.EnablePtc;
System.EnableLowPowerPtc.Value = configurationFileFormat.EnableLowPowerPtc;
System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess;
System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks;
System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode;
System.AudioBackend.Value = configurationFileFormat.AudioBackend;
System.AudioVolume.Value = configurationFileFormat.AudioVolume;
System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode;
System.DramSize.Value = configurationFileFormat.DramSize;
System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices;
System.UseHypervisor.Value = configurationFileFormat.UseHypervisor;
UI.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn;
UI.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn;
UI.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn;
UI.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn;
UI.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn;
UI.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn;
UI.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn;
UI.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn;
UI.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn;
UI.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn;
UI.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId;
UI.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending;
UI.GameDirs.Value = configurationFileFormat.GameDirs;
UI.AutoloadDirs.Value = configurationFileFormat.AutoloadDirs ?? [];
UI.ShownFileTypes.NSP.Value = configurationFileFormat.ShownFileTypes.NSP;
UI.ShownFileTypes.PFS0.Value = configurationFileFormat.ShownFileTypes.PFS0;
UI.ShownFileTypes.XCI.Value = configurationFileFormat.ShownFileTypes.XCI;
UI.ShownFileTypes.NCA.Value = configurationFileFormat.ShownFileTypes.NCA;
UI.ShownFileTypes.NRO.Value = configurationFileFormat.ShownFileTypes.NRO;
UI.ShownFileTypes.NSO.Value = configurationFileFormat.ShownFileTypes.NSO;
UI.LanguageCode.Value = configurationFileFormat.LanguageCode;
UI.BaseStyle.Value = configurationFileFormat.BaseStyle;
UI.GameListViewMode.Value = configurationFileFormat.GameListViewMode;
UI.ShowNames.Value = configurationFileFormat.ShowNames;
UI.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder;
UI.GridSize.Value = configurationFileFormat.GridSize;
UI.ApplicationSort.Value = configurationFileFormat.ApplicationSort;
UI.StartFullscreen.Value = configurationFileFormat.StartFullscreen;
UI.ShowConsole.Value = configurationFileFormat.ShowConsole;
UI.WindowStartup.WindowSizeWidth.Value = configurationFileFormat.WindowStartup.WindowSizeWidth;
UI.WindowStartup.WindowSizeHeight.Value = configurationFileFormat.WindowStartup.WindowSizeHeight;
UI.WindowStartup.WindowPositionX.Value = configurationFileFormat.WindowStartup.WindowPositionX;
UI.WindowStartup.WindowPositionY.Value = configurationFileFormat.WindowStartup.WindowPositionY;
UI.WindowStartup.WindowMaximized.Value = configurationFileFormat.WindowStartup.WindowMaximized;
Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard;
Hid.EnableMouse.Value = configurationFileFormat.EnableMouse;
Hid.Hotkeys.Value = configurationFileFormat.Hotkeys;
Hid.InputConfig.Value = configurationFileFormat.InputConfig ?? [];
Multiplayer.LanInterfaceId.Value = configurationFileFormat.MultiplayerLanInterfaceId;
Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode;
Multiplayer.DisableP2p.Value = configurationFileFormat.MultiplayerDisableP2p;
Multiplayer.LdnPassphrase.Value = configurationFileFormat.MultiplayerLdnPassphrase;
Multiplayer.LdnServer.Value = configurationFileFormat.LdnServer;
Hacks.ShowDirtyHacks.Value = configurationFileFormat.ShowDirtyHacks;
{
EnabledDirtyHack[] hacks = (configurationFileFormat.DirtyHacks ?? []).Select(EnabledDirtyHack.Unpack).ToArray();
Hacks.Xc2MenuSoftlockFix.Value = hacks.Any(it => it.Hack == DirtyHacks.Xc2MenuSoftlockFix);
var shaderCompilationThreadSleep = hacks.FirstOrDefault(it =>
it.Hack == DirtyHacks.ShaderCompilationThreadSleep);
Hacks.EnableShaderTranslationDelay.Value = shaderCompilationThreadSleep != null;
Hacks.ShaderTranslationDelay.Value = shaderCompilationThreadSleep?.Value ?? 0;
}
if (configurationFileUpdated)
{
ToFileFormat().SaveConfig(configurationFilePath);
Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}");
}
}
// This was accidentally enabled by default when it was PRed. That is not what we want,
// so as a compromise users who want to use it will simply need to re-enable it once after updating.
cff.IgnoreApplet = false;
})
);
}
}

View File

@@ -645,6 +645,9 @@ namespace Ryujinx.Ava.Utilities.Configuration
private void HackChanged(object sender, ReactiveEventArgs<bool> rxe)
{
if (!ShowDirtyHacks)
return;
var newHacks = EnabledHacks.Select(x => x.Hack)
.JoinToString(", ");
@@ -666,14 +669,14 @@ namespace Ryujinx.Ava.Utilities.Configuration
List<EnabledDirtyHack> enabledHacks = [];
if (Xc2MenuSoftlockFix)
Apply(DirtyHacks.Xc2MenuSoftlockFix);
Apply(DirtyHack.Xc2MenuSoftlockFix);
if (EnableShaderTranslationDelay)
Apply(DirtyHacks.ShaderCompilationThreadSleep, ShaderTranslationDelay);
Apply(DirtyHack.ShaderTranslationDelay, ShaderTranslationDelay);
return enabledHacks.ToArray();
void Apply(DirtyHacks hack, int value = 0)
void Apply(DirtyHack hack, int value = 0)
{
enabledHacks.Add(new EnabledDirtyHack(hack, value));
}