Compare commits
374 Commits
feature/av
...
c8b12ee3ec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8b12ee3ec | ||
|
|
4937b9ee7f | ||
|
|
1c6636d3cd | ||
|
|
e60b90fc47 | ||
|
|
cedc8e00df | ||
|
|
0ca4c03af4 | ||
|
|
7d86cb8d7f | ||
|
|
f58920b944 | ||
|
|
ca30248d97 | ||
|
|
6fed9b51b5 | ||
|
|
bb917a4aa4 | ||
|
|
7245193f08 | ||
|
|
2f0235fc37 | ||
|
|
04c0090653 | ||
|
|
d5502b02b1 | ||
|
|
691b0de6e1 | ||
|
|
b43ff78ba1 | ||
|
|
16eb005e8b | ||
|
|
ce23bff285 | ||
|
|
6b2bc16dc3 | ||
|
|
302ee73f34 | ||
|
|
6a46943af9 | ||
|
|
a968ec71fd | ||
|
|
d7c71c8a7b | ||
|
|
f06c869df1 | ||
|
|
8a579b64be | ||
|
|
e928ec9708 | ||
|
|
c7c80dc2fb | ||
|
|
fc581cf707 | ||
|
|
bdb00f3981 | ||
|
|
6e3aaa6360 | ||
|
|
fff3a4f8f8 | ||
|
|
01f41b8b0e | ||
|
|
080af8db24 | ||
|
|
29e6f17978 | ||
|
|
068a83bdfb | ||
|
|
8fa8f3a390 | ||
|
|
3360740250 | ||
|
|
c77f3b90a9 | ||
|
|
d5e19a70bd | ||
|
|
245778bc7e | ||
|
|
4cd15cb1a6 | ||
|
|
d9025904a7 | ||
|
|
47b99e6bc3 | ||
|
|
d07f6ed38e | ||
|
|
7490afbdc3 | ||
|
|
62b8d25315 | ||
|
|
911389db63 | ||
|
|
4f6860cfd4 | ||
|
|
e8dda2d5ef | ||
|
|
810b5792a8 | ||
|
|
1b9377023a | ||
|
|
29cca80d9f | ||
|
|
3214a4cf8e | ||
|
|
62602e58b7 | ||
|
|
997e8d11f7 | ||
|
|
42c6611563 | ||
|
|
3d12f7ef74 | ||
|
|
e42e4931a8 | ||
|
|
3a04d72686 | ||
|
|
aa6e87e8a6 | ||
|
|
b434cae2c2 | ||
|
|
2b919493e3 | ||
|
|
fdf7578928 | ||
|
|
558752594c | ||
|
|
a31e461db8 | ||
|
|
650f309b58 | ||
|
|
4e5cf38009 | ||
|
|
b44167d12a | ||
|
|
eb2dae561f | ||
|
|
1287098b8b | ||
|
|
9f2c99fcfa | ||
|
|
a6f5f2f82b | ||
|
|
655823ecc7 | ||
|
|
18a1741348 | ||
|
|
b734c81683 | ||
|
|
6e80cc6caa | ||
|
|
ea30e543e6 | ||
|
|
e3468d35b6 | ||
|
|
d22feff1d2 | ||
|
|
9d866ff282 | ||
|
|
fd0329f2eb | ||
|
|
468ab8242f | ||
|
|
7b9b23e500 | ||
|
|
0c1acb5107 | ||
|
|
8e8dcf0d7f | ||
|
|
9f0a468f55 | ||
|
|
ab79959975 | ||
|
|
de5bf3a141 | ||
|
|
5e8606c89a | ||
|
|
daee63c451 | ||
|
|
971c270bcf | ||
|
|
6aff6401fb | ||
|
|
6f6ccb7898 | ||
|
|
2511bf1e4c | ||
|
|
80f9a5d0da | ||
|
|
ed4f7a5602 | ||
|
|
edceb1607f | ||
|
|
e02df72323 | ||
|
|
9d26aa8d06 | ||
|
|
c8c4fd730d | ||
|
|
e27ade5aee | ||
|
|
b33c1ae22f | ||
|
|
242fcc2481 | ||
|
|
ef4a2fb3b5 | ||
|
|
c4731c0555 | ||
|
|
0c562a2c50 | ||
|
|
ab1e02c56a | ||
|
|
a264d9273d | ||
|
|
05189c7749 | ||
|
|
b7ddb693bc | ||
|
|
a60643620d | ||
|
|
113e721cce | ||
|
|
c8308d27f1 | ||
|
|
a71b5f1a3a | ||
|
|
b094d34575 | ||
|
|
4578ee53d3 | ||
|
|
72cbb41609 | ||
|
|
e7fab91c69 | ||
|
|
97a36298fa | ||
|
|
03161d8048 | ||
|
|
b1928461bb | ||
|
|
30b50a99e4 | ||
|
|
a638060dee | ||
|
|
49781fde65 | ||
|
|
84f3b4a3e1 | ||
|
|
2c511cdf4f | ||
|
|
17cfcf07d2 | ||
|
|
410287aba2 | ||
|
|
6ebe5bb406 | ||
|
|
02de48a6f2 | ||
|
|
58b3e2e82b | ||
|
|
d0946213fa | ||
|
|
66e2533c90 | ||
|
|
b821cb1739 | ||
|
|
122f0f45c8 | ||
|
|
9a6759d1e5 | ||
|
|
e97c9bc959 | ||
|
|
bc5df02d7d | ||
|
|
1c5937c40b | ||
|
|
4bb736d70a | ||
|
|
efb7baf15c | ||
|
|
fad653c12e | ||
|
|
bb4cb531f2 | ||
|
|
3c188718c4 | ||
|
|
362672ae12 | ||
|
|
970914e2b4 | ||
|
|
f7e97a30af | ||
|
|
aae9dc0c2e | ||
|
|
b0ba5d5da1 | ||
|
|
a6de2c9274 | ||
|
|
d323a8d44a | ||
|
|
ba07a8c603 | ||
|
|
362746887e | ||
|
|
b064d76a4f | ||
|
|
131ab75d55 | ||
|
|
65149cfe9f | ||
|
|
a435d94fae | ||
|
|
88dd2984be | ||
|
|
43460186a8 | ||
|
|
0a6f11d247 | ||
|
|
1b86360a61 | ||
|
|
dc01de61cd | ||
|
|
e423f81155 | ||
|
|
35f68c1b31 | ||
|
|
cb8fdeafbc | ||
|
|
1f29a76ea3 | ||
|
|
1f91c74a95 | ||
|
|
20b1f6a6ee | ||
|
|
8b7ac4e87f | ||
|
|
bbcd05aacf | ||
|
|
0e095c778a | ||
|
|
2833642858 | ||
|
|
f470430c2f | ||
|
|
051bd144e1 | ||
|
|
68f6c08287 | ||
|
|
704a78c11f | ||
|
|
acce02bdf5 | ||
|
|
8d7be4fe25 | ||
|
|
57a173a671 | ||
|
|
e6e898b297 | ||
|
|
7654f0b16c | ||
|
|
c26df1f7a3 | ||
|
|
41fb433495 | ||
|
|
1a0b928c35 | ||
|
|
17334b2131 | ||
|
|
be9f5dcf69 | ||
|
|
f08d6c1cad | ||
|
|
8eba42447f | ||
|
|
3ec45f73f4 | ||
|
|
b475a44941 | ||
|
|
295845e6e3 | ||
|
|
79acae3709 | ||
|
|
d423a53595 | ||
|
|
f4190bd95a | ||
|
|
997393bc65 | ||
|
|
937d84018e | ||
|
|
4bbf7b67d4 | ||
|
|
b1549be8c3 | ||
|
|
0d15f0fc90 | ||
|
|
20beb2e250 | ||
|
|
e1279f67fe | ||
|
|
bd3df5f26a | ||
|
|
8feee9c005 | ||
|
|
087bf71a13 | ||
|
|
3e1f624308 | ||
|
|
8b2cc4ccf1 | ||
|
|
1aa2b793eb | ||
|
|
6f44dcc416 | ||
|
|
bd14efb220 | ||
|
|
f5cffa0b46 | ||
|
|
979da4c1ab | ||
|
|
f08d3a7517 | ||
|
|
21029e895a | ||
|
|
bab9542020 | ||
|
|
f2490347af | ||
|
|
684e025d61 | ||
|
|
7983bc062b | ||
|
|
fe2337d61a | ||
|
|
e72c69cf19 | ||
|
|
9ecaacc977 | ||
|
|
d04e24c382 | ||
|
|
bb425bf640 | ||
|
|
0444e43654 | ||
|
|
ccce85e1bb | ||
|
|
348a37a355 | ||
|
|
918e1c16b7 | ||
|
|
2abadbd649 | ||
|
|
14c58f62eb | ||
|
|
102c87e623 | ||
|
|
a7e5c26011 | ||
|
|
20e1d1cd33 | ||
|
|
f98d9bae24 | ||
|
|
1db8decd12 | ||
|
|
71ccb7eaef | ||
|
|
e6c2e5873c | ||
|
|
c97e7d621b | ||
|
|
45b533b23b | ||
|
|
fbe275204b | ||
|
|
738227519d | ||
|
|
de86f20b94 | ||
|
|
fcc7cb55df | ||
|
|
4e6abb0191 | ||
|
|
35b0436a2b | ||
|
|
e99f9e2af0 | ||
|
|
bc3fd22f05 | ||
|
|
fefdabf257 | ||
|
|
73bb0712a8 | ||
|
|
75781ba698 | ||
|
|
262452f586 | ||
|
|
f56117a5c7 | ||
|
|
aff8fdb2f8 | ||
|
|
3651e8ea32 | ||
|
|
2d609ad57b | ||
|
|
559122f591 | ||
|
|
64005ba9ee | ||
|
|
a11247b72d | ||
|
|
320c317113 | ||
|
|
6295153a28 | ||
|
|
e638172753 | ||
|
|
32db6cc281 | ||
|
|
722aa4e45d | ||
|
|
00b99770a2 | ||
|
|
df6821d023 | ||
|
|
17aa3c6d0f | ||
|
|
5a320cca19 | ||
|
|
192a84aa2d | ||
|
|
ebc53d7961 | ||
|
|
4d063f80b8 | ||
|
|
316fea1fa9 | ||
|
|
a9db9f5b27 | ||
|
|
009f791879 | ||
|
|
c0bb55cf5e | ||
|
|
54c8dabadc | ||
|
|
04ca284e14 | ||
|
|
d58f79ae0f | ||
|
|
cd7d62542a | ||
|
|
72209ba2a6 | ||
|
|
70ba3506b0 | ||
|
|
35cc208435 | ||
|
|
8dca53685a | ||
|
|
e517cfeb8f | ||
|
|
4a30b58e0b | ||
|
|
bdd9ede4fd | ||
|
|
84a8edf675 | ||
|
|
e8a2637d46 | ||
|
|
e4a14dd23a | ||
|
|
ffb7423260 | ||
|
|
80340c98d3 | ||
|
|
b8c60e993a | ||
|
|
d88314424b | ||
|
|
df8fca012f | ||
|
|
3d897c4f9a | ||
|
|
62bf395970 | ||
|
|
bb742f64c6 | ||
|
|
a669592651 | ||
|
|
eb5fa2b546 | ||
|
|
8e99199e19 | ||
|
|
b439a52ac7 | ||
|
|
b9c4a23f22 | ||
|
|
64c95bd8d8 | ||
|
|
264742f085 | ||
|
|
64d12e8d23 | ||
|
|
a9e9819b33 | ||
|
|
a58d1cffe4 | ||
|
|
511db833db | ||
|
|
2890fc1069 | ||
|
|
7f41e7dbd4 | ||
|
|
c58cc76b39 | ||
|
|
8232ce7d72 | ||
|
|
db9de66437 | ||
|
|
5c9d1bd0da | ||
|
|
fb5402ce81 | ||
|
|
ed11cdda8d | ||
|
|
6017c225b2 | ||
|
|
98e2ab5a49 | ||
|
|
d5758cb310 | ||
|
|
81b1ae4bcf | ||
|
|
ce5f383f5d | ||
|
|
d2ec22a01b | ||
|
|
53b886d893 | ||
|
|
29ef76f153 | ||
|
|
a1b314acd2 | ||
|
|
5198fcb881 | ||
|
|
b37c109673 | ||
|
|
163be0a159 | ||
|
|
1f8ae7e5b1 | ||
|
|
bbc2ac2e9b | ||
|
|
f07327166c | ||
|
|
1790050a14 | ||
|
|
f2c090fe55 | ||
|
|
fd0eaaafc1 | ||
|
|
0233a0d35a | ||
|
|
61910fe342 | ||
|
|
1cb2ec7ebc | ||
|
|
4ec37d1798 | ||
|
|
27effab989 | ||
|
|
d0d5c76f06 | ||
|
|
a03471a8ab | ||
|
|
93c71110e1 | ||
|
|
00fce5a51d | ||
|
|
ce5f5a6442 | ||
|
|
541cdfebb7 | ||
|
|
07be20c369 | ||
|
|
aaa140e510 | ||
|
|
6d722d83ba | ||
|
|
6c3435aaac | ||
|
|
425177a876 | ||
|
|
e3da359acf | ||
|
|
96bbc86331 | ||
|
|
3d42543f03 | ||
|
|
0f52165e86 | ||
|
|
628772f685 | ||
|
|
118d10bc32 | ||
|
|
33a986317b | ||
|
|
7a2ab77b4d | ||
|
|
08126b26b1 | ||
|
|
abcd2b2754 | ||
|
|
d076a70816 | ||
|
|
28da4248ae | ||
|
|
f4aea9b7ec | ||
|
|
e269d1605d | ||
|
|
8b21447018 | ||
|
|
66d575965c | ||
|
|
4104af65a3 | ||
|
|
8da7c42cf8 | ||
|
|
da9a194023 | ||
|
|
5dd444f605 | ||
|
|
0f3358b931 | ||
|
|
177303d223 | ||
|
|
0eaee442c7 | ||
|
|
70f54f23c9 | ||
|
|
1e36815713 | ||
|
|
ebaf1d8258 |
@@ -258,13 +258,13 @@ Global
|
|||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}.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}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C08931FA-1191-417A-864F-3882D93E683B}.Debug|Any CPU.ActiveCfg = Debug|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}.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.ActiveCfg = Release|Any CPU
|
||||||
{C08931FA-1191-417A-864F-3882D93E683B}.Release|Any CPU.Build.0 = 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}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4A89A234-4F19-497D-A576-DDE8CDFC5B22}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ namespace Ryujinx.Common.Configuration
|
|||||||
[JsonConverter(typeof(TypedStringEnumConverter<GraphicsBackend>))]
|
[JsonConverter(typeof(TypedStringEnumConverter<GraphicsBackend>))]
|
||||||
public enum GraphicsBackend
|
public enum GraphicsBackend
|
||||||
{
|
{
|
||||||
Auto,
|
|
||||||
Vulkan,
|
Vulkan,
|
||||||
OpenGl,
|
OpenGl,
|
||||||
Metal
|
Metal
|
||||||
|
|||||||
@@ -838,7 +838,6 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
TargetApi.OpenGL => TargetLanguage.Glsl,
|
TargetApi.OpenGL => TargetLanguage.Glsl,
|
||||||
TargetApi.Vulkan => GraphicsConfig.EnableSpirvCompilationOnVulkan ? TargetLanguage.Spirv : TargetLanguage.Glsl,
|
TargetApi.Vulkan => GraphicsConfig.EnableSpirvCompilationOnVulkan ? TargetLanguage.Spirv : TargetLanguage.Glsl,
|
||||||
TargetApi.Metal => TargetLanguage.Msl,
|
TargetApi.Metal => TargetLanguage.Msl,
|
||||||
_ => throw new NotImplementedException()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return new TranslationOptions(lang, api, flags);
|
return new TranslationOptions(lang, api, flags);
|
||||||
|
|||||||
@@ -1767,7 +1767,6 @@ namespace Ryujinx.Graphics.Metal
|
|||||||
Constants.StorageBuffersSetIndex => Constants.StorageBuffersIndex,
|
Constants.StorageBuffersSetIndex => Constants.StorageBuffersIndex,
|
||||||
Constants.TexturesSetIndex => Constants.TexturesIndex,
|
Constants.TexturesSetIndex => Constants.TexturesIndex,
|
||||||
Constants.ImagesSetIndex => Constants.ImagesIndex,
|
Constants.ImagesSetIndex => Constants.ImagesIndex,
|
||||||
_ => throw new NotImplementedException()
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,13 +20,8 @@ namespace Ryujinx.Graphics.Metal
|
|||||||
|
|
||||||
private Pipeline _pipeline;
|
private Pipeline _pipeline;
|
||||||
private Window _window;
|
private Window _window;
|
||||||
|
|
||||||
public uint ProgramCount { get; set; }
|
|
||||||
|
|
||||||
#pragma warning disable CS0067 // The event is never used
|
|
||||||
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
|
public event EventHandler<ScreenCaptureImageInfo> ScreenCaptured;
|
||||||
#pragma warning restore CS0067
|
|
||||||
|
|
||||||
public bool PreferThreading => true;
|
public bool PreferThreading => true;
|
||||||
public IPipeline Pipeline => _pipeline;
|
public IPipeline Pipeline => _pipeline;
|
||||||
public IWindow Window => _window;
|
public IWindow Window => _window;
|
||||||
@@ -107,7 +102,6 @@ namespace Ryujinx.Graphics.Metal
|
|||||||
|
|
||||||
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
|
public IProgram CreateProgram(ShaderSource[] shaders, ShaderInfo info)
|
||||||
{
|
{
|
||||||
ProgramCount++;
|
|
||||||
return new Program(this, _device, shaders, info.ResourceLayout, info.ComputeLocalSize);
|
return new Program(this, _device, shaders, info.ResourceLayout, info.ComputeLocalSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -137,10 +137,10 @@ namespace Ryujinx.Graphics.Metal
|
|||||||
_requestedWidth = width;
|
_requestedWidth = width;
|
||||||
_requestedHeight = height;
|
_requestedHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ChangeVSyncMode(VSyncMode vSyncMode)
|
public void ChangeVSyncMode(bool vsyncEnabled)
|
||||||
{
|
{
|
||||||
//_vSyncMode = vSyncMode;
|
// _vsyncEnabled = vsyncEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAntiAliasing(AntiAliasing effect)
|
public void SetAntiAliasing(AntiAliasing effect)
|
||||||
|
|||||||
@@ -125,7 +125,6 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Msl.Instructions
|
|||||||
Instruction.Add => "PreciseFAdd",
|
Instruction.Add => "PreciseFAdd",
|
||||||
Instruction.Subtract => "PreciseFSub",
|
Instruction.Subtract => "PreciseFSub",
|
||||||
Instruction.Multiply => "PreciseFMul",
|
Instruction.Multiply => "PreciseFMul",
|
||||||
_ => throw new NotImplementedException()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return $"{func}({expr[0]}, {expr[1]})";
|
return $"{func}({expr[0]}, {expr[1]})";
|
||||||
|
|||||||
@@ -22,9 +22,8 @@ namespace Ryujinx.Headless.SDL2.Metal
|
|||||||
GraphicsDebugLevel glLogLevel,
|
GraphicsDebugLevel glLogLevel,
|
||||||
AspectRatio aspectRatio,
|
AspectRatio aspectRatio,
|
||||||
bool enableMouse,
|
bool enableMouse,
|
||||||
HideCursorMode hideCursorMode,
|
HideCursorMode hideCursorMode)
|
||||||
bool ignoreControllerApplet)
|
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode) { }
|
||||||
: base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode, ignoreControllerApplet) { }
|
|
||||||
|
|
||||||
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL;
|
public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL;
|
||||||
|
|
||||||
|
|||||||
755
src/Ryujinx.Headless.SDL2/Program.cs.orig
Normal file
755
src/Ryujinx.Headless.SDL2/Program.cs.orig
Normal file
@@ -0,0 +1,755 @@
|
|||||||
|
using CommandLine;
|
||||||
|
using LibHac.Tools.FsSystem;
|
||||||
|
using Ryujinx.Audio.Backends.SDL2;
|
||||||
|
using Ryujinx.Common;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
|
using Ryujinx.Common.Configuration.Hid;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
|
||||||
|
using Ryujinx.Common.Configuration.Hid.Keyboard;
|
||||||
|
using Ryujinx.Common.GraphicsDriver;
|
||||||
|
using Ryujinx.Common.Logging;
|
||||||
|
using Ryujinx.Common.Logging.Targets;
|
||||||
|
using Ryujinx.Common.SystemInterop;
|
||||||
|
using Ryujinx.Common.Utilities;
|
||||||
|
using Ryujinx.Cpu;
|
||||||
|
using Ryujinx.Graphics.GAL;
|
||||||
|
using Ryujinx.Graphics.GAL.Multithreading;
|
||||||
|
using Ryujinx.Graphics.Gpu;
|
||||||
|
using Ryujinx.Graphics.Gpu.Shader;
|
||||||
|
using Ryujinx.Graphics.Metal;
|
||||||
|
using Ryujinx.Graphics.OpenGL;
|
||||||
|
using Ryujinx.Graphics.Vulkan;
|
||||||
|
<<<<<<< HEAD
|
||||||
|
using Ryujinx.Graphics.Vulkan.MoltenVK;
|
||||||
|
using Ryujinx.Graphics.Metal;
|
||||||
|
=======
|
||||||
|
>>>>>>> 137f5970f (Vertex Input Attributes)
|
||||||
|
using Ryujinx.Headless.SDL2.Metal;
|
||||||
|
using Ryujinx.Headless.SDL2.OpenGL;
|
||||||
|
using Ryujinx.Headless.SDL2.Vulkan;
|
||||||
|
using Ryujinx.HLE;
|
||||||
|
using Ryujinx.HLE.FileSystem;
|
||||||
|
using Ryujinx.HLE.HOS;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||||
|
using Ryujinx.Input;
|
||||||
|
using Ryujinx.Input.HLE;
|
||||||
|
using Ryujinx.Input.SDL2;
|
||||||
|
using Ryujinx.SDL2.Common;
|
||||||
|
using Silk.NET.Vulkan;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading;
|
||||||
|
using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
|
||||||
|
using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||||
|
using Key = Ryujinx.Common.Configuration.Hid.Key;
|
||||||
|
|
||||||
|
namespace Ryujinx.Headless.SDL2
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
public static string Version { get; private set; }
|
||||||
|
|
||||||
|
private static VirtualFileSystem _virtualFileSystem;
|
||||||
|
private static ContentManager _contentManager;
|
||||||
|
private static AccountManager _accountManager;
|
||||||
|
private static LibHacHorizonManager _libHacHorizonManager;
|
||||||
|
private static UserChannelPersistence _userChannelPersistence;
|
||||||
|
private static InputManager _inputManager;
|
||||||
|
private static Switch _emulationContext;
|
||||||
|
private static WindowBase _window;
|
||||||
|
private static WindowsMultimediaTimerResolution _windowsMultimediaTimerResolution;
|
||||||
|
private static List<InputConfig> _inputConfiguration;
|
||||||
|
private static bool _enableKeyboard;
|
||||||
|
private static bool _enableMouse;
|
||||||
|
|
||||||
|
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Version = ReleaseInformation.Version;
|
||||||
|
|
||||||
|
// Make process DPI aware for proper window sizing on high-res screens.
|
||||||
|
ForceDpiAware.Windows();
|
||||||
|
|
||||||
|
Console.Title = $"Ryujinx Console {Version} (Headless SDL2)";
|
||||||
|
|
||||||
|
if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
|
||||||
|
{
|
||||||
|
AutoResetEvent invoked = new(false);
|
||||||
|
|
||||||
|
// MacOS must perform SDL polls from the main thread.
|
||||||
|
SDL2Driver.MainThreadDispatcher = action =>
|
||||||
|
{
|
||||||
|
invoked.Reset();
|
||||||
|
|
||||||
|
WindowBase.QueueMainThreadAction(() =>
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
|
||||||
|
invoked.Set();
|
||||||
|
});
|
||||||
|
|
||||||
|
invoked.WaitOne();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
MVKInitialization.InitializeResolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
Parser.Default.ParseArguments<Options>(args)
|
||||||
|
.WithParsed(Load)
|
||||||
|
.WithNotParsed(errors => errors.Output());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputConfig HandlePlayerConfiguration(string inputProfileName, string inputId, PlayerIndex index)
|
||||||
|
{
|
||||||
|
if (inputId == null)
|
||||||
|
{
|
||||||
|
if (index == PlayerIndex.Player1)
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"{index} not configured, defaulting to default keyboard.");
|
||||||
|
|
||||||
|
// Default to keyboard
|
||||||
|
inputId = "0";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"{index} not configured");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IGamepad gamepad;
|
||||||
|
|
||||||
|
bool isKeyboard = true;
|
||||||
|
|
||||||
|
gamepad = _inputManager.KeyboardDriver.GetGamepad(inputId);
|
||||||
|
|
||||||
|
if (gamepad == null)
|
||||||
|
{
|
||||||
|
gamepad = _inputManager.GamepadDriver.GetGamepad(inputId);
|
||||||
|
isKeyboard = false;
|
||||||
|
|
||||||
|
if (gamepad == null)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"{index} gamepad not found (\"{inputId}\")");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
string gamepadName = gamepad.Name;
|
||||||
|
|
||||||
|
gamepad.Dispose();
|
||||||
|
|
||||||
|
InputConfig config;
|
||||||
|
|
||||||
|
if (inputProfileName == null || inputProfileName.Equals("default"))
|
||||||
|
{
|
||||||
|
if (isKeyboard)
|
||||||
|
{
|
||||||
|
config = new StandardKeyboardInputConfig
|
||||||
|
{
|
||||||
|
Version = InputConfig.CurrentVersion,
|
||||||
|
Backend = InputBackendType.WindowKeyboard,
|
||||||
|
Id = null,
|
||||||
|
ControllerType = ControllerType.JoyconPair,
|
||||||
|
LeftJoycon = new LeftJoyconCommonConfig<Key>
|
||||||
|
{
|
||||||
|
DpadUp = Key.Up,
|
||||||
|
DpadDown = Key.Down,
|
||||||
|
DpadLeft = Key.Left,
|
||||||
|
DpadRight = Key.Right,
|
||||||
|
ButtonMinus = Key.Minus,
|
||||||
|
ButtonL = Key.E,
|
||||||
|
ButtonZl = Key.Q,
|
||||||
|
ButtonSl = Key.Unbound,
|
||||||
|
ButtonSr = Key.Unbound,
|
||||||
|
},
|
||||||
|
|
||||||
|
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||||
|
{
|
||||||
|
StickUp = Key.W,
|
||||||
|
StickDown = Key.S,
|
||||||
|
StickLeft = Key.A,
|
||||||
|
StickRight = Key.D,
|
||||||
|
StickButton = Key.F,
|
||||||
|
},
|
||||||
|
|
||||||
|
RightJoycon = new RightJoyconCommonConfig<Key>
|
||||||
|
{
|
||||||
|
ButtonA = Key.Z,
|
||||||
|
ButtonB = Key.X,
|
||||||
|
ButtonX = Key.C,
|
||||||
|
ButtonY = Key.V,
|
||||||
|
ButtonPlus = Key.Plus,
|
||||||
|
ButtonR = Key.U,
|
||||||
|
ButtonZr = Key.O,
|
||||||
|
ButtonSl = Key.Unbound,
|
||||||
|
ButtonSr = Key.Unbound,
|
||||||
|
},
|
||||||
|
|
||||||
|
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
|
||||||
|
{
|
||||||
|
StickUp = Key.I,
|
||||||
|
StickDown = Key.K,
|
||||||
|
StickLeft = Key.J,
|
||||||
|
StickRight = Key.L,
|
||||||
|
StickButton = Key.H,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool isNintendoStyle = gamepadName.Contains("Nintendo");
|
||||||
|
|
||||||
|
config = new StandardControllerInputConfig
|
||||||
|
{
|
||||||
|
Version = InputConfig.CurrentVersion,
|
||||||
|
Backend = InputBackendType.GamepadSDL2,
|
||||||
|
Id = null,
|
||||||
|
ControllerType = ControllerType.JoyconPair,
|
||||||
|
DeadzoneLeft = 0.1f,
|
||||||
|
DeadzoneRight = 0.1f,
|
||||||
|
RangeLeft = 1.0f,
|
||||||
|
RangeRight = 1.0f,
|
||||||
|
TriggerThreshold = 0.5f,
|
||||||
|
LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
|
||||||
|
{
|
||||||
|
DpadUp = ConfigGamepadInputId.DpadUp,
|
||||||
|
DpadDown = ConfigGamepadInputId.DpadDown,
|
||||||
|
DpadLeft = ConfigGamepadInputId.DpadLeft,
|
||||||
|
DpadRight = ConfigGamepadInputId.DpadRight,
|
||||||
|
ButtonMinus = ConfigGamepadInputId.Minus,
|
||||||
|
ButtonL = ConfigGamepadInputId.LeftShoulder,
|
||||||
|
ButtonZl = ConfigGamepadInputId.LeftTrigger,
|
||||||
|
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||||
|
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||||
|
},
|
||||||
|
|
||||||
|
LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||||
|
{
|
||||||
|
Joystick = ConfigStickInputId.Left,
|
||||||
|
StickButton = ConfigGamepadInputId.LeftStick,
|
||||||
|
InvertStickX = false,
|
||||||
|
InvertStickY = false,
|
||||||
|
Rotate90CW = false,
|
||||||
|
},
|
||||||
|
|
||||||
|
RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
|
||||||
|
{
|
||||||
|
ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
|
||||||
|
ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
|
||||||
|
ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
|
||||||
|
ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
|
||||||
|
ButtonPlus = ConfigGamepadInputId.Plus,
|
||||||
|
ButtonR = ConfigGamepadInputId.RightShoulder,
|
||||||
|
ButtonZr = ConfigGamepadInputId.RightTrigger,
|
||||||
|
ButtonSl = ConfigGamepadInputId.Unbound,
|
||||||
|
ButtonSr = ConfigGamepadInputId.Unbound,
|
||||||
|
},
|
||||||
|
|
||||||
|
RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
|
||||||
|
{
|
||||||
|
Joystick = ConfigStickInputId.Right,
|
||||||
|
StickButton = ConfigGamepadInputId.RightStick,
|
||||||
|
InvertStickX = false,
|
||||||
|
InvertStickY = false,
|
||||||
|
Rotate90CW = false,
|
||||||
|
},
|
||||||
|
|
||||||
|
Motion = new StandardMotionConfigController
|
||||||
|
{
|
||||||
|
MotionBackend = MotionInputBackendType.GamepadDriver,
|
||||||
|
EnableMotion = true,
|
||||||
|
Sensitivity = 100,
|
||||||
|
GyroDeadzone = 1,
|
||||||
|
},
|
||||||
|
Rumble = new RumbleConfigController
|
||||||
|
{
|
||||||
|
StrongRumble = 1f,
|
||||||
|
WeakRumble = 1f,
|
||||||
|
EnableRumble = false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string profileBasePath;
|
||||||
|
|
||||||
|
if (isKeyboard)
|
||||||
|
{
|
||||||
|
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "keyboard");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
profileBasePath = Path.Combine(AppDataManager.ProfilesDirPath, "controller");
|
||||||
|
}
|
||||||
|
|
||||||
|
string path = Path.Combine(profileBasePath, inputProfileName + ".json");
|
||||||
|
|
||||||
|
if (!File.Exists(path))
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" not found for \"{inputId}\"");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
config = JsonHelper.DeserializeFromFile(path, _serializerContext.InputConfig);
|
||||||
|
}
|
||||||
|
catch (JsonException)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, $"Input profile \"{inputProfileName}\" parsing failed for \"{inputId}\"");
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Id = inputId;
|
||||||
|
config.PlayerIndex = index;
|
||||||
|
|
||||||
|
string inputTypeName = isKeyboard ? "Keyboard" : "Gamepad";
|
||||||
|
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} configured with {inputTypeName} \"{config.Id}\"");
|
||||||
|
|
||||||
|
// If both stick ranges are 0 (usually indicative of an outdated profile load) then both sticks will be set to 1.0.
|
||||||
|
if (config is StandardControllerInputConfig controllerConfig)
|
||||||
|
{
|
||||||
|
if (controllerConfig.RangeLeft <= 0.0f && controllerConfig.RangeRight <= 0.0f)
|
||||||
|
{
|
||||||
|
controllerConfig.RangeLeft = 1.0f;
|
||||||
|
controllerConfig.RangeRight = 1.0f;
|
||||||
|
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"{config.PlayerIndex} stick range reset. Save the profile now to update your configuration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Load(Options option)
|
||||||
|
{
|
||||||
|
AppDataManager.Initialize(option.BaseDataDir);
|
||||||
|
|
||||||
|
_virtualFileSystem = VirtualFileSystem.CreateInstance();
|
||||||
|
_libHacHorizonManager = new LibHacHorizonManager();
|
||||||
|
|
||||||
|
_libHacHorizonManager.InitializeFsServer(_virtualFileSystem);
|
||||||
|
_libHacHorizonManager.InitializeArpServer();
|
||||||
|
_libHacHorizonManager.InitializeBcatServer();
|
||||||
|
_libHacHorizonManager.InitializeSystemClients();
|
||||||
|
|
||||||
|
_contentManager = new ContentManager(_virtualFileSystem);
|
||||||
|
_accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, option.UserProfile);
|
||||||
|
_userChannelPersistence = new UserChannelPersistence();
|
||||||
|
|
||||||
|
_inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver());
|
||||||
|
|
||||||
|
GraphicsConfig.EnableShaderCache = true;
|
||||||
|
|
||||||
|
if (OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
if (option.GraphicsBackend == GraphicsBackend.OpenGl)
|
||||||
|
{
|
||||||
|
option.GraphicsBackend = GraphicsBackend.Vulkan;
|
||||||
|
Logger.Warning?.Print(LogClass.Application, "OpenGL is not supported on macOS, switching to Vulkan!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IGamepad gamepad;
|
||||||
|
|
||||||
|
if (option.ListInputIds)
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Application, "Input Ids:");
|
||||||
|
|
||||||
|
foreach (string id in _inputManager.KeyboardDriver.GamepadsIds)
|
||||||
|
{
|
||||||
|
gamepad = _inputManager.KeyboardDriver.GetGamepad(id);
|
||||||
|
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
||||||
|
|
||||||
|
gamepad.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string id in _inputManager.GamepadDriver.GamepadsIds)
|
||||||
|
{
|
||||||
|
gamepad = _inputManager.GamepadDriver.GetGamepad(id);
|
||||||
|
|
||||||
|
Logger.Info?.Print(LogClass.Application, $"- {id} (\"{gamepad.Name}\")");
|
||||||
|
|
||||||
|
gamepad.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option.InputPath == null)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, "Please provide a file to load");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_inputConfiguration = new List<InputConfig>();
|
||||||
|
_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);
|
||||||
|
LoadPlayerConfiguration(option.InputProfile3Name, option.InputId3, PlayerIndex.Player3);
|
||||||
|
LoadPlayerConfiguration(option.InputProfile4Name, option.InputId4, PlayerIndex.Player4);
|
||||||
|
LoadPlayerConfiguration(option.InputProfile5Name, option.InputId5, PlayerIndex.Player5);
|
||||||
|
LoadPlayerConfiguration(option.InputProfile6Name, option.InputId6, PlayerIndex.Player6);
|
||||||
|
LoadPlayerConfiguration(option.InputProfile7Name, option.InputId7, PlayerIndex.Player7);
|
||||||
|
LoadPlayerConfiguration(option.InputProfile8Name, option.InputId8, PlayerIndex.Player8);
|
||||||
|
LoadPlayerConfiguration(option.InputProfileHandheldName, option.InputIdHandheld, PlayerIndex.Handheld);
|
||||||
|
|
||||||
|
if (_inputConfiguration.Count == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup logging level
|
||||||
|
Logger.SetEnable(LogLevel.Debug, option.LoggingEnableDebug);
|
||||||
|
Logger.SetEnable(LogLevel.Stub, !option.LoggingDisableStub);
|
||||||
|
Logger.SetEnable(LogLevel.Info, !option.LoggingDisableInfo);
|
||||||
|
Logger.SetEnable(LogLevel.Warning, !option.LoggingDisableWarning);
|
||||||
|
Logger.SetEnable(LogLevel.Error, option.LoggingEnableError);
|
||||||
|
Logger.SetEnable(LogLevel.Trace, option.LoggingEnableTrace);
|
||||||
|
Logger.SetEnable(LogLevel.Guest, !option.LoggingDisableGuest);
|
||||||
|
Logger.SetEnable(LogLevel.AccessLog, option.LoggingEnableFsAccessLog);
|
||||||
|
|
||||||
|
if (!option.DisableFileLog)
|
||||||
|
{
|
||||||
|
string logDir = AppDataManager.LogsDirPath;
|
||||||
|
FileStream logFile = null;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(logDir))
|
||||||
|
{
|
||||||
|
logFile = FileLogTarget.PrepareLogFile(logDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logFile != null)
|
||||||
|
{
|
||||||
|
Logger.AddTarget(new AsyncLogTargetWrapper(
|
||||||
|
new FileLogTarget("file", logFile),
|
||||||
|
1000,
|
||||||
|
AsyncLogTargetOverflowAction.Block
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the Logs directory, Application Data, or the Ryujinx directory is writable.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup graphics configuration
|
||||||
|
GraphicsConfig.EnableShaderCache = !option.DisableShaderCache;
|
||||||
|
GraphicsConfig.EnableTextureRecompression = option.EnableTextureRecompression;
|
||||||
|
GraphicsConfig.ResScale = option.ResScale;
|
||||||
|
GraphicsConfig.MaxAnisotropy = option.MaxAnisotropy;
|
||||||
|
GraphicsConfig.ShadersDumpPath = option.GraphicsShadersDumpPath;
|
||||||
|
GraphicsConfig.EnableMacroHLE = !option.DisableMacroHLE;
|
||||||
|
|
||||||
|
DriverUtilities.InitDriverConfig(option.BackendThreading == BackendThreading.Off);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
LoadApplication(option);
|
||||||
|
|
||||||
|
if (_userChannelPersistence.PreviousIndex == -1 || !_userChannelPersistence.ShouldRestart)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_userChannelPersistence.ShouldRestart = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_inputManager.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetupProgressHandler()
|
||||||
|
{
|
||||||
|
if (_emulationContext.Processes.ActiveApplication.DiskCacheLoadState != null)
|
||||||
|
{
|
||||||
|
_emulationContext.Processes.ActiveApplication.DiskCacheLoadState.StateChanged -= ProgressHandler;
|
||||||
|
_emulationContext.Processes.ActiveApplication.DiskCacheLoadState.StateChanged += ProgressHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
_emulationContext.Gpu.ShaderCacheStateChanged -= ProgressHandler;
|
||||||
|
_emulationContext.Gpu.ShaderCacheStateChanged += ProgressHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ProgressHandler<T>(T state, int current, int total) where T : Enum
|
||||||
|
{
|
||||||
|
string label = state switch
|
||||||
|
{
|
||||||
|
LoadState => $"PTC : {current}/{total}",
|
||||||
|
ShaderCacheState => $"Shaders : {current}/{total}",
|
||||||
|
_ => throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.Info?.Print(LogClass.Application, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WindowBase CreateWindow(Options options)
|
||||||
|
{
|
||||||
|
return options.GraphicsBackend switch
|
||||||
|
{
|
||||||
|
GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode),
|
||||||
|
GraphicsBackend.Metal => new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode),
|
||||||
|
_ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRenderer CreateRenderer(Options options, WindowBase window)
|
||||||
|
{
|
||||||
|
if (options.GraphicsBackend == GraphicsBackend.Vulkan && window is VulkanWindow vulkanWindow)
|
||||||
|
{
|
||||||
|
string preferredGpuId = string.Empty;
|
||||||
|
Vk api = Vk.GetApi();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(options.PreferredGPUVendor))
|
||||||
|
{
|
||||||
|
string preferredGpuVendor = options.PreferredGPUVendor.ToLowerInvariant();
|
||||||
|
var devices = VulkanRenderer.GetPhysicalDevices(api);
|
||||||
|
|
||||||
|
foreach (var device in devices)
|
||||||
|
{
|
||||||
|
if (device.Vendor.ToLowerInvariant() == preferredGpuVendor)
|
||||||
|
{
|
||||||
|
preferredGpuId = device.Id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new VulkanRenderer(
|
||||||
|
api,
|
||||||
|
(instance, vk) => new SurfaceKHR((ulong)(vulkanWindow.CreateWindowSurface(instance.Handle))),
|
||||||
|
vulkanWindow.GetRequiredInstanceExtensions,
|
||||||
|
preferredGpuId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.GraphicsBackend == GraphicsBackend.Metal && window is MetalWindow metalWindow && OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
return new MetalRenderer(metalWindow.GetLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OpenGLRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Switch InitializeEmulationContext(WindowBase window, IRenderer renderer, Options options)
|
||||||
|
{
|
||||||
|
BackendThreading threadingMode = options.BackendThreading;
|
||||||
|
|
||||||
|
bool threadedGAL = threadingMode == BackendThreading.On || (threadingMode == BackendThreading.Auto && renderer.PreferThreading);
|
||||||
|
|
||||||
|
if (threadedGAL)
|
||||||
|
{
|
||||||
|
renderer = new ThreadedRenderer(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
HLEConfiguration configuration = new(_virtualFileSystem,
|
||||||
|
_libHacHorizonManager,
|
||||||
|
_contentManager,
|
||||||
|
_accountManager,
|
||||||
|
_userChannelPersistence,
|
||||||
|
renderer,
|
||||||
|
new SDL2HardwareDeviceDriver(),
|
||||||
|
options.ExpandRAM ? MemoryConfiguration.MemoryConfiguration6GiB : MemoryConfiguration.MemoryConfiguration4GiB,
|
||||||
|
window,
|
||||||
|
options.SystemLanguage,
|
||||||
|
options.SystemRegion,
|
||||||
|
!options.DisableVSync,
|
||||||
|
!options.DisableDockedMode,
|
||||||
|
!options.DisablePTC,
|
||||||
|
options.EnableInternetAccess,
|
||||||
|
!options.DisableFsIntegrityChecks ? IntegrityCheckLevel.ErrorOnInvalid : IntegrityCheckLevel.None,
|
||||||
|
options.FsGlobalAccessLogMode,
|
||||||
|
options.SystemTimeOffset,
|
||||||
|
options.SystemTimeZone,
|
||||||
|
options.MemoryManagerMode,
|
||||||
|
options.IgnoreMissingServices,
|
||||||
|
options.AspectRatio,
|
||||||
|
options.AudioVolume,
|
||||||
|
options.UseHypervisor ?? true,
|
||||||
|
options.MultiplayerLanInterfaceId,
|
||||||
|
Common.Configuration.Multiplayer.MultiplayerMode.Disabled);
|
||||||
|
|
||||||
|
return new Switch(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ExecutionEntrypoint()
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
_windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
DisplaySleep.Prevent();
|
||||||
|
|
||||||
|
_window.Initialize(_emulationContext, _inputConfiguration, _enableKeyboard, _enableMouse);
|
||||||
|
|
||||||
|
_window.Execute();
|
||||||
|
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
_window.Dispose();
|
||||||
|
|
||||||
|
if (OperatingSystem.IsWindows())
|
||||||
|
{
|
||||||
|
_windowsMultimediaTimerResolution?.Dispose();
|
||||||
|
_windowsMultimediaTimerResolution = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool LoadApplication(Options options)
|
||||||
|
{
|
||||||
|
string path = options.InputPath;
|
||||||
|
|
||||||
|
Logger.RestartTime();
|
||||||
|
|
||||||
|
WindowBase window = CreateWindow(options);
|
||||||
|
IRenderer renderer = CreateRenderer(options, window);
|
||||||
|
|
||||||
|
_window = window;
|
||||||
|
|
||||||
|
_window.IsFullscreen = options.IsFullscreen;
|
||||||
|
_window.DisplayId = options.DisplayId;
|
||||||
|
_window.IsExclusiveFullscreen = options.IsExclusiveFullscreen;
|
||||||
|
_window.ExclusiveFullscreenWidth = options.ExclusiveFullscreenWidth;
|
||||||
|
_window.ExclusiveFullscreenHeight = options.ExclusiveFullscreenHeight;
|
||||||
|
_window.AntiAliasing = options.AntiAliasing;
|
||||||
|
_window.ScalingFilter = options.ScalingFilter;
|
||||||
|
_window.ScalingFilterLevel = options.ScalingFilterLevel;
|
||||||
|
|
||||||
|
_emulationContext = InitializeEmulationContext(window, renderer, options);
|
||||||
|
|
||||||
|
SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion();
|
||||||
|
|
||||||
|
Logger.Notice.Print(LogClass.Application, $"Using Firmware Version: {firmwareVersion?.VersionString}");
|
||||||
|
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
string[] romFsFiles = Directory.GetFiles(path, "*.istorage");
|
||||||
|
|
||||||
|
if (romFsFiles.Length == 0)
|
||||||
|
{
|
||||||
|
romFsFiles = Directory.GetFiles(path, "*.romfs");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (romFsFiles.Length > 0)
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Application, "Loading as cart with RomFS.");
|
||||||
|
|
||||||
|
if (!_emulationContext.LoadCart(path, romFsFiles[0]))
|
||||||
|
{
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Info?.Print(LogClass.Application, "Loading as cart WITHOUT RomFS.");
|
||||||
|
|
||||||
|
if (!_emulationContext.LoadCart(path))
|
||||||
|
{
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (File.Exists(path))
|
||||||
|
{
|
||||||
|
switch (Path.GetExtension(path).ToLowerInvariant())
|
||||||
|
{
|
||||||
|
case ".xci":
|
||||||
|
Logger.Info?.Print(LogClass.Application, "Loading as XCI.");
|
||||||
|
|
||||||
|
if (!_emulationContext.LoadXci(path))
|
||||||
|
{
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ".nca":
|
||||||
|
Logger.Info?.Print(LogClass.Application, "Loading as NCA.");
|
||||||
|
|
||||||
|
if (!_emulationContext.LoadNca(path))
|
||||||
|
{
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ".nsp":
|
||||||
|
case ".pfs0":
|
||||||
|
Logger.Info?.Print(LogClass.Application, "Loading as NSP.");
|
||||||
|
|
||||||
|
if (!_emulationContext.LoadNsp(path))
|
||||||
|
{
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Logger.Info?.Print(LogClass.Application, "Loading as Homebrew.");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_emulationContext.LoadProgram(path))
|
||||||
|
{
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
Logger.Error?.Print(LogClass.Application, "The specified file is not supported by Ryujinx.");
|
||||||
|
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger.Warning?.Print(LogClass.Application, $"Couldn't load '{options.InputPath}'. Please specify a valid XCI/NCA/NSP/PFS0/NRO file.");
|
||||||
|
|
||||||
|
_emulationContext.Dispose();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetupProgressHandler();
|
||||||
|
ExecutionEntrypoint();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -305,15 +305,14 @@ namespace Ryujinx.UI.Common.Configuration
|
|||||||
|
|
||||||
private static GraphicsBackend DefaultGraphicsBackend()
|
private static GraphicsBackend DefaultGraphicsBackend()
|
||||||
{
|
{
|
||||||
// Any system running macOS should default to auto, so it uses Vulkan everywhere and Metal in games where it works well.
|
// Any system running macOS or returning any amount of valid Vulkan devices should default to Vulkan.
|
||||||
if (OperatingSystem.IsMacOS())
|
|
||||||
return GraphicsBackend.Auto;
|
|
||||||
|
|
||||||
// Any system returning any amount of valid Vulkan devices should default to Vulkan.
|
|
||||||
// Checks for if the Vulkan version and featureset is compatible should be performed within VulkanRenderer.
|
// Checks for if the Vulkan version and featureset is compatible should be performed within VulkanRenderer.
|
||||||
return VulkanRenderer.GetPhysicalDevices().Length > 0
|
if (OperatingSystem.IsMacOS() || VulkanRenderer.GetPhysicalDevices().Length > 0)
|
||||||
? GraphicsBackend.Vulkan
|
{
|
||||||
: GraphicsBackend.OpenGl;
|
return GraphicsBackend.Vulkan;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GraphicsBackend.OpenGl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<Application
|
<Application
|
||||||
x:Class="Ryujinx.Ava.RyujinxApp"
|
x:Class="Ryujinx.Ava.App"
|
||||||
xmlns="https://github.com/avaloniaui"
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:sty="using:FluentAvalonia.Styling">
|
xmlns:sty="using:FluentAvalonia.Styling">
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Input.Platform;
|
|
||||||
using Avalonia.Markup.Xaml;
|
using Avalonia.Markup.Xaml;
|
||||||
using Avalonia.Platform;
|
using Avalonia.Platform;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
@@ -20,7 +19,7 @@ using System.Diagnostics;
|
|||||||
|
|
||||||
namespace Ryujinx.Ava
|
namespace Ryujinx.Ava
|
||||||
{
|
{
|
||||||
public class RyujinxApp : Application
|
public class App : Application
|
||||||
{
|
{
|
||||||
internal static string FormatTitle(LocaleKeys? windowTitleKey = null)
|
internal static string FormatTitle(LocaleKeys? windowTitleKey = null)
|
||||||
=> windowTitleKey is null
|
=> windowTitleKey is null
|
||||||
@@ -33,12 +32,6 @@ namespace Ryujinx.Ava
|
|||||||
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>()
|
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>()
|
||||||
.MainWindow.Cast<MainWindow>();
|
.MainWindow.Cast<MainWindow>();
|
||||||
|
|
||||||
public static bool IsClipboardAvailable(out IClipboard clipboard)
|
|
||||||
{
|
|
||||||
clipboard = MainWindow.Clipboard;
|
|
||||||
return clipboard != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void SetTaskbarProgress(TaskBarProgressBarState state) => MainWindow.PlatformFeatures.SetTaskBarProgressBarState(state);
|
public static void SetTaskbarProgress(TaskBarProgressBarState state) => MainWindow.PlatformFeatures.SetTaskBarProgressBarState(state);
|
||||||
public static void SetTaskbarProgressValue(ulong current, ulong total) => MainWindow.PlatformFeatures.SetTaskBarProgressBarValue(current, total);
|
public static void SetTaskbarProgressValue(ulong current, ulong total) => MainWindow.PlatformFeatures.SetTaskBarProgressBarValue(current, total);
|
||||||
public static void SetTaskbarProgressValue(long current, long total) => SetTaskbarProgressValue(Convert.ToUInt64(current), Convert.ToUInt64(total));
|
public static void SetTaskbarProgressValue(long current, long total) => SetTaskbarProgressValue(Convert.ToUInt64(current), Convert.ToUInt64(total));
|
||||||
@@ -98,9 +91,6 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private void ThemeChanged_Event(object _, ReactiveEventArgs<string> rArgs) => ApplyConfiguredTheme(rArgs.NewValue);
|
private void ThemeChanged_Event(object _, ReactiveEventArgs<string> rArgs) => ApplyConfiguredTheme(rArgs.NewValue);
|
||||||
|
|
||||||
|
|
||||||
public static readonly ThemeVariant AmoledThemeVariant = new("Amoled", ThemeVariant.Dark);
|
|
||||||
|
|
||||||
public void ApplyConfiguredTheme(string baseStyle)
|
public void ApplyConfiguredTheme(string baseStyle)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -119,7 +109,6 @@ namespace Ryujinx.Ava
|
|||||||
"Auto" => DetectSystemTheme(),
|
"Auto" => DetectSystemTheme(),
|
||||||
"Light" => ThemeVariant.Light,
|
"Light" => ThemeVariant.Light,
|
||||||
"Dark" => ThemeVariant.Dark,
|
"Dark" => ThemeVariant.Dark,
|
||||||
"AMOLED" => AmoledThemeVariant,
|
|
||||||
_ => ThemeVariant.Default,
|
_ => ThemeVariant.Default,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -143,7 +132,7 @@ namespace Ryujinx.Ava
|
|||||||
};
|
};
|
||||||
|
|
||||||
public static ThemeVariant DetectSystemTheme() =>
|
public static ThemeVariant DetectSystemTheme() =>
|
||||||
Current is RyujinxApp { PlatformSettings: not null } app
|
Current is App { PlatformSettings: not null } app
|
||||||
? ConvertThemeVariant(app.PlatformSettings.GetColorValues().ThemeVariant)
|
? ConvertThemeVariant(app.PlatformSettings.GetColorValues().ThemeVariant)
|
||||||
: ThemeVariant.Default;
|
: ThemeVariant.Default;
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,6 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Controls.ApplicationLifetimes;
|
using Avalonia.Controls.ApplicationLifetimes;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Gommon;
|
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Ns;
|
using LibHac.Ns;
|
||||||
using LibHac.Tools.FsSystem;
|
using LibHac.Tools.FsSystem;
|
||||||
@@ -143,23 +142,6 @@ namespace Ryujinx.Ava
|
|||||||
public ulong ApplicationId { get; private set; }
|
public ulong ApplicationId { get; private set; }
|
||||||
public bool ScreenshotRequested { get; set; }
|
public bool ScreenshotRequested { get; set; }
|
||||||
|
|
||||||
public bool ShouldInitMetal
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64 &&
|
|
||||||
(
|
|
||||||
(
|
|
||||||
(
|
|
||||||
ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Auto &&
|
|
||||||
RendererHost.KnownGreatMetalTitles.ContainsIgnoreCase(ApplicationId.ToString("X16"))
|
|
||||||
) ||
|
|
||||||
ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Metal
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public AppHost(
|
public AppHost(
|
||||||
RendererHost renderer,
|
RendererHost renderer,
|
||||||
InputManager inputManager,
|
InputManager inputManager,
|
||||||
@@ -913,22 +895,18 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
// Initialize Renderer.
|
// Initialize Renderer.
|
||||||
IRenderer renderer;
|
IRenderer renderer;
|
||||||
GraphicsBackend backend = ConfigurationState.Instance.Graphics.GraphicsBackend;
|
|
||||||
|
|
||||||
if (ShouldInitMetal)
|
if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan)
|
||||||
{
|
{
|
||||||
#pragma warning disable CA1416 // This call site is reachable on all platforms
|
renderer = new VulkanRenderer(
|
||||||
// The condition does a check for Mac, on top of checking if it's an ARM Mac. This isn't a problem.
|
|
||||||
renderer = new MetalRenderer((RendererHost.EmbeddedWindow as EmbeddedWindowMetal)!.CreateSurface);
|
|
||||||
#pragma warning restore CA1416
|
|
||||||
}
|
|
||||||
else if (backend == GraphicsBackend.Vulkan || (backend == GraphicsBackend.Auto && !ShouldInitMetal))
|
|
||||||
{
|
|
||||||
renderer = VulkanRenderer.Create(
|
|
||||||
ConfigurationState.Instance.Graphics.PreferredGpu,
|
ConfigurationState.Instance.Graphics.PreferredGpu,
|
||||||
(RendererHost.EmbeddedWindow as EmbeddedWindowVulkan)!.CreateSurface,
|
(RendererHost.EmbeddedWindow as EmbeddedWindowVulkan)!.CreateSurface,
|
||||||
VulkanHelper.GetRequiredInstanceExtensions);
|
VulkanHelper.GetRequiredInstanceExtensions);
|
||||||
}
|
}
|
||||||
|
else if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Metal && OperatingSystem.IsMacOS())
|
||||||
|
{
|
||||||
|
renderer = new MetalRenderer((RendererHost.EmbeddedWindow as EmbeddedWindowMetal).CreateSurface);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
renderer = new OpenGLRenderer();
|
renderer = new OpenGLRenderer();
|
||||||
@@ -1145,7 +1123,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
public void InitStatus()
|
public void InitStatus()
|
||||||
{
|
{
|
||||||
_viewModel.BackendText = RendererHost.Backend switch
|
_viewModel.BackendText = ConfigurationState.Instance.Graphics.GraphicsBackend.Value switch
|
||||||
{
|
{
|
||||||
GraphicsBackend.Vulkan => "Vulkan",
|
GraphicsBackend.Vulkan => "Vulkan",
|
||||||
GraphicsBackend.OpenGl => "OpenGL",
|
GraphicsBackend.OpenGl => "OpenGL",
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
xmlns:ryu="clr-namespace:Ryujinx.Ava">
|
|
||||||
<ResourceDictionary.ThemeDictionaries>
|
<ResourceDictionary.ThemeDictionaries>
|
||||||
<ResourceDictionary x:Key="Default">
|
<ResourceDictionary x:Key="Default">
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
||||||
@@ -53,22 +52,5 @@
|
|||||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
<Color x:Key="Unbounded">#FFFF4554</Color>
|
||||||
<Color x:Key="Custom">#6483F5</Color>
|
<Color x:Key="Custom">#6483F5</Color>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
<ResourceDictionary x:Key="{x:Static ryu:RyujinxApp.AmoledThemeVariant}">
|
|
||||||
<SolidColorBrush x:Key="DataGridSelectionBackgroundBrush"
|
|
||||||
Color="{DynamicResource DataGridSelectionColor}" />
|
|
||||||
<Color x:Key="ControlFillColorSecondary">#008AA8</Color>
|
|
||||||
<Color x:Key="DataGridSelectionColor">#FF00FABB</Color>
|
|
||||||
<Color x:Key="ThemeContentBackgroundColor">#FF000000</Color>
|
|
||||||
<Color x:Key="ThemeControlBorderColor">#2D000000</Color>
|
|
||||||
<Color x:Key="ThemeForegroundColor">#FFFFFFFF</Color>
|
|
||||||
<Color x:Key="MenuFlyoutPresenterBorderColor">#79000000</Color>
|
|
||||||
<Color x:Key="AppListBackgroundColor">#50000000</Color>
|
|
||||||
<Color x:Key="AppListHoverBackgroundColor">#40000000</Color>
|
|
||||||
<Color x:Key="SecondaryTextColor">#A0FFFFFF</Color>
|
|
||||||
<Color x:Key="FavoriteApplicationIconColor">#fffcd12a</Color>
|
|
||||||
<Color x:Key="Switch">#FF2EEAC9</Color>
|
|
||||||
<Color x:Key="Unbounded">#FFFF4554</Color>
|
|
||||||
<Color x:Key="Custom">#6483F5</Color>
|
|
||||||
</ResourceDictionary>
|
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -19677,54 +19677,6 @@
|
|||||||
"zh_TW": "選擇模擬器將使用的圖形後端。\n\n只要驅動程式是最新的,Vulkan 對所有現代顯示卡來說都更好用。Vulkan 還能在所有 GPU 廠商上實現更快的著色器編譯 (減少卡頓)。\n\nOpenGL 在舊式 Nvidia GPU、Linux 上的舊式 AMD GPU 或 VRAM 較低的 GPU 上可能會取得更好的效果,不過著色器編譯的卡頓會更嚴重。\n\n如果不確定,請設定為 Vulkan。如果您的 GPU 使用最新的圖形驅動程式也不支援 Vulkan,請設定為 OpenGL。"
|
"zh_TW": "選擇模擬器將使用的圖形後端。\n\n只要驅動程式是最新的,Vulkan 對所有現代顯示卡來說都更好用。Vulkan 還能在所有 GPU 廠商上實現更快的著色器編譯 (減少卡頓)。\n\nOpenGL 在舊式 Nvidia GPU、Linux 上的舊式 AMD GPU 或 VRAM 較低的 GPU 上可能會取得更好的效果,不過著色器編譯的卡頓會更嚴重。\n\n如果不確定,請設定為 Vulkan。如果您的 GPU 使用最新的圖形驅動程式也不支援 Vulkan,請設定為 OpenGL。"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ID": "SettingsTabGraphicsBackendAuto",
|
|
||||||
"Translations": {
|
|
||||||
"ar_SA": "",
|
|
||||||
"de_DE": "",
|
|
||||||
"el_GR": "",
|
|
||||||
"en_US": "Auto",
|
|
||||||
"es_ES": "",
|
|
||||||
"fr_FR": "",
|
|
||||||
"he_IL": "",
|
|
||||||
"it_IT": "",
|
|
||||||
"ja_JP": "",
|
|
||||||
"ko_KR": "",
|
|
||||||
"no_NO": "",
|
|
||||||
"pl_PL": "",
|
|
||||||
"pt_BR": "",
|
|
||||||
"ru_RU": "",
|
|
||||||
"th_TH": "",
|
|
||||||
"tr_TR": "",
|
|
||||||
"uk_UA": "",
|
|
||||||
"zh_CN": "",
|
|
||||||
"zh_TW": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"ID": "SettingsTabGraphicsBackendAutoTooltip",
|
|
||||||
"Translations": {
|
|
||||||
"ar_SA": "",
|
|
||||||
"de_DE": "",
|
|
||||||
"el_GR": "",
|
|
||||||
"en_US": "Uses Vulkan.\nOn an ARM Mac, and when playing a game that runs well under it, uses the Metal backend.",
|
|
||||||
"es_ES": "",
|
|
||||||
"fr_FR": "",
|
|
||||||
"he_IL": "",
|
|
||||||
"it_IT": "",
|
|
||||||
"ja_JP": "",
|
|
||||||
"ko_KR": "",
|
|
||||||
"no_NO": "",
|
|
||||||
"pl_PL": "",
|
|
||||||
"pt_BR": "",
|
|
||||||
"ru_RU": "",
|
|
||||||
"th_TH": "",
|
|
||||||
"tr_TR": "",
|
|
||||||
"uk_UA": "",
|
|
||||||
"zh_CN": "",
|
|
||||||
"zh_TW": ""
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ID": "SettingsEnableTextureRecompression",
|
"ID": "SettingsEnableTextureRecompression",
|
||||||
"Translations": {
|
"Translations": {
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ namespace Ryujinx.Ava.Common
|
|||||||
var cancellationToken = new CancellationTokenSource();
|
var cancellationToken = new CancellationTokenSource();
|
||||||
|
|
||||||
UpdateWaitWindow waitingDialog = new(
|
UpdateWaitWindow waitingDialog = new(
|
||||||
RyujinxApp.FormatTitle(LocaleKeys.DialogNcaExtractionTitle),
|
App.FormatTitle(LocaleKeys.DialogNcaExtractionTitle),
|
||||||
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogNcaExtractionMessage, ncaSectionType, Path.GetFileName(titleFilePath)),
|
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogNcaExtractionMessage, ncaSectionType, Path.GetFileName(titleFilePath)),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
||||||
@@ -268,9 +268,10 @@ namespace Ryujinx.Ava.Common
|
|||||||
{
|
{
|
||||||
Dispatcher.UIThread.Post(waitingDialog.Close);
|
Dispatcher.UIThread.Post(waitingDialog.Close);
|
||||||
|
|
||||||
NotificationHelper.ShowInformation(
|
NotificationHelper.Show(
|
||||||
RyujinxApp.FormatTitle(LocaleKeys.DialogNcaExtractionTitle),
|
App.FormatTitle(LocaleKeys.DialogNcaExtractionTitle),
|
||||||
$"{titleName}\n\n{LocaleManager.Instance[LocaleKeys.DialogNcaExtractionSuccessMessage]}");
|
$"{titleName}\n\n{LocaleManager.Instance[LocaleKeys.DialogNcaExtractionSuccessMessage]}",
|
||||||
|
NotificationType.Information);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ namespace Ryujinx.Ava
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static AppBuilder BuildAvaloniaApp() =>
|
public static AppBuilder BuildAvaloniaApp() =>
|
||||||
AppBuilder.Configure<RyujinxApp>()
|
AppBuilder.Configure<App>()
|
||||||
.UsePlatformDetect()
|
.UsePlatformDetect()
|
||||||
.With(new X11PlatformOptions
|
.With(new X11PlatformOptions
|
||||||
{
|
{
|
||||||
@@ -100,7 +100,7 @@ namespace Ryujinx.Ava
|
|||||||
// Delete backup files after updating.
|
// Delete backup files after updating.
|
||||||
Task.Run(Updater.CleanupUpdate);
|
Task.Run(Updater.CleanupUpdate);
|
||||||
|
|
||||||
Console.Title = $"{RyujinxApp.FullAppName} Console {Version}";
|
Console.Title = $"{App.FullAppName} Console {Version}";
|
||||||
|
|
||||||
// Hook unhandled exception and process exit events.
|
// Hook unhandled exception and process exit events.
|
||||||
AppDomain.CurrentDomain.UnhandledException += (sender, e)
|
AppDomain.CurrentDomain.UnhandledException += (sender, e)
|
||||||
@@ -225,7 +225,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
private static void PrintSystemInfo()
|
private static void PrintSystemInfo()
|
||||||
{
|
{
|
||||||
Logger.Notice.Print(LogClass.Application, $"{RyujinxApp.FullAppName} Version: {Version}");
|
Logger.Notice.Print(LogClass.Application, $"{App.FullAppName} Version: {Version}");
|
||||||
SystemInfo.Gather().Print();
|
SystemInfo.Gather().Print();
|
||||||
|
|
||||||
var enabledLogLevels = Logger.GetEnabledLevels().ToArray();
|
var enabledLogLevels = Logger.GetEnabledLevels().ToArray();
|
||||||
|
|||||||
@@ -55,7 +55,6 @@
|
|||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
ClipToBounds="True"
|
ClipToBounds="True"
|
||||||
Background="{DynamicResource ThemeControlBorderColor}"
|
|
||||||
CornerRadius="5">
|
CornerRadius="5">
|
||||||
<Grid ColumnDefinitions="Auto,10,*,150,100">
|
<Grid ColumnDefinitions="Auto,10,*,150,100">
|
||||||
<Image
|
<Image
|
||||||
@@ -102,22 +101,11 @@
|
|||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
Spacing="5">
|
Spacing="5">
|
||||||
<Button
|
<TextBlock
|
||||||
Click="IdString_OnClick"
|
HorizontalAlignment="Stretch"
|
||||||
HorizontalContentAlignment="Left"
|
Text="{Binding IdString}"
|
||||||
VerticalAlignment="Center"
|
TextAlignment="Start"
|
||||||
|
TextWrapping="Wrap" />
|
||||||
Background="{DynamicResource AppListBackgroundColor}"
|
|
||||||
Margin="-1, 0, 0, 0"
|
|
||||||
Padding="0" >
|
|
||||||
<TextBlock
|
|
||||||
Margin="1.5"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
Text="{Binding IdString}"
|
|
||||||
Tag="{Binding Id}"
|
|
||||||
TextAlignment="Start"
|
|
||||||
TextWrapping="Wrap" />
|
|
||||||
</Button>
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Text="{Binding FileExtension}"
|
Text="{Binding FileExtension}"
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Notifications;
|
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using FluentAvalonia.UI.Controls;
|
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.UI.App.Common;
|
using Ryujinx.UI.App.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Controls
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
{
|
{
|
||||||
@@ -35,27 +32,5 @@ namespace Ryujinx.Ava.UI.Controls
|
|||||||
if (DataContext is MainWindowViewModel viewModel && sender is ListBox { SelectedItem: ApplicationData selected })
|
if (DataContext is MainWindowViewModel viewModel && sender is ListBox { SelectedItem: ApplicationData selected })
|
||||||
viewModel.ListSelectedApplication = selected;
|
viewModel.ListSelectedApplication = selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void IdString_OnClick(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
if (DataContext is not MainWindowViewModel mwvm)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (sender is not Button { Content: TextBlock idText })
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!RyujinxApp.IsClipboardAvailable(out var clipboard))
|
|
||||||
return;
|
|
||||||
|
|
||||||
var appData = mwvm.Applications.FirstOrDefault(it => it.IdString == idText.Text);
|
|
||||||
if (appData is null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
await clipboard.SetTextAsync(appData.IdString);
|
|
||||||
|
|
||||||
NotificationHelper.ShowInformation(
|
|
||||||
"Copied Title ID",
|
|
||||||
$"{appData.Name} ({appData.IdString})");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,46 +62,9 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||||||
_notifications.Add(new Notification(title, text, type, delay, onClick, onClose));
|
_notifications.Add(new Notification(title, text, type, delay, onClick, onClose));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ShowError(string message) =>
|
public static void ShowError(string message)
|
||||||
ShowError(
|
{
|
||||||
LocaleManager.Instance[LocaleKeys.DialogErrorTitle],
|
Show(LocaleManager.Instance[LocaleKeys.DialogErrorTitle], $"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}", NotificationType.Error);
|
||||||
$"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}"
|
}
|
||||||
);
|
|
||||||
|
|
||||||
public static void ShowInformation(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
|
|
||||||
Show(
|
|
||||||
title,
|
|
||||||
text,
|
|
||||||
NotificationType.Information,
|
|
||||||
waitingExit,
|
|
||||||
onClick,
|
|
||||||
onClose);
|
|
||||||
|
|
||||||
public static void ShowSuccess(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
|
|
||||||
Show(
|
|
||||||
title,
|
|
||||||
text,
|
|
||||||
NotificationType.Success,
|
|
||||||
waitingExit,
|
|
||||||
onClick,
|
|
||||||
onClose);
|
|
||||||
|
|
||||||
public static void ShowWarning(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
|
|
||||||
Show(
|
|
||||||
title,
|
|
||||||
text,
|
|
||||||
NotificationType.Warning,
|
|
||||||
waitingExit,
|
|
||||||
onClick,
|
|
||||||
onClose);
|
|
||||||
|
|
||||||
public static void ShowError(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
|
|
||||||
Show(
|
|
||||||
title,
|
|
||||||
text,
|
|
||||||
NotificationType.Error,
|
|
||||||
waitingExit,
|
|
||||||
onClick,
|
|
||||||
onClose);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Gommon;
|
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Ava.UI.Renderer
|
namespace Ryujinx.Ava.UI.Renderer
|
||||||
{
|
{
|
||||||
@@ -24,70 +21,13 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||||||
{
|
{
|
||||||
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
|
GraphicsBackend.OpenGl => new EmbeddedWindowOpenGL(),
|
||||||
GraphicsBackend.Metal => new EmbeddedWindowMetal(),
|
GraphicsBackend.Metal => new EmbeddedWindowMetal(),
|
||||||
GraphicsBackend.Vulkan or GraphicsBackend.Auto => new EmbeddedWindowVulkan(),
|
GraphicsBackend.Vulkan => new EmbeddedWindowVulkan(),
|
||||||
_ => throw new NotSupportedException()
|
_ => throw new NotSupportedException()
|
||||||
};
|
};
|
||||||
|
|
||||||
Initialize();
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly string[] KnownGreatMetalTitles =
|
|
||||||
[
|
|
||||||
"01006A800016E000", // Smash Ultimate
|
|
||||||
"0100000000010000", // Super Mario Odyessy
|
|
||||||
"01008C0016544000", // Sea of Stars
|
|
||||||
"01005CA01580E000", // Persona 5
|
|
||||||
"010028600EBDA000", // Mario 3D World
|
|
||||||
];
|
|
||||||
|
|
||||||
public GraphicsBackend Backend =>
|
|
||||||
EmbeddedWindow switch
|
|
||||||
{
|
|
||||||
EmbeddedWindowVulkan => GraphicsBackend.Vulkan,
|
|
||||||
EmbeddedWindowOpenGL => GraphicsBackend.OpenGl,
|
|
||||||
EmbeddedWindowMetal => GraphicsBackend.Metal,
|
|
||||||
_ => throw new NotImplementedException()
|
|
||||||
};
|
|
||||||
|
|
||||||
public RendererHost(string titleId)
|
|
||||||
{
|
|
||||||
InitializeComponent();
|
|
||||||
|
|
||||||
switch (ConfigurationState.Instance.Graphics.GraphicsBackend.Value)
|
|
||||||
{
|
|
||||||
case GraphicsBackend.Auto:
|
|
||||||
EmbeddedWindow =
|
|
||||||
OperatingSystem.IsMacOS() &&
|
|
||||||
RuntimeInformation.ProcessArchitecture == Architecture.Arm64 &&
|
|
||||||
KnownGreatMetalTitles.ContainsIgnoreCase(titleId)
|
|
||||||
? new EmbeddedWindowMetal()
|
|
||||||
: new EmbeddedWindowVulkan();
|
|
||||||
break;
|
|
||||||
case GraphicsBackend.OpenGl:
|
|
||||||
EmbeddedWindow = new EmbeddedWindowOpenGL();
|
|
||||||
break;
|
|
||||||
case GraphicsBackend.Metal:
|
|
||||||
EmbeddedWindow = new EmbeddedWindowMetal();
|
|
||||||
break;
|
|
||||||
case GraphicsBackend.Vulkan:
|
|
||||||
EmbeddedWindow = new EmbeddedWindowVulkan();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
string backendText = EmbeddedWindow switch
|
|
||||||
{
|
|
||||||
EmbeddedWindowVulkan => "Vulkan",
|
|
||||||
EmbeddedWindowOpenGL => "OpenGL",
|
|
||||||
EmbeddedWindowMetal => "Metal",
|
|
||||||
_ => throw new NotImplementedException()
|
|
||||||
};
|
|
||||||
|
|
||||||
Logger.Info?.PrintMsg(LogClass.Gpu, $"Backend ({ConfigurationState.Instance.Graphics.GraphicsBackend.Value}): {backendText}");
|
|
||||||
|
|
||||||
Initialize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void Initialize()
|
private void Initialize()
|
||||||
{
|
{
|
||||||
EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated;
|
EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
public AboutWindowViewModel()
|
public AboutWindowViewModel()
|
||||||
{
|
{
|
||||||
Version = RyujinxApp.FullAppName + "\n" + Program.Version;
|
Version = App.FullAppName + "\n" + Program.Version;
|
||||||
UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value);
|
UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value);
|
||||||
|
|
||||||
ThemeManager.ThemeChanged += ThemeManager_ThemeChanged;
|
ThemeManager.ThemeChanged += ThemeManager_ThemeChanged;
|
||||||
@@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
private void UpdateLogoTheme(string theme)
|
private void UpdateLogoTheme(string theme)
|
||||||
{
|
{
|
||||||
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
|
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && App.DetectSystemTheme() == ThemeVariant.Dark);
|
||||||
|
|
||||||
string basePath = "resm:Ryujinx.UI.Common.Resources.";
|
string basePath = "resm:Ryujinx.UI.Common.Resources.";
|
||||||
string themeSuffix = isDarkTheme ? "Dark.png" : "Light.png";
|
string themeSuffix = isDarkTheme ? "Dark.png" : "Light.png";
|
||||||
|
|||||||
@@ -1938,7 +1938,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
PrepareLoadScreen();
|
PrepareLoadScreen();
|
||||||
|
|
||||||
RendererHostControl = new RendererHost(application.Id.ToString("X16"));
|
RendererHostControl = new RendererHost();
|
||||||
|
|
||||||
AppHost = new AppHost(
|
AppHost = new AppHost(
|
||||||
RendererHostControl,
|
RendererHostControl,
|
||||||
@@ -2051,7 +2051,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
Dispatcher.UIThread.InvokeAsync(() =>
|
Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
Title = RyujinxApp.FormatTitle();
|
Title = App.FormatTitle();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,9 +120,11 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsMetalAvailable => OperatingSystem.IsMacOS();
|
||||||
|
|
||||||
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
||||||
|
|
||||||
public bool IsAppleSiliconMac => OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
|
public bool IsHypervisorAvailable => OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
|
||||||
|
|
||||||
public bool GameDirectoryChanged
|
public bool GameDirectoryChanged
|
||||||
{
|
{
|
||||||
@@ -252,8 +254,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
public bool IsCustomResolutionScaleActive => _resolutionScale == 4;
|
public bool IsCustomResolutionScaleActive => _resolutionScale == 4;
|
||||||
public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr;
|
public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr;
|
||||||
|
|
||||||
public bool IsVulkanSelected =>
|
public bool IsVulkanSelected => GraphicsBackendIndex == 0;
|
||||||
GraphicsBackendIndex == 1 || (GraphicsBackendIndex == 0 && !OperatingSystem.IsMacOS());
|
|
||||||
public bool UseHypervisor { get; set; }
|
public bool UseHypervisor { get; set; }
|
||||||
public bool DisableP2P { get; set; }
|
public bool DisableP2P { get; set; }
|
||||||
|
|
||||||
@@ -433,7 +434,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
if (devices.Length == 0)
|
if (devices.Length == 0)
|
||||||
{
|
{
|
||||||
IsVulkanAvailable = false;
|
IsVulkanAvailable = false;
|
||||||
GraphicsBackendIndex = 2;
|
GraphicsBackendIndex = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -547,7 +548,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
"Auto" => 0,
|
"Auto" => 0,
|
||||||
"Light" => 1,
|
"Light" => 1,
|
||||||
"Dark" => 2,
|
"Dark" => 2,
|
||||||
"AMOLED" => 3,
|
|
||||||
_ => 0
|
_ => 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -657,7 +657,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
0 => "Auto",
|
0 => "Auto",
|
||||||
1 => "Light",
|
1 => "Light",
|
||||||
2 => "Dark",
|
2 => "Dark",
|
||||||
3 => "AMOLED",
|
|
||||||
_ => "Auto"
|
_ => "Auto"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
</ComboBox>
|
</ComboBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<CheckBox IsChecked="{Binding UseHypervisor}"
|
<CheckBox IsChecked="{Binding UseHypervisor}"
|
||||||
IsVisible="{Binding IsAppleSiliconMac}"
|
IsVisible="{Binding IsHypervisorAvailable}"
|
||||||
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}">
|
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}">
|
||||||
<TextBlock Text="{ext:Locale SettingsTabSystemUseHypervisor}"
|
<TextBlock Text="{ext:Locale SettingsTabSystemUseHypervisor}"
|
||||||
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" />
|
ToolTip.Tip="{ext:Locale UseHypervisorTooltip}" />
|
||||||
|
|||||||
@@ -33,23 +33,18 @@
|
|||||||
ToolTip.Tip="{ext:Locale SettingsTabGraphicsBackendTooltip}"
|
ToolTip.Tip="{ext:Locale SettingsTabGraphicsBackendTooltip}"
|
||||||
Text="{ext:Locale SettingsTabGraphicsBackend}"
|
Text="{ext:Locale SettingsTabGraphicsBackend}"
|
||||||
Width="250" />
|
Width="250" />
|
||||||
<ComboBox
|
<ComboBox Width="350"
|
||||||
Name="GraphicsBackendSelector"
|
HorizontalContentAlignment="Left"
|
||||||
Width="350"
|
ToolTip.Tip="{ext:Locale SettingsTabGraphicsBackendTooltip}"
|
||||||
HorizontalContentAlignment="Left"
|
SelectedIndex="{Binding GraphicsBackendIndex}">
|
||||||
ToolTip.Tip="{ext:Locale SettingsTabGraphicsBackendTooltip}"
|
|
||||||
SelectedIndex="{Binding GraphicsBackendIndex}">
|
|
||||||
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}" ToolTip.Tip="{ext:Locale SettingsTabGraphicsBackendAutoTooltip}" >
|
|
||||||
<TextBlock Text="{ext:Locale SettingsTabGraphicsBackendAuto}" />
|
|
||||||
</ComboBoxItem>
|
|
||||||
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}">
|
<ComboBoxItem IsVisible="{Binding IsVulkanAvailable}">
|
||||||
<TextBlock Text="Vulkan" />
|
<TextBlock Text="Vulkan" />
|
||||||
</ComboBoxItem>
|
</ComboBoxItem>
|
||||||
<ComboBoxItem IsEnabled="{Binding IsOpenGLAvailable}">
|
<ComboBoxItem IsEnabled="{Binding IsOpenGLAvailable}">
|
||||||
<TextBlock Text="OpenGL" />
|
<TextBlock Text="OpenGL" />
|
||||||
</ComboBoxItem>
|
</ComboBoxItem>
|
||||||
<ComboBoxItem IsEnabled="{Binding IsAppleSiliconMac}">
|
<ComboBoxItem IsVisible="{Binding IsMetalAvailable}">
|
||||||
<TextBlock Text="Metal (ARM Mac only, Experimental)" />
|
<TextBlock Text="Metal" />
|
||||||
</ComboBoxItem>
|
</ComboBoxItem>
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -77,9 +77,6 @@
|
|||||||
<ComboBoxItem>
|
<ComboBoxItem>
|
||||||
<TextBlock Text="{ext:Locale SettingsTabGeneralThemeDark}" />
|
<TextBlock Text="{ext:Locale SettingsTabGeneralThemeDark}" />
|
||||||
</ComboBoxItem>
|
</ComboBoxItem>
|
||||||
<ComboBoxItem>
|
|
||||||
<TextBlock Text="AMOLED" />
|
|
||||||
</ComboBoxItem>
|
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Title = RyujinxApp.FormatTitle(LocaleKeys.Amiibo);
|
Title = App.FormatTitle(LocaleKeys.Amiibo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AmiiboWindow()
|
public AmiiboWindow()
|
||||||
@@ -27,7 +27,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
if (Program.PreviewerDetached)
|
if (Program.PreviewerDetached)
|
||||||
{
|
{
|
||||||
Title = RyujinxApp.FormatTitle(LocaleKeys.Amiibo);
|
Title = App.FormatTitle(LocaleKeys.Amiibo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
Title = RyujinxApp.FormatTitle(LocaleKeys.CheatWindowTitle);
|
Title = App.FormatTitle(LocaleKeys.CheatWindowTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
|
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
|
||||||
@@ -93,7 +93,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
DataContext = this;
|
DataContext = this;
|
||||||
|
|
||||||
Title = RyujinxApp.FormatTitle(LocaleKeys.CheatWindowTitle);
|
Title = App.FormatTitle(LocaleKeys.CheatWindowTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save()
|
public void Save()
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
UiHandler = new AvaHostUIHandler(this);
|
UiHandler = new AvaHostUIHandler(this);
|
||||||
|
|
||||||
ViewModel.Title = RyujinxApp.FormatTitle();
|
ViewModel.Title = App.FormatTitle();
|
||||||
|
|
||||||
TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowTitleBar;
|
TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowTitleBar;
|
||||||
TitleBar.TitleBarHitTestType = (ConfigurationState.Instance.ShowTitleBar) ? TitleBarHitTestType.Simple : TitleBarHitTestType.Complex;
|
TitleBar.TitleBarHitTestType = (ConfigurationState.Instance.ShowTitleBar) ? TitleBarHitTestType.Simple : TitleBarHitTestType.Complex;
|
||||||
@@ -98,9 +98,6 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
StatusBarHeight = StatusBarView.StatusBar.MinHeight;
|
StatusBarHeight = StatusBarView.StatusBar.MinHeight;
|
||||||
MenuBarHeight = MenuBar.MinHeight;
|
MenuBarHeight = MenuBar.MinHeight;
|
||||||
|
|
||||||
ApplicationList.DataContext = DataContext;
|
|
||||||
ApplicationGrid.DataContext = DataContext;
|
|
||||||
|
|
||||||
SetWindowSizePosition();
|
SetWindowSizePosition();
|
||||||
|
|
||||||
if (Program.PreviewerDetached)
|
if (Program.PreviewerDetached)
|
||||||
@@ -117,7 +114,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private static void OnPlatformColorValuesChanged(object sender, PlatformColorValues e)
|
private static void OnPlatformColorValuesChanged(object sender, PlatformColorValues e)
|
||||||
{
|
{
|
||||||
if (Application.Current is RyujinxApp app)
|
if (Application.Current is App app)
|
||||||
app.ApplyConfiguredTheme(ConfigurationState.Instance.UI.BaseStyle);
|
app.ApplyConfiguredTheme(ConfigurationState.Instance.UI.BaseStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
|
|
||||||
public SettingsWindow(VirtualFileSystem virtualFileSystem, ContentManager contentManager)
|
public SettingsWindow(VirtualFileSystem virtualFileSystem, ContentManager contentManager)
|
||||||
{
|
{
|
||||||
Title = RyujinxApp.FormatTitle(LocaleKeys.Settings);
|
Title = App.FormatTitle(LocaleKeys.Settings);
|
||||||
|
|
||||||
DataContext = ViewModel = new SettingsViewModel(virtualFileSystem, contentManager);
|
DataContext = ViewModel = new SettingsViewModel(virtualFileSystem, contentManager);
|
||||||
|
|
||||||
@@ -56,34 +56,34 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
{
|
{
|
||||||
switch (navItem.Tag.ToString())
|
switch (navItem.Tag.ToString())
|
||||||
{
|
{
|
||||||
case nameof(UiPage):
|
case "UiPage":
|
||||||
UiPage.ViewModel = ViewModel;
|
UiPage.ViewModel = ViewModel;
|
||||||
NavPanel.Content = UiPage;
|
NavPanel.Content = UiPage;
|
||||||
break;
|
break;
|
||||||
case nameof(InputPage):
|
case "InputPage":
|
||||||
NavPanel.Content = InputPage;
|
NavPanel.Content = InputPage;
|
||||||
break;
|
break;
|
||||||
case nameof(HotkeysPage):
|
case "HotkeysPage":
|
||||||
NavPanel.Content = HotkeysPage;
|
NavPanel.Content = HotkeysPage;
|
||||||
break;
|
break;
|
||||||
case nameof(SystemPage):
|
case "SystemPage":
|
||||||
SystemPage.ViewModel = ViewModel;
|
SystemPage.ViewModel = ViewModel;
|
||||||
NavPanel.Content = SystemPage;
|
NavPanel.Content = SystemPage;
|
||||||
break;
|
break;
|
||||||
case nameof(CpuPage):
|
case "CpuPage":
|
||||||
NavPanel.Content = CpuPage;
|
NavPanel.Content = CpuPage;
|
||||||
break;
|
break;
|
||||||
case nameof(GraphicsPage):
|
case "GraphicsPage":
|
||||||
NavPanel.Content = GraphicsPage;
|
NavPanel.Content = GraphicsPage;
|
||||||
break;
|
break;
|
||||||
case nameof(AudioPage):
|
case "AudioPage":
|
||||||
NavPanel.Content = AudioPage;
|
NavPanel.Content = AudioPage;
|
||||||
break;
|
break;
|
||||||
case nameof(NetworkPage):
|
case "NetworkPage":
|
||||||
NetworkPage.ViewModel = ViewModel;
|
NetworkPage.ViewModel = ViewModel;
|
||||||
NavPanel.Content = NetworkPage;
|
NavPanel.Content = NetworkPage;
|
||||||
break;
|
break;
|
||||||
case nameof(LoggingPage):
|
case "LoggingPage":
|
||||||
NavPanel.Content = LoggingPage;
|
NavPanel.Content = LoggingPage;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
if (!Version.TryParse(Program.Version, out Version currentVersion))
|
if (!Version.TryParse(Program.Version, out Version currentVersion))
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Application, $"Failed to convert the current {RyujinxApp.FullAppName} version!");
|
Logger.Error?.Print(LogClass.Application, $"Failed to convert the current {App.FullAppName} version!");
|
||||||
|
|
||||||
await ContentDialogHelper.CreateWarningDialog(
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage],
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage],
|
||||||
@@ -159,7 +159,7 @@ namespace Ryujinx.Ava
|
|||||||
|
|
||||||
if (!Version.TryParse(_buildVer, out Version newVersion))
|
if (!Version.TryParse(_buildVer, out Version newVersion))
|
||||||
{
|
{
|
||||||
Logger.Error?.Print(LogClass.Application, $"Failed to convert the received {RyujinxApp.FullAppName} version from GitHub!");
|
Logger.Error?.Print(LogClass.Application, $"Failed to convert the received {App.FullAppName} version from GitHub!");
|
||||||
|
|
||||||
await ContentDialogHelper.CreateWarningDialog(
|
await ContentDialogHelper.CreateWarningDialog(
|
||||||
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
|
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
|
||||||
@@ -266,7 +266,7 @@ namespace Ryujinx.Ava
|
|||||||
SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading],
|
SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterDownloading],
|
||||||
IconSource = new SymbolIconSource { Symbol = Symbol.Download },
|
IconSource = new SymbolIconSource { Symbol = Symbol.Download },
|
||||||
ShowProgressBar = true,
|
ShowProgressBar = true,
|
||||||
XamlRoot = RyujinxApp.MainWindow,
|
XamlRoot = App.MainWindow,
|
||||||
};
|
};
|
||||||
|
|
||||||
taskDialog.Opened += (s, e) =>
|
taskDialog.Opened += (s, e) =>
|
||||||
@@ -490,7 +490,7 @@ namespace Ryujinx.Ava
|
|||||||
bytesWritten += readSize;
|
bytesWritten += readSize;
|
||||||
|
|
||||||
taskDialog.SetProgressBarState(GetPercentage(bytesWritten, totalBytes), TaskDialogProgressState.Normal);
|
taskDialog.SetProgressBarState(GetPercentage(bytesWritten, totalBytes), TaskDialogProgressState.Normal);
|
||||||
RyujinxApp.SetTaskbarProgressValue(bytesWritten, totalBytes);
|
App.SetTaskbarProgressValue(bytesWritten, totalBytes);
|
||||||
|
|
||||||
updateFileStream.Write(buffer, 0, readSize);
|
updateFileStream.Write(buffer, 0, readSize);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user