Compare commits
48 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e2e8502278 | |||
| aa806b1032 | |||
| aabb786016 | |||
| 2a38f1bbbf | |||
| fdece62f88 | |||
| 6fb58a611e | |||
| 02ff76f89a | |||
| d39b3a5864 | |||
| f976c3c362 | |||
| d9f2b813a0 | |||
| 8cb6767c7c | |||
| 80377c1553 | |||
| 1dbcaf1fd7 | |||
| bad1f72918 | |||
| a317184594 | |||
| 0cde245875 | |||
| e3638d13b1 | |||
| 2fe19044cf | |||
| 9320decc45 | |||
| 35b23bcafb | |||
| 4add4829c7 | |||
| eb46909808 | |||
| c91d9d8049 | |||
| 21f23f0a2e | |||
| 9ca0926439 | |||
| 7b8c8776a2 | |||
| b00d80c17a | |||
| 8c0a82bb6e | |||
| 17233d30da | |||
| 1bac6ab19e | |||
| dac137fd43 | |||
| d83d80de73 | |||
| 097836bfac | |||
| 695f9e277d | |||
| 2bf48f57d2 | |||
| b19ee23c6b | |||
| 748e93ba65 | |||
| 412d4065b8 | |||
| e6644626fc | |||
| 0bacdb8765 | |||
| 0ca4d6e921 | |||
| f0aa7eedf6 | |||
| 41acc4b1f3 | |||
| 732a1af863 | |||
| 7aede70ba9 | |||
| f538cee2e8 | |||
| a0a4f78cff | |||
| 4275a778aa |
+3
-3
@@ -80,6 +80,7 @@ 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}"
|
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
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ryujinx.HLE.Generators", "src\Ryujinx.HLE.Generators\Ryujinx.HLE.Generators.csproj", "{B575BCDE-2FD8-4A5D-8756-31CDD7FE81F0}"
|
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}"
|
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
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} = {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}
|
{A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E} = {A602AE97-91A5-4608-8DF1-EBF4ED7A0B9E}
|
||||||
@@ -258,13 +259,12 @@ 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}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
|
using Humanizer;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
@@ -58,8 +59,8 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
_ptc = ptc;
|
_ptc = ptc;
|
||||||
|
|
||||||
_timer = new Timer(SaveInterval * 1000d);
|
_timer = new Timer(SaveInterval.Seconds());
|
||||||
_timer.Elapsed += PreSave;
|
_timer.Elapsed += TimerElapsed;
|
||||||
|
|
||||||
_outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan());
|
_outerHeaderMagic = BinaryPrimitives.ReadUInt64LittleEndian(EncodingCache.UTF8NoBOM.GetBytes(OuterHeaderMagicString).AsSpan());
|
||||||
|
|
||||||
@@ -72,6 +73,9 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
Enabled = false;
|
Enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void TimerElapsed(object _, ElapsedEventArgs __)
|
||||||
|
=> new Thread(PreSave) { Name = "Ptc.DiskWriter" }.Start();
|
||||||
|
|
||||||
public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
|
public void AddEntry(ulong address, ExecutionMode mode, bool highCq)
|
||||||
{
|
{
|
||||||
if (IsAddressInStaticCodeRange(address))
|
if (IsAddressInStaticCodeRange(address))
|
||||||
@@ -262,7 +266,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
compressedStream.SetLength(0L);
|
compressedStream.SetLength(0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PreSave(object source, ElapsedEventArgs e)
|
private void PreSave()
|
||||||
{
|
{
|
||||||
_waitEvent.Reset();
|
_waitEvent.Reset();
|
||||||
|
|
||||||
@@ -428,7 +432,7 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
{
|
{
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
|
|
||||||
_timer.Elapsed -= PreSave;
|
_timer.Elapsed -= TimerElapsed;
|
||||||
_timer.Dispose();
|
_timer.Dispose();
|
||||||
|
|
||||||
Wait();
|
Wait();
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Microsoft.Build.Utilities;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.IO;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Microsoft.Build.Framework;
|
|
||||||
|
|
||||||
namespace Ryujinx.BuildValidationTasks
|
|
||||||
{
|
|
||||||
public class LocaleValidationTask : Task
|
|
||||||
{
|
|
||||||
public override bool Execute()
|
|
||||||
{
|
|
||||||
string path = System.Reflection.Assembly.GetExecutingAssembly().Location;
|
|
||||||
|
|
||||||
if (path.Split(["src"], StringSplitOptions.None).Length == 1)
|
|
||||||
{
|
|
||||||
//i assume that we are in a build directory in the solution dir
|
|
||||||
path = new FileInfo(path).Directory!.Parent!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
path = path.Split(["src"], StringSplitOptions.None)[0];
|
|
||||||
path = new FileInfo(path).Directory!.GetDirectories("src")[0].GetDirectories("Ryujinx")[0].GetDirectories("Assets")[0].GetFiles("locales.json")[0].FullName;
|
|
||||||
}
|
|
||||||
|
|
||||||
string data;
|
|
||||||
|
|
||||||
using (StreamReader sr = new(path))
|
|
||||||
{
|
|
||||||
data = sr.ReadToEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalesJson json = JsonConvert.DeserializeObject<LocalesJson>(data);
|
|
||||||
|
|
||||||
for (int i = 0; i < json.Locales.Count; i++)
|
|
||||||
{
|
|
||||||
LocalesEntry locale = json.Locales[i];
|
|
||||||
|
|
||||||
foreach (string langCode in json.Languages.Where(it => !locale.Translations.ContainsKey(it)))
|
|
||||||
{
|
|
||||||
locale.Translations.Add(langCode, string.Empty);
|
|
||||||
Log.LogMessage(MessageImportance.High, $"Added '{langCode}' to Locale '{locale.ID}'");
|
|
||||||
}
|
|
||||||
|
|
||||||
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
|
|
||||||
json.Locales[i] = locale;
|
|
||||||
}
|
|
||||||
|
|
||||||
string jsonString = JsonConvert.SerializeObject(json, Formatting.Indented);
|
|
||||||
|
|
||||||
using (StreamWriter sw = new(path))
|
|
||||||
{
|
|
||||||
sw.Write(jsonString);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LocalesJson
|
|
||||||
{
|
|
||||||
public List<string> Languages { get; set; }
|
|
||||||
public List<LocalesEntry> Locales { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LocalesEntry
|
|
||||||
{
|
|
||||||
public string ID { get; set; }
|
|
||||||
public Dictionary<string, string> Translations { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Encodings.Web;
|
||||||
|
|
||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public class LocalesValidationTask : ValidationTask
|
||||||
|
{
|
||||||
|
public static bool Execute(string projectPath)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Running Locale Validation Task...");
|
||||||
|
|
||||||
|
string path = projectPath + "src/Ryujinx/Assets/locales.json";
|
||||||
|
string data;
|
||||||
|
|
||||||
|
using (StreamReader sr = new(path))
|
||||||
|
{
|
||||||
|
data = sr.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalesJson json;
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
json = JsonSerializer.Deserialize<LocalesJson>(data);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (JsonException e)
|
||||||
|
{
|
||||||
|
throw new JsonException(e.Message); //shorter and easier stacktrace
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGitRunner = path.Contains("runner") || path.Contains("D:\\a\\Ryujinx\\Ryujinx");
|
||||||
|
if (isGitRunner)
|
||||||
|
Console.WriteLine("Is Git Runner!");
|
||||||
|
bool encounteredIssue = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < json.Locales.Count; i++)
|
||||||
|
{
|
||||||
|
LocalesEntry locale = json.Locales[i];
|
||||||
|
|
||||||
|
foreach (string langCode in json.Languages.Where(lang => !locale.Translations.ContainsKey(lang)))
|
||||||
|
{
|
||||||
|
encounteredIssue = true;
|
||||||
|
|
||||||
|
if (!isGitRunner)
|
||||||
|
{
|
||||||
|
locale.Translations.Add(langCode, string.Empty);
|
||||||
|
Console.WriteLine($"Added '{langCode}' to Locale '{locale.ID}'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Missing '{langCode}' in Locale '{locale.ID}'!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string langCode in json.Languages.Where(lang => locale.Translations.ContainsKey(lang) && lang != "en_US" && locale.Translations[lang] == locale.Translations["en_US"]))
|
||||||
|
{
|
||||||
|
encounteredIssue = true;
|
||||||
|
|
||||||
|
if (!isGitRunner)
|
||||||
|
{
|
||||||
|
locale.Translations[langCode] = string.Empty;
|
||||||
|
Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'! Resetting it...");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Lanugage '{langCode}' is a duplicate of en_US in Locale '{locale.ID}'!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
locale.Translations = locale.Translations.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||||
|
json.Locales[i] = locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGitRunner && encounteredIssue)
|
||||||
|
throw new JsonException("1 or more locales are invalid!");
|
||||||
|
|
||||||
|
JsonSerializerOptions jsonOptions = new JsonSerializerOptions()
|
||||||
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
NewLine = "\n",
|
||||||
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
|
||||||
|
};
|
||||||
|
|
||||||
|
string jsonString = JsonSerializer.Serialize(json, jsonOptions);
|
||||||
|
|
||||||
|
using (StreamWriter sw = new(path))
|
||||||
|
{
|
||||||
|
sw.Write(jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Finished Locale Validation Task!");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LocalesJson
|
||||||
|
{
|
||||||
|
public List<string> Languages { get; set; }
|
||||||
|
public List<LocalesEntry> Locales { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LocalesEntry
|
||||||
|
{
|
||||||
|
public string ID { get; set; }
|
||||||
|
public Dictionary<string, string> Translations { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// Display the number of command line arguments.
|
||||||
|
if (args.Length != 1)
|
||||||
|
{
|
||||||
|
if (args.Length == 0)
|
||||||
|
throw new ArgumentException("Error: too few arguments!");
|
||||||
|
else
|
||||||
|
throw new ArgumentException("Error: too many arguments!");
|
||||||
|
}
|
||||||
|
|
||||||
|
string path = args[0];
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(path))
|
||||||
|
throw new ArgumentException("Error: path is null or empty!");
|
||||||
|
|
||||||
|
if (!Path.Exists(args[0]))
|
||||||
|
throw new ArgumentException($"path {{{path}}} does not exist!");
|
||||||
|
|
||||||
|
path = Path.GetFullPath(path);
|
||||||
|
|
||||||
|
if (!Directory.GetDirectories(path).Contains($"{path}src"))
|
||||||
|
throw new ArgumentException($"path {{{path}}} is not a valid ryujinx project!");
|
||||||
|
|
||||||
|
LocalesValidationTask.Execute(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,16 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<OutputType>Exe</OutputType>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<Target Name="PostBuildTarget" AfterTargets="AfterBuild">
|
||||||
<PackageReference Include="Microsoft.Build.Utilities.Core" />
|
<Message Text="Running Validation Project" Importance="high" />
|
||||||
<PackageReference Include="Newtonsoft.Json" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<UsingTask TaskName="Ryujinx.BuildValidationTasks.LocaleValidationTask" TaskFactory="TaskHostFactory" AssemblyFile="$(OutDir)Ryujinx.BuildValidationTasks.dll" />
|
<Exec WorkingDirectory="$(ProjectDir)bin\Debug\$(TargetFramework)\"
|
||||||
|
Command="dotnet Ryujinx.BuildValidationTasks.dll "$(ProjectDir)..\..\\""
|
||||||
<Target Name="LocalesJsonValidation" AfterTargets="AfterRebuild">
|
ConsoleToMsBuild="true"
|
||||||
<LocaleValidationTask />
|
/>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ryujinx.BuildValidationTasks
|
||||||
|
{
|
||||||
|
public interface ValidationTask
|
||||||
|
{
|
||||||
|
public static bool Execute(string projectPath) { return true; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
using Gommon;
|
||||||
|
using Ryujinx.Common.Configuration;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.Common
|
||||||
|
{
|
||||||
|
public static class TitleIDs
|
||||||
|
{
|
||||||
|
public static GraphicsBackend SelectGraphicsBackend(string titleId, GraphicsBackend currentBackend)
|
||||||
|
{
|
||||||
|
switch (currentBackend)
|
||||||
|
{
|
||||||
|
case GraphicsBackend.OpenGl when OperatingSystem.IsMacOS():
|
||||||
|
return GraphicsBackend.Vulkan;
|
||||||
|
case GraphicsBackend.Vulkan or GraphicsBackend.OpenGl or GraphicsBackend.Metal:
|
||||||
|
return currentBackend;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture is Architecture.Arm64))
|
||||||
|
return GraphicsBackend.Vulkan;
|
||||||
|
|
||||||
|
return GreatMetalTitles.ContainsIgnoreCase(titleId) ? GraphicsBackend.Metal : GraphicsBackend.Vulkan;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly string[] GreatMetalTitles =
|
||||||
|
[
|
||||||
|
"01006f8002326000", // Animal Crossings: New Horizons
|
||||||
|
"01009bf0072d4000", // Captain Toad: Treasure Tracker
|
||||||
|
"0100a5c00d162000", // Cuphead
|
||||||
|
"010023800d64a000", // Deltarune
|
||||||
|
"010028600EBDA000", // Mario 3D World
|
||||||
|
"0100152000022000", // Mario Kart 8 Deluxe
|
||||||
|
"01005CA01580E000", // Persona 5
|
||||||
|
"01008C0016544000", // Sea of Stars
|
||||||
|
"01006A800016E000", // Smash Ultimate
|
||||||
|
"0100000000010000", // Super Mario Odyessy
|
||||||
|
];
|
||||||
|
|
||||||
|
public static string GetDiscordGameAsset(string titleId)
|
||||||
|
=> DiscordGameAssetKeys.Contains(titleId) ? titleId : "game";
|
||||||
|
|
||||||
|
public static readonly string[] DiscordGameAssetKeys =
|
||||||
|
[
|
||||||
|
"010055d009f78000", // Fire Emblem: Three Houses
|
||||||
|
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
|
||||||
|
"0100a6301214e000", // Fire Emblem Engage
|
||||||
|
"0100f15003e64000", // Fire Emblem Warriors
|
||||||
|
"010071f0143ea000", // Fire Emblem Warriors: Three Hopes
|
||||||
|
|
||||||
|
"01007e3006dda000", // Kirby Star Allies
|
||||||
|
"01004d300c5ae000", // Kirby and the Forgotten Land
|
||||||
|
"01006b601380e000", // Kirby's Return to Dream Land Deluxe
|
||||||
|
"01003fb00c5a8000", // Super Kirby Clash
|
||||||
|
"0100227010460000", // Kirby Fighters 2
|
||||||
|
"0100a8e016236000", // Kirby's Dream Buffet
|
||||||
|
|
||||||
|
"01007ef00011e000", // The Legend of Zelda: Breath of the Wild
|
||||||
|
"01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
|
||||||
|
"01002da013484000", // The Legend of Zelda: Skyward Sword HD
|
||||||
|
"0100f2c0115b6000", // The Legend of Zelda: Tears of the Kingdom
|
||||||
|
"01008cf01baac000", // The Legend of Zelda: Echoes of Wisdom
|
||||||
|
"01000b900d8b0000", // Cadence of Hyrule
|
||||||
|
"0100ae00096ea000", // Hyrule Warriors: Definitive Edition
|
||||||
|
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
|
||||||
|
|
||||||
|
"010048701995e000", // Luigi's Mansion 2 HD
|
||||||
|
"0100dca0064a6000", // Luigi's Mansion 3
|
||||||
|
|
||||||
|
"010093801237c000", // Metroid Dread
|
||||||
|
"010012101468c000", // Metroid Prime Remastered
|
||||||
|
|
||||||
|
"0100000000010000", // SUPER MARIO ODYSSEY
|
||||||
|
"0100ea80032ea000", // Super Mario Bros. U Deluxe
|
||||||
|
"01009b90006dc000", // Super Mario Maker 2
|
||||||
|
"010049900f546000", // Super Mario 3D All-Stars
|
||||||
|
"010049900F546001", // ^ 64
|
||||||
|
"010049900F546002", // ^ Sunshine
|
||||||
|
"010049900F546003", // ^ Galaxy
|
||||||
|
"010028600ebda000", // Super Mario 3D World + Bowser's Fury
|
||||||
|
"010015100b514000", // Super Mario Bros. Wonder
|
||||||
|
"0100152000022000", // Mario Kart 8 Deluxe
|
||||||
|
"010036b0034e4000", // Super Mario Party
|
||||||
|
"01006fe013472000", // Mario Party Superstars
|
||||||
|
"0100965017338000", // Super Mario Party Jamboree
|
||||||
|
"01006d0017f7a000", // Mario & Luigi: Brothership
|
||||||
|
"010067300059a000", // Mario + Rabbids: Kingdom Battle
|
||||||
|
"0100317013770000", // Mario + Rabbids: Sparks of Hope
|
||||||
|
"0100a3900c3e2000", // Paper Mario: The Origami King
|
||||||
|
"0100ecd018ebe000", // Paper Mario: The Thousand-Year Door
|
||||||
|
"0100bc0018138000", // Super Mario RPG
|
||||||
|
"0100bde00862a000", // Mario Tennis Aces
|
||||||
|
"0100c9c00e25c000", // Mario Golf: Super Rush
|
||||||
|
"010019401051c000", // Mario Strikers: Battle League
|
||||||
|
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
|
||||||
|
"0100b99019412000", // Mario vs. Donkey Kong
|
||||||
|
|
||||||
|
"0100aa80194b0000", // Pikmin 1
|
||||||
|
"0100d680194b2000", // Pikmin 2
|
||||||
|
"0100f4c009322000", // Pikmin 3 Deluxe
|
||||||
|
"0100b7c00933a000", // Pikmin 4
|
||||||
|
|
||||||
|
"010003f003a34000", // Pokémon: Let's Go Pikachu!
|
||||||
|
"0100187003a36000", // Pokémon: Let's Go Eevee!
|
||||||
|
"0100abf008968000", // Pokémon Sword
|
||||||
|
"01008db008c2c000", // Pokémon Shield
|
||||||
|
"0100000011d90000", // Pokémon Brilliant Diamond
|
||||||
|
"010018e011d92000", // Pokémon Shining Pearl
|
||||||
|
"01001f5010dfa000", // Pokémon Legends: Arceus
|
||||||
|
"0100a3d008c5c000", // Pokémon Scarlet
|
||||||
|
"01008f6008c5e000", // Pokémon Violet
|
||||||
|
"0100b3f000be2000", // Pokkén Tournament DX
|
||||||
|
"0100f4300bf2c000", // New Pokémon Snap
|
||||||
|
|
||||||
|
"01003bc0000a0000", // Splatoon 2 (US)
|
||||||
|
"0100f8f0000a2000", // Splatoon 2 (EU)
|
||||||
|
"01003c700009c000", // Splatoon 2 (JP)
|
||||||
|
"0100c2500fc20000", // Splatoon 3
|
||||||
|
"0100ba0018500000", // Splatoon 3: Splatfest World Premiere
|
||||||
|
|
||||||
|
"010040600c5ce000", // Tetris 99
|
||||||
|
"0100277011f1a000", // Super Mario Bros. 35
|
||||||
|
"0100ad9012510000", // PAC-MAN 99
|
||||||
|
"0100ccf019c8c000", // F-ZERO 99
|
||||||
|
"0100d870045b6000", // NES - Nintendo Switch Online
|
||||||
|
"01008d300c50c000", // SNES - Nintendo Switch Online
|
||||||
|
"0100c9a00ece6000", // N64 - Nintendo Switch Online
|
||||||
|
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
|
||||||
|
"0100c62011050000", // GB - Nintendo Switch Online
|
||||||
|
"010012f017576000", // GBA - Nintendo Switch Online
|
||||||
|
|
||||||
|
"01000320000cc000", // 1-2 Switch
|
||||||
|
"0100300012f2a000", // Advance Wars 1+2: Re-Boot Camp
|
||||||
|
"01006f8002326000", // Animal Crossing: New Horizons
|
||||||
|
"0100620012d6e000", // Big Brain Academy: Brain vs. Brain
|
||||||
|
"010018300d006000", // BOXBOY! + BOXGIRL!
|
||||||
|
"0100c1f0051b6000", // Donkey Kong Country: Tropical Freeze
|
||||||
|
"0100ed000d390000", // Dr. Kawashima's Brain Training
|
||||||
|
"010067b017588000", // Endless Ocean Luminous
|
||||||
|
"0100d2f00d5c0000", // Nintendo Switch Sports
|
||||||
|
"01006b5012b32000", // Part Time UFO
|
||||||
|
"0100704000B3A000", // Snipperclips
|
||||||
|
"01006a800016e000", // Super Smash Bros. Ultimate
|
||||||
|
"0100a9400c9c2000", // Tokyo Mirage Sessions #FE Encore
|
||||||
|
|
||||||
|
"010076f0049a2000", // Bayonetta
|
||||||
|
"01007960049a0000", // Bayonetta 2
|
||||||
|
"01004a4010fea000", // Bayonetta 3
|
||||||
|
"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
|
||||||
|
|
||||||
|
"0100dcd01525a000", // Persona 3 Portable
|
||||||
|
"010062b01525c000", // Persona 4 Golden
|
||||||
|
"010075a016a3a000", // Persona 4 Arena Ultimax
|
||||||
|
"01005ca01580e000", // Persona 5 Royal
|
||||||
|
"0100801011c3e000", // Persona 5 Strikers
|
||||||
|
"010087701b092000", // Persona 5 Tactica
|
||||||
|
|
||||||
|
"01009aa000faa000", // Sonic Mania
|
||||||
|
"01004ad014bf0000", // Sonic Frontiers
|
||||||
|
"01005ea01c0fc000", // SONIC X SHADOW GENERATIONS
|
||||||
|
"01005ea01c0fc001", // ^
|
||||||
|
|
||||||
|
"010056e00853a000", // A Hat in Time
|
||||||
|
"0100dbf01000a000", // Burnout Paradise Remastered
|
||||||
|
"0100744001588000", // Cars 3: Driven to Win
|
||||||
|
"0100b41013c82000", // Cruis'n Blast
|
||||||
|
"01001b300b9be000", // Diablo III: Eternal Collection
|
||||||
|
"01008c8012920000", // Dying Light Platinum Edition
|
||||||
|
"010073c01af34000", // LEGO Horizon Adventures
|
||||||
|
"0100770008dd8000", // Monster Hunter Generations Ultimate
|
||||||
|
"0100b04011742000", // Monster Hunter Rise
|
||||||
|
"0100853015e86000", // No Man's Sky
|
||||||
|
"01007bb017812000", // Portal
|
||||||
|
"0100abd01785c000", // Portal 2
|
||||||
|
"01008e200c5c2000", // Muse Dash
|
||||||
|
"01007820196a6000", // Red Dead Redemption
|
||||||
|
"01002f7013224000", // Rune Factory 5
|
||||||
|
"01008d100d43e000", // Saints Row IV
|
||||||
|
"0100de600beee000", // Saints Row: The Third - The Full Package
|
||||||
|
"01001180021fa000", // Shovel Knight: Specter of Torment
|
||||||
|
"0100d7a01b7a2000", // Star Wars: Bounty Hunter
|
||||||
|
"0100800015926000", // Suika Game
|
||||||
|
"0100e46006708000", // Terraria
|
||||||
|
"01000a10041ea000", // The Elder Scrolls V: Skyrim
|
||||||
|
"010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon-
|
||||||
|
"010080b00ad66000", // Undertale
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ namespace Ryujinx.Graphics.OpenGL.Queries
|
|||||||
|
|
||||||
_current = new CounterQueueEvent(this, glType, 0);
|
_current = new CounterQueueEvent(this, glType, 0);
|
||||||
|
|
||||||
_consumerThread = new Thread(EventConsumer);
|
_consumerThread = new Thread(EventConsumer) { Name = "CPU.CounterQueue." + (int)type };
|
||||||
_consumerThread.Start();
|
_consumerThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Vulkan.Queries
|
|||||||
|
|
||||||
_current = new CounterQueueEvent(this, type, 0);
|
_current = new CounterQueueEvent(this, type, 0);
|
||||||
|
|
||||||
_consumerThread = new Thread(EventConsumer);
|
_consumerThread = new Thread(EventConsumer) { Name = "CPU.CounterQueue." + (int)type };
|
||||||
_consumerThread.Start();
|
_consumerThread.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1034,16 +1034,16 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
switch (fileName)
|
switch (fileName)
|
||||||
{
|
{
|
||||||
case "prod.keys":
|
case "prod.keys":
|
||||||
verified = verifyKeys(lines, genericPattern);
|
verified = VerifyKeys(lines, genericPattern);
|
||||||
break;
|
break;
|
||||||
case "title.keys":
|
case "title.keys":
|
||||||
verified = verifyKeys(lines, titlePattern);
|
verified = VerifyKeys(lines, titlePattern);
|
||||||
break;
|
break;
|
||||||
case "console.keys":
|
case "console.keys":
|
||||||
verified = verifyKeys(lines, genericPattern);
|
verified = VerifyKeys(lines, genericPattern);
|
||||||
break;
|
break;
|
||||||
case "dev.keys":
|
case "dev.keys":
|
||||||
verified = verifyKeys(lines, genericPattern);
|
verified = VerifyKeys(lines, genericPattern);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported.");
|
throw new FormatException($"Keys file name \"{fileName}\" not supported. Only \"prod.keys\", \"title.keys\", \"console.keys\", \"dev.keys\" are supported.");
|
||||||
@@ -1056,20 +1056,22 @@ namespace Ryujinx.HLE.FileSystem
|
|||||||
{
|
{
|
||||||
throw new FileNotFoundException($"Keys file not found at \"{filePath}\".");
|
throw new FileNotFoundException($"Keys file not found at \"{filePath}\".");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private bool verifyKeys(string[] lines, string regex)
|
return;
|
||||||
{
|
|
||||||
foreach (string line in lines)
|
bool VerifyKeys(string[] lines, string regex)
|
||||||
{
|
{
|
||||||
if (!Regex.IsMatch(line, regex))
|
foreach (string line in lines)
|
||||||
{
|
{
|
||||||
return false;
|
if (!Regex.IsMatch(line, regex))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AreKeysAlredyPresent(string pathToCheck)
|
public bool AreKeysAlredyPresent(string pathToCheck)
|
||||||
{
|
{
|
||||||
string[] fileNames = { "prod.keys", "title.keys", "console.keys", "dev.keys" };
|
string[] fileNames = { "prod.keys", "title.keys", "console.keys", "dev.keys" };
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Threading
|
|||||||
is64Bits = true;
|
is64Bits = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
HostThread = new Thread(ThreadStart);
|
HostThread = new Thread(ThreadStart) { Name = "HLE.KThread" };
|
||||||
|
|
||||||
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
|
Context = owner?.CreateExecutionContext() ?? new ProcessExecutionContext();
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ namespace Ryujinx.UI.Common
|
|||||||
{
|
{
|
||||||
Assets = new Assets
|
Assets = new Assets
|
||||||
{
|
{
|
||||||
LargeImageKey = _discordGameAssetKeys.Contains(procRes.ProgramIdText) ? procRes.ProgramIdText : "game",
|
LargeImageKey = TitleIDs.GetDiscordGameAsset(procRes.ProgramIdText),
|
||||||
LargeImageText = TruncateToByteLength($"{appMeta.Title} (v{procRes.DisplayVersion})"),
|
LargeImageText = TruncateToByteLength($"{appMeta.Title} (v{procRes.DisplayVersion})"),
|
||||||
SmallImageKey = "ryujinx",
|
SmallImageKey = "ryujinx",
|
||||||
SmallImageText = TruncateToByteLength(_description)
|
SmallImageText = TruncateToByteLength(_description)
|
||||||
@@ -122,151 +122,5 @@ namespace Ryujinx.UI.Common
|
|||||||
{
|
{
|
||||||
_discordClient?.Dispose();
|
_discordClient?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static readonly string[] _discordGameAssetKeys =
|
|
||||||
[
|
|
||||||
"010055d009f78000", // Fire Emblem: Three Houses
|
|
||||||
"0100a12011cc8000", // Fire Emblem: Shadow Dragon
|
|
||||||
"0100a6301214e000", // Fire Emblem Engage
|
|
||||||
"0100f15003e64000", // Fire Emblem Warriors
|
|
||||||
"010071f0143ea000", // Fire Emblem Warriors: Three Hopes
|
|
||||||
|
|
||||||
"01007e3006dda000", // Kirby Star Allies
|
|
||||||
"01004d300c5ae000", // Kirby and the Forgotten Land
|
|
||||||
"01006b601380e000", // Kirby's Return to Dream Land Deluxe
|
|
||||||
"01003fb00c5a8000", // Super Kirby Clash
|
|
||||||
"0100227010460000", // Kirby Fighters 2
|
|
||||||
"0100a8e016236000", // Kirby's Dream Buffet
|
|
||||||
|
|
||||||
"01007ef00011e000", // The Legend of Zelda: Breath of the Wild
|
|
||||||
"01006bb00c6f0000", // The Legend of Zelda: Link's Awakening
|
|
||||||
"01002da013484000", // The Legend of Zelda: Skyward Sword HD
|
|
||||||
"0100f2c0115b6000", // The Legend of Zelda: Tears of the Kingdom
|
|
||||||
"01008cf01baac000", // The Legend of Zelda: Echoes of Wisdom
|
|
||||||
"01000b900d8b0000", // Cadence of Hyrule
|
|
||||||
"0100ae00096ea000", // Hyrule Warriors: Definitive Edition
|
|
||||||
"01002b00111a2000", // Hyrule Warriors: Age of Calamity
|
|
||||||
|
|
||||||
"010048701995e000", // Luigi's Mansion 2 HD
|
|
||||||
"0100dca0064a6000", // Luigi's Mansion 3
|
|
||||||
|
|
||||||
"010093801237c000", // Metroid Dread
|
|
||||||
"010012101468c000", // Metroid Prime Remastered
|
|
||||||
|
|
||||||
"0100000000010000", // SUPER MARIO ODYSSEY
|
|
||||||
"0100ea80032ea000", // Super Mario Bros. U Deluxe
|
|
||||||
"01009b90006dc000", // Super Mario Maker 2
|
|
||||||
"010049900f546000", // Super Mario 3D All-Stars
|
|
||||||
"010049900F546001", // ^ 64
|
|
||||||
"010049900F546002", // ^ Sunshine
|
|
||||||
"010049900F546003", // ^ Galaxy
|
|
||||||
"010028600ebda000", // Super Mario 3D World + Bowser's Fury
|
|
||||||
"010015100b514000", // Super Mario Bros. Wonder
|
|
||||||
"0100152000022000", // Mario Kart 8 Deluxe
|
|
||||||
"010036b0034e4000", // Super Mario Party
|
|
||||||
"01006fe013472000", // Mario Party Superstars
|
|
||||||
"0100965017338000", // Super Mario Party Jamboree
|
|
||||||
"01006d0017f7a000", // Mario & Luigi: Brothership
|
|
||||||
"010067300059a000", // Mario + Rabbids: Kingdom Battle
|
|
||||||
"0100317013770000", // Mario + Rabbids: Sparks of Hope
|
|
||||||
"0100a3900c3e2000", // Paper Mario: The Origami King
|
|
||||||
"0100ecd018ebe000", // Paper Mario: The Thousand-Year Door
|
|
||||||
"0100bc0018138000", // Super Mario RPG
|
|
||||||
"0100bde00862a000", // Mario Tennis Aces
|
|
||||||
"0100c9c00e25c000", // Mario Golf: Super Rush
|
|
||||||
"010019401051c000", // Mario Strikers: Battle League
|
|
||||||
"010003000e146000", // Mario & Sonic at the Olympic Games Tokyo 2020
|
|
||||||
"0100b99019412000", // Mario vs. Donkey Kong
|
|
||||||
|
|
||||||
"0100aa80194b0000", // Pikmin 1
|
|
||||||
"0100d680194b2000", // Pikmin 2
|
|
||||||
"0100f4c009322000", // Pikmin 3 Deluxe
|
|
||||||
"0100b7c00933a000", // Pikmin 4
|
|
||||||
|
|
||||||
"010003f003a34000", // Pokémon: Let's Go Pikachu!
|
|
||||||
"0100187003a36000", // Pokémon: Let's Go Eevee!
|
|
||||||
"0100abf008968000", // Pokémon Sword
|
|
||||||
"01008db008c2c000", // Pokémon Shield
|
|
||||||
"0100000011d90000", // Pokémon Brilliant Diamond
|
|
||||||
"010018e011d92000", // Pokémon Shining Pearl
|
|
||||||
"01001f5010dfa000", // Pokémon Legends: Arceus
|
|
||||||
"0100a3d008c5c000", // Pokémon Scarlet
|
|
||||||
"01008f6008c5e000", // Pokémon Violet
|
|
||||||
"0100b3f000be2000", // Pokkén Tournament DX
|
|
||||||
"0100f4300bf2c000", // New Pokémon Snap
|
|
||||||
|
|
||||||
"01003bc0000a0000", // Splatoon 2 (US)
|
|
||||||
"0100f8f0000a2000", // Splatoon 2 (EU)
|
|
||||||
"01003c700009c000", // Splatoon 2 (JP)
|
|
||||||
"0100c2500fc20000", // Splatoon 3
|
|
||||||
"0100ba0018500000", // Splatoon 3: Splatfest World Premiere
|
|
||||||
|
|
||||||
"010040600c5ce000", // Tetris 99
|
|
||||||
"0100277011f1a000", // Super Mario Bros. 35
|
|
||||||
"0100ad9012510000", // PAC-MAN 99
|
|
||||||
"0100ccf019c8c000", // F-ZERO 99
|
|
||||||
"0100d870045b6000", // NES - Nintendo Switch Online
|
|
||||||
"01008d300c50c000", // SNES - Nintendo Switch Online
|
|
||||||
"0100c9a00ece6000", // N64 - Nintendo Switch Online
|
|
||||||
"0100e0601c632000", // N64 - Nintendo Switch Online 18+
|
|
||||||
"0100c62011050000", // GB - Nintendo Switch Online
|
|
||||||
"010012f017576000", // GBA - Nintendo Switch Online
|
|
||||||
|
|
||||||
"01000320000cc000", // 1-2 Switch
|
|
||||||
"0100300012f2a000", // Advance Wars 1+2: Re-Boot Camp
|
|
||||||
"01006f8002326000", // Animal Crossing: New Horizons
|
|
||||||
"0100620012d6e000", // Big Brain Academy: Brain vs. Brain
|
|
||||||
"010018300d006000", // BOXBOY! + BOXGIRL!
|
|
||||||
"0100c1f0051b6000", // Donkey Kong Country: Tropical Freeze
|
|
||||||
"0100ed000d390000", // Dr. Kawashima's Brain Training
|
|
||||||
"010067b017588000", // Endless Ocean Luminous
|
|
||||||
"0100d2f00d5c0000", // Nintendo Switch Sports
|
|
||||||
"01006b5012b32000", // Part Time UFO
|
|
||||||
"0100704000B3A000", // Snipperclips
|
|
||||||
"01006a800016e000", // Super Smash Bros. Ultimate
|
|
||||||
"0100a9400c9c2000", // Tokyo Mirage Sessions #FE Encore
|
|
||||||
|
|
||||||
"010076f0049a2000", // Bayonetta
|
|
||||||
"01007960049a0000", // Bayonetta 2
|
|
||||||
"01004a4010fea000", // Bayonetta 3
|
|
||||||
"0100cf5010fec000", // Bayonetta Origins: Cereza and the Lost Demon
|
|
||||||
|
|
||||||
"0100dcd01525a000", // Persona 3 Portable
|
|
||||||
"010062b01525c000", // Persona 4 Golden
|
|
||||||
"010075a016a3a000", // Persona 4 Arena Ultimax
|
|
||||||
"01005ca01580e000", // Persona 5 Royal
|
|
||||||
"0100801011c3e000", // Persona 5 Strikers
|
|
||||||
"010087701b092000", // Persona 5 Tactica
|
|
||||||
|
|
||||||
"01009aa000faa000", // Sonic Mania
|
|
||||||
"01004ad014bf0000", // Sonic Frontiers
|
|
||||||
"01005ea01c0fc000", // SONIC X SHADOW GENERATIONS
|
|
||||||
"01005ea01c0fc001", // ^
|
|
||||||
|
|
||||||
"010056e00853a000", // A Hat in Time
|
|
||||||
"0100dbf01000a000", // Burnout Paradise Remastered
|
|
||||||
"0100744001588000", // Cars 3: Driven to Win
|
|
||||||
"0100b41013c82000", // Cruis'n Blast
|
|
||||||
"01001b300b9be000", // Diablo III: Eternal Collection
|
|
||||||
"01008c8012920000", // Dying Light Platinum Edition
|
|
||||||
"010073c01af34000", // LEGO Horizon Adventures
|
|
||||||
"0100770008dd8000", // Monster Hunter Generations Ultimate
|
|
||||||
"0100b04011742000", // Monster Hunter Rise
|
|
||||||
"0100853015e86000", // No Man's Sky
|
|
||||||
"01007bb017812000", // Portal
|
|
||||||
"0100abd01785c000", // Portal 2
|
|
||||||
"01008e200c5c2000", // Muse Dash
|
|
||||||
"01007820196a6000", // Red Dead Redemption
|
|
||||||
"01002f7013224000", // Rune Factory 5
|
|
||||||
"01008d100d43e000", // Saints Row IV
|
|
||||||
"0100de600beee000", // Saints Row: The Third - The Full Package
|
|
||||||
"01001180021fa000", // Shovel Knight: Specter of Torment
|
|
||||||
"0100d7a01b7a2000", // Star Wars: Bounty Hunter
|
|
||||||
"0100800015926000", // Suika Game
|
|
||||||
"0100e46006708000", // Terraria
|
|
||||||
"01000a10041ea000", // The Elder Scrolls V: Skyrim
|
|
||||||
"010057a01e4d4000", // TSUKIHIME -A piece of blue glass moon-
|
|
||||||
"010080b00ad66000", // Undertale
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using LibHac.Common;
|
||||||
|
using LibHac.Ncm;
|
||||||
|
using LibHac.Ns;
|
||||||
|
using LibHac.Tools.FsSystem.NcaUtils;
|
||||||
|
using Ryujinx.HLE;
|
||||||
|
using Ryujinx.HLE.FileSystem;
|
||||||
|
using Ryujinx.UI.App.Common;
|
||||||
|
|
||||||
|
namespace Ryujinx.UI.Common.Helper
|
||||||
|
{
|
||||||
|
public readonly struct AppletMetadata
|
||||||
|
{
|
||||||
|
private readonly ContentManager _contentManager;
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
public ulong ProgramId { get; }
|
||||||
|
|
||||||
|
public string Version { get; }
|
||||||
|
|
||||||
|
public AppletMetadata(ContentManager contentManager, string name, ulong programId, string version = "1.0.0")
|
||||||
|
: this(name, programId, version)
|
||||||
|
{
|
||||||
|
_contentManager = contentManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppletMetadata(string name, ulong programId, string version = "1.0.0")
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
ProgramId = programId;
|
||||||
|
Version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetContentPath(ContentManager contentManager)
|
||||||
|
=> (contentManager ?? _contentManager)
|
||||||
|
.GetInstalledContentPath(ProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
|
||||||
|
|
||||||
|
public bool CanStart(ContentManager contentManager, out ApplicationData appData, out BlitStruct<ApplicationControlProperty> appControl)
|
||||||
|
{
|
||||||
|
contentManager ??= _contentManager;
|
||||||
|
if (contentManager == null)
|
||||||
|
{
|
||||||
|
appData = null;
|
||||||
|
appControl = new BlitStruct<ApplicationControlProperty>(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
appData = new()
|
||||||
|
{
|
||||||
|
Name = Name,
|
||||||
|
Id = ProgramId,
|
||||||
|
Path = GetContentPath(contentManager)
|
||||||
|
};
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(appData.Path))
|
||||||
|
{
|
||||||
|
appControl = new BlitStruct<ApplicationControlProperty>(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
appControl = StructHelpers.CreateCustomNacpData(Name, Version);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 609 KiB |
@@ -33,7 +33,7 @@
|
|||||||
<EmbeddedResource Include="Resources\Icon_XCI.png" />
|
<EmbeddedResource Include="Resources\Icon_XCI.png" />
|
||||||
<EmbeddedResource Include="Resources\Logo_Amiibo.png" />
|
<EmbeddedResource Include="Resources\Logo_Amiibo.png" />
|
||||||
<EmbeddedResource Include="Resources\Logo_Ryujinx.png" />
|
<EmbeddedResource Include="Resources\Logo_Ryujinx.png" />
|
||||||
<EmbeddedResource Include="Resources\Logo_Thiccjinx.png" />
|
<EmbeddedResource Include="Resources\Logo_Ryujinx_AntiAlias.png" />
|
||||||
<EmbeddedResource Include="Resources\Logo_Discord_Dark.png" />
|
<EmbeddedResource Include="Resources\Logo_Discord_Dark.png" />
|
||||||
<EmbeddedResource Include="Resources\Logo_Discord_Light.png" />
|
<EmbeddedResource Include="Resources\Logo_Discord_Light.png" />
|
||||||
<EmbeddedResource Include="Resources\Logo_GitHub_Dark.png" />
|
<EmbeddedResource Include="Resources\Logo_GitHub_Dark.png" />
|
||||||
|
|||||||
+8
-32
@@ -143,23 +143,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,
|
||||||
@@ -912,27 +895,20 @@ namespace Ryujinx.Ava
|
|||||||
VirtualFileSystem.ReloadKeySet();
|
VirtualFileSystem.ReloadKeySet();
|
||||||
|
|
||||||
// Initialize Renderer.
|
// Initialize Renderer.
|
||||||
IRenderer renderer;
|
GraphicsBackend backend = TitleIDs.SelectGraphicsBackend(ApplicationId.ToString("X16"), ConfigurationState.Instance.Graphics.GraphicsBackend);
|
||||||
GraphicsBackend backend = ConfigurationState.Instance.Graphics.GraphicsBackend;
|
|
||||||
|
|
||||||
if (ShouldInitMetal)
|
IRenderer renderer = backend switch
|
||||||
{
|
{
|
||||||
#pragma warning disable CA1416 // This call site is reachable on all platforms
|
#pragma warning disable CA1416 // This call site is reachable on all platforms
|
||||||
// The condition does a check for Mac, on top of checking if it's an ARM Mac. This isn't a problem.
|
// SelectGraphicsBackend 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);
|
GraphicsBackend.Metal => new MetalRenderer((RendererHost.EmbeddedWindow as EmbeddedWindowMetal)!.CreateSurface),
|
||||||
#pragma warning restore CA1416
|
#pragma warning restore CA1416
|
||||||
}
|
GraphicsBackend.Vulkan => VulkanRenderer.Create(
|
||||||
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),
|
||||||
}
|
_ => new OpenGLRenderer()
|
||||||
else
|
};
|
||||||
{
|
|
||||||
renderer = new OpenGLRenderer();
|
|
||||||
}
|
|
||||||
|
|
||||||
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
BackendThreading threadingMode = ConfigurationState.Instance.Graphics.BackendThreading;
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -1042,7 +1042,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "720p",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -1066,7 +1066,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "1080p",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -2122,7 +2122,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "ExeFS",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -2170,7 +2170,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "RomFS",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -2218,7 +2218,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "ロゴ",
|
"ja_JP": "ロゴ",
|
||||||
"ko_KR": "로고",
|
"ko_KR": "로고",
|
||||||
"no_NO": "Logo",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "Логотип",
|
"ru_RU": "Логотип",
|
||||||
@@ -3130,7 +3130,7 @@
|
|||||||
"it_IT": "Sistema",
|
"it_IT": "Sistema",
|
||||||
"ja_JP": "システム",
|
"ja_JP": "システム",
|
||||||
"ko_KR": "시스템",
|
"ko_KR": "시스템",
|
||||||
"no_NO": "System",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Sistema",
|
"pt_BR": "Sistema",
|
||||||
"ru_RU": "Система",
|
"ru_RU": "Система",
|
||||||
@@ -3202,7 +3202,7 @@
|
|||||||
"it_IT": "Giappone",
|
"it_IT": "Giappone",
|
||||||
"ja_JP": "日本",
|
"ja_JP": "日本",
|
||||||
"ko_KR": "일본",
|
"ko_KR": "일본",
|
||||||
"no_NO": "Japan",
|
"no_NO": "",
|
||||||
"pl_PL": "Japonia",
|
"pl_PL": "Japonia",
|
||||||
"pt_BR": "Japão",
|
"pt_BR": "Japão",
|
||||||
"ru_RU": "Япония",
|
"ru_RU": "Япония",
|
||||||
@@ -3226,7 +3226,7 @@
|
|||||||
"it_IT": "Stati Uniti d'America",
|
"it_IT": "Stati Uniti d'America",
|
||||||
"ja_JP": "アメリカ",
|
"ja_JP": "アメリカ",
|
||||||
"ko_KR": "미국",
|
"ko_KR": "미국",
|
||||||
"no_NO": "USA",
|
"no_NO": "",
|
||||||
"pl_PL": "Stany Zjednoczone",
|
"pl_PL": "Stany Zjednoczone",
|
||||||
"pt_BR": "EUA",
|
"pt_BR": "EUA",
|
||||||
"ru_RU": "США",
|
"ru_RU": "США",
|
||||||
@@ -3274,7 +3274,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "オーストラリア",
|
"ja_JP": "オーストラリア",
|
||||||
"ko_KR": "호주",
|
"ko_KR": "호주",
|
||||||
"no_NO": "Australia",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Austrália",
|
"pt_BR": "Austrália",
|
||||||
"ru_RU": "Австралия",
|
"ru_RU": "Австралия",
|
||||||
@@ -3322,7 +3322,7 @@
|
|||||||
"it_IT": "Corea",
|
"it_IT": "Corea",
|
||||||
"ja_JP": "韓国",
|
"ja_JP": "韓国",
|
||||||
"ko_KR": "한국",
|
"ko_KR": "한국",
|
||||||
"no_NO": "Korea",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "Coreia",
|
"pt_BR": "Coreia",
|
||||||
"ru_RU": "Корея",
|
"ru_RU": "Корея",
|
||||||
@@ -3346,7 +3346,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "台湾",
|
"ja_JP": "台湾",
|
||||||
"ko_KR": "대만",
|
"ko_KR": "대만",
|
||||||
"no_NO": "Taiwan",
|
"no_NO": "",
|
||||||
"pl_PL": "Tajwan",
|
"pl_PL": "Tajwan",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "Тайвань",
|
"ru_RU": "Тайвань",
|
||||||
@@ -3797,7 +3797,7 @@
|
|||||||
"el_GR": "Ζώνη Ώρας Συστήματος:",
|
"el_GR": "Ζώνη Ώρας Συστήματος:",
|
||||||
"en_US": "System Time Zone:",
|
"en_US": "System Time Zone:",
|
||||||
"es_ES": "Zona horaria del sistema:",
|
"es_ES": "Zona horaria del sistema:",
|
||||||
"fr_FR": "Fuseau horaire du système :",
|
"fr_FR": "Fuseau horaire du système\u00A0:",
|
||||||
"he_IL": "אזור זמן מערכת:",
|
"he_IL": "אזור זמן מערכת:",
|
||||||
"it_IT": "Fuso orario del sistema:",
|
"it_IT": "Fuso orario del sistema:",
|
||||||
"ja_JP": "タイムゾーン:",
|
"ja_JP": "タイムゾーン:",
|
||||||
@@ -3970,7 +3970,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "ダミー",
|
"ja_JP": "ダミー",
|
||||||
"ko_KR": "더미",
|
"ko_KR": "더미",
|
||||||
"no_NO": "Dummy",
|
"no_NO": "",
|
||||||
"pl_PL": "Atrapa",
|
"pl_PL": "Atrapa",
|
||||||
"pt_BR": "Nenhuma",
|
"pt_BR": "Nenhuma",
|
||||||
"ru_RU": "Без звука",
|
"ru_RU": "Без звука",
|
||||||
@@ -3994,7 +3994,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "OpenAL",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4042,7 +4042,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "SDL2",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4061,12 +4061,12 @@
|
|||||||
"el_GR": "Μικροδιορθώσεις",
|
"el_GR": "Μικροδιορθώσεις",
|
||||||
"en_US": "Hacks",
|
"en_US": "Hacks",
|
||||||
"es_ES": "",
|
"es_ES": "",
|
||||||
"fr_FR": "Hacks",
|
"fr_FR": "",
|
||||||
"he_IL": "האצות",
|
"he_IL": "האצות",
|
||||||
"it_IT": "Espedienti",
|
"it_IT": "Espedienti",
|
||||||
"ja_JP": "ハック",
|
"ja_JP": "ハック",
|
||||||
"ko_KR": "핵",
|
"ko_KR": "핵",
|
||||||
"no_NO": "Hacks",
|
"no_NO": "",
|
||||||
"pl_PL": "Hacki",
|
"pl_PL": "Hacki",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "Хаки",
|
"ru_RU": "Хаки",
|
||||||
@@ -4402,7 +4402,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "2배",
|
"ko_KR": "2배",
|
||||||
"no_NO": "2x",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4426,7 +4426,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "4배",
|
"ko_KR": "4배",
|
||||||
"no_NO": "4x",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4450,7 +4450,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "8배",
|
"ko_KR": "8배",
|
||||||
"no_NO": "8x",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4474,7 +4474,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "16배",
|
"ko_KR": "16배",
|
||||||
"no_NO": "16x",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4570,7 +4570,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "2배(1440p/2160p)",
|
"ko_KR": "2배(1440p/2160p)",
|
||||||
"no_NO": "2x (1440p/2160p)",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4594,7 +4594,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "3배(2160p/3240p)",
|
"ko_KR": "3배(2160p/3240p)",
|
||||||
"no_NO": "3x (2160p/3240p)",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4666,7 +4666,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "4:3",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4690,7 +4690,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "16:9",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4714,7 +4714,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "16:10",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4738,7 +4738,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "21:9",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4762,7 +4762,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "32:9",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -4858,7 +4858,7 @@
|
|||||||
"it_IT": "Log",
|
"it_IT": "Log",
|
||||||
"ja_JP": "ロギング",
|
"ja_JP": "ロギング",
|
||||||
"ko_KR": "로그 기록",
|
"ko_KR": "로그 기록",
|
||||||
"no_NO": "Logging",
|
"no_NO": "",
|
||||||
"pl_PL": "Dziennik zdarzeń",
|
"pl_PL": "Dziennik zdarzeń",
|
||||||
"pt_BR": "Log",
|
"pt_BR": "Log",
|
||||||
"ru_RU": "Журналирование",
|
"ru_RU": "Журналирование",
|
||||||
@@ -4882,7 +4882,7 @@
|
|||||||
"it_IT": "Log",
|
"it_IT": "Log",
|
||||||
"ja_JP": "ロギング",
|
"ja_JP": "ロギング",
|
||||||
"ko_KR": "로그 기록",
|
"ko_KR": "로그 기록",
|
||||||
"no_NO": "Logging",
|
"no_NO": "",
|
||||||
"pl_PL": "Dziennik zdarzeń",
|
"pl_PL": "Dziennik zdarzeń",
|
||||||
"pt_BR": "Log",
|
"pt_BR": "Log",
|
||||||
"ru_RU": "Журналирование",
|
"ru_RU": "Журналирование",
|
||||||
@@ -5434,7 +5434,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "확인",
|
"ko_KR": "확인",
|
||||||
"no_NO": "OK",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "Ок",
|
"ru_RU": "Ок",
|
||||||
@@ -6106,7 +6106,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "A",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -6130,7 +6130,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "B",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -6154,7 +6154,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "X",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -6178,7 +6178,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "",
|
"ko_KR": "",
|
||||||
"no_NO": "Y",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -15125,7 +15125,7 @@
|
|||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "Aspect Ratio applied to the renderer window.\n\nOnly change this if you're using an aspect ratio mod for your game, otherwise the graphics will be stretched.\n\nLeave on 16:9 if unsure.",
|
"en_US": "Aspect Ratio applied to the renderer window.\n\nOnly change this if you're using an aspect ratio mod for your game, otherwise the graphics will be stretched.\n\nLeave on 16:9 if unsure.",
|
||||||
"es_ES": "Relación de aspecto aplicada a la ventana del renderizador.\n\nSolamente modificar esto si estás utilizando un mod de relación de aspecto para su juego, en cualquier otro caso los gráficos se estirarán.\n\nDejar en 16:9 si no sabe que hacer.",
|
"es_ES": "Relación de aspecto aplicada a la ventana del renderizador.\n\nSolamente modificar esto si estás utilizando un mod de relación de aspecto para su juego, en cualquier otro caso los gráficos se estirarán.\n\nDejar en 16:9 si no sabe que hacer.",
|
||||||
"fr_FR": "Format d'affichage appliqué à la fenêtre du moteur de rendu.\n\nChangez cela uniquement si vous utilisez un mod changeant le format d'affichage pour votre jeu, sinon les graphismes seront étirés.\n\nLaissez sur 16:9 si vous n'êtes pas sûr.",
|
"fr_FR": "Format\u00A0d'affichage appliqué à la fenêtre du moteur de rendu.\n\nChangez cela uniquement si vous utilisez un mod changeant le format\u00A0d'affichage pour votre jeu, sinon les graphismes seront étirés.\n\nLaissez sur 16:9 si vous n'êtes pas sûr.",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "Proporzioni dello schermo applicate alla finestra di renderizzazione.\n\nCambialo solo se stai usando una mod di proporzioni per il tuo gioco, altrimenti la grafica verrà allungata.\n\nLasciare il 16:9 se incerto.",
|
"it_IT": "Proporzioni dello schermo applicate alla finestra di renderizzazione.\n\nCambialo solo se stai usando una mod di proporzioni per il tuo gioco, altrimenti la grafica verrà allungata.\n\nLasciare il 16:9 se incerto.",
|
||||||
"ja_JP": "レンダリングウインドウに適用するアスペクト比です.\n\nゲームにアスペクト比を変更する mod を使用している場合のみ変更してください.\n\nわからない場合は16:9のままにしておいてください.\n",
|
"ja_JP": "レンダリングウインドウに適用するアスペクト比です.\n\nゲームにアスペクト比を変更する mod を使用している場合のみ変更してください.\n\nわからない場合は16:9のままにしておいてください.\n",
|
||||||
@@ -18658,7 +18658,7 @@
|
|||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
"ko_KR": "XCI 파일 트리머",
|
"ko_KR": "XCI 파일 트리머",
|
||||||
"no_NO": "XCI File Trimmer",
|
"no_NO": "",
|
||||||
"pl_PL": "",
|
"pl_PL": "",
|
||||||
"pt_BR": "",
|
"pt_BR": "",
|
||||||
"ru_RU": "",
|
"ru_RU": "",
|
||||||
@@ -20213,7 +20213,7 @@
|
|||||||
"el_GR": "Όνομα",
|
"el_GR": "Όνομα",
|
||||||
"en_US": "Name",
|
"en_US": "Name",
|
||||||
"es_ES": "Nombre",
|
"es_ES": "Nombre",
|
||||||
"fr_FR": "Nom ",
|
"fr_FR": "Nom\u00A0",
|
||||||
"he_IL": "שם",
|
"he_IL": "שם",
|
||||||
"it_IT": "Nome",
|
"it_IT": "Nome",
|
||||||
"ja_JP": "名称",
|
"ja_JP": "名称",
|
||||||
@@ -21365,7 +21365,7 @@
|
|||||||
"el_GR": "",
|
"el_GR": "",
|
||||||
"en_US": "Switch",
|
"en_US": "Switch",
|
||||||
"es_ES": "",
|
"es_ES": "",
|
||||||
"fr_FR": "Switch",
|
"fr_FR": "",
|
||||||
"he_IL": "",
|
"he_IL": "",
|
||||||
"it_IT": "",
|
"it_IT": "",
|
||||||
"ja_JP": "",
|
"ja_JP": "",
|
||||||
@@ -21694,4 +21694,4 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using Gommon;
|
using Gommon;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Logging;
|
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
using System;
|
using System;
|
||||||
@@ -17,7 +16,6 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
private const string DefaultLanguageCode = "en_US";
|
private const string DefaultLanguageCode = "en_US";
|
||||||
|
|
||||||
private readonly Dictionary<LocaleKeys, string> _localeStrings;
|
private readonly Dictionary<LocaleKeys, string> _localeStrings;
|
||||||
private Dictionary<LocaleKeys, string> _localeDefaultStrings;
|
|
||||||
private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues;
|
private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues;
|
||||||
private string _localeLanguageCode;
|
private string _localeLanguageCode;
|
||||||
|
|
||||||
@@ -27,7 +25,6 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
public LocaleManager()
|
public LocaleManager()
|
||||||
{
|
{
|
||||||
_localeStrings = new Dictionary<LocaleKeys, string>();
|
_localeStrings = new Dictionary<LocaleKeys, string>();
|
||||||
_localeDefaultStrings = new Dictionary<LocaleKeys, string>();
|
|
||||||
_dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>();
|
_dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>();
|
||||||
|
|
||||||
Load();
|
Load();
|
||||||
@@ -37,9 +34,7 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
{
|
{
|
||||||
var localeLanguageCode = !string.IsNullOrEmpty(ConfigurationState.Instance.UI.LanguageCode.Value) ?
|
var localeLanguageCode = !string.IsNullOrEmpty(ConfigurationState.Instance.UI.LanguageCode.Value) ?
|
||||||
ConfigurationState.Instance.UI.LanguageCode.Value : CultureInfo.CurrentCulture.Name.Replace('-', '_');
|
ConfigurationState.Instance.UI.LanguageCode.Value : CultureInfo.CurrentCulture.Name.Replace('-', '_');
|
||||||
|
|
||||||
// Load en_US as default, if the target language translation is missing or incomplete.
|
|
||||||
LoadDefaultLanguage();
|
|
||||||
LoadLanguage(localeLanguageCode);
|
LoadLanguage(localeLanguageCode);
|
||||||
|
|
||||||
// Save whatever we ended up with.
|
// Save whatever we ended up with.
|
||||||
@@ -66,26 +61,14 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
// If formatting failed use the default text instead.
|
// If formatting the text failed,
|
||||||
if (_localeDefaultStrings.TryGetValue(key, out value))
|
// continue to the below line & return the text without formatting.
|
||||||
try
|
|
||||||
{
|
|
||||||
return string.Format(value, dynamicValue);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// If formatting the default text failed return the key.
|
|
||||||
return key.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the locale doesn't contain the key return the default one.
|
return key.ToString(); // If the locale text doesn't exist return the key.
|
||||||
return _localeDefaultStrings.TryGetValue(key, out string defaultValue)
|
|
||||||
? defaultValue
|
|
||||||
: key.ToString(); // If the locale text doesn't exist return the key.
|
|
||||||
}
|
}
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
@@ -109,16 +92,11 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
{
|
{
|
||||||
_dynamicValues[key] = values;
|
_dynamicValues[key] = values;
|
||||||
|
|
||||||
OnPropertyChanged("Item");
|
OnPropertyChanged("Translation");
|
||||||
|
|
||||||
return this[key];
|
return this[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadDefaultLanguage()
|
|
||||||
{
|
|
||||||
_localeDefaultStrings = LoadJsonLanguage(DefaultLanguageCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void LoadLanguage(string languageCode)
|
public void LoadLanguage(string languageCode)
|
||||||
{
|
{
|
||||||
var locale = LoadJsonLanguage(languageCode);
|
var locale = LoadJsonLanguage(languageCode);
|
||||||
@@ -126,7 +104,7 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
if (locale == null)
|
if (locale == null)
|
||||||
{
|
{
|
||||||
_localeLanguageCode = DefaultLanguageCode;
|
_localeLanguageCode = DefaultLanguageCode;
|
||||||
locale = _localeDefaultStrings;
|
locale = LoadJsonLanguage(_localeLanguageCode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -138,16 +116,12 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
_localeStrings[key] = val;
|
_localeStrings[key] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnPropertyChanged("Item");
|
OnPropertyChanged("Translation");
|
||||||
|
|
||||||
LocaleChanged?.Invoke();
|
LocaleChanged?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
#nullable enable
|
|
||||||
|
|
||||||
private static LocalesJson? _localeData;
|
private static LocalesJson? _localeData;
|
||||||
|
|
||||||
#nullable disable
|
|
||||||
|
|
||||||
private static Dictionary<LocaleKeys, string> LoadJsonLanguage(string languageCode)
|
private static Dictionary<LocaleKeys, string> LoadJsonLanguage(string languageCode)
|
||||||
{
|
{
|
||||||
@@ -158,18 +132,29 @@ namespace Ryujinx.Ava.Common.Locale
|
|||||||
|
|
||||||
foreach (LocalesEntry locale in _localeData.Value.Locales)
|
foreach (LocalesEntry locale in _localeData.Value.Locales)
|
||||||
{
|
{
|
||||||
if (locale.Translations.Count != _localeData.Value.Languages.Count)
|
if (locale.Translations.Count < _localeData.Value.Languages.Count)
|
||||||
{
|
{
|
||||||
throw new Exception($"Locale key {{{locale.ID}}} is missing languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!");
|
throw new Exception($"Locale key {{{locale.ID}}} is missing languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locale.Translations.Count > _localeData.Value.Languages.Count)
|
||||||
|
{
|
||||||
|
throw new Exception($"Locale key {{{locale.ID}}} has too many languages! Has {locale.Translations.Count} translations, expected {_localeData.Value.Languages.Count}!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Enum.TryParse<LocaleKeys>(locale.ID, out var localeKey))
|
if (!Enum.TryParse<LocaleKeys>(locale.ID, out var localeKey))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
localeStrings[localeKey] =
|
var str = locale.Translations.TryGetValue(languageCode, out string val) && !string.IsNullOrEmpty(val)
|
||||||
locale.Translations.TryGetValue(languageCode, out string val) && val != string.Empty
|
? val
|
||||||
? val
|
: locale.Translations[DefaultLanguageCode];
|
||||||
: locale.Translations[DefaultLanguageCode];
|
|
||||||
|
if (string.IsNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
throw new Exception($"Locale key '{locale.ID}' has no valid translations for desired language {languageCode}! {DefaultLanguageCode} is an empty string or null");
|
||||||
|
}
|
||||||
|
|
||||||
|
localeStrings[localeKey] = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
return localeStrings;
|
return localeStrings;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Ryujinx.Ava.Common.Markup
|
|||||||
{
|
{
|
||||||
internal abstract class BasicMarkupExtension<T> : MarkupExtension
|
internal abstract class BasicMarkupExtension<T> : MarkupExtension
|
||||||
{
|
{
|
||||||
public virtual string Name => "Item";
|
public abstract string Name { get; }
|
||||||
public virtual Action<object, T?>? Setter => null;
|
public virtual Action<object, T?>? Setter => null;
|
||||||
|
|
||||||
protected abstract T? Value { get; }
|
protected abstract T? Value { get; }
|
||||||
|
|||||||
@@ -6,16 +6,19 @@ namespace Ryujinx.Ava.Common.Markup
|
|||||||
{
|
{
|
||||||
internal class IconExtension(string iconString) : BasicMarkupExtension<Icon>
|
internal class IconExtension(string iconString) : BasicMarkupExtension<Icon>
|
||||||
{
|
{
|
||||||
|
public override string Name => "Icon";
|
||||||
protected override Icon Value => new() { Value = iconString };
|
protected override Icon Value => new() { Value = iconString };
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class SpinningIconExtension(string iconString) : BasicMarkupExtension<Icon>
|
internal class SpinningIconExtension(string iconString) : BasicMarkupExtension<Icon>
|
||||||
{
|
{
|
||||||
|
public override string Name => "SIcon";
|
||||||
protected override Icon Value => new() { Value = iconString, Animation = IconAnimation.Spin };
|
protected override Icon Value => new() { Value = iconString, Animation = IconAnimation.Spin };
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class LocaleExtension(LocaleKeys key) : BasicMarkupExtension<string>
|
internal class LocaleExtension(LocaleKeys key) : BasicMarkupExtension<string>
|
||||||
{
|
{
|
||||||
|
public override string Name => "Translation";
|
||||||
protected override string Value => LocaleManager.Instance[key];
|
protected override string Value => LocaleManager.Instance[key];
|
||||||
|
|
||||||
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
protected override void ConfigureBindingExtension(CompiledBindingExtension bindingExtension)
|
||||||
|
|||||||
@@ -13,9 +13,13 @@
|
|||||||
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);._*</DefaultItemExcludes>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<Target Name="BuildValidationProj" BeforeTargets="BeforeRebuild">
|
<Target Name="BuildValidationProj" BeforeTargets="BeforeBuild">
|
||||||
<MSBuild Projects="..\Ryujinx.BuildValidationTasks\Ryujinx.BuildValidationTasks.csproj" Targets="Rebuild">
|
<Message Text="Building Validation Project for $(TargetFramework)" Importance="high" Condition="'$(RuntimeIdentifier)' == ''" />
|
||||||
</MSBuild>
|
<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" />
|
||||||
|
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
|
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$([MSBuild]::IsOSPlatform('OSX'))">
|
||||||
|
|||||||
@@ -98,9 +98,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 +116,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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -106,7 +105,6 @@
|
|||||||
Click="IdString_OnClick"
|
Click="IdString_OnClick"
|
||||||
HorizontalContentAlignment="Left"
|
HorizontalContentAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
|
||||||
Background="{DynamicResource AppListBackgroundColor}"
|
Background="{DynamicResource AppListBackgroundColor}"
|
||||||
Margin="-1, 0, 0, 0"
|
Margin="-1, 0, 0, 0"
|
||||||
Padding="0" >
|
Padding="0" >
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
|
namespace Ryujinx.Ava.UI.Controls
|
||||||
|
{
|
||||||
|
public class MiniVerticalSeparator : Border
|
||||||
|
{
|
||||||
|
public MiniVerticalSeparator()
|
||||||
|
{
|
||||||
|
Width = 2;
|
||||||
|
Height = 12;
|
||||||
|
Margin = new Thickness();
|
||||||
|
BorderBrush = Brushes.Gray;
|
||||||
|
Background = Brushes.Gray;
|
||||||
|
BorderThickness = new Thickness(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
using Avalonia.Data.Converters;
|
using Avalonia.Data.Converters;
|
||||||
|
using Gommon;
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.UI.Common.Models;
|
using Ryujinx.UI.Common.Models;
|
||||||
using System;
|
using System;
|
||||||
@@ -32,11 +33,11 @@ namespace Ryujinx.Ava.UI.Helpers
|
|||||||
|
|
||||||
if (app.CurrentSavingsB < app.PotentialSavingsB)
|
if (app.CurrentSavingsB < app.PotentialSavingsB)
|
||||||
{
|
{
|
||||||
return LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleXCICanSaveLabel, (app.PotentialSavingsB - app.CurrentSavingsB) / _bytesPerMB);
|
return LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleXCICanSaveLabel, ((app.PotentialSavingsB - app.CurrentSavingsB) / _bytesPerMB).CoerceAtLeast(0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleXCISavingLabel, app.CurrentSavingsB / _bytesPerMB);
|
return LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleXCISavingLabel, (app.CurrentSavingsB / _bytesPerMB).CoerceAtLeast(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
@@ -31,15 +32,6 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||||||
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 =>
|
public GraphicsBackend Backend =>
|
||||||
EmbeddedWindow switch
|
EmbeddedWindow switch
|
||||||
{
|
{
|
||||||
@@ -53,16 +45,8 @@ namespace Ryujinx.Ava.UI.Renderer
|
|||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
switch (ConfigurationState.Instance.Graphics.GraphicsBackend.Value)
|
switch (TitleIDs.SelectGraphicsBackend(titleId, ConfigurationState.Instance.Graphics.GraphicsBackend))
|
||||||
{
|
{
|
||||||
case GraphicsBackend.Auto:
|
|
||||||
EmbeddedWindow =
|
|
||||||
OperatingSystem.IsMacOS() &&
|
|
||||||
RuntimeInformation.ProcessArchitecture == Architecture.Arm64 &&
|
|
||||||
KnownGreatMetalTitles.ContainsIgnoreCase(titleId)
|
|
||||||
? new EmbeddedWindowMetal()
|
|
||||||
: new EmbeddedWindowVulkan();
|
|
||||||
break;
|
|
||||||
case GraphicsBackend.OpenGl:
|
case GraphicsBackend.OpenGl:
|
||||||
EmbeddedWindow = new EmbeddedWindowOpenGL();
|
EmbeddedWindow = new EmbeddedWindowOpenGL();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
@@ -11,5 +12,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void OnPropertiesChanged(params ReadOnlySpan<string> propertyNames)
|
||||||
|
{
|
||||||
|
foreach (var propertyName in propertyNames)
|
||||||
|
{
|
||||||
|
OnPropertyChanged(propertyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
|
// For an example of this, download canary 1.2.95, then open the settings menu, and look at the icon in the top-left.
|
||||||
// The border gets reduced to colored pixels in the 4 corners.
|
// The border gets reduced to colored pixels in the 4 corners.
|
||||||
public static readonly Bitmap IconBitmap =
|
public static readonly Bitmap IconBitmap =
|
||||||
new(Assembly.GetAssembly(typeof(ConfigurationState))!.GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Thiccjinx.png")!);
|
new(Assembly.GetAssembly(typeof(ConfigurationState))!.GetManifestResourceStream("Ryujinx.UI.Common.Resources.Logo_Ryujinx_AntiAlias.png")!);
|
||||||
|
|
||||||
public MainWindow Window { get; init; }
|
public MainWindow Window { get; init; }
|
||||||
|
|
||||||
|
|||||||
@@ -71,8 +71,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
{
|
{
|
||||||
_resolutionScale = value;
|
_resolutionScale = value;
|
||||||
|
|
||||||
OnPropertyChanged(nameof(CustomResolutionScale));
|
OnPropertiesChanged(nameof(CustomResolutionScale), nameof(IsCustomResolutionScaleActive));
|
||||||
OnPropertyChanged(nameof(IsCustomResolutionScaleActive));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,8 +180,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
int newInterval = (int)((value / 100f) * 60);
|
int newInterval = (int)((value / 100f) * 60);
|
||||||
_customVSyncInterval = newInterval;
|
_customVSyncInterval = newInterval;
|
||||||
_customVSyncIntervalPercentageProxy = value;
|
_customVSyncIntervalPercentageProxy = value;
|
||||||
OnPropertyChanged((nameof(CustomVSyncInterval)));
|
OnPropertiesChanged(
|
||||||
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText)));
|
nameof(CustomVSyncInterval),
|
||||||
|
nameof(CustomVSyncIntervalPercentageText));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
string text = CustomVSyncIntervalPercentageProxy.ToString() + "%";
|
string text = CustomVSyncIntervalPercentageProxy + "%";
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,8 +221,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
_customVSyncInterval = value;
|
_customVSyncInterval = value;
|
||||||
int newPercent = (int)((value / 60f) * 100);
|
int newPercent = (int)((value / 60f) * 100);
|
||||||
_customVSyncIntervalPercentageProxy = newPercent;
|
_customVSyncIntervalPercentageProxy = newPercent;
|
||||||
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
|
OnPropertiesChanged(
|
||||||
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
|
nameof(CustomVSyncIntervalPercentageProxy),
|
||||||
|
nameof(CustomVSyncIntervalPercentageText));
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -91,39 +91,42 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
private void SortingChanged()
|
private void SortingChanged()
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(IsSortedByName));
|
OnPropertiesChanged(
|
||||||
OnPropertyChanged(nameof(IsSortedBySaved));
|
nameof(IsSortedByName),
|
||||||
OnPropertyChanged(nameof(SortingAscending));
|
nameof(IsSortedBySaved),
|
||||||
OnPropertyChanged(nameof(SortingField));
|
nameof(SortingAscending),
|
||||||
OnPropertyChanged(nameof(SortingFieldName));
|
nameof(SortingField),
|
||||||
|
nameof(SortingFieldName));
|
||||||
|
|
||||||
SortAndFilter();
|
SortAndFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisplayedChanged()
|
private void DisplayedChanged()
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(Status));
|
OnPropertiesChanged(nameof(Status), nameof(DisplayedXCIFiles), nameof(SelectedDisplayedXCIFiles));
|
||||||
OnPropertyChanged(nameof(DisplayedXCIFiles));
|
|
||||||
OnPropertyChanged(nameof(SelectedDisplayedXCIFiles));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplicationsChanged()
|
private void ApplicationsChanged()
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(AllXCIFiles));
|
OnPropertiesChanged(
|
||||||
OnPropertyChanged(nameof(Status));
|
nameof(AllXCIFiles),
|
||||||
OnPropertyChanged(nameof(PotentialSavings));
|
nameof(Status),
|
||||||
OnPropertyChanged(nameof(ActualSavings));
|
nameof(PotentialSavings),
|
||||||
OnPropertyChanged(nameof(CanTrim));
|
nameof(ActualSavings),
|
||||||
OnPropertyChanged(nameof(CanUntrim));
|
nameof(CanTrim),
|
||||||
|
nameof(CanUntrim));
|
||||||
|
|
||||||
DisplayedChanged();
|
DisplayedChanged();
|
||||||
SortAndFilter();
|
SortAndFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SelectionChanged(bool displayedChanged = true)
|
private void SelectionChanged(bool displayedChanged = true)
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(Status));
|
OnPropertiesChanged(
|
||||||
OnPropertyChanged(nameof(CanTrim));
|
nameof(Status),
|
||||||
OnPropertyChanged(nameof(CanUntrim));
|
nameof(CanTrim),
|
||||||
OnPropertyChanged(nameof(SelectedXCIFiles));
|
nameof(CanUntrim),
|
||||||
|
nameof(SelectedXCIFiles));
|
||||||
|
|
||||||
if (displayedChanged)
|
if (displayedChanged)
|
||||||
OnPropertyChanged(nameof(SelectedDisplayedXCIFiles));
|
OnPropertyChanged(nameof(SelectedDisplayedXCIFiles));
|
||||||
@@ -131,11 +134,12 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
|
|
||||||
private void ProcessingChanged()
|
private void ProcessingChanged()
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(Processing));
|
OnPropertiesChanged(
|
||||||
OnPropertyChanged(nameof(Cancel));
|
nameof(Processing),
|
||||||
OnPropertyChanged(nameof(Status));
|
nameof(Cancel),
|
||||||
OnPropertyChanged(nameof(CanTrim));
|
nameof(Status),
|
||||||
OnPropertyChanged(nameof(CanUntrim));
|
nameof(CanTrim),
|
||||||
|
nameof(CanUntrim));
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<XCITrimmerFileModel> GetSelectedDisplayedXCIFiles()
|
private IEnumerable<XCITrimmerFileModel> GetSelectedDisplayedXCIFiles()
|
||||||
@@ -360,7 +364,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
|||||||
value = _processingApplication.Value with { PercentageProgress = null };
|
value = _processingApplication.Value with { PercentageProgress = null };
|
||||||
|
|
||||||
if (value.HasValue)
|
if (value.HasValue)
|
||||||
_displayedXCIFiles.ReplaceWith(value.Value);
|
_displayedXCIFiles.ReplaceWith(value);
|
||||||
|
|
||||||
_processingApplication = value;
|
_processingApplication = value;
|
||||||
OnPropertyChanged();
|
OnPropertyChanged();
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
Height="25"
|
Height="25"
|
||||||
Width="25"
|
Width="25"
|
||||||
ToolTip.Tip="{Binding Title}"
|
ToolTip.Tip="{Binding Title}"
|
||||||
Source="resm:Ryujinx.UI.Common.Resources.Logo_Thiccjinx.png?assembly=Ryujinx.UI.Common" />
|
Source="resm:Ryujinx.UI.Common.Resources.Logo_Ryujinx_AntiAlias.png?assembly=Ryujinx.UI.Common" />
|
||||||
<Menu
|
<Menu
|
||||||
Name="Menu"
|
Name="Menu"
|
||||||
Height="32"
|
Height="32"
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
using Gommon;
|
using Gommon;
|
||||||
using LibHac.Ncm;
|
|
||||||
using LibHac.Tools.FsSystem.NcaUtils;
|
|
||||||
using Ryujinx.Ava.Common.Locale;
|
using Ryujinx.Ava.Common.Locale;
|
||||||
using Ryujinx.Ava.UI.Helpers;
|
using Ryujinx.Ava.UI.Helpers;
|
||||||
using Ryujinx.Ava.UI.ViewModels;
|
using Ryujinx.Ava.UI.ViewModels;
|
||||||
@@ -12,8 +10,6 @@ using Ryujinx.Ava.UI.Windows;
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Utilities;
|
using Ryujinx.Common.Utilities;
|
||||||
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
|
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
|
||||||
using Ryujinx.HLE;
|
|
||||||
using Ryujinx.UI.App.Common;
|
|
||||||
using Ryujinx.UI.Common;
|
using Ryujinx.UI.Common;
|
||||||
using Ryujinx.UI.Common.Configuration;
|
using Ryujinx.UI.Common.Configuration;
|
||||||
using Ryujinx.UI.Common.Helper;
|
using Ryujinx.UI.Common.Helper;
|
||||||
@@ -124,26 +120,13 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
ViewModel.LoadConfigurableHotKeys();
|
ViewModel.LoadConfigurableHotKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static readonly AppletMetadata MiiApplet = new("miiEdit", 0x0100000000001009);
|
||||||
|
|
||||||
public async void OpenMiiApplet(object sender, RoutedEventArgs e)
|
public async void OpenMiiApplet(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
const string AppletName = "miiEdit";
|
if (MiiApplet.CanStart(ViewModel.ContentManager, out var appData, out var nacpData))
|
||||||
const ulong AppletProgramId = 0x0100000000001009;
|
|
||||||
const string AppletVersion = "1.0.0";
|
|
||||||
|
|
||||||
string contentPath = ViewModel.ContentManager.GetInstalledContentPath(AppletProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(contentPath))
|
|
||||||
{
|
{
|
||||||
ApplicationData applicationData = new()
|
await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
|
||||||
{
|
|
||||||
Name = AppletName,
|
|
||||||
Id = AppletProgramId,
|
|
||||||
Path = contentPath
|
|
||||||
};
|
|
||||||
|
|
||||||
var nacpData = StructHelpers.CreateCustomNacpData(AppletName, AppletVersion);
|
|
||||||
|
|
||||||
await ViewModel.LoadApplication(applicationData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
|
||||||
|
xmlns:local="clr-namespace:Ryujinx.Ava.UI.Views.Main"
|
||||||
xmlns:config="clr-namespace:Ryujinx.Common.Configuration;assembly=Ryujinx.Common"
|
xmlns:config="clr-namespace:Ryujinx.Common.Configuration;assembly=Ryujinx.Common"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="Ryujinx.Ava.UI.Views.Main.MainStatusBarView"
|
x:Class="Ryujinx.Ava.UI.Views.Main.MainStatusBarView"
|
||||||
@@ -132,14 +133,7 @@
|
|||||||
</Flyout>
|
</Flyout>
|
||||||
</Button.Flyout>
|
</Button.Flyout>
|
||||||
</Button>
|
</Button>
|
||||||
<Border
|
<controls:MiniVerticalSeparator IsVisible="{Binding !ShowLoadProgress}" />
|
||||||
Width="2"
|
|
||||||
Height="12"
|
|
||||||
Margin="0"
|
|
||||||
BorderBrush="Gray"
|
|
||||||
Background="Gray"
|
|
||||||
BorderThickness="1"
|
|
||||||
IsVisible="{Binding !ShowLoadProgress}" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Name="DockedStatus"
|
Name="DockedStatus"
|
||||||
Margin="5,0,5,0"
|
Margin="5,0,5,0"
|
||||||
@@ -149,14 +143,7 @@
|
|||||||
PointerReleased="DockedStatus_PointerReleased"
|
PointerReleased="DockedStatus_PointerReleased"
|
||||||
Text="{Binding DockedStatusText}"
|
Text="{Binding DockedStatusText}"
|
||||||
TextAlignment="Start" />
|
TextAlignment="Start" />
|
||||||
<Border
|
<controls:MiniVerticalSeparator IsVisible="{Binding !ShowLoadProgress}" />
|
||||||
Width="2"
|
|
||||||
Height="12"
|
|
||||||
Margin="0"
|
|
||||||
BorderBrush="Gray"
|
|
||||||
Background="Gray"
|
|
||||||
BorderThickness="1"
|
|
||||||
IsVisible="{Binding !ShowLoadProgress}" />
|
|
||||||
<SplitButton
|
<SplitButton
|
||||||
Name="AspectRatioStatus"
|
Name="AspectRatioStatus"
|
||||||
Padding="5,0,5,0"
|
Padding="5,0,5,0"
|
||||||
@@ -203,14 +190,7 @@
|
|||||||
</MenuFlyout>
|
</MenuFlyout>
|
||||||
</SplitButton.Flyout>
|
</SplitButton.Flyout>
|
||||||
</SplitButton>
|
</SplitButton>
|
||||||
<Border
|
<controls:MiniVerticalSeparator IsVisible="{Binding !ShowLoadProgress}" />
|
||||||
Width="2"
|
|
||||||
Height="12"
|
|
||||||
Margin="0"
|
|
||||||
BorderBrush="Gray"
|
|
||||||
Background="Gray"
|
|
||||||
BorderThickness="1"
|
|
||||||
IsVisible="{Binding !ShowLoadProgress}" />
|
|
||||||
<ToggleSplitButton
|
<ToggleSplitButton
|
||||||
Name="VolumeStatus"
|
Name="VolumeStatus"
|
||||||
Padding="5,0,5,0"
|
Padding="5,0,5,0"
|
||||||
@@ -254,14 +234,7 @@
|
|||||||
</Flyout>
|
</Flyout>
|
||||||
</ToggleSplitButton.Flyout>
|
</ToggleSplitButton.Flyout>
|
||||||
</ToggleSplitButton>
|
</ToggleSplitButton>
|
||||||
<Border
|
<controls:MiniVerticalSeparator IsVisible="{Binding !ShowLoadProgress}" />
|
||||||
Width="2"
|
|
||||||
Height="12"
|
|
||||||
Margin="0"
|
|
||||||
BorderBrush="Gray"
|
|
||||||
Background="Gray"
|
|
||||||
BorderThickness="1"
|
|
||||||
IsVisible="{Binding !ShowLoadProgress}" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,5,0"
|
Margin="5,0,5,0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
@@ -269,14 +242,7 @@
|
|||||||
IsVisible="{Binding !ShowLoadProgress}"
|
IsVisible="{Binding !ShowLoadProgress}"
|
||||||
Text="{Binding GameStatusText}"
|
Text="{Binding GameStatusText}"
|
||||||
TextAlignment="Start" />
|
TextAlignment="Start" />
|
||||||
<Border
|
<controls:MiniVerticalSeparator IsVisible="{Binding !ShowLoadProgress}" />
|
||||||
Width="2"
|
|
||||||
Height="12"
|
|
||||||
Margin="0"
|
|
||||||
BorderBrush="Gray"
|
|
||||||
Background="Gray"
|
|
||||||
BorderThickness="1"
|
|
||||||
IsVisible="{Binding !ShowLoadProgress}" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,5,0"
|
Margin="5,0,5,0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
@@ -298,13 +264,7 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
IsVisible="{Binding ShowShaderCompilationHint}"
|
IsVisible="{Binding ShowShaderCompilationHint}"
|
||||||
Text="{Binding ShaderCountText}" />
|
Text="{Binding ShaderCountText}" />
|
||||||
<Border
|
<controls:MiniVerticalSeparator IsVisible="{Binding ShowShaderCompilationHint}" />
|
||||||
Width="2"
|
|
||||||
Height="12"
|
|
||||||
Margin="0"
|
|
||||||
BorderBrush="Gray"
|
|
||||||
BorderThickness="1"
|
|
||||||
IsVisible="{Binding ShowShaderCompilationHint}" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,5,0"
|
Margin="5,0,5,0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
@@ -312,14 +272,7 @@
|
|||||||
IsVisible="{Binding !ShowLoadProgress}"
|
IsVisible="{Binding !ShowLoadProgress}"
|
||||||
Text="{Binding BackendText}"
|
Text="{Binding BackendText}"
|
||||||
TextAlignment="Start" />
|
TextAlignment="Start" />
|
||||||
<Border
|
<controls:MiniVerticalSeparator IsVisible="{Binding !ShowLoadProgress}" />
|
||||||
Width="2"
|
|
||||||
Height="12"
|
|
||||||
Margin="0"
|
|
||||||
BorderBrush="Gray"
|
|
||||||
Background="Gray"
|
|
||||||
BorderThickness="1"
|
|
||||||
IsVisible="{Binding !ShowLoadProgress}" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="5,0,0,0"
|
Margin="5,0,0,0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
@@ -334,13 +287,7 @@
|
|||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
IsVisible="{Binding ShowFirmwareStatus}"
|
IsVisible="{Binding ShowFirmwareStatus}"
|
||||||
Orientation="Horizontal">
|
Orientation="Horizontal">
|
||||||
<Border
|
<controls:MiniVerticalSeparator IsVisible="{Binding IsGameRunning}" />
|
||||||
Width="2"
|
|
||||||
Height="12"
|
|
||||||
Margin="0"
|
|
||||||
BorderBrush="Gray"
|
|
||||||
BorderThickness="1"
|
|
||||||
IsVisible="{Binding IsGameRunning}" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Name="FirmwareStatus"
|
Name="FirmwareStatus"
|
||||||
Margin="5, 0, 0, 0"
|
Margin="5, 0, 0, 0"
|
||||||
|
|||||||
@@ -62,12 +62,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||||||
// Change the volume by 5% at a time
|
// Change the volume by 5% at a time
|
||||||
float newValue = Window.ViewModel.Volume + (float)e.Delta.Y * 0.05f;
|
float newValue = Window.ViewModel.Volume + (float)e.Delta.Y * 0.05f;
|
||||||
|
|
||||||
Window.ViewModel.Volume = newValue switch
|
Window.ViewModel.Volume = Math.Clamp(newValue, 0, 1);
|
||||||
{
|
|
||||||
< 0 => 0,
|
|
||||||
> 1 => 1,
|
|
||||||
_ => newValue,
|
|
||||||
};
|
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -91,12 +91,14 @@ namespace Ryujinx.Ava.UI.Windows
|
|||||||
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;
|
||||||
|
|
||||||
// Correctly size window when 'TitleBar' is enabled (Nov. 14, 2024)
|
|
||||||
TitleBarHeight = (ConfigurationState.Instance.ShowTitleBar ? TitleBar.Height : 0);
|
|
||||||
|
|
||||||
// NOTE: Height of MenuBar and StatusBar is not usable here, since it would still be 0 at this point.
|
// NOTE: Height of MenuBar and StatusBar is not usable here, since it would still be 0 at this point.
|
||||||
StatusBarHeight = StatusBarView.StatusBar.MinHeight;
|
StatusBarHeight = StatusBarView.StatusBar.MinHeight;
|
||||||
MenuBarHeight = MenuBar.MinHeight;
|
MenuBarHeight = MenuBar.MinHeight;
|
||||||
|
|
||||||
|
TitleBar.Height = MenuBarHeight;
|
||||||
|
|
||||||
|
// Correctly size window when 'TitleBar' is enabled (Nov. 14, 2024)
|
||||||
|
TitleBarHeight = (ConfigurationState.Instance.ShowTitleBar ? TitleBar.Height : 0);
|
||||||
|
|
||||||
ApplicationList.DataContext = DataContext;
|
ApplicationList.DataContext = DataContext;
|
||||||
ApplicationGrid.DataContext = DataContext;
|
ApplicationGrid.DataContext = DataContext;
|
||||||
|
|||||||
Reference in New Issue
Block a user