diff options
| author | Isaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com> | 2024-02-11 02:09:18 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-02-11 03:09:18 +0100 |
| commit | f06d22d6f01e657ebbc0c8ef082739cd468e47b5 (patch) | |
| tree | c10a566438d3801b33c1d7b4eff73ea62b2f1a63 /src/Ryujinx.UI.Common | |
| parent | 84d6e8d121a1b329d26cc0e462aadd1108d99a04 (diff) | |
Infra: Capitalisation Consistency (#6296)
* Rename Ryujinx.UI.Common
* Rename Ryujinx.UI.LocaleGenerator
* Update in Files
AboutWindow
* Configuration State
* Rename projects
* Ryujinx/UI
* Fix build
* Main remaining inconsistencies
* HLE.UI Namespace
* HLE.UI Files
* Namespace
* Ryujinx.UI.Common.Configuration.UI
* Ryujinx.UI.Common,Configuration.UI Files
* More instances
Diffstat (limited to 'src/Ryujinx.UI.Common')
64 files changed, 5524 insertions, 0 deletions
diff --git a/src/Ryujinx.UI.Common/App/ApplicationAddedEventArgs.cs b/src/Ryujinx.UI.Common/App/ApplicationAddedEventArgs.cs new file mode 100644 index 00000000..58e066b9 --- /dev/null +++ b/src/Ryujinx.UI.Common/App/ApplicationAddedEventArgs.cs @@ -0,0 +1,9 @@ +using System; + +namespace Ryujinx.UI.App.Common +{ + public class ApplicationAddedEventArgs : EventArgs + { + public ApplicationData AppData { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/App/ApplicationCountUpdatedEventArgs.cs b/src/Ryujinx.UI.Common/App/ApplicationCountUpdatedEventArgs.cs new file mode 100644 index 00000000..5ed7baf1 --- /dev/null +++ b/src/Ryujinx.UI.Common/App/ApplicationCountUpdatedEventArgs.cs @@ -0,0 +1,10 @@ +using System; + +namespace Ryujinx.UI.App.Common +{ + public class ApplicationCountUpdatedEventArgs : EventArgs + { + public int NumAppsFound { get; set; } + public int NumAppsLoaded { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/App/ApplicationData.cs b/src/Ryujinx.UI.Common/App/ApplicationData.cs new file mode 100644 index 00000000..8cc7238e --- /dev/null +++ b/src/Ryujinx.UI.Common/App/ApplicationData.cs @@ -0,0 +1,158 @@ +using LibHac.Common; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.FsSystem; +using LibHac.Loader; +using LibHac.Ns; +using LibHac.Tools.Fs; +using LibHac.Tools.FsSystem; +using LibHac.Tools.FsSystem.NcaUtils; +using Ryujinx.Common.Logging; +using Ryujinx.HLE.FileSystem; +using Ryujinx.UI.Common.Helper; +using System; +using System.IO; + +namespace Ryujinx.UI.App.Common +{ + public class ApplicationData + { + public bool Favorite { get; set; } + public byte[] Icon { get; set; } + public string TitleName { get; set; } + public string TitleId { get; set; } + public string Developer { get; set; } + public string Version { get; set; } + public TimeSpan TimePlayed { get; set; } + public DateTime? LastPlayed { get; set; } + public string FileExtension { get; set; } + public long FileSize { get; set; } + public string Path { get; set; } + public BlitStruct<ApplicationControlProperty> ControlHolder { get; set; } + + public string TimePlayedString => ValueFormatUtils.FormatTimeSpan(TimePlayed); + + public string LastPlayedString => ValueFormatUtils.FormatDateTime(LastPlayed); + + public string FileSizeString => ValueFormatUtils.FormatFileSize(FileSize); + + public static string GetApplicationBuildId(VirtualFileSystem virtualFileSystem, string titleFilePath) + { + using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read); + + Nca mainNca = null; + Nca patchNca = null; + + if (!System.IO.Path.Exists(titleFilePath)) + { + Logger.Error?.Print(LogClass.Application, $"File does not exists. {titleFilePath}"); + return string.Empty; + } + + string extension = System.IO.Path.GetExtension(titleFilePath).ToLower(); + + if (extension is ".nsp" or ".xci") + { + IFileSystem pfs; + + if (extension == ".xci") + { + Xci xci = new(virtualFileSystem.KeySet, file.AsStorage()); + + pfs = xci.OpenPartition(XciPartitionType.Secure); + } + else + { + var pfsTemp = new PartitionFileSystem(); + pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure(); + pfs = pfsTemp; + } + + foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) + { + using var ncaFile = new UniqueRef<IFile>(); + + pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + Nca nca = new(virtualFileSystem.KeySet, ncaFile.Get.AsStorage()); + + if (nca.Header.ContentType != NcaContentType.Program) + { + continue; + } + + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); + + if (nca.Header.GetFsHeader(dataIndex).IsPatchSection()) + { + patchNca = nca; + } + else + { + mainNca = nca; + } + } + } + else if (extension == ".nca") + { + mainNca = new Nca(virtualFileSystem.KeySet, file.AsStorage()); + } + + if (mainNca == null) + { + Logger.Error?.Print(LogClass.Application, "Extraction failure. The main NCA was not present in the selected file"); + + return string.Empty; + } + + (Nca updatePatchNca, _) = ApplicationLibrary.GetGameUpdateData(virtualFileSystem, mainNca.Header.TitleId.ToString("x16"), 0, out _); + + if (updatePatchNca != null) + { + patchNca = updatePatchNca; + } + + IFileSystem codeFs = null; + + if (patchNca == null) + { + if (mainNca.CanOpenSection(NcaSectionType.Code)) + { + codeFs = mainNca.OpenFileSystem(NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid); + } + } + else + { + if (patchNca.CanOpenSection(NcaSectionType.Code)) + { + codeFs = mainNca.OpenFileSystemWithPatch(patchNca, NcaSectionType.Code, IntegrityCheckLevel.ErrorOnInvalid); + } + } + + if (codeFs == null) + { + Logger.Error?.Print(LogClass.Loader, "No ExeFS found in NCA"); + + return string.Empty; + } + + const string MainExeFs = "main"; + + if (!codeFs.FileExists($"/{MainExeFs}")) + { + Logger.Error?.Print(LogClass.Loader, "No main binary ExeFS found in ExeFS"); + + return string.Empty; + } + + using var nsoFile = new UniqueRef<IFile>(); + + codeFs.OpenFile(ref nsoFile.Ref, $"/{MainExeFs}".ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + NsoReader reader = new(); + reader.Initialize(nsoFile.Release().AsStorage().AsFile(OpenMode.Read)).ThrowIfFailure(); + + return BitConverter.ToString(reader.Header.ModuleId.ItemsRo.ToArray()).Replace("-", "").ToUpper()[..16]; + } + } +} diff --git a/src/Ryujinx.UI.Common/App/ApplicationJsonSerializerContext.cs b/src/Ryujinx.UI.Common/App/ApplicationJsonSerializerContext.cs new file mode 100644 index 00000000..ada7cc34 --- /dev/null +++ b/src/Ryujinx.UI.Common/App/ApplicationJsonSerializerContext.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.App.Common +{ + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(ApplicationMetadata))] + internal partial class ApplicationJsonSerializerContext : JsonSerializerContext + { + } +} diff --git a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs new file mode 100644 index 00000000..65cf7a9e --- /dev/null +++ b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs @@ -0,0 +1,930 @@ +using LibHac; +using LibHac.Common; +using LibHac.Common.Keys; +using LibHac.Fs; +using LibHac.Fs.Fsa; +using LibHac.FsSystem; +using LibHac.Ns; +using LibHac.Tools.Fs; +using LibHac.Tools.FsSystem; +using LibHac.Tools.FsSystem.NcaUtils; +using Ryujinx.Common; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Logging; +using Ryujinx.Common.Utilities; +using Ryujinx.HLE.FileSystem; +using Ryujinx.HLE.HOS.SystemState; +using Ryujinx.HLE.Loaders.Npdm; +using Ryujinx.UI.Common.Configuration; +using Ryujinx.UI.Common.Configuration.System; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.Json; +using System.Threading; +using Path = System.IO.Path; +using TimeSpan = System.TimeSpan; + +namespace Ryujinx.UI.App.Common +{ + public class ApplicationLibrary + { + public event EventHandler<ApplicationAddedEventArgs> ApplicationAdded; + public event EventHandler<ApplicationCountUpdatedEventArgs> ApplicationCountUpdated; + + private readonly byte[] _nspIcon; + private readonly byte[] _xciIcon; + private readonly byte[] _ncaIcon; + private readonly byte[] _nroIcon; + private readonly byte[] _nsoIcon; + + private readonly VirtualFileSystem _virtualFileSystem; + private Language _desiredTitleLanguage; + private CancellationTokenSource _cancellationToken; + + private static readonly ApplicationJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + private static readonly TitleUpdateMetadataJsonSerializerContext _titleSerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + + public ApplicationLibrary(VirtualFileSystem virtualFileSystem) + { + _virtualFileSystem = virtualFileSystem; + + _nspIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NSP.png"); + _xciIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_XCI.png"); + _ncaIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NCA.png"); + _nroIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NRO.png"); + _nsoIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NSO.png"); + } + + private static byte[] GetResourceBytes(string resourceName) + { + Stream resourceStream = Assembly.GetCallingAssembly().GetManifestResourceStream(resourceName); + byte[] resourceByteArray = new byte[resourceStream.Length]; + + resourceStream.Read(resourceByteArray); + + return resourceByteArray; + } + + public void CancelLoading() + { + _cancellationToken?.Cancel(); + } + + public static void ReadControlData(IFileSystem controlFs, Span<byte> outProperty) + { + using UniqueRef<IFile> controlFile = new(); + + controlFs.OpenFile(ref controlFile.Ref, "/control.nacp".ToU8Span(), OpenMode.Read).ThrowIfFailure(); + controlFile.Get.Read(out _, 0, outProperty, ReadOption.None).ThrowIfFailure(); + } + + public void LoadApplications(List<string> appDirs, Language desiredTitleLanguage) + { + int numApplicationsFound = 0; + int numApplicationsLoaded = 0; + + _desiredTitleLanguage = desiredTitleLanguage; + + _cancellationToken = new CancellationTokenSource(); + + // Builds the applications list with paths to found applications + List<string> applications = new(); + + try + { + foreach (string appDir in appDirs) + { + if (_cancellationToken.Token.IsCancellationRequested) + { + return; + } + + if (!Directory.Exists(appDir)) + { + Logger.Warning?.Print(LogClass.Application, $"The \"game_dirs\" section in \"{ReleaseInformation.ConfigName}\" contains an invalid directory: \"{appDir}\""); + + continue; + } + + try + { + IEnumerable<string> files = Directory.EnumerateFiles(appDir, "*", SearchOption.AllDirectories).Where(file => + { + return + (Path.GetExtension(file).ToLower() is ".nsp" && ConfigurationState.Instance.UI.ShownFileTypes.NSP.Value) || + (Path.GetExtension(file).ToLower() is ".pfs0" && ConfigurationState.Instance.UI.ShownFileTypes.PFS0.Value) || + (Path.GetExtension(file).ToLower() is ".xci" && ConfigurationState.Instance.UI.ShownFileTypes.XCI.Value) || + (Path.GetExtension(file).ToLower() is ".nca" && ConfigurationState.Instance.UI.ShownFileTypes.NCA.Value) || + (Path.GetExtension(file).ToLower() is ".nro" && ConfigurationState.Instance.UI.ShownFileTypes.NRO.Value) || + (Path.GetExtension(file).ToLower() is ".nso" && ConfigurationState.Instance.UI.ShownFileTypes.NSO.Value); + }); + + foreach (string app in files) + { + if (_cancellationToken.Token.IsCancellationRequested) + { + return; + } + + var fileInfo = new FileInfo(app); + string extension = fileInfo.Extension.ToLower(); + + if (!fileInfo.Attributes.HasFlag(FileAttributes.Hidden) && extension is ".nsp" or ".pfs0" or ".xci" or ".nca" or ".nro" or ".nso") + { + var fullPath = fileInfo.ResolveLinkTarget(true)?.FullName ?? fileInfo.FullName; + + if (!File.Exists(fullPath)) + { + Logger.Warning?.Print(LogClass.Application, $"Skipping invalid symlink: {fileInfo.FullName}"); + continue; + } + + applications.Add(fullPath); + numApplicationsFound++; + } + } + } + catch (UnauthorizedAccessException) + { + Logger.Warning?.Print(LogClass.Application, $"Failed to get access to directory: \"{appDir}\""); + } + } + + // Loops through applications list, creating a struct and then firing an event containing the struct for each application + foreach (string applicationPath in applications) + { + if (_cancellationToken.Token.IsCancellationRequested) + { + return; + } + + long fileSize = new FileInfo(applicationPath).Length; + string titleName = "Unknown"; + string titleId = "0000000000000000"; + string developer = "Unknown"; + string version = "0"; + byte[] applicationIcon = null; + + BlitStruct<ApplicationControlProperty> controlHolder = new(1); + + try + { + string extension = Path.GetExtension(applicationPath).ToLower(); + + using FileStream file = new(applicationPath, FileMode.Open, FileAccess.Read); + + if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci") + { + try + { + IFileSystem pfs; + + bool isExeFs = false; + + if (extension == ".xci") + { + Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage()); + + pfs = xci.OpenPartition(XciPartitionType.Secure); + } + else + { + var pfsTemp = new PartitionFileSystem(); + pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure(); + pfs = pfsTemp; + + // If the NSP doesn't have a main NCA, decrement the number of applications found and then continue to the next application. + bool hasMainNca = false; + + foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*")) + { + if (Path.GetExtension(fileEntry.FullPath).ToLower() == ".nca") + { + using UniqueRef<IFile> ncaFile = new(); + + pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + Nca nca = new(_virtualFileSystem.KeySet, ncaFile.Get.AsStorage()); + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); + + // Some main NCAs don't have a data partition, so check if the partition exists before opening it + if (nca.Header.ContentType == NcaContentType.Program && !(nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())) + { + hasMainNca = true; + + break; + } + } + else if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main") + { + isExeFs = true; + } + } + + if (!hasMainNca && !isExeFs) + { + numApplicationsFound--; + + continue; + } + } + + if (isExeFs) + { + applicationIcon = _nspIcon; + + using UniqueRef<IFile> npdmFile = new(); + + Result result = pfs.OpenFile(ref npdmFile.Ref, "/main.npdm".ToU8Span(), OpenMode.Read); + + if (ResultFs.PathNotFound.Includes(result)) + { + Npdm npdm = new(npdmFile.Get.AsStream()); + + titleName = npdm.TitleName; + titleId = npdm.Aci0.TitleId.ToString("x16"); + } + } + else + { + GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out titleId); + + // Check if there is an update available. + if (IsUpdateApplied(titleId, out IFileSystem updatedControlFs)) + { + // Replace the original ControlFs by the updated one. + controlFs = updatedControlFs; + } + + ReadControlData(controlFs, controlHolder.ByteSpan); + + GetGameInformation(ref controlHolder.Value, out titleName, out _, out developer, out version); + + // Read the icon from the ControlFS and store it as a byte array + try + { + using UniqueRef<IFile> icon = new(); + + controlFs.OpenFile(ref icon.Ref, $"/icon_{_desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + using MemoryStream stream = new(); + + icon.Get.AsStream().CopyTo(stream); + applicationIcon = stream.ToArray(); + } + catch (HorizonResultException) + { + foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) + { + if (entry.Name == "control.nacp") + { + continue; + } + + using var icon = new UniqueRef<IFile>(); + + controlFs.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + using MemoryStream stream = new(); + + icon.Get.AsStream().CopyTo(stream); + applicationIcon = stream.ToArray(); + + if (applicationIcon != null) + { + break; + } + } + + applicationIcon ??= extension == ".xci" ? _xciIcon : _nspIcon; + } + } + } + catch (MissingKeyException exception) + { + applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon; + + Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}"); + } + catch (InvalidDataException) + { + applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon; + + Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {applicationPath}"); + } + catch (Exception exception) + { + Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}"); + + numApplicationsFound--; + + continue; + } + } + else if (extension == ".nro") + { + BinaryReader reader = new(file); + + byte[] Read(long position, int size) + { + file.Seek(position, SeekOrigin.Begin); + + return reader.ReadBytes(size); + } + + try + { + file.Seek(24, SeekOrigin.Begin); + + int assetOffset = reader.ReadInt32(); + + if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET") + { + byte[] iconSectionInfo = Read(assetOffset + 8, 0x10); + + long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0); + long iconSize = BitConverter.ToInt64(iconSectionInfo, 8); + + ulong nacpOffset = reader.ReadUInt64(); + ulong nacpSize = reader.ReadUInt64(); + + // Reads and stores game icon as byte array + if (iconSize > 0) + { + applicationIcon = Read(assetOffset + iconOffset, (int)iconSize); + } + else + { + applicationIcon = _nroIcon; + } + + // Read the NACP data + Read(assetOffset + (int)nacpOffset, (int)nacpSize).AsSpan().CopyTo(controlHolder.ByteSpan); + + GetGameInformation(ref controlHolder.Value, out titleName, out titleId, out developer, out version); + } + else + { + applicationIcon = _nroIcon; + titleName = Path.GetFileNameWithoutExtension(applicationPath); + } + } + catch + { + Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); + + numApplicationsFound--; + + continue; + } + } + else if (extension == ".nca") + { + try + { + Nca nca = new(_virtualFileSystem.KeySet, new FileStream(applicationPath, FileMode.Open, FileAccess.Read).AsStorage()); + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); + + if (nca.Header.ContentType != NcaContentType.Program || (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection())) + { + numApplicationsFound--; + + continue; + } + } + catch (InvalidDataException) + { + Logger.Warning?.Print(LogClass.Application, $"The NCA header content type check has failed. This is usually because the header key is incorrect or missing. Errored File: {applicationPath}"); + } + catch + { + Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); + + numApplicationsFound--; + + continue; + } + + applicationIcon = _ncaIcon; + titleName = Path.GetFileNameWithoutExtension(applicationPath); + } + // If its an NSO we just set defaults + else if (extension == ".nso") + { + applicationIcon = _nsoIcon; + titleName = Path.GetFileNameWithoutExtension(applicationPath); + } + } + catch (IOException exception) + { + Logger.Warning?.Print(LogClass.Application, exception.Message); + + numApplicationsFound--; + + continue; + } + + ApplicationMetadata appMetadata = LoadAndSaveMetaData(titleId, appMetadata => + { + appMetadata.Title = titleName; + + // Only do the migration if time_played has a value and timespan_played hasn't been updated yet. + if (appMetadata.TimePlayedOld != default && appMetadata.TimePlayed == TimeSpan.Zero) + { + appMetadata.TimePlayed = TimeSpan.FromSeconds(appMetadata.TimePlayedOld); + appMetadata.TimePlayedOld = default; + } + + // Only do the migration if last_played has a value and last_played_utc doesn't exist yet. + if (appMetadata.LastPlayedOld != default && !appMetadata.LastPlayed.HasValue) + { + // Migrate from string-based last_played to DateTime-based last_played_utc. + if (DateTime.TryParse(appMetadata.LastPlayedOld, out DateTime lastPlayedOldParsed)) + { + appMetadata.LastPlayed = lastPlayedOldParsed; + + // Migration successful: deleting last_played from the metadata file. + appMetadata.LastPlayedOld = default; + } + + } + }); + + ApplicationData data = new() + { + Favorite = appMetadata.Favorite, + Icon = applicationIcon, + TitleName = titleName, + TitleId = titleId, + Developer = developer, + Version = version, + TimePlayed = appMetadata.TimePlayed, + LastPlayed = appMetadata.LastPlayed, + FileExtension = Path.GetExtension(applicationPath).TrimStart('.').ToUpper(), + FileSize = fileSize, + Path = applicationPath, + ControlHolder = controlHolder, + }; + + numApplicationsLoaded++; + + OnApplicationAdded(new ApplicationAddedEventArgs + { + AppData = data, + }); + + OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs + { + NumAppsFound = numApplicationsFound, + NumAppsLoaded = numApplicationsLoaded, + }); + } + + OnApplicationCountUpdated(new ApplicationCountUpdatedEventArgs + { + NumAppsFound = numApplicationsFound, + NumAppsLoaded = numApplicationsLoaded, + }); + } + finally + { + _cancellationToken.Dispose(); + _cancellationToken = null; + } + } + + protected void OnApplicationAdded(ApplicationAddedEventArgs e) + { + ApplicationAdded?.Invoke(null, e); + } + + protected void OnApplicationCountUpdated(ApplicationCountUpdatedEventArgs e) + { + ApplicationCountUpdated?.Invoke(null, e); + } + + private void GetControlFsAndTitleId(IFileSystem pfs, out IFileSystem controlFs, out string titleId) + { + (_, _, Nca controlNca) = GetGameData(_virtualFileSystem, pfs, 0); + + // Return the ControlFS + controlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None); + titleId = controlNca?.Header.TitleId.ToString("x16"); + } + + public static ApplicationMetadata LoadAndSaveMetaData(string titleId, Action<ApplicationMetadata> modifyFunction = null) + { + string metadataFolder = Path.Combine(AppDataManager.GamesDirPath, titleId, "gui"); + string metadataFile = Path.Combine(metadataFolder, "metadata.json"); + + ApplicationMetadata appMetadata; + + if (!File.Exists(metadataFile)) + { + Directory.CreateDirectory(metadataFolder); + + appMetadata = new ApplicationMetadata(); + + JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata); + } + + try + { + appMetadata = JsonHelper.DeserializeFromFile(metadataFile, _serializerContext.ApplicationMetadata); + } + catch (JsonException) + { + Logger.Warning?.Print(LogClass.Application, $"Failed to parse metadata json for {titleId}. Loading defaults."); + + appMetadata = new ApplicationMetadata(); + } + + if (modifyFunction != null) + { + modifyFunction(appMetadata); + + JsonHelper.SerializeToFile(metadataFile, appMetadata, _serializerContext.ApplicationMetadata); + } + + return appMetadata; + } + + public byte[] GetApplicationIcon(string applicationPath, Language desiredTitleLanguage) + { + byte[] applicationIcon = null; + + try + { + // Look for icon only if applicationPath is not a directory + if (!Directory.Exists(applicationPath)) + { + string extension = Path.GetExtension(applicationPath).ToLower(); + + using FileStream file = new(applicationPath, FileMode.Open, FileAccess.Read); + + if (extension == ".nsp" || extension == ".pfs0" || extension == ".xci") + { + try + { + IFileSystem pfs; + + bool isExeFs = false; + + if (extension == ".xci") + { + Xci xci = new(_virtualFileSystem.KeySet, file.AsStorage()); + + pfs = xci.OpenPartition(XciPartitionType.Secure); + } + else + { + var pfsTemp = new PartitionFileSystem(); + pfsTemp.Initialize(file.AsStorage()).ThrowIfFailure(); + pfs = pfsTemp; + + foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*")) + { + if (Path.GetFileNameWithoutExtension(fileEntry.FullPath) == "main") + { + isExeFs = true; + } + } + } + + if (isExeFs) + { + applicationIcon = _nspIcon; + } + else + { + // Store the ControlFS in variable called controlFs + GetControlFsAndTitleId(pfs, out IFileSystem controlFs, out _); + + // Read the icon from the ControlFS and store it as a byte array + try + { + using var icon = new UniqueRef<IFile>(); + + controlFs.OpenFile(ref icon.Ref, $"/icon_{desiredTitleLanguage}.dat".ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + using MemoryStream stream = new(); + + icon.Get.AsStream().CopyTo(stream); + applicationIcon = stream.ToArray(); + } + catch (HorizonResultException) + { + foreach (DirectoryEntryEx entry in controlFs.EnumerateEntries("/", "*")) + { + if (entry.Name == "control.nacp") + { + continue; + } + + using var icon = new UniqueRef<IFile>(); + + controlFs.OpenFile(ref icon.Ref, entry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + using (MemoryStream stream = new()) + { + icon.Get.AsStream().CopyTo(stream); + applicationIcon = stream.ToArray(); + } + + if (applicationIcon != null) + { + break; + } + } + + applicationIcon ??= extension == ".xci" ? _xciIcon : _nspIcon; + } + } + } + catch (MissingKeyException) + { + applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon; + } + catch (InvalidDataException) + { + applicationIcon = extension == ".xci" ? _xciIcon : _nspIcon; + } + catch (Exception exception) + { + Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}"); + } + } + else if (extension == ".nro") + { + BinaryReader reader = new(file); + + byte[] Read(long position, int size) + { + file.Seek(position, SeekOrigin.Begin); + + return reader.ReadBytes(size); + } + + try + { + file.Seek(24, SeekOrigin.Begin); + + int assetOffset = reader.ReadInt32(); + + if (Encoding.ASCII.GetString(Read(assetOffset, 4)) == "ASET") + { + byte[] iconSectionInfo = Read(assetOffset + 8, 0x10); + + long iconOffset = BitConverter.ToInt64(iconSectionInfo, 0); + long iconSize = BitConverter.ToInt64(iconSectionInfo, 8); + + // Reads and stores game icon as byte array + if (iconSize > 0) + { + applicationIcon = Read(assetOffset + iconOffset, (int)iconSize); + } + else + { + applicationIcon = _nroIcon; + } + } + else + { + applicationIcon = _nroIcon; + } + } + catch + { + Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); + } + } + else if (extension == ".nca") + { + applicationIcon = _ncaIcon; + } + // If its an NSO we just set defaults + else if (extension == ".nso") + { + applicationIcon = _nsoIcon; + } + } + } + catch (Exception) + { + Logger.Warning?.Print(LogClass.Application, $"Could not retrieve a valid icon for the app. Default icon will be used. Errored File: {applicationPath}"); + } + + return applicationIcon ?? _ncaIcon; + } + + private void GetGameInformation(ref ApplicationControlProperty controlData, out string titleName, out string titleId, out string publisher, out string version) + { + _ = Enum.TryParse(_desiredTitleLanguage.ToString(), out TitleLanguage desiredTitleLanguage); + + if (controlData.Title.ItemsRo.Length > (int)desiredTitleLanguage) + { + titleName = controlData.Title[(int)desiredTitleLanguage].NameString.ToString(); + publisher = controlData.Title[(int)desiredTitleLanguage].PublisherString.ToString(); + } + else + { + titleName = null; + publisher = null; + } + + if (string.IsNullOrWhiteSpace(titleName)) + { + foreach (ref readonly var controlTitle in controlData.Title.ItemsRo) + { + if (!controlTitle.NameString.IsEmpty()) + { + titleName = controlTitle.NameString.ToString(); + + break; + } + } + } + + if (string.IsNullOrWhiteSpace(publisher)) + { + foreach (ref readonly var controlTitle in controlData.Title.ItemsRo) + { + if (!controlTitle.PublisherString.IsEmpty()) + { + publisher = controlTitle.PublisherString.ToString(); + + break; + } + } + } + + if (controlData.PresenceGroupId != 0) + { + titleId = controlData.PresenceGroupId.ToString("x16"); + } + else if (controlData.SaveDataOwnerId != 0) + { + titleId = controlData.SaveDataOwnerId.ToString(); + } + else if (controlData.AddOnContentBaseId != 0) + { + titleId = (controlData.AddOnContentBaseId - 0x1000).ToString("x16"); + } + else + { + titleId = "0000000000000000"; + } + + version = controlData.DisplayVersionString.ToString(); + } + + private bool IsUpdateApplied(string titleId, out IFileSystem updatedControlFs) + { + updatedControlFs = null; + + string updatePath = "(unknown)"; + + try + { + (Nca patchNca, Nca controlNca) = GetGameUpdateData(_virtualFileSystem, titleId, 0, out updatePath); + + if (patchNca != null && controlNca != null) + { + updatedControlFs = controlNca?.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.None); + + return true; + } + } + catch (InvalidDataException) + { + Logger.Warning?.Print(LogClass.Application, $"The header key is incorrect or missing and therefore the NCA header content type check has failed. Errored File: {updatePath}"); + } + catch (MissingKeyException exception) + { + Logger.Warning?.Print(LogClass.Application, $"Your key set is missing a key with the name: {exception.Name}. Errored File: {updatePath}"); + } + + return false; + } + + public static (Nca main, Nca patch, Nca control) GetGameData(VirtualFileSystem fileSystem, IFileSystem pfs, int programIndex) + { + Nca mainNca = null; + Nca patchNca = null; + Nca controlNca = null; + + fileSystem.ImportTickets(pfs); + + foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) + { + using var ncaFile = new UniqueRef<IFile>(); + + pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage()); + + int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF); + + if (ncaProgramIndex != programIndex) + { + continue; + } + + if (nca.Header.ContentType == NcaContentType.Program) + { + int dataIndex = Nca.GetSectionIndexFromType(NcaSectionType.Data, NcaContentType.Program); + + if (nca.SectionExists(NcaSectionType.Data) && nca.Header.GetFsHeader(dataIndex).IsPatchSection()) + { + patchNca = nca; + } + else + { + mainNca = nca; + } + } + else if (nca.Header.ContentType == NcaContentType.Control) + { + controlNca = nca; + } + } + + return (mainNca, patchNca, controlNca); + } + + public static (Nca patch, Nca control) GetGameUpdateDataFromPartition(VirtualFileSystem fileSystem, PartitionFileSystem pfs, string titleId, int programIndex) + { + Nca patchNca = null; + Nca controlNca = null; + + fileSystem.ImportTickets(pfs); + + foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) + { + using var ncaFile = new UniqueRef<IFile>(); + + pfs.OpenFile(ref ncaFile.Ref, fileEntry.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); + + Nca nca = new(fileSystem.KeySet, ncaFile.Release().AsStorage()); + + int ncaProgramIndex = (int)(nca.Header.TitleId & 0xF); + + if (ncaProgramIndex != programIndex) + { + continue; + } + + if ($"{nca.Header.TitleId.ToString("x16")[..^3]}000" != titleId) + { + break; + } + + if (nca.Header.ContentType == NcaContentType.Program) + { + patchNca = nca; + } + else if (nca.Header.ContentType == NcaContentType.Control) + { + controlNca = nca; + } + } + + return (patchNca, controlNca); + } + + public static (Nca patch, Nca control) GetGameUpdateData(VirtualFileSystem fileSystem, string titleId, int programIndex, out string updatePath) + { + updatePath = null; + + if (ulong.TryParse(titleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdBase)) + { + // Clear the program index part. + titleIdBase &= ~0xFUL; + + // Load update information if exists. + string titleUpdateMetadataPath = Path.Combine(AppDataManager.GamesDirPath, titleIdBase.ToString("x16"), "updates.json"); + + if (File.Exists(titleUpdateMetadataPath)) + { + updatePath = JsonHelper.DeserializeFromFile(titleUpdateMetadataPath, _titleSerializerContext.TitleUpdateMetadata).Selected; + + if (File.Exists(updatePath)) + { + FileStream file = new(updatePath, FileMode.Open, FileAccess.Read); + PartitionFileSystem nsp = new(); + nsp.Initialize(file.AsStorage()).ThrowIfFailure(); + + return GetGameUpdateDataFromPartition(fileSystem, nsp, titleIdBase.ToString("x16"), programIndex); + } + } + } + + return (null, null); + } + } +} diff --git a/src/Ryujinx.UI.Common/App/ApplicationMetadata.cs b/src/Ryujinx.UI.Common/App/ApplicationMetadata.cs new file mode 100644 index 00000000..81193c5b --- /dev/null +++ b/src/Ryujinx.UI.Common/App/ApplicationMetadata.cs @@ -0,0 +1,51 @@ +using System; +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.App.Common +{ + public class ApplicationMetadata + { + public string Title { get; set; } + public bool Favorite { get; set; } + + [JsonPropertyName("timespan_played")] + public TimeSpan TimePlayed { get; set; } = TimeSpan.Zero; + + [JsonPropertyName("last_played_utc")] + public DateTime? LastPlayed { get; set; } = null; + + [JsonPropertyName("time_played")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public double TimePlayedOld { get; set; } + + [JsonPropertyName("last_played")] + [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] + public string LastPlayedOld { get; set; } + + /// <summary> + /// Updates <see cref="LastPlayed"/>. Call this before launching a game. + /// </summary> + public void UpdatePreGame() + { + LastPlayed = DateTime.UtcNow; + } + + /// <summary> + /// Updates <see cref="LastPlayed"/> and <see cref="TimePlayed"/>. Call this after a game ends. + /// </summary> + public void UpdatePostGame() + { + DateTime? prevLastPlayed = LastPlayed; + UpdatePreGame(); + + if (!prevLastPlayed.HasValue) + { + return; + } + + TimeSpan diff = DateTime.UtcNow - prevLastPlayed.Value; + double newTotalSeconds = TimePlayed.Add(diff).TotalSeconds; + TimePlayed = TimeSpan.FromSeconds(Math.Round(newTotalSeconds, MidpointRounding.AwayFromZero)); + } + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/AudioBackend.cs b/src/Ryujinx.UI.Common/Configuration/AudioBackend.cs new file mode 100644 index 00000000..a952e7ac --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/AudioBackend.cs @@ -0,0 +1,14 @@ +using Ryujinx.Common.Utilities; +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Configuration +{ + [JsonConverter(typeof(TypedStringEnumConverter<AudioBackend>))] + public enum AudioBackend + { + Dummy, + OpenAl, + SoundIo, + SDL2, + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs new file mode 100644 index 00000000..0ee51d83 --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormat.cs @@ -0,0 +1,409 @@ +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Configuration.Multiplayer; +using Ryujinx.Common.Logging; +using Ryujinx.Common.Utilities; +using Ryujinx.UI.Common.Configuration.System; +using Ryujinx.UI.Common.Configuration.UI; +using System.Collections.Generic; +using System.Text.Json.Nodes; + +namespace Ryujinx.UI.Common.Configuration +{ + public class ConfigurationFileFormat + { + /// <summary> + /// The current version of the file format + /// </summary> + public const int CurrentVersion = 48; + + /// <summary> + /// Version of the configuration file format + /// </summary> + public int Version { get; set; } + + /// <summary> + /// Enables or disables logging to a file on disk + /// </summary> + public bool EnableFileLog { get; set; } + + /// <summary> + /// Whether or not backend threading is enabled. The "Auto" setting will determine whether threading should be enabled at runtime. + /// </summary> + public BackendThreading BackendThreading { get; set; } + + /// <summary> + /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead. + /// </summary> + public int ResScale { get; set; } + + /// <summary> + /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1. + /// </summary> + public float ResScaleCustom { get; set; } + + /// <summary> + /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. + /// </summary> + public float MaxAnisotropy { get; set; } + + /// <summary> + /// Aspect Ratio applied to the renderer window. + /// </summary> + public AspectRatio AspectRatio { get; set; } + + /// <summary> + /// Applies anti-aliasing to the renderer. + /// </summary> + public AntiAliasing AntiAliasing { get; set; } + + /// <summary> + /// Sets the framebuffer upscaling type. + /// </summary> + public ScalingFilter ScalingFilter { get; set; } + + /// <summary> + /// Sets the framebuffer upscaling level. + /// </summary> + public int ScalingFilterLevel { get; set; } + + /// <summary> + /// Dumps shaders in this local directory + /// </summary> + public string GraphicsShadersDumpPath { get; set; } + + /// <summary> + /// Enables printing debug log messages + /// </summary> + public bool LoggingEnableDebug { get; set; } + + /// <summary> + /// Enables printing stub log messages + /// </summary> + public bool LoggingEnableStub { get; set; } + + /// <summary> + /// Enables printing info log messages + /// </summary> + public bool LoggingEnableInfo { get; set; } + + /// <summary> + /// Enables printing warning log messages + /// </summary> + public bool LoggingEnableWarn { get; set; } + + /// <summary> + /// Enables printing error log messages + /// </summary> + public bool LoggingEnableError { get; set; } + + /// <summary> + /// Enables printing trace log messages + /// </summary> + public bool LoggingEnableTrace { get; set; } + + /// <summary> + /// Enables printing guest log messages + /// </summary> + public bool LoggingEnableGuest { get; set; } + + /// <summary> + /// Enables printing FS access log messages + /// </summary> + public bool LoggingEnableFsAccessLog { get; set; } + + /// <summary> + /// Controls which log messages are written to the log targets + /// </summary> + public LogClass[] LoggingFilteredClasses { get; set; } + + /// <summary> + /// Change Graphics API debug log level + /// </summary> + public GraphicsDebugLevel LoggingGraphicsDebugLevel { get; set; } + + /// <summary> + /// Change System Language + /// </summary> + public Language SystemLanguage { get; set; } + + /// <summary> + /// Change System Region + /// </summary> + public Region SystemRegion { get; set; } + + /// <summary> + /// Change System TimeZone + /// </summary> + public string SystemTimeZone { get; set; } + + /// <summary> + /// Change System Time Offset in seconds + /// </summary> + public long SystemTimeOffset { get; set; } + + /// <summary> + /// Enables or disables Docked Mode + /// </summary> + public bool DockedMode { get; set; } + + /// <summary> + /// Enables or disables Discord Rich Presence + /// </summary> + public bool EnableDiscordIntegration { get; set; } + + /// <summary> + /// Checks for updates when Ryujinx starts when enabled + /// </summary> + public bool CheckUpdatesOnStart { get; set; } + + /// <summary> + /// Show "Confirm Exit" Dialog + /// </summary> + public bool ShowConfirmExit { get; set; } + + /// <summary> + /// Whether to hide cursor on idle, always or never + /// </summary> + public HideCursorMode HideCursor { get; set; } + + /// <summary> + /// Enables or disables Vertical Sync + /// </summary> + public bool EnableVsync { get; set; } + + /// <summary> + /// Enables or disables Shader cache + /// </summary> + public bool EnableShaderCache { get; set; } + + /// <summary> + /// Enables or disables texture recompression + /// </summary> + public bool EnableTextureRecompression { get; set; } + + /// <summary> + /// Enables or disables Macro high-level emulation + /// </summary> + public bool EnableMacroHLE { get; set; } + + /// <summary> + /// Enables or disables color space passthrough, if available. + /// </summary> + public bool EnableColorSpacePassthrough { get; set; } + + /// <summary> + /// Enables or disables profiled translation cache persistency + /// </summary> + public bool EnablePtc { get; set; } + + /// <summary> + /// Enables or disables guest Internet access + /// </summary> + public bool EnableInternetAccess { get; set; } + + /// <summary> + /// Enables integrity checks on Game content files + /// </summary> + public bool EnableFsIntegrityChecks { get; set; } + + /// <summary> + /// Enables FS access log output to the console. Possible modes are 0-3 + /// </summary> + public int FsGlobalAccessLogMode { get; set; } + + /// <summary> + /// The selected audio backend + /// </summary> + public AudioBackend AudioBackend { get; set; } + + /// <summary> + /// The audio volume + /// </summary> + public float AudioVolume { get; set; } + + /// <summary> + /// The selected memory manager mode + /// </summary> + public MemoryManagerMode MemoryManagerMode { get; set; } + + /// <summary> + /// Expands the RAM amount on the emulated system from 4GiB to 6GiB + /// </summary> + public bool ExpandRam { get; set; } + + /// <summary> + /// Enable or disable ignoring missing services + /// </summary> + public bool IgnoreMissingServices { get; set; } + + /// <summary> + /// Used to toggle columns in the GUI + /// </summary> + public GuiColumns GuiColumns { get; set; } + + /// <summary> + /// Used to configure column sort settings in the GUI + /// </summary> + public ColumnSort ColumnSort { get; set; } + + /// <summary> + /// A list of directories containing games to be used to load games into the games list + /// </summary> + public List<string> GameDirs { get; set; } + + /// <summary> + /// A list of file types to be hidden in the games List + /// </summary> + public ShownFileTypes ShownFileTypes { get; set; } + + /// <summary> + /// Main window start-up position, size and state + /// </summary> + public WindowStartup WindowStartup { get; set; } + + /// <summary> + /// Language Code for the UI + /// </summary> + public string LanguageCode { get; set; } + + /// <summary> + /// Enable or disable custom themes in the GUI + /// </summary> + public bool EnableCustomTheme { get; set; } + + /// <summary> + /// Path to custom GUI theme + /// </summary> + public string CustomThemePath { get; set; } + + /// <summary> + /// Chooses the base style // Not Used + /// </summary> + public string BaseStyle { get; set; } + + /// <summary> + /// Chooses the view mode of the game list // Not Used + /// </summary> + public int GameListViewMode { get; set; } + + /// <summary> + /// Show application name in Grid Mode // Not Used + /// </summary> + public bool ShowNames { get; set; } + + /// <summary> + /// Sets App Icon Size // Not Used + /// </summary> + public int GridSize { get; set; } + + /// <summary> + /// Sorts Apps in the game list // Not Used + /// </summary> + public int ApplicationSort { get; set; } + + /// <summary> + /// Sets if Grid is ordered in Ascending Order // Not Used + /// </summary> + public bool IsAscendingOrder { get; set; } + + /// <summary> + /// Start games in fullscreen mode + /// </summary> + public bool StartFullscreen { get; set; } + + /// <summary> + /// Show console window + /// </summary> + public bool ShowConsole { get; set; } + + /// <summary> + /// Enable or disable keyboard support (Independent from controllers binding) + /// </summary> + public bool EnableKeyboard { get; set; } + + /// <summary> + /// Enable or disable mouse support (Independent from controllers binding) + /// </summary> + public bool EnableMouse { get; set; } + + /// <summary> + /// Hotkey Keyboard Bindings + /// </summary> + public KeyboardHotkeys Hotkeys { get; set; } + + /// <summary> + /// Legacy keyboard control bindings + /// </summary> + /// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks> + /// TODO: Remove this when those older versions aren't in use anymore. + public List<JsonObject> KeyboardConfig { get; set; } + + /// <summary> + /// Legacy controller control bindings + /// </summary> + /// <remarks>Kept for file format compatibility (to avoid possible failure when parsing configuration on old versions)</remarks> + /// TODO: Remove this when those older versions aren't in use anymore. + public List<JsonObject> ControllerConfig { get; set; } + + /// <summary> + /// Input configurations + /// </summary> + public List<InputConfig> InputConfig { get; set; } + + /// <summary> + /// Graphics backend + /// </summary> + public GraphicsBackend GraphicsBackend { get; set; } + + /// <summary> + /// Preferred GPU + /// </summary> + public string PreferredGpu { get; set; } + + /// <summary> + /// Multiplayer Mode + /// </summary> + public MultiplayerMode MultiplayerMode { get; set; } + + /// <summary> + /// GUID for the network interface used by LAN (or 0 for default) + /// </summary> + public string MultiplayerLanInterfaceId { get; set; } + + /// <summary> + /// Uses Hypervisor over JIT if available + /// </summary> + public bool UseHypervisor { get; set; } + + /// <summary> + /// Loads a configuration file from disk + /// </summary> + /// <param name="path">The path to the JSON configuration file</param> + /// <param name="configurationFileFormat">Parsed configuration file</param> + public static bool TryLoad(string path, out ConfigurationFileFormat configurationFileFormat) + { + try + { + configurationFileFormat = JsonHelper.DeserializeFromFile(path, ConfigurationFileFormatSettings.SerializerContext.ConfigurationFileFormat); + + return configurationFileFormat.Version != 0; + } + catch + { + configurationFileFormat = null; + + return false; + } + } + + /// <summary> + /// Save a configuration file to disk + /// </summary> + /// <param name="path">The path to the JSON configuration file</param> + public void SaveConfig(string path) + { + JsonHelper.SerializeToFile(path, this, ConfigurationFileFormatSettings.SerializerContext.ConfigurationFileFormat); + } + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormatSettings.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormatSettings.cs new file mode 100644 index 00000000..9861ebf1 --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationFileFormatSettings.cs @@ -0,0 +1,9 @@ +using Ryujinx.Common.Utilities; + +namespace Ryujinx.UI.Common.Configuration +{ + internal static class ConfigurationFileFormatSettings + { + public static readonly ConfigurationJsonSerializerContext SerializerContext = new(JsonHelper.GetDefaultSerializerOptions()); + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationJsonSerializerContext.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationJsonSerializerContext.cs new file mode 100644 index 00000000..3c3e3f20 --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationJsonSerializerContext.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Configuration +{ + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(ConfigurationFileFormat))] + internal partial class ConfigurationJsonSerializerContext : JsonSerializerContext + { + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs new file mode 100644 index 00000000..1d6934ce --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/ConfigurationState.cs @@ -0,0 +1,1562 @@ +using Ryujinx.Common; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Configuration.Hid; +using Ryujinx.Common.Configuration.Hid.Controller; +using Ryujinx.Common.Configuration.Hid.Keyboard; +using Ryujinx.Common.Configuration.Multiplayer; +using Ryujinx.Common.Logging; +using Ryujinx.Graphics.Vulkan; +using Ryujinx.UI.Common.Configuration.System; +using Ryujinx.UI.Common.Configuration.UI; +using Ryujinx.UI.Common.Helper; +using System; +using System.Collections.Generic; +using System.Text.Json.Nodes; + +namespace Ryujinx.UI.Common.Configuration +{ + public class ConfigurationState + { + /// <summary> + /// UI configuration section + /// </summary> + public class UISection + { + public class Columns + { + public ReactiveObject<bool> FavColumn { get; private set; } + public ReactiveObject<bool> IconColumn { get; private set; } + public ReactiveObject<bool> AppColumn { get; private set; } + public ReactiveObject<bool> DevColumn { get; private set; } + public ReactiveObject<bool> VersionColumn { get; private set; } + public ReactiveObject<bool> TimePlayedColumn { get; private set; } + public ReactiveObject<bool> LastPlayedColumn { get; private set; } + public ReactiveObject<bool> FileExtColumn { get; private set; } + public ReactiveObject<bool> FileSizeColumn { get; private set; } + public ReactiveObject<bool> PathColumn { get; private set; } + + public Columns() + { + FavColumn = new ReactiveObject<bool>(); + IconColumn = new ReactiveObject<bool>(); + AppColumn = new ReactiveObject<bool>(); + DevColumn = new ReactiveObject<bool>(); + VersionColumn = new ReactiveObject<bool>(); + TimePlayedColumn = new ReactiveObject<bool>(); + LastPlayedColumn = new ReactiveObject<bool>(); + FileExtColumn = new ReactiveObject<bool>(); + FileSizeColumn = new ReactiveObject<bool>(); + PathColumn = new ReactiveObject<bool>(); + } + } + + public class ColumnSortSettings + { + public ReactiveObject<int> SortColumnId { get; private set; } + public ReactiveObject<bool> SortAscending { get; private set; } + + public ColumnSortSettings() + { + SortColumnId = new ReactiveObject<int>(); + SortAscending = new ReactiveObject<bool>(); + } + } + + /// <summary> + /// Used to toggle which file types are shown in the UI + /// </summary> + public class ShownFileTypeSettings + { + public ReactiveObject<bool> NSP { get; private set; } + public ReactiveObject<bool> PFS0 { get; private set; } + public ReactiveObject<bool> XCI { get; private set; } + public ReactiveObject<bool> NCA { get; private set; } + public ReactiveObject<bool> NRO { get; private set; } + public ReactiveObject<bool> NSO { get; private set; } + + public ShownFileTypeSettings() + { + NSP = new ReactiveObject<bool>(); + PFS0 = new ReactiveObject<bool>(); + XCI = new ReactiveObject<bool>(); + NCA = new ReactiveObject<bool>(); + NRO = new ReactiveObject<bool>(); + NSO = new ReactiveObject<bool>(); + } + } + + // <summary> + /// Determines main window start-up position, size and state + ///<summary> + public class WindowStartupSettings + { + public ReactiveObject<int> WindowSizeWidth { get; private set; } + public ReactiveObject<int> WindowSizeHeight { get; private set; } + public ReactiveObject<int> WindowPositionX { get; private set; } + public ReactiveObject<int> WindowPositionY { get; private set; } + public ReactiveObject<bool> WindowMaximized { get; private set; } + + public WindowStartupSettings() + { + WindowSizeWidth = new ReactiveObject<int>(); + WindowSizeHeight = new ReactiveObject<int>(); + WindowPositionX = new ReactiveObject<int>(); + WindowPositionY = new ReactiveObject<int>(); + WindowMaximized = new ReactiveObject<bool>(); + } + } + + /// <summary> + /// Used to toggle columns in the GUI + /// </summary> + public Columns GuiColumns { get; private set; } + + /// <summary> + /// Used to configure column sort settings in the GUI + /// </summary> + public ColumnSortSettings ColumnSort { get; private set; } + + /// <summary> + /// A list of directories containing games to be used to load games into the games list + /// </summary> + public ReactiveObject<List<string>> GameDirs { get; private set; } + + /// <summary> + /// A list of file types to be hidden in the games List + /// </summary> + public ShownFileTypeSettings ShownFileTypes { get; private set; } + + /// <summary> + /// Determines main window start-up position, size and state + /// </summary> + public WindowStartupSettings WindowStartup { get; private set; } + + /// <summary> + /// Language Code for the UI + /// </summary> + public ReactiveObject<string> LanguageCode { get; private set; } + + /// <summary> + /// Enable or disable custom themes in the GUI + /// </summary> + public ReactiveObject<bool> EnableCustomTheme { get; private set; } + + /// <summary> + /// Path to custom GUI theme + /// </summary> + public ReactiveObject<string> CustomThemePath { get; private set; } + + /// <summary> + /// Selects the base style + /// </summary> + public ReactiveObject<string> BaseStyle { get; private set; } + + /// <summary> + /// Start games in fullscreen mode + /// </summary> + public ReactiveObject<bool> StartFullscreen { get; private set; } + + /// <summary> + /// Hide / Show Console Window + /// </summary> + public ReactiveObject<bool> ShowConsole { get; private set; } + + /// <summary> + /// View Mode of the Game list + /// </summary> + public ReactiveObject<int> GameListViewMode { get; private set; } + + /// <summary> + /// Show application name in Grid Mode + /// </summary> + public ReactiveObject<bool> ShowNames { get; private set; } + + /// <summary> + /// Sets App Icon Size in Grid Mode + /// </summary> + public ReactiveObject<int> GridSize { get; private set; } + + /// <summary> + /// Sorts Apps in Grid Mode + /// </summary> + public ReactiveObject<int> ApplicationSort { get; private set; } + + /// <summary> + /// Sets if Grid is ordered in Ascending Order + /// </summary> + public ReactiveObject<bool> IsAscendingOrder { get; private set; } + + public UISection() + { + GuiColumns = new Columns(); + ColumnSort = new ColumnSortSettings(); + GameDirs = new ReactiveObject<List<string>>(); + ShownFileTypes = new ShownFileTypeSettings(); + WindowStartup = new WindowStartupSettings(); + EnableCustomTheme = new ReactiveObject<bool>(); + CustomThemePath = new ReactiveObject<string>(); + BaseStyle = new ReactiveObject<string>(); + StartFullscreen = new ReactiveObject<bool>(); + GameListViewMode = new ReactiveObject<int>(); + ShowNames = new ReactiveObject<bool>(); + GridSize = new ReactiveObject<int>(); + ApplicationSort = new ReactiveObject<int>(); + IsAscendingOrder = new ReactiveObject<bool>(); + LanguageCode = new ReactiveObject<string>(); + ShowConsole = new ReactiveObject<bool>(); + ShowConsole.Event += static (s, e) => { ConsoleHelper.SetConsoleWindowState(e.NewValue); }; + } + } + + /// <summary> + /// Logger configuration section + /// </summary> + public class LoggerSection + { + /// <summary> + /// Enables printing debug log messages + /// </summary> + public ReactiveObject<bool> EnableDebug { get; private set; } + + /// <summary> + /// Enables printing stub log messages + /// </summary> + public ReactiveObject<bool> EnableStub { get; private set; } + + /// <summary> + /// Enables printing info log messages + /// </summary> + public ReactiveObject<bool> EnableInfo { get; private set; } + + /// <summary> + /// Enables printing warning log messages + /// </summary> + public ReactiveObject<bool> EnableWarn { get; private set; } + + /// <summary> + /// Enables printing error log messages + /// </summary> + public ReactiveObject<bool> EnableError { get; private set; } + + /// <summary> + /// Enables printing trace log messages + /// </summary> + public ReactiveObject<bool> EnableTrace { get; private set; } + + /// <summary> + /// Enables printing guest log messages + /// </summary> + public ReactiveObject<bool> EnableGuest { get; private set; } + + /// <summary> + /// Enables printing FS access log messages + /// </summary> + public ReactiveObject<bool> EnableFsAccessLog { get; private set; } + + /// <summary> + /// Controls which log messages are written to the log targets + /// </summary> + public ReactiveObject<LogClass[]> FilteredClasses { get; private set; } + + /// <summary> + /// Enables or disables logging to a file on disk + /// </summary> + public ReactiveObject<bool> EnableFileLog { get; private set; } + + /// <summary> + /// Controls which OpenGL log messages are recorded in the log + /// </summary> + public ReactiveObject<GraphicsDebugLevel> GraphicsDebugLevel { get; private set; } + + public LoggerSection() + { + EnableDebug = new ReactiveObject<bool>(); + EnableStub = new ReactiveObject<bool>(); + EnableInfo = new ReactiveObject<bool>(); + EnableWarn = new ReactiveObject<bool>(); + EnableError = new ReactiveObject<bool>(); + EnableTrace = new ReactiveObject<bool>(); + EnableGuest = new ReactiveObject<bool>(); + EnableFsAccessLog = new ReactiveObject<bool>(); + FilteredClasses = new ReactiveObject<LogClass[]>(); + EnableFileLog = new ReactiveObject<bool>(); + EnableFileLog.Event += static (sender, e) => LogValueChange(e, nameof(EnableFileLog)); + GraphicsDebugLevel = new ReactiveObject<GraphicsDebugLevel>(); + } + } + + /// <summary> + /// System configuration section + /// </summary> + public class SystemSection + { + /// <summary> + /// Change System Language + /// </summary> + public ReactiveObject<Language> Language { get; private set; } + + /// <summary> + /// Change System Region + /// </summary> + public ReactiveObject<Region> Region { get; private set; } + + /// <summary> + /// Change System TimeZone + /// </summary> + public ReactiveObject<string> TimeZone { get; private set; } + + /// <summary> + /// System Time Offset in Seconds + /// </summary> + public ReactiveObject<long> SystemTimeOffset { get; private set; } + + /// <summary> + /// Enables or disables Docked Mode + /// </summary> + public ReactiveObject<bool> EnableDockedMode { get; private set; } + + /// <summary> + /// Enables or disables profiled translation cache persistency + /// </summary> + public ReactiveObject<bool> EnablePtc { get; private set; } + + /// <summary> + /// Enables or disables guest Internet access + /// </summary> + public ReactiveObject<bool> EnableInternetAccess { get; private set; } + + /// <summary> + /// Enables integrity checks on Game content files + /// </summary> + public ReactiveObject<bool> EnableFsIntegrityChecks { get; private set; } + + /// <summary> + /// Enables FS access log output to the console. Possible modes are 0-3 + /// </summary> + public ReactiveObject<int> FsGlobalAccessLogMode { get; private set; } + + /// <summary> + /// The selected audio backend + /// </summary> + public ReactiveObject<AudioBackend> AudioBackend { get; private set; } + + /// <summary> + /// The audio backend volume + /// </summary> + public ReactiveObject<float> AudioVolume { get; private set; } + + /// <summary> + /// The selected memory manager mode + /// </summary> + public ReactiveObject<MemoryManagerMode> MemoryManagerMode { get; private set; } + + /// <summary> + /// Defines the amount of RAM available on the emulated system, and how it is distributed + /// </summary> + public ReactiveObject<bool> ExpandRam { get; private set; } + + /// <summary> + /// Enable or disable ignoring missing services + /// </summary> + public ReactiveObject<bool> IgnoreMissingServices { get; private set; } + + /// <summary> + /// Uses Hypervisor over JIT if available + /// </summary> + public ReactiveObject<bool> UseHypervisor { get; private set; } + + public SystemSection() + { + Language = new ReactiveObject<Language>(); + Region = new ReactiveObject<Region>(); + TimeZone = new ReactiveObject<string>(); + SystemTimeOffset = new ReactiveObject<long>(); + EnableDockedMode = new ReactiveObject<bool>(); + EnableDockedMode.Event += static (sender, e) => LogValueChange(e, nameof(EnableDockedMode)); + EnablePtc = new ReactiveObject<bool>(); + EnablePtc.Event += static (sender, e) => LogValueChange(e, nameof(EnablePtc)); + EnableInternetAccess = new ReactiveObject<bool>(); + EnableInternetAccess.Event += static (sender, e) => LogValueChange(e, nameof(EnableInternetAccess)); + EnableFsIntegrityChecks = new ReactiveObject<bool>(); + EnableFsIntegrityChecks.Event += static (sender, e) => LogValueChange(e, nameof(EnableFsIntegrityChecks)); + FsGlobalAccessLogMode = new ReactiveObject<int>(); + FsGlobalAccessLogMode.Event += static (sender, e) => LogValueChange(e, nameof(FsGlobalAccessLogMode)); + AudioBackend = new ReactiveObject<AudioBackend>(); + AudioBackend.Event += static (sender, e) => LogValueChange(e, nameof(AudioBackend)); + MemoryManagerMode = new ReactiveObject<MemoryManagerMode>(); + MemoryManagerMode.Event += static (sender, e) => LogValueChange(e, nameof(MemoryManagerMode)); + ExpandRam = new ReactiveObject<bool>(); + ExpandRam.Event += static (sender, e) => LogValueChange(e, nameof(ExpandRam)); + IgnoreMissingServices = new ReactiveObject<bool>(); + IgnoreMissingServices.Event += static (sender, e) => LogValueChange(e, nameof(IgnoreMissingServices)); + AudioVolume = new ReactiveObject<float>(); + AudioVolume.Event += static (sender, e) => LogValueChange(e, nameof(AudioVolume)); + UseHypervisor = new ReactiveObject<bool>(); + UseHypervisor.Event += static (sender, e) => LogValueChange(e, nameof(UseHypervisor)); + } + } + + /// <summary> + /// Hid configuration section + /// </summary> + public class HidSection + { + /// <summary> + /// Enable or disable keyboard support (Independent from controllers binding) + /// </summary> + public ReactiveObject<bool> EnableKeyboard { get; private set; } + + /// <summary> + /// Enable or disable mouse support (Independent from controllers binding) + /// </summary> + public ReactiveObject<bool> EnableMouse { get; private set; } + + /// <summary> + /// Hotkey Keyboard Bindings + /// </summary> + public ReactiveObject<KeyboardHotkeys> Hotkeys { get; private set; } + + /// <summary> + /// Input device configuration. + /// NOTE: This ReactiveObject won't issue an event when the List has elements added or removed. + /// TODO: Implement a ReactiveList class. + /// </summary> + public ReactiveObject<List<InputConfig>> InputConfig { get; private set; } + + public HidSection() + { + EnableKeyboard = new ReactiveObject<bool>(); + EnableMouse = new ReactiveObject<bool>(); + Hotkeys = new ReactiveObject<KeyboardHotkeys>(); + InputConfig = new ReactiveObject<List<InputConfig>>(); + } + } + + /// <summary> + /// Graphics configuration section + /// </summary> + public class GraphicsSection + { + /// <summary> + /// Whether or not backend threading is enabled. The "Auto" setting will determine whether threading should be enabled at runtime. + /// </summary> + public ReactiveObject<BackendThreading> BackendThreading { get; private set; } + + /// <summary> + /// Max Anisotropy. Values range from 0 - 16. Set to -1 to let the game decide. + /// </summary> + public ReactiveObject<float> MaxAnisotropy { get; private set; } + + /// <summary> + /// Aspect Ratio applied to the renderer window. + /// </summary> + public ReactiveObject<AspectRatio> AspectRatio { get; private set; } + + /// <summary> + /// Resolution Scale. An integer scale applied to applicable render targets. Values 1-4, or -1 to use a custom floating point scale instead. + /// </summary> + public ReactiveObject<int> ResScale { get; private set; } + + /// <summary> + /// Custom Resolution Scale. A custom floating point scale applied to applicable render targets. Only active when Resolution Scale is -1. + /// </summary> + public ReactiveObject<float> ResScaleCustom { get; private set; } + + /// <summary> + /// Dumps shaders in this local directory + /// </summary> + public ReactiveObject<string> ShadersDumpPath { get; private set; } + + /// <summary> + /// Enables or disables Vertical Sync + /// </summary> + public ReactiveObject<bool> EnableVsync { get; private set; } + + /// <summary> + /// Enables or disables Shader cache + /// </summary> + public ReactiveObject<bool> EnableShaderCache { get; private set; } + + /// <summary> + /// Enables or disables texture recompression + /// </summary> + public ReactiveObject<bool> EnableTextureRecompression { get; private set; } + + /// <summary> + /// Enables or disables Macro high-level emulation + /// </summary> + public ReactiveObject<bool> EnableMacroHLE { get; private set; } + + /// <summary> + /// Enables or disables color space passthrough, if available. + /// </summary> + public ReactiveObject<bool> EnableColorSpacePassthrough { get; private set; } + + /// <summary> + /// Graphics backend + /// </summary> + public ReactiveObject<GraphicsBackend> GraphicsBackend { get; private set; } + + /// <summary> + /// Applies anti-aliasing to the renderer. + /// </summary> + public ReactiveObject<AntiAliasing> AntiAliasing { get; private set; } + + /// <summary> + /// Sets the framebuffer upscaling type. + /// </summary> + public ReactiveObject<ScalingFilter> ScalingFilter { get; private set; } + + /// <summary> + /// Sets the framebuffer upscaling level. + /// </summary> + public ReactiveObject<int> ScalingFilterLevel { get; private set; } + + /// <summary> + /// Preferred GPU + /// </summary> + public ReactiveObject<string> PreferredGpu { get; private set; } + + public GraphicsSection() + { + BackendThreading = new ReactiveObject<BackendThreading>(); + BackendThreading.Event += static (sender, e) => LogValueChange(e, nameof(BackendThreading)); + ResScale = new ReactiveObject<int>(); + ResScale.Event += static (sender, e) => LogValueChange(e, nameof(ResScale)); + ResScaleCustom = new ReactiveObject<float>(); + ResScaleCustom.Event += static (sender, e) => LogValueChange(e, nameof(ResScaleCustom)); + MaxAnisotropy = new ReactiveObject<float>(); + MaxAnisotropy.Event += static (sender, e) => LogValueChange(e, nameof(MaxAnisotropy)); + AspectRatio = new ReactiveObject<AspectRatio>(); + AspectRatio.Event += static (sender, e) => LogValueChange(e, nameof(AspectRatio)); + ShadersDumpPath = new ReactiveObject<string>(); + EnableVsync = new ReactiveObject<bool>(); + EnableVsync.Event += static (sender, e) => LogValueChange(e, nameof(EnableVsync)); + EnableShaderCache = new ReactiveObject<bool>(); + EnableShaderCache.Event += static (sender, e) => LogValueChange(e, nameof(EnableShaderCache)); + EnableTextureRecompression = new ReactiveObject<bool>(); + EnableTextureRecompression.Event += static (sender, e) => LogValueChange(e, nameof(EnableTextureRecompression)); + GraphicsBackend = new ReactiveObject<GraphicsBackend>(); + GraphicsBackend.Event += static (sender, e) => LogValueChange(e, nameof(GraphicsBackend)); + PreferredGpu = new ReactiveObject<string>(); + PreferredGpu.Event += static (sender, e) => LogValueChange(e, nameof(PreferredGpu)); + EnableMacroHLE = new ReactiveObject<bool>(); + EnableMacroHLE.Event += static (sender, e) => LogValueChange(e, nameof(EnableMacroHLE)); + EnableColorSpacePassthrough = new ReactiveObject<bool>(); + EnableColorSpacePassthrough.Event += static (sender, e) => LogValueChange(e, nameof(EnableColorSpacePassthrough)); + AntiAliasing = new ReactiveObject<AntiAliasing>(); + AntiAliasing.Event += static (sender, e) => LogValueChange(e, nameof(AntiAliasing)); + ScalingFilter = new ReactiveObject<ScalingFilter>(); + ScalingFilter.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilter)); + ScalingFilterLevel = new ReactiveObject<int>(); + ScalingFilterLevel.Event += static (sender, e) => LogValueChange(e, nameof(ScalingFilterLevel)); + } + } + + /// <summary> + /// Multiplayer configuration section + /// </summary> + public class MultiplayerSection + { + /// <summary> + /// GUID for the network interface used by LAN (or 0 for default) + /// </summary> + public ReactiveObject<string> LanInterfaceId { get; private set; } + + /// <summary> + /// Multiplayer Mode + /// </summary> + public ReactiveObject<MultiplayerMode> Mode { get; private set; } + + public MultiplayerSection() + { + LanInterfaceId = new ReactiveObject<string>(); + Mode = new ReactiveObject<MultiplayerMode>(); + Mode.Event += static (_, e) => LogValueChange(e, nameof(MultiplayerMode)); + } + } + + /// <summary> + /// The default configuration instance + /// </summary> + public static ConfigurationState Instance { get; private set; } + + /// <summary> + /// The UI section + /// </summary> + public UISection UI { get; private set; } + + /// <summary> + /// The Logger section + /// </summary> + public LoggerSection Logger { get; private set; } + + /// <summary> + /// The System section + /// </summary> + public SystemSection System { get; private set; } + + /// <summary> + /// The Graphics section + /// </summary> + public GraphicsSection Graphics { get; private set; } + + /// <summary> + /// The Hid section + /// </summary> + public HidSection Hid { get; private set; } + + /// <summary> + /// The Multiplayer section + /// </summary> + public MultiplayerSection Multiplayer { get; private set; } + + /// <summary> + /// Enables or disables Discord Rich Presence + /// </summary> + public ReactiveObject<bool> EnableDiscordIntegration { get; private set; } + + /// <summary> + /// Checks for updates when Ryujinx starts when enabled + /// </summary> + public ReactiveObject<bool> CheckUpdatesOnStart { get; private set; } + + /// <summary> + /// Show "Confirm Exit" Dialog + /// </summary> + public ReactiveObject<bool> ShowConfirmExit { get; private set; } + + /// <summary> + /// Hide Cursor on Idle + /// </summary> + public ReactiveObject<HideCursorMode> HideCursor { get; private set; } + + private ConfigurationState() + { + UI = new UISection(); + Logger = new LoggerSection(); + System = new SystemSection(); + Graphics = new GraphicsSection(); + Hid = new HidSection(); + Multiplayer = new MultiplayerSection(); + EnableDiscordIntegration = new ReactiveObject<bool>(); + CheckUpdatesOnStart = new ReactiveObject<bool>(); + ShowConfirmExit = new ReactiveObject<bool>(); + HideCursor = new ReactiveObject<HideCursorMode>(); + } + + public ConfigurationFileFormat ToFileFormat() + { + ConfigurationFileFormat configurationFile = new() + { + Version = ConfigurationFileFormat.CurrentVersion, + BackendThreading = Graphics.BackendThreading, + EnableFileLog = Logger.EnableFileLog, + ResScale = Graphics.ResScale, + ResScaleCustom = Graphics.ResScaleCustom, + MaxAnisotropy = Graphics.MaxAnisotropy, + AspectRatio = Graphics.AspectRatio, + AntiAliasing = Graphics.AntiAliasing, + ScalingFilter = Graphics.ScalingFilter, + ScalingFilterLevel = Graphics.ScalingFilterLevel, + GraphicsShadersDumpPath = Graphics.ShadersDumpPath, + LoggingEnableDebug = Logger.EnableDebug, + LoggingEnableStub = Logger.EnableStub, + LoggingEnableInfo = Logger.EnableInfo, + LoggingEnableWarn = Logger.EnableWarn, + LoggingEnableError = Logger.EnableError, + LoggingEnableTrace = Logger.EnableTrace, + LoggingEnableGuest = Logger.EnableGuest, + LoggingEnableFsAccessLog = Logger.EnableFsAccessLog, + LoggingFilteredClasses = Logger.FilteredClasses, + LoggingGraphicsDebugLevel = Logger.GraphicsDebugLevel, + SystemLanguage = System.Language, + SystemRegion = System.Region, + SystemTimeZone = System.TimeZone, + SystemTimeOffset = System.SystemTimeOffset, + DockedMode = System.EnableDockedMode, + EnableDiscordIntegration = EnableDiscordIntegration, + CheckUpdatesOnStart = CheckUpdatesOnStart, + ShowConfirmExit = ShowConfirmExit, + HideCursor = HideCursor, + EnableVsync = Graphics.EnableVsync, + EnableShaderCache = Graphics.EnableShaderCache, + EnableTextureRecompression = Graphics.EnableTextureRecompression, + EnableMacroHLE = Graphics.EnableMacroHLE, + EnableColorSpacePassthrough = Graphics.EnableColorSpacePassthrough, + EnablePtc = System.EnablePtc, + EnableInternetAccess = System.EnableInternetAccess, + EnableFsIntegrityChecks = System.EnableFsIntegrityChecks, + FsGlobalAccessLogMode = System.FsGlobalAccessLogMode, + AudioBackend = System.AudioBackend, + AudioVolume = System.AudioVolume, + MemoryManagerMode = System.MemoryManagerMode, + ExpandRam = System.ExpandRam, + IgnoreMissingServices = System.IgnoreMissingServices, + UseHypervisor = System.UseHypervisor, + GuiColumns = new GuiColumns + { + FavColumn = UI.GuiColumns.FavColumn, + IconColumn = UI.GuiColumns.IconColumn, + AppColumn = UI.GuiColumns.AppColumn, + DevColumn = UI.GuiColumns.DevColumn, + VersionColumn = UI.GuiColumns.VersionColumn, + TimePlayedColumn = UI.GuiColumns.TimePlayedColumn, + LastPlayedColumn = UI.GuiColumns.LastPlayedColumn, + FileExtColumn = UI.GuiColumns.FileExtColumn, + FileSizeColumn = UI.GuiColumns.FileSizeColumn, + PathColumn = UI.GuiColumns.PathColumn, + }, + ColumnSort = new ColumnSort + { + SortColumnId = UI.ColumnSort.SortColumnId, + SortAscending = UI.ColumnSort.SortAscending, + }, + GameDirs = UI.GameDirs, + ShownFileTypes = new ShownFileTypes + { + NSP = UI.ShownFileTypes.NSP, + PFS0 = UI.ShownFileTypes.PFS0, + XCI = UI.ShownFileTypes.XCI, + NCA = UI.ShownFileTypes.NCA, + NRO = UI.ShownFileTypes.NRO, + NSO = UI.ShownFileTypes.NSO, + }, + WindowStartup = new WindowStartup + { + WindowSizeWidth = UI.WindowStartup.WindowSizeWidth, + WindowSizeHeight = UI.WindowStartup.WindowSizeHeight, + WindowPositionX = UI.WindowStartup.WindowPositionX, + WindowPositionY = UI.WindowStartup.WindowPositionY, + WindowMaximized = UI.WindowStartup.WindowMaximized, + }, + LanguageCode = UI.LanguageCode, + EnableCustomTheme = UI.EnableCustomTheme, + CustomThemePath = UI.CustomThemePath, + BaseStyle = UI.BaseStyle, + GameListViewMode = UI.GameListViewMode, + ShowNames = UI.ShowNames, + GridSize = UI.GridSize, + ApplicationSort = UI.ApplicationSort, + IsAscendingOrder = UI.IsAscendingOrder, + StartFullscreen = UI.StartFullscreen, + ShowConsole = UI.ShowConsole, + EnableKeyboard = Hid.EnableKeyboard, + EnableMouse = Hid.EnableMouse, + Hotkeys = Hid.Hotkeys, + KeyboardConfig = new List<JsonObject>(), + ControllerConfig = new List<JsonObject>(), + InputConfig = Hid.InputConfig, + GraphicsBackend = Graphics.GraphicsBackend, + PreferredGpu = Graphics.PreferredGpu, + MultiplayerLanInterfaceId = Multiplayer.LanInterfaceId, + MultiplayerMode = Multiplayer.Mode, + }; + + return configurationFile; + } + + public void LoadDefault() + { + Logger.EnableFileLog.Value = true; + Graphics.BackendThreading.Value = BackendThreading.Auto; + Graphics.ResScale.Value = 1; + Graphics.ResScaleCustom.Value = 1.0f; + Graphics.MaxAnisotropy.Value = -1.0f; + Graphics.AspectRatio.Value = AspectRatio.Fixed16x9; + Graphics.GraphicsBackend.Value = DefaultGraphicsBackend(); + Graphics.PreferredGpu.Value = ""; + Graphics.ShadersDumpPath.Value = ""; + Logger.EnableDebug.Value = false; + Logger.EnableStub.Value = true; + Logger.EnableInfo.Value = true; + Logger.EnableWarn.Value = true; + Logger.EnableError.Value = true; + Logger.EnableTrace.Value = false; + Logger.EnableGuest.Value = true; + Logger.EnableFsAccessLog.Value = false; + Logger.FilteredClasses.Value = Array.Empty<LogClass>(); + Logger.GraphicsDebugLevel.Value = GraphicsDebugLevel.None; + System.Language.Value = Language.AmericanEnglish; + System.Region.Value = Region.USA; + System.TimeZone.Value = "UTC"; + System.SystemTimeOffset.Value = 0; + System.EnableDockedMode.Value = true; + EnableDiscordIntegration.Value = true; + CheckUpdatesOnStart.Value = true; + ShowConfirmExit.Value = true; + HideCursor.Value = HideCursorMode.OnIdle; + Graphics.EnableVsync.Value = true; + Graphics.EnableShaderCache.Value = true; + Graphics.EnableTextureRecompression.Value = false; + Graphics.EnableMacroHLE.Value = true; + Graphics.EnableColorSpacePassthrough.Value = false; + Graphics.AntiAliasing.Value = AntiAliasing.None; + Graphics.ScalingFilter.Value = ScalingFilter.Bilinear; + Graphics.ScalingFilterLevel.Value = 80; + System.EnablePtc.Value = true; + System.EnableInternetAccess.Value = false; + System.EnableFsIntegrityChecks.Value = true; + System.FsGlobalAccessLogMode.Value = 0; + System.AudioBackend.Value = AudioBackend.SDL2; + System.AudioVolume.Value = 1; + System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe; + System.ExpandRam.Value = false; + System.IgnoreMissingServices.Value = false; + System.UseHypervisor.Value = true; + Multiplayer.LanInterfaceId.Value = "0"; + Multiplayer.Mode.Value = MultiplayerMode.Disabled; + UI.GuiColumns.FavColumn.Value = true; + UI.GuiColumns.IconColumn.Value = true; + UI.GuiColumns.AppColumn.Value = true; + UI.GuiColumns.DevColumn.Value = true; + UI.GuiColumns.VersionColumn.Value = true; + UI.GuiColumns.TimePlayedColumn.Value = true; + UI.GuiColumns.LastPlayedColumn.Value = true; + UI.GuiColumns.FileExtColumn.Value = true; + UI.GuiColumns.FileSizeColumn.Value = true; + UI.GuiColumns.PathColumn.Value = true; + UI.ColumnSort.SortColumnId.Value = 0; + UI.ColumnSort.SortAscending.Value = false; + UI.GameDirs.Value = new List<string>(); + UI.ShownFileTypes.NSP.Value = true; + UI.ShownFileTypes.PFS0.Value = true; + UI.ShownFileTypes.XCI.Value = true; + UI.ShownFileTypes.NCA.Value = true; + UI.ShownFileTypes.NRO.Value = true; + UI.ShownFileTypes.NSO.Value = true; + UI.EnableCustomTheme.Value = true; + UI.LanguageCode.Value = "en_US"; + UI.CustomThemePath.Value = ""; + UI.BaseStyle.Value = "Dark"; + UI.GameListViewMode.Value = 0; + UI.ShowNames.Value = true; + UI.GridSize.Value = 2; + UI.ApplicationSort.Value = 0; + UI.IsAscendingOrder.Value = true; + UI.StartFullscreen.Value = false; + UI.ShowConsole.Value = true; + UI.WindowStartup.WindowSizeWidth.Value = 1280; + UI.WindowStartup.WindowSizeHeight.Value = 760; + UI.WindowStartup.WindowPositionX.Value = 0; + UI.WindowStartup.WindowPositionY.Value = 0; + UI.WindowStartup.WindowMaximized.Value = false; + Hid.EnableKeyboard.Value = false; + Hid.EnableMouse.Value = false; + Hid.Hotkeys.Value = new KeyboardHotkeys + { + ToggleVsync = Key.F1, + ToggleMute = Key.F2, + Screenshot = Key.F8, + ShowUI = Key.F4, + Pause = Key.F5, + ResScaleUp = Key.Unbound, + ResScaleDown = Key.Unbound, + VolumeUp = Key.Unbound, + VolumeDown = Key.Unbound, + }; + Hid.InputConfig.Value = new List<InputConfig> + { + new StandardKeyboardInputConfig + { + Version = InputConfig.CurrentVersion, + Backend = InputBackendType.WindowKeyboard, + Id = "0", + PlayerIndex = PlayerIndex.Player1, + ControllerType = ControllerType.JoyconPair, + LeftJoycon = new LeftJoyconCommonConfig<Key> + { + DpadUp = Key.Up, + DpadDown = Key.Down, + DpadLeft = Key.Left, + DpadRight = Key.Right, + ButtonMinus = Key.Minus, + ButtonL = Key.E, + ButtonZl = Key.Q, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound, + }, + LeftJoyconStick = new JoyconConfigKeyboardStick<Key> + { + StickUp = Key.W, + StickDown = Key.S, + StickLeft = Key.A, + StickRight = Key.D, + StickButton = Key.F, + }, + RightJoycon = new RightJoyconCommonConfig<Key> + { + ButtonA = Key.Z, + ButtonB = Key.X, + ButtonX = Key.C, + ButtonY = Key.V, + ButtonPlus = Key.Plus, + ButtonR = Key.U, + ButtonZr = Key.O, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound, + }, + RightJoyconStick = new JoyconConfigKeyboardStick<Key> + { + StickUp = Key.I, + StickDown = Key.K, + StickLeft = Key.J, + StickRight = Key.L, + StickButton = Key.H, + }, + }, + }; + } + + public void Load(ConfigurationFileFormat configurationFileFormat, string configurationFilePath) + { + bool configurationFileUpdated = false; + + if (configurationFileFormat.Version < 0 || configurationFileFormat.Version > ConfigurationFileFormat.CurrentVersion) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Unsupported configuration version {configurationFileFormat.Version}, loading default."); + + LoadDefault(); + } + + if (configurationFileFormat.Version < 2) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 2."); + + configurationFileFormat.SystemRegion = Region.USA; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 3) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 3."); + + configurationFileFormat.SystemTimeZone = "UTC"; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 4) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 4."); + + configurationFileFormat.MaxAnisotropy = -1; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 5) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 5."); + + configurationFileFormat.SystemTimeOffset = 0; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 8) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 8."); + + configurationFileFormat.EnablePtc = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 9) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 9."); + + configurationFileFormat.ColumnSort = new ColumnSort + { + SortColumnId = 0, + SortAscending = false, + }; + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleVsync = Key.F1, + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 10) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 10."); + + configurationFileFormat.AudioBackend = AudioBackend.OpenAl; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 11) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 11."); + + configurationFileFormat.ResScale = 1; + configurationFileFormat.ResScaleCustom = 1.0f; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 12) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 12."); + + configurationFileFormat.LoggingGraphicsDebugLevel = GraphicsDebugLevel.None; + + configurationFileUpdated = true; + } + + // configurationFileFormat.Version == 13 -> LDN1 + + if (configurationFileFormat.Version < 14) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 14."); + + configurationFileFormat.CheckUpdatesOnStart = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 16) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 16."); + + configurationFileFormat.EnableShaderCache = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 17) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 17."); + + configurationFileFormat.StartFullscreen = false; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 18) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 18."); + + configurationFileFormat.AspectRatio = AspectRatio.Fixed16x9; + + configurationFileUpdated = true; + } + + // configurationFileFormat.Version == 19 -> LDN2 + + if (configurationFileFormat.Version < 20) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 20."); + + configurationFileFormat.ShowConfirmExit = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 21) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 21."); + + // Initialize network config. + + configurationFileFormat.MultiplayerMode = MultiplayerMode.Disabled; + configurationFileFormat.MultiplayerLanInterfaceId = "0"; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 22) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 22."); + + configurationFileFormat.HideCursor = HideCursorMode.Never; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 24) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 24."); + + configurationFileFormat.InputConfig = new List<InputConfig> + { + new StandardKeyboardInputConfig + { + Version = InputConfig.CurrentVersion, + Backend = InputBackendType.WindowKeyboard, + Id = "0", + PlayerIndex = PlayerIndex.Player1, + ControllerType = ControllerType.JoyconPair, + LeftJoycon = new LeftJoyconCommonConfig<Key> + { + DpadUp = Key.Up, + DpadDown = Key.Down, + DpadLeft = Key.Left, + DpadRight = Key.Right, + ButtonMinus = Key.Minus, + ButtonL = Key.E, + ButtonZl = Key.Q, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound, + }, + LeftJoyconStick = new JoyconConfigKeyboardStick<Key> + { + StickUp = Key.W, + StickDown = Key.S, + StickLeft = Key.A, + StickRight = Key.D, + StickButton = Key.F, + }, + RightJoycon = new RightJoyconCommonConfig<Key> + { + ButtonA = Key.Z, + ButtonB = Key.X, + ButtonX = Key.C, + ButtonY = Key.V, + ButtonPlus = Key.Plus, + ButtonR = Key.U, + ButtonZr = Key.O, + ButtonSl = Key.Unbound, + ButtonSr = Key.Unbound, + }, + RightJoyconStick = new JoyconConfigKeyboardStick<Key> + { + StickUp = Key.I, + StickDown = Key.K, + StickLeft = Key.J, + StickRight = Key.L, + StickButton = Key.H, + }, + }, + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 25) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 25."); + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 26) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 26."); + + configurationFileFormat.MemoryManagerMode = MemoryManagerMode.HostMappedUnsafe; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 27) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 27."); + + configurationFileFormat.EnableMouse = false; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 28) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 28."); + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleVsync = Key.F1, + Screenshot = Key.F8, + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 29) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 29."); + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleVsync = Key.F1, + Screenshot = Key.F8, + ShowUI = Key.F4, + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 30) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 30."); + + foreach (InputConfig config in configurationFileFormat.InputConfig) + { + if (config is StandardControllerInputConfig controllerConfig) + { + controllerConfig.Rumble = new RumbleConfigController + { + EnableRumble = false, + StrongRumble = 1f, + WeakRumble = 1f, + }; + } + } + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 31) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 31."); + + configurationFileFormat.BackendThreading = BackendThreading.Auto; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 32) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 32."); + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, + Screenshot = configurationFileFormat.Hotkeys.Screenshot, + ShowUI = configurationFileFormat.Hotkeys.ShowUI, + Pause = Key.F5, + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 33) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 33."); + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, + Screenshot = configurationFileFormat.Hotkeys.Screenshot, + ShowUI = configurationFileFormat.Hotkeys.ShowUI, + Pause = configurationFileFormat.Hotkeys.Pause, + ToggleMute = Key.F2, + }; + + configurationFileFormat.AudioVolume = 1; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 34) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 34."); + + configurationFileFormat.EnableInternetAccess = false; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 35) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 35."); + + foreach (InputConfig config in configurationFileFormat.InputConfig) + { + if (config is StandardControllerInputConfig controllerConfig) + { + controllerConfig.RangeLeft = 1.0f; + controllerConfig.RangeRight = 1.0f; + } + } + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 36) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 36."); + + configurationFileFormat.LoggingEnableTrace = false; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 37) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 37."); + + configurationFileFormat.ShowConsole = true; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 38) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 38."); + + configurationFileFormat.BaseStyle = "Dark"; + configurationFileFormat.GameListViewMode = 0; + configurationFileFormat.ShowNames = true; + configurationFileFormat.GridSize = 2; + configurationFileFormat.LanguageCode = "en_US"; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 39) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 39."); + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, + Screenshot = configurationFileFormat.Hotkeys.Screenshot, + ShowUI = configurationFileFormat.Hotkeys.ShowUI, + Pause = configurationFileFormat.Hotkeys.Pause, + ToggleMute = configurationFileFormat.Hotkeys.ToggleMute, + ResScaleUp = Key.Unbound, + ResScaleDown = Key.Unbound, + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 40) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 40."); + + configurationFileFormat.GraphicsBackend = GraphicsBackend.OpenGl; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 41) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 41."); + + configurationFileFormat.Hotkeys = new KeyboardHotkeys + { + ToggleVsync = configurationFileFormat.Hotkeys.ToggleVsync, + Screenshot = configurationFileFormat.Hotkeys.Screenshot, + ShowUI = configurationFileFormat.Hotkeys.ShowUI, + Pause = configurationFileFormat.Hotkeys.Pause, + ToggleMute = configurationFileFormat.Hotkeys.ToggleMute, + ResScaleUp = configurationFileFormat.Hotkeys.ResScaleUp, + ResScaleDown = configurationFileFormat.Hotkeys.ResScaleDown, + VolumeUp = Key.Unbound, + VolumeDown = Key.Unbound, + }; + } + + if (configurationFileFormat.Version < 42) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 42."); + + configurationFileFormat.EnableMacroHLE = true; + } + + if (configurationFileFormat.Version < 43) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 43."); + + configurationFileFormat.UseHypervisor = true; + } + + if (configurationFileFormat.Version < 44) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 44."); + + configurationFileFormat.AntiAliasing = AntiAliasing.None; + configurationFileFormat.ScalingFilter = ScalingFilter.Bilinear; + configurationFileFormat.ScalingFilterLevel = 80; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 45) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 45."); + + configurationFileFormat.ShownFileTypes = new ShownFileTypes + { + NSP = true, + PFS0 = true, + XCI = true, + NCA = true, + NRO = true, + NSO = true, + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 46) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 46."); + + configurationFileFormat.MultiplayerLanInterfaceId = "0"; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 47) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 47."); + + configurationFileFormat.WindowStartup = new WindowStartup + { + WindowPositionX = 0, + WindowPositionY = 0, + WindowSizeHeight = 760, + WindowSizeWidth = 1280, + WindowMaximized = false, + }; + + configurationFileUpdated = true; + } + + if (configurationFileFormat.Version < 48) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 48."); + + configurationFileFormat.EnableColorSpacePassthrough = false; + + configurationFileUpdated = true; + } + + Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; + Graphics.ResScale.Value = configurationFileFormat.ResScale; + Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; + Graphics.MaxAnisotropy.Value = configurationFileFormat.MaxAnisotropy; + Graphics.AspectRatio.Value = configurationFileFormat.AspectRatio; + Graphics.ShadersDumpPath.Value = configurationFileFormat.GraphicsShadersDumpPath; + Graphics.BackendThreading.Value = configurationFileFormat.BackendThreading; + Graphics.GraphicsBackend.Value = configurationFileFormat.GraphicsBackend; + Graphics.PreferredGpu.Value = configurationFileFormat.PreferredGpu; + Graphics.AntiAliasing.Value = configurationFileFormat.AntiAliasing; + Graphics.ScalingFilter.Value = configurationFileFormat.ScalingFilter; + Graphics.ScalingFilterLevel.Value = configurationFileFormat.ScalingFilterLevel; + Logger.EnableDebug.Value = configurationFileFormat.LoggingEnableDebug; + Logger.EnableStub.Value = configurationFileFormat.LoggingEnableStub; + Logger.EnableInfo.Value = configurationFileFormat.LoggingEnableInfo; + Logger.EnableWarn.Value = configurationFileFormat.LoggingEnableWarn; + Logger.EnableError.Value = configurationFileFormat.LoggingEnableError; + Logger.EnableTrace.Value = configurationFileFormat.LoggingEnableTrace; + Logger.EnableGuest.Value = configurationFileFormat.LoggingEnableGuest; + Logger.EnableFsAccessLog.Value = configurationFileFormat.LoggingEnableFsAccessLog; + Logger.FilteredClasses.Value = configurationFileFormat.LoggingFilteredClasses; + Logger.GraphicsDebugLevel.Value = configurationFileFormat.LoggingGraphicsDebugLevel; + System.Language.Value = configurationFileFormat.SystemLanguage; + System.Region.Value = configurationFileFormat.SystemRegion; + System.TimeZone.Value = configurationFileFormat.SystemTimeZone; + System.SystemTimeOffset.Value = configurationFileFormat.SystemTimeOffset; + System.EnableDockedMode.Value = configurationFileFormat.DockedMode; + EnableDiscordIntegration.Value = configurationFileFormat.EnableDiscordIntegration; + CheckUpdatesOnStart.Value = configurationFileFormat.CheckUpdatesOnStart; + ShowConfirmExit.Value = configurationFileFormat.ShowConfirmExit; + HideCursor.Value = configurationFileFormat.HideCursor; + Graphics.EnableVsync.Value = configurationFileFormat.EnableVsync; + Graphics.EnableShaderCache.Value = configurationFileFormat.EnableShaderCache; + Graphics.EnableTextureRecompression.Value = configurationFileFormat.EnableTextureRecompression; + Graphics.EnableMacroHLE.Value = configurationFileFormat.EnableMacroHLE; + Graphics.EnableColorSpacePassthrough.Value = configurationFileFormat.EnableColorSpacePassthrough; + System.EnablePtc.Value = configurationFileFormat.EnablePtc; + System.EnableInternetAccess.Value = configurationFileFormat.EnableInternetAccess; + System.EnableFsIntegrityChecks.Value = configurationFileFormat.EnableFsIntegrityChecks; + System.FsGlobalAccessLogMode.Value = configurationFileFormat.FsGlobalAccessLogMode; + System.AudioBackend.Value = configurationFileFormat.AudioBackend; + System.AudioVolume.Value = configurationFileFormat.AudioVolume; + System.MemoryManagerMode.Value = configurationFileFormat.MemoryManagerMode; + System.ExpandRam.Value = configurationFileFormat.ExpandRam; + System.IgnoreMissingServices.Value = configurationFileFormat.IgnoreMissingServices; + System.UseHypervisor.Value = configurationFileFormat.UseHypervisor; + UI.GuiColumns.FavColumn.Value = configurationFileFormat.GuiColumns.FavColumn; + UI.GuiColumns.IconColumn.Value = configurationFileFormat.GuiColumns.IconColumn; + UI.GuiColumns.AppColumn.Value = configurationFileFormat.GuiColumns.AppColumn; + UI.GuiColumns.DevColumn.Value = configurationFileFormat.GuiColumns.DevColumn; + UI.GuiColumns.VersionColumn.Value = configurationFileFormat.GuiColumns.VersionColumn; + UI.GuiColumns.TimePlayedColumn.Value = configurationFileFormat.GuiColumns.TimePlayedColumn; + UI.GuiColumns.LastPlayedColumn.Value = configurationFileFormat.GuiColumns.LastPlayedColumn; + UI.GuiColumns.FileExtColumn.Value = configurationFileFormat.GuiColumns.FileExtColumn; + UI.GuiColumns.FileSizeColumn.Value = configurationFileFormat.GuiColumns.FileSizeColumn; + UI.GuiColumns.PathColumn.Value = configurationFileFormat.GuiColumns.PathColumn; + UI.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId; + UI.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending; + UI.GameDirs.Value = configurationFileFormat.GameDirs; + UI.ShownFileTypes.NSP.Value = configurationFileFormat.ShownFileTypes.NSP; + UI.ShownFileTypes.PFS0.Value = configurationFileFormat.ShownFileTypes.PFS0; + UI.ShownFileTypes.XCI.Value = configurationFileFormat.ShownFileTypes.XCI; + UI.ShownFileTypes.NCA.Value = configurationFileFormat.ShownFileTypes.NCA; + UI.ShownFileTypes.NRO.Value = configurationFileFormat.ShownFileTypes.NRO; + UI.ShownFileTypes.NSO.Value = configurationFileFormat.ShownFileTypes.NSO; + UI.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme; + UI.LanguageCode.Value = configurationFileFormat.LanguageCode; + UI.CustomThemePath.Value = configurationFileFormat.CustomThemePath; + UI.BaseStyle.Value = configurationFileFormat.BaseStyle; + UI.GameListViewMode.Value = configurationFileFormat.GameListViewMode; + UI.ShowNames.Value = configurationFileFormat.ShowNames; + UI.IsAscendingOrder.Value = configurationFileFormat.IsAscendingOrder; + UI.GridSize.Value = configurationFileFormat.GridSize; + UI.ApplicationSort.Value = configurationFileFormat.ApplicationSort; + UI.StartFullscreen.Value = configurationFileFormat.StartFullscreen; + UI.ShowConsole.Value = configurationFileFormat.ShowConsole; + UI.WindowStartup.WindowSizeWidth.Value = configurationFileFormat.WindowStartup.WindowSizeWidth; + UI.WindowStartup.WindowSizeHeight.Value = configurationFileFormat.WindowStartup.WindowSizeHeight; + UI.WindowStartup.WindowPositionX.Value = configurationFileFormat.WindowStartup.WindowPositionX; + UI.WindowStartup.WindowPositionY.Value = configurationFileFormat.WindowStartup.WindowPositionY; + UI.WindowStartup.WindowMaximized.Value = configurationFileFormat.WindowStartup.WindowMaximized; + Hid.EnableKeyboard.Value = configurationFileFormat.EnableKeyboard; + Hid.EnableMouse.Value = configurationFileFormat.EnableMouse; + Hid.Hotkeys.Value = configurationFileFormat.Hotkeys; + Hid.InputConfig.Value = configurationFileFormat.InputConfig; + + if (Hid.InputConfig.Value == null) + { + Hid.InputConfig.Value = new List<InputConfig>(); + } + + Multiplayer.LanInterfaceId.Value = configurationFileFormat.MultiplayerLanInterfaceId; + Multiplayer.Mode.Value = configurationFileFormat.MultiplayerMode; + + if (configurationFileUpdated) + { + ToFileFormat().SaveConfig(configurationFilePath); + + Ryujinx.Common.Logging.Logger.Notice.Print(LogClass.Application, $"Configuration file updated to version {ConfigurationFileFormat.CurrentVersion}"); + } + } + + private static GraphicsBackend DefaultGraphicsBackend() + { + // Any system running macOS or returning any amount of valid Vulkan devices should default to Vulkan. + // Checks for if the Vulkan version and featureset is compatible should be performed within VulkanRenderer. + if (OperatingSystem.IsMacOS() || VulkanRenderer.GetPhysicalDevices().Length > 0) + { + return GraphicsBackend.Vulkan; + } + + return GraphicsBackend.OpenGl; + } + + private static void LogValueChange<T>(ReactiveEventArgs<T> eventArgs, string valueName) + { + Ryujinx.Common.Logging.Logger.Info?.Print(LogClass.Configuration, $"{valueName} set to: {eventArgs.NewValue}"); + } + + public static void Initialize() + { + if (Instance != null) + { + throw new InvalidOperationException("Configuration is already initialized"); + } + + Instance = new ConfigurationState(); + } + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/FileTypes.cs b/src/Ryujinx.UI.Common/Configuration/FileTypes.cs new file mode 100644 index 00000000..1974207b --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/FileTypes.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.UI.Common +{ + public enum FileTypes + { + NSP, + PFS0, + XCI, + NCA, + NRO, + NSO + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/LoggerModule.cs b/src/Ryujinx.UI.Common/Configuration/LoggerModule.cs new file mode 100644 index 00000000..9cb28359 --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/LoggerModule.cs @@ -0,0 +1,113 @@ +using Ryujinx.Common; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Logging; +using Ryujinx.Common.Logging.Targets; +using System; +using System.IO; + +namespace Ryujinx.UI.Common.Configuration +{ + public static class LoggerModule + { + public static void Initialize() + { + ConfigurationState.Instance.Logger.EnableDebug.Event += ReloadEnableDebug; + ConfigurationState.Instance.Logger.EnableStub.Event += ReloadEnableStub; + ConfigurationState.Instance.Logger.EnableInfo.Event += ReloadEnableInfo; + ConfigurationState.Instance.Logger.EnableWarn.Event += ReloadEnableWarning; + ConfigurationState.Instance.Logger.EnableError.Event += ReloadEnableError; + ConfigurationState.Instance.Logger.EnableTrace.Event += ReloadEnableTrace; + ConfigurationState.Instance.Logger.EnableGuest.Event += ReloadEnableGuest; + ConfigurationState.Instance.Logger.EnableFsAccessLog.Event += ReloadEnableFsAccessLog; + ConfigurationState.Instance.Logger.FilteredClasses.Event += ReloadFilteredClasses; + ConfigurationState.Instance.Logger.EnableFileLog.Event += ReloadFileLogger; + } + + private static void ReloadEnableDebug(object sender, ReactiveEventArgs<bool> e) + { + Logger.SetEnable(LogLevel.Debug, e.NewValue); + } + + private static void ReloadEnableStub(object sender, ReactiveEventArgs<bool> e) + { + Logger.SetEnable(LogLevel.Stub, e.NewValue); + } + + private static void ReloadEnableInfo(object sender, ReactiveEventArgs<bool> e) + { + Logger.SetEnable(LogLevel.Info, e.NewValue); + } + + private static void ReloadEnableWarning(object sender, ReactiveEventArgs<bool> e) + { + Logger.SetEnable(LogLevel.Warning, e.NewValue); + } + + private static void ReloadEnableError(object sender, ReactiveEventArgs<bool> e) + { + Logger.SetEnable(LogLevel.Error, e.NewValue); + } + + private static void ReloadEnableTrace(object sender, ReactiveEventArgs<bool> e) + { + Logger.SetEnable(LogLevel.Trace, e.NewValue); + } + + private static void ReloadEnableGuest(object sender, ReactiveEventArgs<bool> e) + { + Logger.SetEnable(LogLevel.Guest, e.NewValue); + } + + private static void ReloadEnableFsAccessLog(object sender, ReactiveEventArgs<bool> e) + { + Logger.SetEnable(LogLevel.AccessLog, e.NewValue); + } + + private static void ReloadFilteredClasses(object sender, ReactiveEventArgs<LogClass[]> e) + { + bool noFilter = e.NewValue.Length == 0; + + foreach (var logClass in Enum.GetValues<LogClass>()) + { + Logger.SetEnable(logClass, noFilter); + } + + foreach (var logClass in e.NewValue) + { + Logger.SetEnable(logClass, true); + } + } + + private static void ReloadFileLogger(object sender, ReactiveEventArgs<bool> e) + { + if (e.NewValue) + { + string logDir = AppDataManager.LogsDirPath; + FileStream logFile = null; + + if (!string.IsNullOrEmpty(logDir)) + { + logFile = FileLogTarget.PrepareLogFile(logDir); + } + + if (logFile == null) + { + Logger.Error?.Print(LogClass.Application, "No writable log directory available. Make sure either the Logs directory, Application Data, or the Ryujinx directory is writable."); + Logger.RemoveTarget("file"); + + return; + } + + Logger.AddTarget(new AsyncLogTargetWrapper( + new FileLogTarget("file", logFile), + 1000, + AsyncLogTargetOverflowAction.Block + )); + } + else + { + Logger.RemoveTarget("file"); + } + } + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/System/Language.cs b/src/Ryujinx.UI.Common/Configuration/System/Language.cs new file mode 100644 index 00000000..d1d395b0 --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/System/Language.cs @@ -0,0 +1,28 @@ +using Ryujinx.Common.Utilities; +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Configuration.System +{ + [JsonConverter(typeof(TypedStringEnumConverter<Language>))] + public enum Language + { + Japanese, + AmericanEnglish, + French, + German, + Italian, + Spanish, + Chinese, + Korean, + Dutch, + Portuguese, + Russian, + Taiwanese, + BritishEnglish, + CanadianFrench, + LatinAmericanSpanish, + SimplifiedChinese, + TraditionalChinese, + BrazilianPortuguese, + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/System/Region.cs b/src/Ryujinx.UI.Common/Configuration/System/Region.cs new file mode 100644 index 00000000..6087c70e --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/System/Region.cs @@ -0,0 +1,17 @@ +using Ryujinx.Common.Utilities; +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Configuration.System +{ + [JsonConverter(typeof(TypedStringEnumConverter<Region>))] + public enum Region + { + Japan, + USA, + Europe, + Australia, + China, + Korea, + Taiwan, + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/UI/ColumnSort.cs b/src/Ryujinx.UI.Common/Configuration/UI/ColumnSort.cs new file mode 100644 index 00000000..44e98c40 --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/UI/ColumnSort.cs @@ -0,0 +1,8 @@ +namespace Ryujinx.UI.Common.Configuration.UI +{ + public struct ColumnSort + { + public int SortColumnId { get; set; } + public bool SortAscending { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/UI/GuiColumns.cs b/src/Ryujinx.UI.Common/Configuration/UI/GuiColumns.cs new file mode 100644 index 00000000..c778ef1f --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/UI/GuiColumns.cs @@ -0,0 +1,16 @@ +namespace Ryujinx.UI.Common.Configuration.UI +{ + public struct GuiColumns + { + public bool FavColumn { get; set; } + public bool IconColumn { get; set; } + public bool AppColumn { get; set; } + public bool DevColumn { get; set; } + public bool VersionColumn { get; set; } + public bool TimePlayedColumn { get; set; } + public bool LastPlayedColumn { get; set; } + public bool FileExtColumn { get; set; } + public bool FileSizeColumn { get; set; } + public bool PathColumn { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/UI/ShownFileTypes.cs b/src/Ryujinx.UI.Common/Configuration/UI/ShownFileTypes.cs new file mode 100644 index 00000000..6c72a693 --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/UI/ShownFileTypes.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.UI.Common.Configuration.UI +{ + public struct ShownFileTypes + { + public bool NSP { get; set; } + public bool PFS0 { get; set; } + public bool XCI { get; set; } + public bool NCA { get; set; } + public bool NRO { get; set; } + public bool NSO { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/Configuration/UI/WindowStartup.cs b/src/Ryujinx.UI.Common/Configuration/UI/WindowStartup.cs new file mode 100644 index 00000000..0df45913 --- /dev/null +++ b/src/Ryujinx.UI.Common/Configuration/UI/WindowStartup.cs @@ -0,0 +1,11 @@ +namespace Ryujinx.UI.Common.Configuration.UI +{ + public struct WindowStartup + { + public int WindowSizeWidth { get; set; } + public int WindowSizeHeight { get; set; } + public int WindowPositionX { get; set; } + public int WindowPositionY { get; set; } + public bool WindowMaximized { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs b/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs new file mode 100644 index 00000000..0b9439ea --- /dev/null +++ b/src/Ryujinx.UI.Common/DiscordIntegrationModule.cs @@ -0,0 +1,98 @@ +using DiscordRPC; +using Ryujinx.Common; +using Ryujinx.UI.Common.Configuration; + +namespace Ryujinx.UI.Common +{ + public static class DiscordIntegrationModule + { + private const string Description = "A simple, experimental Nintendo Switch emulator."; + private const string CliendId = "568815339807309834"; + + private static DiscordRpcClient _discordClient; + private static RichPresence _discordPresenceMain; + + public static void Initialize() + { + _discordPresenceMain = new RichPresence + { + Assets = new Assets + { + LargeImageKey = "ryujinx", + LargeImageText = Description, + }, + Details = "Main Menu", + State = "Idling", + Timestamps = Timestamps.Now, + Buttons = new[] + { + new Button + { + Label = "Website", + Url = "https://ryujinx.org/", + }, + }, + }; + + ConfigurationState.Instance.EnableDiscordIntegration.Event += Update; + } + + private static void Update(object sender, ReactiveEventArgs<bool> evnt) + { + if (evnt.OldValue != evnt.NewValue) + { + // If the integration was active, disable it and unload everything + if (evnt.OldValue) + { + _discordClient?.Dispose(); + + _discordClient = null; + } + + // If we need to activate it and the client isn't active, initialize it + if (evnt.NewValue && _discordClient == null) + { + _discordClient = new DiscordRpcClient(CliendId); + + _discordClient.Initialize(); + _discordClient.SetPresence(_discordPresenceMain); + } + } + } + + public static void SwitchToPlayingState(string titleId, string titleName) + { + _discordClient?.SetPresence(new RichPresence + { + Assets = new Assets + { + LargeImageKey = "game", + LargeImageText = titleName, + SmallImageKey = "ryujinx", + SmallImageText = Description, + }, + Details = $"Playing {titleName}", + State = (titleId == "0000000000000000") ? "Homebrew" : titleId.ToUpper(), + Timestamps = Timestamps.Now, + Buttons = new[] + { + new Button + { + Label = "Website", + Url = "https://ryujinx.org/", + }, + }, + }); + } + + public static void SwitchToMainMenu() + { + _discordClient?.SetPresence(_discordPresenceMain); + } + + public static void Exit() + { + _discordClient?.Dispose(); + } + } +} diff --git a/src/Ryujinx.UI.Common/Extensions/FileTypeExtensions.cs b/src/Ryujinx.UI.Common/Extensions/FileTypeExtensions.cs new file mode 100644 index 00000000..7e71ba7a --- /dev/null +++ b/src/Ryujinx.UI.Common/Extensions/FileTypeExtensions.cs @@ -0,0 +1,25 @@ +using System; +using static Ryujinx.UI.Common.Configuration.ConfigurationState.UISection; + +namespace Ryujinx.UI.Common +{ + public static class FileTypesExtensions + { + /// <summary> + /// Gets the current <see cref="ShownFileTypeSettings"/> value for the correlating FileType name. + /// </summary> + /// <param name="type">The name of the <see cref="ShownFileTypeSettings"/> parameter to get the value of.</param> + /// <param name="config">The config instance to get the value from.</param> + /// <returns>The current value of the setting. Value is <see langword="true"/> if the file type is the be shown on the games list, <see langword="false"/> otherwise.</returns> + public static bool GetConfigValue(this FileTypes type, ShownFileTypeSettings config) => type switch + { + FileTypes.NSP => config.NSP.Value, + FileTypes.PFS0 => config.PFS0.Value, + FileTypes.XCI => config.XCI.Value, + FileTypes.NCA => config.NCA.Value, + FileTypes.NRO => config.NRO.Value, + FileTypes.NSO => config.NSO.Value, + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null), + }; + } +} diff --git a/src/Ryujinx.UI.Common/Helper/CommandLineState.cs b/src/Ryujinx.UI.Common/Helper/CommandLineState.cs new file mode 100644 index 00000000..c3c5bd37 --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/CommandLineState.cs @@ -0,0 +1,99 @@ +using Ryujinx.Common.Logging; +using System.Collections.Generic; + +namespace Ryujinx.UI.Common.Helper +{ + public static class CommandLineState + { + public static string[] Arguments { get; private set; } + + public static bool? OverrideDockedMode { get; private set; } + public static string OverrideGraphicsBackend { get; private set; } + public static string OverrideHideCursor { get; private set; } + public static string BaseDirPathArg { get; private set; } + public static string Profile { get; private set; } + public static string LaunchPathArg { get; private set; } + public static bool StartFullscreenArg { get; private set; } + + public static void ParseArguments(string[] args) + { + List<string> arguments = new(); + + // Parse Arguments. + for (int i = 0; i < args.Length; ++i) + { + string arg = args[i]; + + switch (arg) + { + case "-r": + case "--root-data-dir": + if (i + 1 >= args.Length) + { + Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'"); + + continue; + } + + BaseDirPathArg = args[++i]; + + arguments.Add(arg); + arguments.Add(args[i]); + break; + case "-p": + case "--profile": + if (i + 1 >= args.Length) + { + Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'"); + + continue; + } + + Profile = args[++i]; + + arguments.Add(arg); + arguments.Add(args[i]); + break; + case "-f": + case "--fullscreen": + StartFullscreenArg = true; + + arguments.Add(arg); + break; + case "-g": + case "--graphics-backend": + if (i + 1 >= args.Length) + { + Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'"); + + continue; + } + + OverrideGraphicsBackend = args[++i]; + break; + case "--docked-mode": + OverrideDockedMode = true; + break; + case "--handheld-mode": + OverrideDockedMode = false; + break; + case "--hide-cursor": + if (i + 1 >= args.Length) + { + Logger.Error?.Print(LogClass.Application, $"Invalid option '{arg}'"); + + continue; + } + + OverrideHideCursor = args[++i]; + break; + default: + LaunchPathArg = arg; + break; + } + } + + Arguments = arguments.ToArray(); + } + } +} diff --git a/src/Ryujinx.UI.Common/Helper/ConsoleHelper.cs b/src/Ryujinx.UI.Common/Helper/ConsoleHelper.cs new file mode 100644 index 00000000..208ff5c9 --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/ConsoleHelper.cs @@ -0,0 +1,50 @@ +using Ryujinx.Common.Logging; +using System; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace Ryujinx.UI.Common.Helper +{ + public static partial class ConsoleHelper + { + public static bool SetConsoleWindowStateSupported => OperatingSystem.IsWindows(); + + public static void SetConsoleWindowState(bool show) + { + if (OperatingSystem.IsWindows()) + { + SetConsoleWindowStateWindows(show); + } + else if (show == false) + { + Logger.Warning?.Print(LogClass.Application, "OS doesn't support hiding console window"); + } + } + + [SupportedOSPlatform("windows")] + private static void SetConsoleWindowStateWindows(bool show) + { + const int SW_HIDE = 0; + const int SW_SHOW = 5; + + IntPtr hWnd = GetConsoleWindow(); + + if (hWnd == IntPtr.Zero) + { + Logger.Warning?.Print(LogClass.Application, "Attempted to show/hide console window but console window does not exist"); + return; + } + + ShowWindow(hWnd, show ? SW_SHOW : SW_HIDE); + } + + [SupportedOSPlatform("windows")] + [LibraryImport("kernel32")] + private static partial IntPtr GetConsoleWindow(); + + [SupportedOSPlatform("windows")] + [LibraryImport("user32")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool ShowWindow(IntPtr hWnd, int nCmdShow); + } +} diff --git a/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs b/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs new file mode 100644 index 00000000..7ed02031 --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/FileAssociationHelper.cs @@ -0,0 +1,202 @@ +using Microsoft.Win32; +using Ryujinx.Common; +using Ryujinx.Common.Logging; +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace Ryujinx.UI.Common.Helper +{ + public static partial class FileAssociationHelper + { + private static readonly string[] _fileExtensions = { ".nca", ".nro", ".nso", ".nsp", ".xci" }; + + [SupportedOSPlatform("linux")] + private static readonly string _mimeDbPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "mime"); + + private const int SHCNE_ASSOCCHANGED = 0x8000000; + private const int SHCNF_FLUSH = 0x1000; + + [LibraryImport("shell32.dll", SetLastError = true)] + public static partial void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2); + + public static bool IsTypeAssociationSupported => (OperatingSystem.IsLinux() || OperatingSystem.IsWindows()) && !ReleaseInformation.IsFlatHubBuild; + + [SupportedOSPlatform("linux")] + private static bool AreMimeTypesRegisteredLinux() => File.Exists(Path.Combine(_mimeDbPath, "packages", "Ryujinx.xml")); + + [SupportedOSPlatform("linux")] + private static bool InstallLinuxMimeTypes(bool uninstall = false) + { + string installKeyword = uninstall ? "uninstall" : "install"; + + if ((uninstall && AreMimeTypesRegisteredLinux()) || (!uninstall && !AreMimeTypesRegisteredLinux())) + { + string mimeTypesFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "mime", "Ryujinx.xml"); + string additionalArgs = !uninstall ? "--novendor" : ""; + + using Process mimeProcess = new(); + + mimeProcess.StartInfo.FileName = "xdg-mime"; + mimeProcess.StartInfo.Arguments = $"{installKeyword} {additionalArgs} --mode user {mimeTypesFile}"; + + mimeProcess.Start(); + mimeProcess.WaitForExit(); + + if (mimeProcess.ExitCode != 0) + { + Logger.Error?.PrintMsg(LogClass.Application, $"Unable to {installKeyword} mime types. Make sure xdg-utils is installed. Process exited with code: {mimeProcess.ExitCode}"); + + return false; + } + + using Process updateMimeProcess = new(); + + updateMimeProcess.StartInfo.FileName = "update-mime-database"; + updateMimeProcess.StartInfo.Arguments = _mimeDbPath; + + updateMimeProcess.Start(); + updateMimeProcess.WaitForExit(); + + if (updateMimeProcess.ExitCode != 0) + { + Logger.Error?.PrintMsg(LogClass.Application, $"Could not update local mime database. Process exited with code: {updateMimeProcess.ExitCode}"); + } + } + + return true; + } + + [SupportedOSPlatform("windows")] + private static bool AreMimeTypesRegisteredWindows() + { + static bool CheckRegistering(string ext) + { + RegistryKey key = Registry.CurrentUser.OpenSubKey(@$"Software\Classes\{ext}"); + + if (key is null) + { + return false; + } + + var openCmd = key.OpenSubKey(@"shell\open\command"); + + string keyValue = (string)openCmd.GetValue(""); + + return keyValue is not null && (keyValue.Contains("Ryujinx") || keyValue.Contains(AppDomain.CurrentDomain.FriendlyName)); + } + + bool registered = false; + + foreach (string ext in _fileExtensions) + { + registered |= CheckRegistering(ext); + } + + return registered; + } + + [SupportedOSPlatform("windows")] + private static bool InstallWindowsMimeTypes(bool uninstall = false) + { + static bool RegisterExtension(string ext, bool uninstall = false) + { + string keyString = @$"Software\Classes\{ext}"; + + if (uninstall) + { + // If the types don't already exist, there's nothing to do and we can call this operation successful. + if (!AreMimeTypesRegisteredWindows()) + { + return true; + } + Logger.Debug?.Print(LogClass.Application, $"Removing type association {ext}"); + Registry.CurrentUser.DeleteSubKeyTree(keyString); + Logger.Debug?.Print(LogClass.Application, $"Removed type association {ext}"); + } + else + { + using var key = Registry.CurrentUser.CreateSubKey(keyString); + + if (key is null) + { + return false; + } + + Logger.Debug?.Print(LogClass.Application, $"Adding type association {ext}"); + using var openCmd = key.CreateSubKey(@"shell\open\command"); + openCmd.SetValue("", $"\"{Environment.ProcessPath}\" \"%1\""); + Logger.Debug?.Print(LogClass.Application, $"Added type association {ext}"); + + } + + return true; + } + + bool registered = false; + + foreach (string ext in _fileExtensions) + { + registered |= RegisterExtension(ext, uninstall); + } + + // Notify Explorer the file association has been changed. + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_FLUSH, IntPtr.Zero, IntPtr.Zero); + + return registered; + } + + public static bool AreMimeTypesRegistered() + { + if (OperatingSystem.IsLinux()) + { + return AreMimeTypesRegisteredLinux(); + } + + if (OperatingSystem.IsWindows()) + { + return AreMimeTypesRegisteredWindows(); + } + + // TODO: Add macOS support. + + return false; + } + + public static bool Install() + { + if (OperatingSystem.IsLinux()) + { + return InstallLinuxMimeTypes(); + } + + if (OperatingSystem.IsWindows()) + { + return InstallWindowsMimeTypes(); + } + + // TODO: Add macOS support. + + return false; + } + + public static bool Uninstall() + { + if (OperatingSystem.IsLinux()) + { + return InstallLinuxMimeTypes(true); + } + + if (OperatingSystem.IsWindows()) + { + return InstallWindowsMimeTypes(true); + } + + // TODO: Add macOS support. + + return false; + } + } +} diff --git a/src/Ryujinx.UI.Common/Helper/LinuxHelper.cs b/src/Ryujinx.UI.Common/Helper/LinuxHelper.cs new file mode 100644 index 00000000..b5779379 --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/LinuxHelper.cs @@ -0,0 +1,62 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.Versioning; + +namespace Ryujinx.UI.Common.Helper +{ + [SupportedOSPlatform("linux")] + public static class LinuxHelper + { + // NOTE: This value was determined by manual tests and might need to be increased again. + public const int RecommendedVmMaxMapCount = 524288; + public const string VmMaxMapCountPath = "/proc/sys/vm/max_map_count"; + public const string SysCtlConfigPath = "/etc/sysctl.d/99-Ryujinx.conf"; + public static int VmMaxMapCount => int.Parse(File.ReadAllText(VmMaxMapCountPath)); + public static string PkExecPath { get; } = GetBinaryPath("pkexec"); + + private static string GetBinaryPath(string binary) + { + string pathVar = Environment.GetEnvironmentVariable("PATH"); + + if (pathVar is null || string.IsNullOrEmpty(binary)) + { + return null; + } + + foreach (var searchPath in pathVar.Split(":", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)) + { + string binaryPath = Path.Combine(searchPath, binary); + + if (File.Exists(binaryPath)) + { + return binaryPath; + } + } + + return null; + } + + public static int RunPkExec(string command) + { + if (PkExecPath == null) + { + return 1; + } + + using Process process = new() + { + StartInfo = + { + FileName = PkExecPath, + ArgumentList = { "sh", "-c", command }, + }, + }; + + process.Start(); + process.WaitForExit(); + + return process.ExitCode; + } + } +} diff --git a/src/Ryujinx.UI.Common/Helper/ObjectiveC.cs b/src/Ryujinx.UI.Common/Helper/ObjectiveC.cs new file mode 100644 index 00000000..6aba377a --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/ObjectiveC.cs @@ -0,0 +1,160 @@ +using System; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace Ryujinx.UI.Common.Helper +{ + [SupportedOSPlatform("macos")] + public static partial class ObjectiveC + { + private const string ObjCRuntime = "/usr/lib/libobjc.A.dylib"; + + [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)] + private static partial IntPtr sel_getUid(string name); + + [LibraryImport(ObjCRuntime, StringMarshalling = StringMarshalling.Utf8)] + private static partial IntPtr objc_getClass(string name); + + [LibraryImport(ObjCRuntime)] + private static partial void objc_msgSend(IntPtr receiver, Selector selector); + + [LibraryImport(ObjCRuntime)] + private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value); + + [LibraryImport(ObjCRuntime)] + private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value); + + [LibraryImport(ObjCRuntime)] + private static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point); + + [LibraryImport(ObjCRuntime)] + private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value); + + [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")] + private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector); + + [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")] + private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param); + + [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend", StringMarshalling = StringMarshalling.Utf8)] + private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector, string param); + + [LibraryImport(ObjCRuntime, EntryPoint = "objc_msgSend")] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool bool_objc_msgSend(IntPtr receiver, Selector selector, IntPtr param); + + public readonly struct Object + { + public readonly IntPtr ObjPtr; + + private Object(IntPtr pointer) + { + ObjPtr = pointer; + } + + public Object(string name) + { + ObjPtr = objc_getClass(name); + } + + public void SendMessage(Selector selector) + { + objc_msgSend(ObjPtr, selector); + } + + public void SendMessage(Selector selector, byte value) + { + objc_msgSend(ObjPtr, selector, value); + } + + public void SendMessage(Selector selector, Object obj) + { + objc_msgSend(ObjPtr, selector, obj.ObjPtr); + } + + public void SendMessage(Selector selector, NSRect point) + { + objc_msgSend(ObjPtr, selector, point); + } + + public void SendMessage(Selector selector, double value) + { + objc_msgSend(ObjPtr, selector, value); + } + + public Object GetFromMessage(Selector selector) + { + return new Object(IntPtr_objc_msgSend(ObjPtr, selector)); + } + + public Object GetFromMessage(Selector selector, Object obj) + { + return new Object(IntPtr_objc_msgSend(ObjPtr, selector, obj.ObjPtr)); + } + + public Object GetFromMessage(Selector selector, NSString nsString) + { + return new Object(IntPtr_objc_msgSend(ObjPtr, selector, nsString.StrPtr)); + } + + public Object GetFromMessage(Selector selector, string param) + { + return new Object(IntPtr_objc_msgSend(ObjPtr, selector, param)); + } + + public bool GetBoolFromMessage(Selector selector, Object obj) + { + return bool_objc_msgSend(ObjPtr, selector, obj.ObjPtr); + } + } + + public readonly struct Selector + { + public readonly IntPtr SelPtr; + + private Selector(string name) + { + SelPtr = sel_getUid(name); + } + + public static implicit operator Selector(string value) => new(value); + } + + public readonly struct NSString + { + public readonly IntPtr StrPtr; + + public NSString(string aString) + { + IntPtr nsString = objc_getClass("NSString"); + StrPtr = IntPtr_objc_msgSend(nsString, "stringWithUTF8String:", aString); + } + + public static implicit operator IntPtr(NSString nsString) => nsString.StrPtr; + } + + public readonly struct NSPoint + { + public readonly double X; + public readonly double Y; + + public NSPoint(double x, double y) + { + X = x; + Y = y; + } + } + + public readonly struct NSRect + { + public readonly NSPoint Pos; + public readonly NSPoint Size; + + public NSRect(double x, double y, double width, double height) + { + Pos = new NSPoint(x, y); + Size = new NSPoint(width, height); + } + } + } +} diff --git a/src/Ryujinx.UI.Common/Helper/OpenHelper.cs b/src/Ryujinx.UI.Common/Helper/OpenHelper.cs new file mode 100644 index 00000000..af6170af --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/OpenHelper.cs @@ -0,0 +1,112 @@ +using Ryujinx.Common.Logging; +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; + +namespace Ryujinx.UI.Common.Helper +{ + public static partial class OpenHelper + { + [LibraryImport("shell32.dll", SetLastError = true)] + private static partial int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags); + + [LibraryImport("shell32.dll", SetLastError = true)] + private static partial void ILFree(IntPtr pidlList); + + [LibraryImport("shell32.dll", SetLastError = true)] + private static partial IntPtr ILCreateFromPathW([MarshalAs(UnmanagedType.LPWStr)] string pszPath); + + public static void OpenFolder(string path) + { + if (Directory.Exists(path)) + { + Process.Start(new ProcessStartInfo + { + FileName = path, + UseShellExecute = true, + Verb = "open", + }); + } + else + { + Logger.Notice.Print(LogClass.Application, $"Directory \"{path}\" doesn't exist!"); + } + } + + public static void LocateFile(string path) + { + if (File.Exists(path)) + { + if (OperatingSystem.IsWindows()) + { + IntPtr pidlList = ILCreateFromPathW(path); + if (pidlList != IntPtr.Zero) + { + try + { + Marshal.ThrowExceptionForHR(SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0)); + } + finally + { + ILFree(pidlList); + } + } + } + else if (OperatingSystem.IsMacOS()) + { + ObjectiveC.NSString nsStringPath = new(path); + ObjectiveC.Object nsUrl = new("NSURL"); + var urlPtr = nsUrl.GetFromMessage("fileURLWithPath:", nsStringPath); + + ObjectiveC.Object nsArray = new("NSArray"); + ObjectiveC.Object urlArray = nsArray.GetFromMessage("arrayWithObject:", urlPtr); + + ObjectiveC.Object nsWorkspace = new("NSWorkspace"); + ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace"); + + sharedWorkspace.SendMessage("activateFileViewerSelectingURLs:", urlArray); + } + else if (OperatingSystem.IsLinux()) + { + Process.Start("dbus-send", $"--session --print-reply --dest=org.freedesktop.FileManager1 --type=method_call /org/freedesktop/FileManager1 org.freedesktop.FileManager1.ShowItems array:string:\"file://{path}\" string:\"\""); + } + else + { + OpenFolder(Path.GetDirectoryName(path)); + } + } + else + { + Logger.Notice.Print(LogClass.Application, $"File \"{path}\" doesn't exist!"); + } + } + + public static void OpenUrl(string url) + { + if (OperatingSystem.IsWindows()) + { + Process.Start(new ProcessStartInfo("cmd", $"/c start {url.Replace("&", "^&")}")); + } + else if (OperatingSystem.IsLinux()) + { + Process.Start("xdg-open", url); + } + else if (OperatingSystem.IsMacOS()) + { + ObjectiveC.NSString nsStringPath = new(url); + ObjectiveC.Object nsUrl = new("NSURL"); + var urlPtr = nsUrl.GetFromMessage("URLWithString:", nsStringPath); + + ObjectiveC.Object nsWorkspace = new("NSWorkspace"); + ObjectiveC.Object sharedWorkspace = nsWorkspace.GetFromMessage("sharedWorkspace"); + + sharedWorkspace.GetBoolFromMessage("openURL:", urlPtr); + } + else + { + Logger.Notice.Print(LogClass.Application, $"Cannot open url \"{url}\" on this platform!"); + } + } + } +} diff --git a/src/Ryujinx.UI.Common/Helper/SetupValidator.cs b/src/Ryujinx.UI.Common/Helper/SetupValidator.cs new file mode 100644 index 00000000..a954be26 --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/SetupValidator.cs @@ -0,0 +1,114 @@ +using Ryujinx.Common.Logging; +using Ryujinx.HLE.FileSystem; +using System; +using System.IO; + +namespace Ryujinx.UI.Common.Helper +{ + /// <summary> + /// Ensure installation validity + /// </summary> + public static class SetupValidator + { + public static bool IsFirmwareValid(ContentManager contentManager, out UserError error) + { + bool hasFirmware = contentManager.GetCurrentFirmwareVersion() != null; + + if (hasFirmware) + { + error = UserError.Success; + + return true; + } + + error = UserError.NoFirmware; + + return false; + } + + public static bool CanFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out SystemVersion firmwareVersion) + { + try + { + firmwareVersion = contentManager.VerifyFirmwarePackage(baseApplicationPath); + } + catch (Exception) + { + firmwareVersion = null; + } + + return error == UserError.NoFirmware && Path.GetExtension(baseApplicationPath).ToLowerInvariant() == ".xci" && firmwareVersion != null; + } + + public static bool TryFixStartApplication(ContentManager contentManager, string baseApplicationPath, UserError error, out UserError outError) + { + if (error == UserError.NoFirmware) + { + string baseApplicationExtension = Path.GetExtension(baseApplicationPath).ToLowerInvariant(); + + // If the target app to start is a XCI, try to install firmware from it + if (baseApplicationExtension == ".xci") + { + SystemVersion firmwareVersion; + + try + { + firmwareVersion = contentManager.VerifyFirmwarePackage(baseApplicationPath); + } + catch (Exception) + { + firmwareVersion = null; + } + + // The XCI is a valid firmware package, try to install the firmware from it! + if (firmwareVersion != null) + { + try + { + Logger.Info?.Print(LogClass.Application, $"Installing firmware {firmwareVersion.VersionString}"); + + contentManager.InstallFirmware(baseApplicationPath); + + Logger.Info?.Print(LogClass.Application, $"System version {firmwareVersion.VersionString} successfully installed."); + + outError = UserError.Success; + + return true; + } + catch (Exception) { } + } + + outError = error; + + return false; + } + } + + outError = error; + + return false; + } + + public static bool CanStartApplication(ContentManager contentManager, string baseApplicationPath, out UserError error) + { + if (Directory.Exists(baseApplicationPath) || File.Exists(baseApplicationPath)) + { + string baseApplicationExtension = Path.GetExtension(baseApplicationPath).ToLowerInvariant(); + + // NOTE: We don't force homebrew developers to install a system firmware. + if (baseApplicationExtension == ".nro" || baseApplicationExtension == ".nso") + { + error = UserError.Success; + + return true; + } + + return IsFirmwareValid(contentManager, out error); + } + + error = UserError.ApplicationNotFound; + + return false; + } + } +} diff --git a/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs b/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs new file mode 100644 index 00000000..c2085b28 --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/ShortcutHelper.cs @@ -0,0 +1,162 @@ +using Ryujinx.Common; +using Ryujinx.Common.Configuration; +using ShellLink; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.Versioning; + +namespace Ryujinx.UI.Common.Helper +{ + public static class ShortcutHelper + { + [SupportedOSPlatform("windows")] + private static void CreateShortcutWindows(string applicationFilePath, byte[] iconData, string iconPath, string cleanedAppName, string desktopPath) + { + string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppDomain.CurrentDomain.FriendlyName + ".exe"); + iconPath += ".ico"; + + MemoryStream iconDataStream = new(iconData); + var image = Image.Load(iconDataStream); + image.Mutate(x => x.Resize(128, 128)); + SaveBitmapAsIcon(image, iconPath); + + var shortcut = Shortcut.CreateShortcut(basePath, GetArgsString(applicationFilePath), iconPath, 0); + shortcut.StringData.NameString = cleanedAppName; + shortcut.WriteToFile(Path.Combine(desktopPath, cleanedAppName + ".lnk")); + } + + [SupportedOSPlatform("linux")] + private static void CreateShortcutLinux(string applicationFilePath, byte[] iconData, string iconPath, string desktopPath, string cleanedAppName) + { + string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx.sh"); + var desktopFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.desktop"); + iconPath += ".png"; + + var image = Image.Load<Rgba32>(iconData); + image.SaveAsPng(iconPath); + + using StreamWriter outputFile = new(Path.Combine(desktopPath, cleanedAppName + ".desktop")); + outputFile.Write(desktopFile, cleanedAppName, iconPath, $"{basePath} {GetArgsString(applicationFilePath)}"); + } + + [SupportedOSPlatform("macos")] + private static void CreateShortcutMacos(string appFilePath, byte[] iconData, string desktopPath, string cleanedAppName) + { + string basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Ryujinx"); + var plistFile = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-template.plist"); + var shortcutScript = EmbeddedResources.ReadAllText("Ryujinx.UI.Common/shortcut-launch-script.sh"); + // Macos .App folder + string contentFolderPath = Path.Combine("/Applications", cleanedAppName + ".app", "Contents"); + string scriptFolderPath = Path.Combine(contentFolderPath, "MacOS"); + + if (!Directory.Exists(scriptFolderPath)) + { + Directory.CreateDirectory(scriptFolderPath); + } + + // Runner script + const string ScriptName = "runner.sh"; + string scriptPath = Path.Combine(scriptFolderPath, ScriptName); + using StreamWriter scriptFile = new(scriptPath); + + scriptFile.Write(shortcutScript, basePath, GetArgsString(appFilePath)); + + // Set execute permission + FileInfo fileInfo = new(scriptPath); + fileInfo.UnixFileMode |= UnixFileMode.UserExecute; + + // img + string resourceFolderPath = Path.Combine(contentFolderPath, "Resources"); + if (!Directory.Exists(resourceFolderPath)) + { + Directory.CreateDirectory(resourceFolderPath); + } + + const string IconName = "icon.png"; + var image = Image.Load<Rgba32>(iconData); + image.SaveAsPng(Path.Combine(resourceFolderPath, IconName)); + + // plist file + using StreamWriter outputFile = new(Path.Combine(contentFolderPath, "Info.plist")); + outputFile.Write(plistFile, ScriptName, cleanedAppName, IconName); + } + + public static void CreateAppShortcut(string applicationFilePath, string applicationName, string applicationId, byte[] iconData) + { + string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); + string cleanedAppName = string.Join("_", applicationName.Split(Path.GetInvalidFileNameChars())); + + if (OperatingSystem.IsWindows()) + { + string iconPath = Path.Combine(AppDataManager.BaseDirPath, "games", applicationId, "app"); + + CreateShortcutWindows(applicationFilePath, iconData, iconPath, cleanedAppName, desktopPath); + + return; + } + + if (OperatingSystem.IsLinux()) + { + string iconPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share", "icons", "Ryujinx"); + + Directory.CreateDirectory(iconPath); + CreateShortcutLinux(applicationFilePath, iconData, Path.Combine(iconPath, applicationId), desktopPath, cleanedAppName); + + return; + } + + if (OperatingSystem.IsMacOS()) + { + CreateShortcutMacos(applicationFilePath, iconData, desktopPath, cleanedAppName); + + return; + } + + throw new NotImplementedException("Shortcut support has not been implemented yet for this OS."); + } + + private static string GetArgsString(string appFilePath) + { + // args are first defined as a list, for easier adjustments in the future + var argsList = new List<string>(); + + if (!string.IsNullOrEmpty(CommandLineState.BaseDirPathArg)) + { + argsList.Add("--root-data-dir"); + argsList.Add($"\"{CommandLineState.BaseDirPathArg}\""); + } + + argsList.Add($"\"{appFilePath}\""); + + return String.Join(" ", argsList); + } + + /// <summary> + /// Creates a Icon (.ico) file using the source bitmap image at the specified file path. + /// </summary> + /// <param name="source">The source bitmap image that will be saved as an .ico file</param> + /// <param name="filePath">The location that the new .ico file will be saved too (Make sure to include '.ico' in the path).</param> + [SupportedOSPlatform("windows")] + private static void SaveBitmapAsIcon(Image source, string filePath) + { + // Code Modified From https://stackoverflow.com/a/11448060/368354 by Benlitz + byte[] header = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 32, 0, 0, 0, 0, 0, 22, 0, 0, 0 }; + using FileStream fs = new(filePath, FileMode.Create); + + fs.Write(header); + // Writing actual data + source.Save(fs, PngFormat.Instance); + // Getting data length (file length minus header) + long dataLength = fs.Length - header.Length; + // Write it in the correct place + fs.Seek(14, SeekOrigin.Begin); + fs.WriteByte((byte)dataLength); + fs.WriteByte((byte)(dataLength >> 8)); + } + } +} diff --git a/src/Ryujinx.UI.Common/Helper/TitleHelper.cs b/src/Ryujinx.UI.Common/Helper/TitleHelper.cs new file mode 100644 index 00000000..8b47ac38 --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/TitleHelper.cs @@ -0,0 +1,30 @@ +using Ryujinx.HLE.Loaders.Processes; +using System; + +namespace Ryujinx.UI.Common.Helper +{ + public static class TitleHelper + { + public static string ActiveApplicationTitle(ProcessResult activeProcess, string applicationVersion, string pauseString = "") + { + if (activeProcess == null) + { + return String.Empty; + } + + string titleNameSection = string.IsNullOrWhiteSpace(activeProcess.Name) ? string.Empty : $" {activeProcess.Name}"; + string titleVersionSection = string.IsNullOrWhiteSpace(activeProcess.DisplayVersion) ? string.Empty : $" v{activeProcess.DisplayVersion}"; + string titleIdSection = $" ({activeProcess.ProgramIdText.ToUpper()})"; + string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)"; + + string appTitle = $"Ryujinx {applicationVersion} -{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}"; + + if (!string.IsNullOrEmpty(pauseString)) + { + appTitle += $" ({pauseString})"; + } + + return appTitle; + } + } +} diff --git a/src/Ryujinx.UI.Common/Helper/ValueFormatUtils.cs b/src/Ryujinx.UI.Common/Helper/ValueFormatUtils.cs new file mode 100644 index 00000000..8ea3e721 --- /dev/null +++ b/src/Ryujinx.UI.Common/Helper/ValueFormatUtils.cs @@ -0,0 +1,219 @@ +using System; +using System.Globalization; +using System.Linq; + +namespace Ryujinx.UI.Common.Helper +{ + public static class ValueFormatUtils + { + private static readonly string[] _fileSizeUnitStrings = + { + "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", // Base 10 units, used for formatting and parsing + "KB", "MB", "GB", "TB", "PB", "EB", // Base 2 units, used for parsing legacy values + }; + + /// <summary> + /// Used by <see cref="FormatFileSize"/>. + /// </summary> + public enum FileSizeUnits + { + Auto = -1, + Bytes = 0, + Kibibytes = 1, + Mebibytes = 2, + Gibibytes = 3, + Tebibytes = 4, + Pebibytes = 5, + Exbibytes = 6, + Kilobytes = 7, + Megabytes = 8, + Gigabytes = 9, + Terabytes = 10, + Petabytes = 11, + Exabytes = 12, + } + + private const double SizeBase10 = 1000; + private const double SizeBase2 = 1024; + private const int UnitEBIndex = 6; + + #region Value formatters + + /// <summary> + /// Creates a human-readable string from a <see cref="TimeSpan"/>. + /// </summary> + /// <param name="timeSpan">The <see cref="TimeSpan"/> to be formatted.</param> + /// <returns>A formatted string that can be displayed in the UI.</returns> + public static string FormatTimeSpan(TimeSpan? timeSpan) + { + if (!timeSpan.HasValue || timeSpan.Value.TotalSeconds < 1) + { + // Game was never played + return TimeSpan.Zero.ToString("c", CultureInfo.InvariantCulture); + } + + if (timeSpan.Value.TotalDays < 1) + { + // Game was played for less than a day + return timeSpan.Value.ToString("c", CultureInfo.InvariantCulture); + } + + // Game was played for more than a day + TimeSpan onlyTime = timeSpan.Value.Subtract(TimeSpan.FromDays(timeSpan.Value.Days)); + string onlyTimeString = onlyTime.ToString("c", CultureInfo.InvariantCulture); + + return $"{timeSpan.Value.Days}d, {onlyTimeString}"; + } + + /// <summary> + /// Creates a human-readable string from a <see cref="DateTime"/>. + /// </summary> + /// <param name="utcDateTime">The <see cref="DateTime"/> to be formatted. This is expected to be UTC-based.</param> + /// <param name="culture">The <see cref="CultureInfo"/> that's used in formatting. Defaults to <see cref="CultureInfo.CurrentCulture"/>.</param> + /// <returns>A formatted string that can be displayed in the UI.</returns> + public static string FormatDateTime(DateTime? utcDateTime, CultureInfo culture = null) + { + culture ??= CultureInfo.CurrentCulture; + + if (!utcDateTime.HasValue) + { + // In the Avalonia UI, this is turned into a localized version of "Never" by LocalizedNeverConverter. + return "Never"; + } + + return utcDateTime.Value.ToLocalTime().ToString(culture); + } + + /// <summary> + /// Creates a human-readable file size string. + /// </summary> + /// <param name="size">The file size in bytes.</param> + /// <param name="forceUnit">Formats the passed size value as this unit, bypassing the automatic unit choice.</param> + /// <returns>A human-readable file size string.</returns> + public static string FormatFileSize(long size, FileSizeUnits forceUnit = FileSizeUnits.Auto) + { + if (size <= 0) + { + return $"0 {_fileSizeUnitStrings[0]}"; + } + + int unitIndex = (int)forceUnit; + if (forceUnit == FileSizeUnits.Auto) + { + unitIndex = Convert.ToInt32(Math.Floor(Math.Log(size, SizeBase10))); + + // Apply an upper bound so that exabytes are the biggest unit used when formatting. + if (unitIndex > UnitEBIndex) + { + unitIndex = UnitEBIndex; + } + } + + double sizeRounded; + + if (unitIndex > UnitEBIndex) + { + sizeRounded = Math.Round(size / Math.Pow(SizeBase10, unitIndex - UnitEBIndex), 1); + } + else + { + sizeRounded = Math.Round(size / Math.Pow(SizeBase2, unitIndex), 1); + } + + string sizeFormatted = sizeRounded.ToString(CultureInfo.InvariantCulture); + + return $"{sizeFormatted} {_fileSizeUnitStrings[unitIndex]}"; + } + + #endregion + + #region Value parsers + + /// <summary> + /// Parses a string generated by <see cref="FormatTimeSpan"/> and returns the original <see cref="TimeSpan"/>. + /// </summary> + /// <param name="timeSpanString">A string representing a <see cref="TimeSpan"/>.</param> + /// <returns>A <see cref="TimeSpan"/> object. If the input string couldn't been parsed, <see cref="TimeSpan.Zero"/> is returned.</returns> + public static TimeSpan ParseTimeSpan(string timeSpanString) + { + TimeSpan returnTimeSpan = TimeSpan.Zero; + + // An input string can either look like "01:23:45" or "1d, 01:23:45" if the timespan represents a duration of more than a day. + // Here, we split the input string to check if it's the former or the latter. + var valueSplit = timeSpanString.Split(", "); + if (valueSplit.Length > 1) + { + var dayPart = valueSplit[0].Split("d")[0]; + if (int.TryParse(dayPart, out int days)) + { + returnTimeSpan = returnTimeSpan.Add(TimeSpan.FromDays(days)); + } + } + + if (TimeSpan.TryParse(valueSplit.Last(), out TimeSpan parsedTimeSpan)) + { + returnTimeSpan = returnTimeSpan.Add(parsedTimeSpan); + } + + return returnTimeSpan; + } + + /// <summary> + /// Parses a string generated by <see cref="FormatDateTime"/> and returns the original <see cref="DateTime"/>. + /// </summary> + /// <param name="dateTimeString">The string representing a <see cref="DateTime"/>.</param> + /// <returns>A <see cref="DateTime"/> object. If the input string couldn't be parsed, <see cref="DateTime.UnixEpoch"/> is returned.</returns> + public static DateTime ParseDateTime(string dateTimeString) + { + if (!DateTime.TryParse(dateTimeString, CultureInfo.CurrentCulture, out DateTime parsedDateTime)) + { + // Games that were never played are supposed to appear before the oldest played games in the list, + // so returning DateTime.UnixEpoch here makes sense. + return DateTime.UnixEpoch; + } + + return parsedDateTime; + } + + /// <summary> + /// Parses a string generated by <see cref="FormatFileSize"/> and returns a <see cref="long"/> representing a number of bytes. + /// </summary> + /// <param name="sizeString">A string representing a file size formatted with <see cref="FormatFileSize"/>.</param> + /// <returns>A <see cref="long"/> representing a number of bytes.</returns> + public static long ParseFileSize(string sizeString) + { + // Enumerating over the units backwards because otherwise, sizeString.EndsWith("B") would exit the loop in the first iteration. + for (int i = _fileSizeUnitStrings.Length - 1; i >= 0; i--) + { + string unit = _fileSizeUnitStrings[i]; + if (!sizeString.EndsWith(unit)) + { + continue; + } + + string numberString = sizeString.Split(" ")[0]; + if (!double.TryParse(numberString, CultureInfo.InvariantCulture, out double number)) + { + break; + } + + double sizeBase = SizeBase2; + + // If the unit index is one that points to a base 10 unit in the FileSizeUnitStrings array, subtract 6 to arrive at a usable power value. + if (i > UnitEBIndex) + { + i -= UnitEBIndex; + sizeBase = SizeBase10; + } + + number *= Math.Pow(sizeBase, i); + + return Convert.ToInt64(number); + } + + return 0; + } + + #endregion + } +} diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApi.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApi.cs new file mode 100644 index 00000000..7989f0f1 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApi.cs @@ -0,0 +1,67 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Models.Amiibo +{ + public struct AmiiboApi : IEquatable<AmiiboApi> + { + [JsonPropertyName("name")] + public string Name { get; set; } + [JsonPropertyName("head")] + public string Head { get; set; } + [JsonPropertyName("tail")] + public string Tail { get; set; } + [JsonPropertyName("image")] + public string Image { get; set; } + [JsonPropertyName("amiiboSeries")] + public string AmiiboSeries { get; set; } + [JsonPropertyName("character")] + public string Character { get; set; } + [JsonPropertyName("gameSeries")] + public string GameSeries { get; set; } + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("release")] + public Dictionary<string, string> Release { get; set; } + + [JsonPropertyName("gamesSwitch")] + public List<AmiiboApiGamesSwitch> GamesSwitch { get; set; } + + public readonly override string ToString() + { + return Name; + } + + public readonly string GetId() + { + return Head + Tail; + } + + public readonly bool Equals(AmiiboApi other) + { + return Head + Tail == other.Head + other.Tail; + } + + public readonly override bool Equals(object obj) + { + return obj is AmiiboApi other && Equals(other); + } + + public readonly override int GetHashCode() + { + return HashCode.Combine(Head, Tail); + } + + public static bool operator ==(AmiiboApi left, AmiiboApi right) + { + return left.Equals(right); + } + + public static bool operator !=(AmiiboApi left, AmiiboApi right) + { + return !(left == right); + } + } +} diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs new file mode 100644 index 00000000..40e635bf --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiGamesSwitch.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Models.Amiibo +{ + public class AmiiboApiGamesSwitch + { + [JsonPropertyName("amiiboUsage")] + public List<AmiiboApiUsage> AmiiboUsage { get; set; } + [JsonPropertyName("gameID")] + public List<string> GameId { get; set; } + [JsonPropertyName("gameName")] + public string GameName { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiUsage.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiUsage.cs new file mode 100644 index 00000000..4f8d292b --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboApiUsage.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Models.Amiibo +{ + public class AmiiboApiUsage + { + [JsonPropertyName("Usage")] + public string Usage { get; set; } + [JsonPropertyName("write")] + public bool Write { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJson.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJson.cs new file mode 100644 index 00000000..15083f50 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJson.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Models.Amiibo +{ + public struct AmiiboJson + { + [JsonPropertyName("amiibo")] + public List<AmiiboApi> Amiibo { get; set; } + [JsonPropertyName("lastUpdated")] + public DateTime LastUpdated { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs new file mode 100644 index 00000000..bc3f1303 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/Amiibo/AmiiboJsonSerializerContext.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Models.Amiibo +{ + [JsonSerializable(typeof(AmiiboJson))] + public partial class AmiiboJsonSerializerContext : JsonSerializerContext + { + } +} diff --git a/src/Ryujinx.UI.Common/Models/Github/GithubReleaseAssetJsonResponse.cs b/src/Ryujinx.UI.Common/Models/Github/GithubReleaseAssetJsonResponse.cs new file mode 100644 index 00000000..8f528dc0 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/Github/GithubReleaseAssetJsonResponse.cs @@ -0,0 +1,9 @@ +namespace Ryujinx.UI.Common.Models.Github +{ + public class GithubReleaseAssetJsonResponse + { + public string Name { get; set; } + public string State { get; set; } + public string BrowserDownloadUrl { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonResponse.cs b/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonResponse.cs new file mode 100644 index 00000000..0250e109 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonResponse.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace Ryujinx.UI.Common.Models.Github +{ + public class GithubReleasesJsonResponse + { + public string Name { get; set; } + public List<GithubReleaseAssetJsonResponse> Assets { get; set; } + } +} diff --git a/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonSerializerContext.cs b/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonSerializerContext.cs new file mode 100644 index 00000000..71864257 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/Github/GithubReleasesJsonSerializerContext.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace Ryujinx.UI.Common.Models.Github +{ + [JsonSerializable(typeof(GithubReleasesJsonResponse), GenerationMode = JsonSourceGenerationMode.Metadata)] + public partial class GithubReleasesJsonSerializerContext : JsonSerializerContext + { + } +} diff --git a/src/Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg b/src/Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg new file mode 100644 index 00000000..03585e65 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Controller_JoyConLeft.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000.8" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000.8 1300" xml:space="preserve"><metadata id="metadata85"/><style id="style2" type="text/css">.st1{fill:#02c5e5}</style><style id="style2-6" type="text/css">.st1{fill:#02c5e5}.st3{fill:#fff}</style><g id="g344" transform="translate(0,300)"><path id="path66-7" d="m 413.1,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 V 207 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 v 79.2 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 269.7 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 V 716 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 157.2 c 0,3.6 -2.9,6.5 -6.5,6.5 z M 405.2,65.7 c -3,0 -5.5,2.4 -5.5,5.5 v 828.9 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 742.9 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 340.1 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path68-5" d="m 399.3,858.9 h -11.2 c -0.3,0 -0.5,-0.2 -0.5,-0.5 V 72 c 0,-0.3 0.2,-0.5 0.5,-0.5 h 11.2 c 0.3,0 0.5,0.2 0.5,0.5 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -10.7,-1 h 10.2 V 72.5 h -10.2 z" class="st3" style="fill:#000"/><path id="path70-3" d="M 382.1,1000 H 275.9 C 158.9,1000 64,905.2 64,788.1 c 0,0 0,0 0,0 V 220.9 C 64,104.1 159.1,9.1 275.9,9.1 h 106.2 c 3.6,0 6.5,2.9 6.5,6.5 v 978 c 0,3.5 -2.9,6.4 -6.5,6.4 z M 275.9,10.1 C 159.6,10.1 65,104.7 65,220.9 V 788.1 C 65,904.4 159.6,999 275.9,999 h 106.2 c 3,0 5.5,-2.4 5.5,-5.5 v -978 c 0,-3 -2.4,-5.5 -5.5,-5.5 H 275.9 Z" class="st3" style="fill:#000"/><path id="path98" d="m 413.1,717.1 h -4.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -79.5 c 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path id="path100" d="m 413.1,314.3 h -4.2 c -0.6,0 -1,-0.4 -1,-1 v -79.5 c 0,-0.6 0.4,-1 1,-1 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1144" d="M 257.24031,997.87141 C 231.00562,994.85925 207.29188,989.42604 182.14949,976.89078 160.25417,965.97443 141.01707,951.17849 124.7007,934.38991 92.385223,901.13922 70.993413,856.60594 65.658526,807.7016 65.28629,804.28935 65.60032,777.25611 65.321787,735.45113 64.265473,576.90901 64.42116,214.87541 65.832698,201.04147 c 1.806274,-17.70261 6.06302,-36.49109 12.012095,-52.35867 2.796862,-7.4599 7.091312,-15.77684 10.715421,-23.13845 C 119.94788,61.78692 180.7783,21.164531 250.9852,11.961211 269.16651,9.5778481 384.12059,8.7019738 386.44913,11.030497 c 0.15343,0.153425 0.87429,2.31235 1.04555,7.011277 0.40459,11.1005 0.35029,35.996153 1.26274,79.381547 0.6886,32.741359 -0.0274,76.313339 0.10052,132.519699 0.15984,70.25759 -1.57659,160.16298 -1.57659,274.77051 0,484.50248 1.44371,491.1849 -0.86873,492.42248 -0.32431,0.17356 -2.47056,1.663 -5.33883,1.8051 -21.9107,1.08549 -119.24063,-0.54237 -120.56646,-0.6946 z"/><polygon id="polygon80" points="225.8 469.9 250 469.9 237.9 448.9" class="st1" transform="matrix(1.1037134,0,0,1.0523169,-24.636066,-24.267048)" style="fill:#333;stroke:#000;stroke-width:.927894;stroke-opacity:1"/><polygon id="polygon82" points="237.9 626.9 225.8 605.9 250 605.9" class="st1" transform="matrix(1.0574383,0,0,1.0316716,-13.259456,-19.457378)" style="fill:#333;stroke:#000;stroke-width:.957418;stroke-opacity:1"/><polygon id="polygon84" points="148.9 537.9 169.9 550 169.9 525.8" class="st1" transform="matrix(1.0443863,0,0,1.1036462,-7.5389156,-55.555947)" style="fill:#333;stroke:#000;stroke-width:.931439;stroke-opacity:1"/><polygon id="polygon86" points="305.9 550 305.9 525.8 326.9 537.9" class="st1" transform="matrix(1.2181479,0,0,1.1364095,-67.797686,-73.39984)" style="fill:#333;stroke:#000;stroke-width:.849928;stroke-opacity:1"/><path id="path102" d="m 81.300444,139.3 c -0.3,0 -0.5,-0.1 -0.7,-0.3 l -3.4,-3.4 c -2,-2 -2.6,-5.1 -1.5,-7.8 C 110.50044,50.1 187.70044,0.1 272.90044,0 h 51.2 c 3.8,0 6.9,3.1 7,7 v 2.6 c 0,0.6 -0.4,1 -1,1 h -54.2 c -84.5,-0.1 -160.8,50.4 -193.699996,128.1 -0.1,0.3 -0.4,0.5 -0.7,0.6 -0.1,0 -0.2,0 -0.2,0 z M 272.90044,2 c -84.4,0.1 -160.9,49.7 -195.399996,126.7 -0.8,1.9 -0.4,4.1 1.1,5.5 l 2.4,2.4 C 114.60044,58.8 191.30044,8.5 276.00044,8.6 h 53.2 V 7 c 0,-2.7 -2.2,-5 -5,-5 z" class="st1" style="fill:#000"/><path id="path104" d="m 359.60044,116.1 h -46.9 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 46.9 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 z m -46.9,-17.6 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 46.9 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 z" class="st1" style="fill:#000"/><path id="path106" d="m 237.90044,502.9 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path108" d="m 237.90044,649.8 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.3 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.2,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path110" d="m 311.40044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path112" d="m 164.50044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path114" d="m 314.10044,753.7 h -45 c -5.5,0 -9.9,-4.4 -9.9,-9.9 v -45 c 0,-5.5 4.4,-9.9 9.9,-9.9 h 45 c 5.5,0 9.9,4.4 9.9,9.9 v 45 c 0,5.5 -4.5,9.9 -9.9,9.9 z m -45,-62.8 c -4.4,0 -7.9,3.6 -7.9,7.9 v 45 c 0,4.4 3.6,7.9 7.9,7.9 h 45 c 4.4,0 7.9,-3.6 7.9,-7.9 v -45 c 0,-4.4 -3.6,-7.9 -7.9,-7.9 z" class="st1" style="fill:#000"/><path id="path116" d="m 291.60044,741.7 c -11.3,0 -20.4,-9.2 -20.4,-20.4 0,-11.3 9.2,-20.4 20.4,-20.4 11.3,0 20.4,9.2 20.4,20.4 0,0 0,0 0,0 0,11.3 -9.1,20.4 -20.4,20.4 z m 0,-38.9 c -10.2,0 -18.4,8.3 -18.4,18.4 0,10.1 8.3,18.4 18.4,18.4 10.2,0 18.4,-8.3 18.4,-18.4 0,-10.1 -8.2,-18.3 -18.4,-18.4 z" class="st1" style="fill:#000"/><path id="path118" d="m 174.80044,260.2 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st1" style="fill:#000"/><path id="path120" d="m 234.60044,338.9 v 0 c -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 V 338 c -0.1,0.5 -0.6,0.9 -1.1,0.9 z m -71,-72 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st1" style="fill:#000"/><path id="path122" d="m 241.30044,338.9 c -0.6,0 -1,-0.4 -1,-1 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.5,71.4 -73.1,73.1 z m 59.7,-72 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 11.2 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st1" style="fill:#000"/><path id="path124" d="m 313.30044,260.2 h -12.3 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1.1 -0.9,1.1 0,0 0,0 0,0 z m -71,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.2,-37.4 -32.7,-67.9 -70,-70 z" class="st1" style="fill:#000"/><path id="path126" d="m 237.90044,339 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 h -12.3 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0.1 -2.2,0.1 -3.4,0.1 z m -2.3,-2 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 h -11.4 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 z" class="st1" style="fill:#000"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path179" d="m 158.02789,574.27925 c -14.73064,-3.25266 -24.85554,-12.70578 -29.04419,-27.11717 -0.98592,-3.39218 -1.21679,-6.26957 -0.93511,-11.65556 0.33774,-6.4583 0.67944,-7.76803 3.52546,-13.51272 11.35216,-22.91431 40.68588,-27.928 58.61532,-10.01846 19.42229,19.40073 11.99924,51.86436 -13.89781,60.78009 -5.19354,1.788 -13.81105,2.50701 -18.26367,1.52382 z m 12.59864,-36.29462 c 0,-7.35074 -0.18108,-13.36496 -0.40241,-13.36496 -0.89601,0 -23.32454,13.1809 -22.99291,13.51259 0.66445,0.66458 22.24473,13.11359 22.82266,13.1657 0.31497,0.0284 0.57266,-5.96261 0.57266,-13.31333 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path181" d="m 232.50517,500.57091 c -6.91699,-0.86484 -15.04235,-4.99807 -20.4853,-10.42051 -14.58513,-14.53016 -14.55979,-36.85709 0.0584,-51.42015 23.0282,-22.94142 62.26853,-6.95317 62.26853,25.37095 0,10.34881 -3.46897,18.75364 -10.723,25.98031 -8.34032,8.30891 -19.22192,11.97685 -31.1186,10.4894 z m 18.58209,-30.69278 c -0.91811,-2.38357 -12.79282,-22.35099 -13.28879,-22.34521 -0.45143,0.005 -5.88471,9.05299 -11.95805,19.91302 l -2.0157,3.60439 h 13.85703 c 12.18288,0 13.80248,-0.14161 13.40551,-1.1722 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path185" d="m 229.21434,646.98161 c -12.9232,-3.46654 -23.15418,-13.73508 -26.52403,-26.62142 -5.92248,-22.64757 11.58541,-45.21876 35.15949,-45.32763 7.44717,-0.0344 11.29183,0.91312 18.09999,4.46071 16.90217,8.80735 23.84898,30.39169 15.40753,47.87245 -7.54225,15.61868 -25.6403,24.04261 -42.14298,19.61589 z M 245.434,616.92014 c 3.65424,-6.30197 6.48622,-11.61534 6.29329,-11.8075 -0.19293,-0.19216 -6.40658,-0.25572 -13.80812,-0.14123 l -13.45735,0.20814 6.66623,11.58776 c 3.66642,6.37327 6.89025,11.59297 7.16405,11.59935 0.27381,0.006 3.48766,-5.14457 7.1419,-11.44652 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path187" d="m 307.85537,574.24407 c -0.34478,-0.0389 -1.62711,-0.27075 -2.84962,-0.51537 -11.23844,-2.24892 -20.9226,-9.70179 -26.17378,-20.1432 -2.82839,-5.62398 -4.20289,-12.18393 -3.75883,-17.93953 1.14218,-14.80435 11.33006,-27.74217 25.61809,-32.53303 8.75405,-2.93529 18.04495,-2.18507 26.72988,2.15843 8.69225,4.34715 15.48783,12.11097 18.64346,21.29973 5.25881,15.31297 -0.71552,32.17026 -14.73029,41.56334 -5.99457,4.01773 -13.35804,6.28235 -20.18834,6.20884 -1.46502,-0.0157 -2.94577,-0.0604 -3.29057,-0.0993 z m -0.66719,-23.08553 c 0.71175,-0.35815 3.02697,-1.62049 5.14496,-2.80516 8.66766,-4.84825 15.63944,-9.1681 16.21592,-10.0477 0.27948,-0.42642 0.28078,-0.49758 0.0166,-0.90068 -0.86957,-1.32678 -21.50733,-13.52937 -22.8817,-13.52937 -0.25925,0 -0.5656,0.11351 -0.68079,0.25225 -0.41371,0.49837 -0.59707,4.78502 -0.59431,13.89388 0.003,9.06159 0.17803,13.03427 0.59744,13.53951 0.32082,0.38645 0.78324,0.3011 2.18189,-0.40273 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path189" d="m 287.96017,739.09726 c -1.01606,-0.21912 -2.9756,-0.9477 -4.35453,-1.61905 -2.09414,-1.01956 -2.88115,-1.59464 -4.77748,-3.49097 -1.89792,-1.89791 -2.4703,-2.68159 -3.48941,-4.77748 -2.66648,-5.48389 -2.66607,-10.55714 10e-4,-16.08572 1.0133,-2.10022 1.56326,-2.85257 3.48092,-4.76199 3.62968,-3.61405 7.72755,-5.3398 12.70198,-5.34921 8.35146,-0.0158 15.68299,5.71579 17.81213,13.92506 0.52326,2.01754 0.54009,6.16569 0.0339,8.34799 -1.47072,6.34008 -6.30854,11.44929 -12.69973,13.41212 -2.44922,0.7522 -6.26202,0.92699 -8.70906,0.39925 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path191" d="m 267.23012,751.2862 c -1.59942,-0.43597 -2.94763,-1.29847 -4.05871,-2.59652 -1.81264,-2.11766 -1.73429,-0.87988 -1.73429,-27.39725 0,-26.73402 -0.0972,-25.30688 1.87658,-27.54923 0.58306,-0.66239 1.71204,-1.51487 2.55332,-1.92799 l 1.5081,-0.74058 h 24.1534 24.15339 l 1.77672,0.87468 c 1.25727,0.61895 2.04823,1.23027 2.70544,2.091 1.78729,2.34073 1.72742,1.33094 1.64816,27.80036 -0.0712,23.78487 -0.0733,23.86757 -0.63865,25.09049 -0.72339,1.56486 -2.26169,3.10316 -3.93043,3.93043 l -1.30842,0.64864 -23.75199,0.0516 c -18.21394,0.0396 -24.03192,-0.0247 -24.95262,-0.27565 z m 27.28995,-9.68076 c 10.60326,-1.53286 18.09097,-10.66806 17.50501,-21.35655 -0.18432,-3.36213 -0.66908,-5.27077 -2.04745,-8.06138 -4.59235,-9.29756 -15.46557,-13.67756 -25.3079,-10.19463 -2.76161,0.97725 -4.68871,2.16763 -7.02836,4.34145 -3.05146,2.83517 -5.11688,6.34636 -6.04249,10.27217 -0.50715,2.151 -0.50715,7.22087 0,9.37186 0.92171,3.90925 2.95421,7.3745 6.0133,10.25221 2.20884,2.07787 4.16469,3.31668 6.72144,4.2573 3.40627,1.25315 6.72782,1.61756 10.18645,1.11757 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1082" d="m 235.77295,330.34531 c 0,-6.0203 -0.0462,-6.51813 -0.73076,-7.87124 -1.06164,-2.09851 -2.95253,-3.39477 -5.65313,-3.87537 -15.06064,-2.68022 -27.49575,-10.15006 -36.51861,-21.93692 -4.96934,-6.49162 -8.83069,-15.11098 -10.3887,-23.18981 -0.83474,-4.3284 -1.3998,-5.65891 -2.97647,-7.00848 -1.7724,-1.51711 -3.30405,-1.79252 -9.96885,-1.79252 h -5.86461 v -2.11107 -2.11107 h 6.26944 c 6.12912,0 6.30805,-0.0192 7.9945,-0.85963 2.44443,-1.21811 3.32179,-2.74063 4.22338,-7.32906 4.56927,-23.25403 22.39532,-40.97679 45.63214,-45.36773 4.16129,-0.78634 5.57438,-1.57205 6.90818,-3.84114 0.9048,-1.53927 0.91186,-1.5954 1.02116,-8.12677 l 0.11006,-6.57679 h 2.0822 2.0822 v 6.27497 c 0,6.20191 0.0104,6.29547 0.89315,8.03629 1.32629,2.61551 2.65075,3.37644 7.56606,4.34684 19.37922,3.82593 35.08856,16.98397 42.28514,35.41774 1.04383,2.67375 1.9437,5.93165 3.31831,12.01372 0.58905,2.60627 1.67368,4.16462 3.60307,5.17675 1.1513,0.60396 1.95144,0.68258 7.85861,0.77219 l 6.57679,0.0998 v 2.0925 2.09249 h -6.26944 c -6.12912,0 -6.30805,0.0192 -7.9945,0.85963 -2.20181,1.09721 -3.39863,2.90223 -3.90849,5.89474 -4.06097,23.83452 -22.22419,42.32715 -45.97159,46.8053 -4.2535,0.8021 -5.71797,1.66037 -6.96502,4.08193 -0.79329,1.54043 -0.83455,1.89301 -0.94026,8.03533 l -0.11057,6.42419 h -2.08169 -2.0817 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1084" d="m 163.78864,257.28223 c 0.0926,-0.49123 0.26012,-1.9162 0.37218,-3.1666 0.34565,-3.85681 1.73866,-10.12043 3.27937,-14.74553 8.02141,-24.0797 28.10082,-42.70464 52.74332,-48.92282 3.12397,-0.78829 7.58171,-1.54879 11.2861,-1.92544 l 2.02988,-0.20639 v 5.8726 c 0,8.54266 -0.3854,9.15422 -6.53853,10.37563 -18.42711,3.65779 -33.66767,15.25204 -41.92018,31.89074 -2.55007,5.14144 -4.14587,10.08856 -5.47376,16.9691 -0.45828,2.3746 -1.81844,3.9985 -3.71595,4.43649 -0.71452,0.16493 -3.75876,0.30335 -6.76499,0.30761 l -5.46587,0.008 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1086" d="m 229.76452,336.39384 c -26.99792,-3.04756 -50.79328,-21.35759 -60.92173,-46.87799 -2.38214,-6.00221 -4.22117,-13.35788 -4.67827,-18.71196 -0.11259,-1.31887 -0.27512,-2.73804 -0.36117,-3.1537 l -0.15645,-0.75574 6.32279,0.10618 c 5.78597,0.0972 6.39885,0.16304 7.21874,0.77582 1.58067,1.18137 2.03872,2.1715 2.89278,6.25312 1.21968,5.82894 2.45374,9.35857 5.18759,14.8375 2.85902,5.72977 5.67403,9.77885 9.85937,14.18161 8.62003,9.0678 19.6967,15.16512 31.73111,17.46684 3.63419,0.69508 4.63135,1.16546 5.80819,2.73983 0.6132,0.82034 0.6781,1.4276 0.77012,7.20628 0.0943,5.92221 0.0643,6.30785 -0.48717,6.26798 -0.32321,-0.0233 -1.75687,-0.17446 -3.1859,-0.33577 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1088" d="m 299.6703,257.71116 c -2.39043,-0.853 -2.81858,-1.58503 -3.81252,-6.51855 -3.66786,-18.20579 -15.40436,-33.45997 -31.99138,-41.57986 -4.81668,-2.35792 -8.58209,-3.67044 -13.47836,-4.69819 -4.72195,-0.99115 -6.17077,-1.58672 -7.05619,-2.9006 -0.70499,-1.04613 -0.73853,-1.38133 -0.73853,-7.38107 0,-3.45685 0.11517,-6.28518 0.25593,-6.28518 0.14076,0 1.93111,0.20926 3.97855,0.46502 11.96867,1.4951 22.85594,5.62979 32.79042,12.45291 4.36974,3.00118 7.416,5.6069 11.57682,9.90259 9.30395,9.60553 15.50823,20.66713 18.77966,33.48224 0.93232,3.65217 2.12151,10.886 2.12151,12.90514 0,0.58643 -0.30132,0.619 -5.60245,0.60551 -3.82949,-0.01 -5.98886,-0.15214 -6.82346,-0.44996 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1090" d="m 242.3249,330.46177 c 0.097,-5.7735 0.163,-6.38655 0.77566,-7.20629 1.18269,-1.58243 2.17182,-2.02925 6.33209,-2.86041 23.48707,-4.69236 41.89612,-23.31363 46.43689,-46.97223 0.66775,-3.47916 1.14738,-4.47847 2.71006,-5.64639 0.81991,-0.6128 1.43277,-0.67865 7.22079,-0.77584 l 6.32483,-0.10621 -0.19591,1.73011 c -1.19107,10.51857 -3.29919,17.9842 -7.45853,26.41337 -11.17834,22.65366 -32.93361,38.14197 -57.96776,41.26919 -2.04744,0.25577 -3.84896,0.46502 -4.00338,0.46502 -0.15442,0 -0.23305,-2.83964 -0.17474,-6.31032 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1092" d="m 311.60253,113.45766 c -0.55307,-0.55307 -0.67321,-1.83753 -0.67321,-7.19731 0,-4.50308 0.15925,-6.68335 0.51409,-7.03819 0.38766,-0.38766 6.43841,-0.5141 24.60307,-0.5141 21.32785,0 24.16614,0.0772 24.76219,0.67322 0.55166,0.55166 0.67322,1.82364 0.67322,7.0445 0,6.09825 -0.0408,6.39986 -0.95215,7.03819 -0.83385,0.58406 -3.89051,0.66691 -24.60307,0.66691 -20.92962,0 -23.72838,-0.0775 -24.32414,-0.67322 z"/><path style="fill:#000;fill-opacity:1;stroke:#4d4d4d;stroke-width:.999998" id="path1094" d="m 78.977784,134.18912 c -2.35328,-2.74929 -2.18932,-3.66269 2.26682,-12.62797 C 92.012734,99.89682 104.871,81.96966 121.771,65.058734 153.11752,33.69194 193.3541,12.833792 237.03838,5.305545 252.10894,2.708387 253.57756,2.630423 291.07604,2.43687 l 34.76922,-0.179466 1.35092,1.207149 c 0.9677,0.864713 1.41875,1.712966 1.59003,2.990242 l 0.23911,1.783092 -33.78877,0.194148 c -36.2509,0.208295 -38.76527,0.335101 -53.2555,2.685802 -38.392,6.2282 -72.8916,22.039868 -103.29303,47.340693 -6.79226,5.652686 -19.46547,18.33117 -25.22484,25.23531 -8.3636,10.02603 -16.479016,21.67655 -22.544486,32.36489 -3.07683,5.42188 -9.61802,18.64996 -9.61802,19.45027 0,0.91062 -0.80534,0.45303 -2.32289,-1.31988 z"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1150" d="m 398.44844,615.98373 c 0,-216.02489 -0.0215,-633.986049 0.12697,-525.973599 0.14845,108.012439 0.29139,614.347419 0.14294,722.359859 -0.0401,29.20619 -0.0907,43.20012 -0.12499,45.04791 -0.0926,4.98585 -0.14492,-83.82167 -0.14492,-241.43417 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1152" d="m 400.62988,903.164 c -1.48283,-2.11702 -0.83255,-44.16773 -0.83255,-417.61555 0,-373.44781 -0.81158,-415.197415 0.67125,-417.31444 1.37591,-1.964385 3.40896,-2.252646 8.48523,-2.252646 1.77094,0 3.84166,-0.08796 5.42907,0.210876 1.40618,0.264716 3.16687,2.038026 3.49464,2.365798 0.49522,0.495217 0.3217,4.318356 0.43962,16.36819 0.1111,11.353396 -0.22256,28.989262 -0.22256,55.337332 0,44.70634 0.60945,61.76349 0.136,69.7887 -0.25741,4.36328 -1.18492,6.13499 -1.9011,8.04917 -1.16098,3.10304 -3.86364,8.15599 -5.61012,10.90989 l -3.1754,5.00708 0.39853,40.34769 c 0.37154,37.61503 -0.21444,39.05077 1.63547,41.67417 1.08842,1.5435 2.94744,6.13491 4.62112,9.33312 l 3.04306,5.81494 1.31284,7.9315 -0.0707,19.78753 -0.10737,15.79956 -0.21131,97.91413 c -0.20099,93.13106 1.25117,126.69008 -0.28021,141.09354 -0.44236,4.16066 -1.62132,6.51589 -2.28217,8.50207 -0.90516,2.72046 -2.09268,4.90784 -3.84656,7.82045 l -3.66064,6.0791 0.3792,15.57297 0.11069,25.0662 c 0.11714,26.5248 0.58051,40.42685 1.28995,40.8653 0.59597,0.36833 2.69223,4.04112 4.32574,8.44952 l 3.32256,8.96672 1.09731,9.02354 -0.19118,15.86739 -0.18943,57.8651 c -0.2026,61.8851 0.4238,84.47685 -0.4696,85.55336 -0.77641,0.93553 -4.47782,2.42762 -8.42197,2.42762 -5.161,0 -7.33923,-0.63936 -8.71946,-2.60992 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1154" d="m 388.84323,464.93186 0.0252,-5.22079 0.35628,-387.023108 h 4.22905 4.22904 V 464.93186 L 398.8,857.9 393.4746,858.08261 388.6,857.9 Z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1156" d="m 409.89998,273.33293 v -38.63294 h 3.04188 c 1.74435,0 3.58682,0.88543 4.31941,2.07573 1.73761,2.82321 1.73761,70.29119 0,73.11439 -0.73259,1.19032 -2.57506,2.07573 -4.31941,2.07573 h -3.04188 z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1158" d="m 409.89998,676.164 v -38.66403 h 3.04381 c 1.74545,0 3.58909,0.88613 4.32215,2.07741 1.7387,2.82547 1.7387,70.34777 0,73.17325 -0.73306,1.19129 -2.5767,2.0774 -4.32215,2.0774 h -3.04381 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/></g><ellipse id="path4030" cx="-630.031" cy="861.013" rx="15.407" ry="14.105" transform="scale(-1,1)" style="fill:#2e2f31;fill-opacity:1;stroke:#000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4038" d="m 531.57205,538.85036 v 45.92786" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4040" d="M 538.66113,544.78398 V 581.251" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4062" d="m 618.21618,561.30922 c 0.15897,-2.39247 0.93393,-4.19426 2.34943,-5.4612 1.05382,-0.94329 2.4969,-1.60711 4.18689,-1.92587 0.38638,-0.0728 1.08711,-0.17756 1.09745,-0.16356 0,0.005 0.0932,0.85525 0.2017,1.89259 0.10822,1.03731 0.20533,1.93952 0.21568,2.00495 0.0181,0.10453 0.0103,0.11877 -0.0516,0.11877 -0.12143,0 -0.66218,0.12325 -1.06042,0.24145 -1.89486,0.56317 -2.9076,1.70318 -3.13568,3.52943 -0.0526,0.41968 0.2402,1.20332 0.3147,1.59414 0.19574,1.0321 0.5477,1.44923 1.24585,1.96064 0.54534,0.39941 0.84078,0.63241 1.52991,0.63397 0.49114,0 0.79513,-0.17703 1.12084,-0.34918 0.22397,-0.11875 0.54525,-0.72408 0.72476,-0.97125 0.4284,-0.59002 0.57331,-0.18167 1.33421,-2.91459 0.47521,-1.70735 0.75977,-2.52129 1.19088,-3.4071 0.58401,-1.19961 1.35632,-2.06979 2.41398,-2.71969 0.58281,-0.35813 1.33375,-0.64229 2.04739,-0.77469 0.33923,-0.0633 0.49023,-0.0718 1.18512,-0.0711 0.6888,7.5e-4 0.84197,0.01 1.1342,0.0705 1.71036,0.34984 3.14515,1.32777 3.98586,2.71644 0.37788,0.62406 0.6928,1.43192 0.8702,2.23216 0.38944,1.75661 0.31125,4.08353 -0.19239,5.72547 -0.23225,0.75754 -0.63066,1.547 -1.06364,2.10803 -0.29761,0.38576 -1.03764,1.06284 -1.46261,1.33836 -0.68025,0.44086 -1.27214,1.08216 -2.11357,1.24388 -0.42538,0.0817 -1.27033,-0.14168 -1.5376,-0.14168 h -0.15716 l -2.2e-4,-0.18229 c -1.6e-4,-0.10006 -0.0391,-0.97392 -0.0865,-1.94151 -0.0477,-0.9676 -0.0862,-1.8095 -0.0862,-1.87098 l -7e-5,-0.11166 0.30292,-0.0566 c 0.67911,-0.12659 0.64274,-0.69151 1.05495,-1.00838 0.80274,-0.61701 1.57932,-1.59904 1.57884,-3.10599 -2.4e-4,-0.99245 -0.26656,-1.2378 -0.6209,-1.90047 -0.41109,-0.7689 -0.52472,-0.63395 -1.25089,-0.66875 -0.54033,-0.0264 -0.60261,0.54818 -0.97987,0.86389 -0.60357,0.50503 -0.65515,0.26871 -1.33681,2.74768 -0.53065,1.92992 -1.61672,3.72692 -2.02402,4.67676 -0.7236,1.68735 -1.46229,1.88688 -2.90464,2.54118 -0.86271,0.39132 -1.65737,0.56338 -2.80448,0.60727 -1.3619,0.0524 -2.61283,-0.24592 -3.80829,-0.90695 -1.3364,-0.73899 -2.29253,-1.88343 -2.83806,-3.39691 -0.47562,-1.31947 -0.68418,-3.07542 -0.56986,-4.79727 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4064" d="m 630.09646,971.66625 h 11.20079 l -7.7e-4,4.47736 c -3.9e-4,2.46263 -0.0181,4.8542 -0.0344,5.31477 -0.12014,3.00951 -0.56807,4.32259 -1.86223,5.4598 -1.43936,1.26481 -3.65136,1.78958 -5.84831,1.38753 -1.22398,-0.224 -2.30114,-0.78622 -3.1233,-1.63027 -0.75525,-0.77541 -1.34589,-2.02193 -1.58341,-3.3415 -0.0526,-0.2928 -0.0649,-0.32336 -0.10591,-0.26949 -0.0258,0.0337 -0.20067,0.27472 -0.38963,0.53623 -0.79262,1.09807 -1.46856,1.72397 -2.8174,2.60895 -0.78277,0.51353 -1.17221,0.74339 -4.12365,2.43453 l -2.49548,1.4299 -0.008,-2.44288 c -0.005,-1.92858 2.7e-4,-2.45065 0.0344,-2.47945 0.0234,-0.0215 1.34449,-0.8352 2.93457,-1.81113 4.5931,-2.81923 5.11319,-3.17081 5.65776,-3.8248 0.54019,-0.64863 0.67406,-1.16979 0.70337,-2.7382 l 0.0181,-0.99053 h -4.67857 -4.67867 v -2.06046 -2.06036 h 11.20079 z m 1.74946,9.28763 c 0.0409,0.67298 0.11392,1.26781 0.18719,1.52499 0.22165,0.77651 0.88153,1.38438 1.75173,1.61386 0.32467,0.0855 1.148,0.12136 1.50829,0.0653 0.87376,-0.13534 1.48211,-0.5375 1.85019,-1.22332 0.35302,-0.65774 0.37769,-0.95998 0.37905,-4.65174 l 7.5e-4,-2.49624 h -2.85643 -2.85653 l 7e-5,2.29025 c 0,1.25954 0.0181,2.55403 0.0356,2.87661 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4066" d="m 618.48834,960.72379 c 0.26992,-3.13481 1.47063,-5.14907 3.82731,-6.42085 0.94544,-0.51008 2.47246,-0.96116 3.66673,-1.08314 l 0.21439,-0.0214 0.0207,0.10785 c 0.0372,0.19794 0.41957,3.90855 0.40445,3.92234 -0.008,0.007 -0.17193,0.0441 -0.3639,0.0822 -0.19212,0.0376 -0.53821,0.12634 -0.76937,0.19651 -1.79072,0.54475 -2.7801,1.57117 -3.10355,3.21988 -0.0989,0.50413 -0.10744,1.60822 -0.0155,2.14051 0.12169,0.71048 0.32194,1.25035 0.6218,1.6747 0.41144,0.58234 0.98794,1.0195 1.60624,1.21829 0.34978,0.11236 1.05168,0.14484 1.3996,0.0645 0.68302,-0.15762 1.12961,-0.53488 1.53764,-1.29896 0.28622,-0.53585 0.48608,-1.14697 1.12493,-3.44026 0.58179,-2.0886 0.89522,-2.93441 1.4688,-3.96444 0.54763,-0.9834 1.29532,-1.75609 2.25091,-2.32632 1.0162,-0.60643 2.16997,-0.88864 3.44103,-0.84174 1.09522,0.0405 2.1108,0.34696 3.03462,0.9161 0.67952,0.41875 1.15791,0.85897 1.62314,1.49397 0.94821,1.29426 1.41875,3.00624 1.41828,5.1604 -5.4e-4,2.4013 -0.5283,4.2219 -1.61346,5.56569 -0.28052,0.34751 -0.87705,0.89358 -1.25657,1.15047 -1.02517,0.69385 -2.17752,1.07827 -3.55571,1.18615 -0.21154,0.0168 -0.38907,0.0262 -0.39448,0.0215 -0.0155,-0.0141 -0.21309,-4.13646 -0.20041,-4.14922 0.008,-0.007 0.14966,-0.0386 0.32003,-0.0726 0.96084,-0.19177 1.73387,-0.57719 2.16612,-1.08024 0.33457,-0.38922 0.56064,-0.89429 0.68786,-1.53658 0.1015,-0.51332 0.11134,-1.67163 0.0181,-2.21419 -0.14526,-0.84985 -0.46593,-1.54361 -0.92193,-1.99457 -0.48336,-0.47793 -1.31478,-0.61609 -1.9837,-0.32951 -0.30417,0.13037 -0.66295,0.44566 -0.87729,0.7711 -0.39693,0.60258 -0.7762,1.64298 -1.28809,3.53321 -0.61793,2.28163 -1.08691,3.57856 -1.64611,4.55253 -0.90497,1.57616 -2.40653,2.63296 -4.21401,2.96573 -0.65494,0.12066 -1.14141,0.15526 -1.88939,0.13511 -0.52546,-0.0141 -0.75937,-0.0355 -1.08943,-0.0994 -1.82284,-0.35238 -3.39382,-1.33729 -4.32844,-2.71383 -0.65796,-0.969 -1.07881,-2.20396 -1.27779,-3.74995 -0.0534,-0.41339 -0.0974,-2.3393 -0.0626,-2.74128 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4068" d="m 630.08177,575.12806 11.69573,-0.0768 0.11296,2.83872 -0.11296,2.7832 -10.22217,-0.0657 -8.46941,0.0657 -0.23931,4.64789 -0.21033,5.23455 -2.19525,-0.11373 h -1.89113 v -7.29401 l -0.13688,-8.09662 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path249" d="m 564.81854,320.07351 2.80254,-2.94783 2.10843,-1.80063 3.89781,-2.62722 4.93974,-2.563 3.81131,-1.26428 3.8729,-0.82566 1.38974,-0.20307 2.88842,-0.16699 h 57.79227 l 1.57144,0.1495 1.7697,0.23946 1.77484,0.23845 2.72964,0.54365 2.31281,0.60657 2.44326,0.75609 2.94394,0.94407 2.12886,0.90455 3.8498,1.71936 2.75741,1.53909 2.10581,1.19691 3.23498,2.16487 2.4201,1.63817 1.43595,1.20589 1.89607,1.45278 3.21175,2.60881 2.42278,2.54722 4.25902,4.70095 2.59949,3.25688 1.67743,2.63026 1.27103,2.18885 1.91183,3.73696 0.72706,1.65104 1.16131,2.96921 0.66224,2.6045 0.78479,3.27949 0.33987,2.68699 0.0483,2.38913 v 4.00596 2.85158 877.28853 l -0.16384,2.4984 -0.34524,3.4016 -1.29885,4.7808 -1.23966,3.7841 -3.60497,7.2728 -2.57375,4.0663 -2.46855,3.2069 -1.48186,1.9802 -2.66944,2.87 -3.06989,3.0298 -2.17649,1.9303 -4.01872,3.1261 -4.11447,2.8611 -2.30753,1.2764 -3.52352,1.8502 -3.6903,1.6841 -4.15406,1.4576 -3.72593,1.1705 -3.68244,0.746 -3.28501,0.4427 -3.07889,0.2681 h -56.72802 l -2.27377,-0.2166 -3.66214,-0.647 -2.13716,-0.5101 -2.60358,-0.9022 -3.70761,-1.5158 -3.72085,-1.8958 -3.11883,-1.9649 -2.49439,-2.0644 -3.08564,-2.8864 -3.11412,-3.839 -2.38795,-3.9255 -1.37928,-3.2422 -1.06978,-2.9089 -0.81446,-3.3604 -0.4154,-3.6114 -0.024,-2.148 V 343.23256 l 0.28062,-2.94096 0.63887,-3.85473 1.31769,-4.26752 1.53215,-3.69272 2.5337,-4.4686 1.96993,-2.5833 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path253" d="m 694.62149,334.10362 2.87464,2.17056 1.39448,1.27449 1.10633,1.19174 1.33926,1.50114 1.38209,1.74045 1.13752,1.55135 1.14707,1.6191 1.76331,2.78539 1.13353,1.9937 0.91903,1.69462 1.33241,2.59815 1.11209,2.33 1.56583,3.39111 0.63568,1.22029 0.77282,1.85718 0.72486,1.75471 0.98903,2.11635 1.04466,2.26736 0.86003,1.7056 0.74871,1.46183 0.77843,1.50459 1.16158,2.03635 0.69941,1.16948 1.32156,2.11591 1.16136,1.5888 0.91829,1.1277 1.46722,1.69949 1.41993,1.42143 1.99344,1.72936 2.2557,1.72741 2.15114,1.20765 1.3718,0.68691 3.115,1.23393 4.1538,1.06385 3.08686,0.4687 3.22131,0.30291 h 28.48289 l 0.94647,0.0524 0.97841,0.35799 1.16352,0.47513 0.9822,0.70154 1.01456,1.07822 0.92826,1.35838 0.65022,1.72693 0.1277,1.59566 -0.29606,1.44502 -0.74147,1.59474 -1.99052,3.45657 -2.4225,4.16279 -2.33536,3.53915 -1.37414,1.9664 -1.24262,1.70801 -1.41326,1.83088 -1.34109,1.74508 -2.14664,2.66591 -1.97231,2.31029 -1.08591,1.37517 -2.41419,2.77055 -1.30886,1.52879 -3.03361,3.40228 -1.58159,1.80779 -1.34438,1.31431 -2.46317,2.6295 -1.04614,1.0908 -4.84623,5.03258 -3.60112,3.77568 -1.74314,1.82893 -2.10543,2.2459 -6.06161,6.49298 -2.39368,2.59389 -2.01406,2.20329 -1.6282,1.85603 -1.14047,1.25547 -1.6465,1.98517 -1.72596,2.18615 -1.52881,1.91959 -1.25534,1.48184 -1.12938,1.52402 -1.65189,2.2517 -1.15137,1.60225 -1.31306,1.81213 -1.08907,1.73832 -1.86192,2.96443 -1.97162,3.32339 -1.21492,2.47246 -1.36959,2.68936 -0.95325,2.42774 -1.07073,2.91455 -0.76263,2.02052 h -0.62464"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path255" d="m 554.98557,806.60461 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97257 -0.93192,0.98281 -0.8244,1.30431 -0.46075,1.2916 -0.0637,0.91287 -0.15809,2.36292 -0.25772,3.06459 -0.2171,3.23629 -0.2039,3.99231 -0.12562,3.06084 -0.14526,4.35384 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37395 0.12161,1.93446 0.12107,1.18541 0.30831,1.25065 0.75377,1.13471 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path298" d="m 554.91046,880.77518 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97256 -0.93192,0.98282 -0.8244,1.3043 -0.46075,1.29161 -0.0637,0.91286 -0.15809,2.36293 -0.25772,3.06459 -0.2171,3.23628 -0.2039,3.99231 -0.12562,3.06085 -0.14526,4.35383 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37396 0.12161,1.93446 0.12107,1.18541 0.30831,1.25065 0.75377,1.1347 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path300" d="m 555.35214,1000.9073 -0.70664,0.01 -1.15041,0.3129 -0.94439,0.9042 -0.33283,0.8403 v 55.3836 l 0.35102,0.988 1.16661,1.0639 0.76614,0.2105 0.79763,-0.043 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path302" d="m 683.4822,322.5276 1.80756,-0.36865 3.52048,0.79736 3.29989,0.79341 3.35684,0.85712 10.58481,3.05757 8.24268,2.61795 6.98289,2.30801 8.19137,2.72032 6.85494,2.1232 7.56186,2.22326 3.02344,0.89258 3.01485,0.78292 2.59184,0.6545 4.39682,1.01106 3.44978,0.73216 4.14889,0.73189 5.67397,0.74901 2.26019,0.25821 2.51619,0.19404 1.51308,0.53857 1.71443,0.82574 1.15366,0.80631 0.81926,0.61787 1.09348,1.17223 1.28918,1.66295 1.03628,2.03633 0.40058,1.60306 0.18894,1.03784 v 22.44381 l -0.19091,1.309 -0.49575,1.41249 -0.82966,1.654 -0.83314,1.22068 -1.26559,1.52171 -1.47306,1.67951 -1.74719,1.81065 -1.52584,1.67117 -1.0269,1.42993 -0.51569,0.92494"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path304" d="m 555.11995,518.09615 -1.01033,0.39258 -1.22841,0.93655 -1.2742,1.02924 -1.33354,1.35102 -1.34981,1.59351 -1.40742,1.80058 -1.06793,1.49244 -0.85098,1.20282 -0.89272,1.39504 -0.99731,1.62995 -0.60208,1.24653 -0.8025,1.69239 -0.93246,1.96822 -0.91473,2.23059 -0.62621,1.91229 -0.57345,2.01006 -0.59474,2.80402 -0.14894,0.35985 -1.18136,-0.13793 -0.97443,-0.18501 -1.29147,-0.54083 -1.00174,-0.69084 -1.15445,-0.99791 -0.60398,-0.85223 -0.49335,-1.12318 -0.37025,-1.37685 v -45.45096 l -0.20339,-1.17956 -0.74794,-1.09777 -0.87864,-0.84867 -1.1084,-0.66091 -1.62768,-0.61457 -1.99954,-0.31262 -2.41898,-0.0433 -3.34195,0.51108 -2.789,1.02869 -1.75751,0.92812 -1.48061,0.99716 -2.10544,1.93079 -1.35698,1.79438 -0.77464,1.80822 -0.53822,2.14889 -0.17548,1.82929 v 15.40503 l -0.74254,2.33437 -0.81509,3.04978 -0.66374,2.10772 -1.44608,5.41074 -0.10817,0.54556 -0.36239,1.62223 -0.43835,2.01252 -0.52816,2.59666 -0.51106,2.94424 -0.53199,3.41725 -0.52183,3.69125 -0.27377,2.56523 -0.17416,1.97814 -0.12505,1.76866 -0.16865,2.53094 -0.0926,2.51807 -0.10085,2.96479 -0.0322,3.59841 0.1372,3.62771 0.15883,3.46399"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path306" d="m 555.11995,607.38224 -1.01033,-0.39258 -1.22841,-0.93654 -1.2742,-1.02925 -1.33354,-1.35102 -1.34981,-1.5935 -1.40742,-1.80059 -1.06793,-1.49243 -0.85098,-1.20282 -0.89272,-1.39505 -0.99731,-1.62995 -0.60208,-1.24653 -0.8025,-1.69239 -0.93246,-1.96821 -0.91473,-2.23059 -0.62621,-1.9123 -0.57345,-2.01006 -0.59474,-2.80402 -0.14894,-0.35985 -1.18136,0.13793 -0.97443,0.18501 -1.29147,0.54083 -1.00174,0.69084 -1.15445,0.99792 -0.60398,0.85223 -0.49335,1.12317 -0.37025,1.37685 v 45.45097 l -0.20339,1.17956 -0.74794,1.09777 -0.87864,0.84866 -1.1084,0.66092 -1.62768,0.61456 -1.99954,0.31262 -2.41898,0.0433 -3.34195,-0.51107 -2.789,-1.0287 -1.75751,-0.92812 -1.48061,-0.99715 -2.10544,-1.93079 -1.35698,-1.79438 -0.77464,-1.80823 -0.53822,-2.14889 -0.17548,-1.82929 v -15.40503 l -0.74254,-2.33437 -0.81509,-3.04977 -0.66374,-2.10773 -1.44608,-5.41074 -0.10817,-0.54555 -0.36239,-1.62224 -0.43835,-2.01252 -0.52816,-2.59665 -0.51106,-2.94425 -0.53199,-3.41725 -0.52183,-3.69125 -0.27377,-2.56522 -0.17416,-1.97815 -0.12505,-1.76866 -0.16865,-2.53094 -0.0926,-2.51807 -0.10085,-2.96479 -0.0322,-3.5984 0.1372,-3.62772 0.15883,-3.46399"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path310" d="m 629.00102,930.67137 h 6.14653 l 2.04067,0.16215 1.12524,0.1958 1.57485,0.44983 1.37911,0.54025 1.49645,0.7516 1.16369,0.77595 1.20645,0.95903 1.07493,1.06679 1.10141,1.41857 0.59407,1.15018 0.53577,1.29561 0.50772,1.37166 0.10921,1.53404 0.0194,1.06304 v 58.84883 l -0.13659,1.1193 -0.20644,0.9935 -0.32745,0.917 -0.29571,0.8905 -0.50231,0.9886 -0.70348,1.073 -0.72708,0.8329 -1.14245,1.2323 -0.95483,0.8506 -1.12308,0.74 -1.3029,0.7638 -1.57811,0.6202 -1.75304,0.421 -1.62477,0.2527 -1.92906,0.036 h -12.21387 l -1.24442,-0.1438 -1.4416,-0.2655 -1.20902,-0.3547 -1.34067,-0.5911 -1.25475,-0.6462 -0.90721,-0.5402 -1.03832,-0.822 -0.71078,-0.7398 -0.67126,-0.637 -1.26722,-1.7893 -1.08212,-2.3971 -0.42262,-1.7353 -0.0315,-1.7747 v -59.09121 l 0.14146,-0.91134 0.21007,-0.66319 0.29836,-1.07418 0.44186,-1.07962 0.47325,-1.02037 0.3698,-0.61649 0.99623,-1.3542 0.95716,-1.00285 0.94225,-0.85279 0.88252,-0.60543 1.18795,-0.67902 1.33894,-0.6658 0.87252,-0.36273 0.97938,-0.32262 0.90474,-0.18457 1.43288,-0.23808 0.46681,-0.0584 1.01236,-0.055 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path320" d="m 705.29946,404.37113 h 4.94953 l 1.01129,0.19824 1.02198,0.65847 0.7694,0.84434 0.62305,1.2788 0.41165,1.37503 0.60375,2.17711 0.53032,2.14857 0.38266,1.97177 0.31418,1.95565 0.25283,2.01634 0.22113,2.18648 0.14186,2.361 0.0464,2.06343 -0.0339,2.90094 -0.18666,2.93049 -0.2597,3.12611 -0.3257,2.7483 -0.47254,2.43606 -0.38375,2.06954 -0.62275,2.43127 -0.48757,1.70574 -0.56732,1.13614 -0.65604,0.75733 -0.78933,0.54765 -0.77997,0.31884 -0.82705,0.0912 h -5.1673 -0.22961 V 404.3608 Z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path322" d="m 555.36415,396.79743 h -3.36229 l -0.95244,0.2579 -0.88685,0.75198 -0.3797,1.096 v 10.8053 l 0.39974,1.00083 0.47383,0.71418 0.63631,0.44263 0.50741,0.16001 h 3.36617 0.21167 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path324" d="m 606.45914,1054.8828 h 46.6816 l -23.3408,37.0116 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path326" d="m 606.45914,1099.1543 h 46.6816 l -23.3408,37.0115 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path328" d="m 606.45914,1143.4531 h 46.6816 l -23.3408,37.0115 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path330" d="m 631.08566,1044.0909 h 27.01297 l 1.86984,0.2805 1.34197,0.3596 1.60607,0.6644 1.16604,0.7523 1.14122,0.8781 0.78333,0.8256 0.70342,0.7968 0.63184,1.1132 0.47977,0.9893 0.34526,1.0282 0.24865,1.1979 0.0693,0.8321 v 125.4568 l -0.0521,0.8725 -0.16665,1.0509 -0.4222,1.198 -0.73285,1.4957 -0.85365,1.1513 -1.41766,1.3555 -1.17786,0.9192 -1.59645,0.8597 -1.9127,0.616 -1.74431,0.1955 h -57.29204 l -1.482,-0.1172 -1.53793,-0.38 -1.02579,-0.42 -1.04703,-0.5563 -0.79838,-0.4864 -1.0868,-0.8174 -1.17978,-1.2797 -0.68706,-0.9209 -0.43671,-0.7767 -0.39717,-0.767 -0.36431,-1.0377 -0.17137,-0.7968 -0.0855,-1.2218 v -125.4649 l 0.0755,-1.1013 0.20402,-0.9527 0.22661,-0.7999 0.34294,-0.7651 0.79684,-1.4733 0.86432,-1.1445 1.36362,-1.2251 1.4025,-0.9497 0.76822,-0.4027 1.66903,-0.5936 1.31204,-0.2503 1.48443,-0.1826 1.15796,0.01 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path332" d="m 584.21811,307.65169 v -3.15652 l 0.37148,-1.45881 0.75589,-1.0701 1.18763,-0.98136 1.7025,-0.4849 h 45.22792 l 1.58355,0.18907 1.21322,0.58954 0.86017,0.63523 0.62083,0.6164 0.7767,1.22224 0.27256,1.40251 v 2.49159 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path334" d="m 554.98557,732.43405 h -3.31475 l -1.21084,0.19637 -1.41973,0.53148 -1.57035,0.97256 -0.93192,0.98282 -0.8244,1.3043 -0.46075,1.29161 -0.0637,0.91286 -0.15809,2.36293 -0.25772,3.06459 -0.2171,3.23628 -0.2039,3.99231 -0.12562,3.06085 -0.14526,4.35383 -0.0857,5.46574 v 13.91733 l 0.15624,2.15982 0.0695,2.19857 0.20282,3.01372 0.22689,2.9539 0.16898,2.8368 0.32646,4.37396 0.12161,1.93446 0.12107,1.1854 0.30831,1.25066 0.75377,1.1347 1.01957,0.99641 1.54585,0.8017 1.28043,0.2251 h 4.57179 0.17232 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path460" d="m 575.40725,1292.5752 c -8.50513,-4.4396 -14.59302,-11.4224 -17.41944,-18.9224 -0.26068,-0.6918 -2.10217,-5.5985 -2.32407,-16.4555 -0.95755,-46.8522 0.0692,-191.628 0.0924,-454.79146 0.0395,-447.17165 -1.16464,-463.77985 2.13444,-471.06146 4.14474,-9.14813 14.82174,-19.11565 24.20501,-21.93419 4.35355,-1.30772 20.60861,-0.88744 41.2504,-0.85913 9.13704,0.0125 16.72265,-0.38909 22.30143,-0.24437 9.7504,0.25294 14.61876,1.40481 19.8754,3.83273 13.20934,6.10107 27.37811,16.4207 32.31917,28.24068 1.2204,2.91943 4.50669,7.46836 6.1373,11.04497 l 1.41675,449.7216 -1.5273,449.96593 -4.08634,10.2294 c -5.14691,12.8843 -20.61785,27.6214 -33.70017,32.5287 -8.98936,3.372 -15.168,3.8603 -44.99389,3.8243 -13.98709,-0.017 -20.27955,0.078 -25.76681,0.1196 -1.4993,0.012 -2.53237,0.1219 -3.63781,0.1486 -1.8856,0.045 -3.47223,-0.1698 -5.13087,-0.6073 -1.2319,-0.3249 -1.88857,-0.4449 -3.07941,-0.9415 -0.66852,-0.2788 -1.67524,-0.6042 -2.54621,-0.9578 z m 96.94271,-95.8531 c 0.34361,-0.068 1.16774,-0.4225 1.45971,-0.6578 1.57938,-1.2724 3.13254,-2.332 3.76998,-3.2892 0.7553,-1.134 1.14301,-187.0038 1.15874,-414.46917 l -0.57612,-411.57378 -4.84312,-3.50599 c -3.43566,-2.48711 -8.52491,-1.47394 -44.87908,-1.47394 -41.01713,0 -42.12736,-0.69464 -45.65154,2.83862 -1.56374,1.56777 -1.68966,2.84556 -1.76015,34.2526 -0.0453,20.16919 -0.25443,52.7638 -0.18971,105.84008 0.042,34.48838 -0.39971,77.46436 -0.36851,131.48656 0.0237,40.99241 -0.34276,87.99166 -0.34276,142.48967 0,287.55485 0.28324,410.83535 1.67493,413.44235 1.09524,2.0518 3.44174,3.3319 5.68762,4.2392 3.12702,1.2631 22.75157,1.4763 43.15146,1.4245 20.73025,-0.053 38.09531,-0.3244 38.91512,-0.4876 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path462" d="m 518.18635,634.34636 c -2.0133,-0.74316 -4.7444,-2.43786 -6.06913,-3.766 -2.24227,-2.24804 -2.45006,-3.20634 -3.00903,-13.87724 -0.37592,-7.17651 -1.34402,-14.09008 -2.5891,-18.48986 -4.49032,-15.86754 -5.9821,-36.98433 -3.75165,-53.1062 0.55771,-4.0312 2.23996,-12.10143 3.73832,-17.93387 2.04085,-7.94409 2.72517,-12.76287 2.72779,-19.20823 0.003,-6.76442 0.37876,-9.22079 1.75882,-11.48976 3.34452,-5.49877 13.94314,-8.16727 17.96065,-4.52211 1.70953,1.55109 1.77236,4.0545 1.77236,70.62081 0,53.82758 -0.25772,69.36608 -1.17129,70.61868 -1.62169,2.2235 -6.99289,2.76866 -11.36774,1.15378 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path466" d="m 532.33814,562.77279 v -19.58771 l 0.74345,0.53648 c 1.46593,1.05782 3.20996,1.86326 4.03453,1.86326 h 0.83922 v 17.02133 17.02133 l -1.42098,0.35872 c -0.78154,0.19731 -2.04541,0.81224 -2.8086,1.36651 l -1.38762,1.00777 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path468" d="m 552.92579,605.12795 c -4.61024,-3.77319 -9.57996,-11.63826 -12.26532,-19.41107 l -1.21822,-3.52618 -0.0956,-18.65027 -0.0956,-18.65026 0.82611,-3.11181 c 2.00396,-7.54852 7.57379,-16.9297 12.61547,-21.24804 0.99001,-0.84797 1.87129,-1.47031 1.9584,-1.38298 0.0871,0.0873 0.12066,19.78469 0.0746,43.7719 l -0.0838,43.61311 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path470" d="m 554.24531,1059.9811 c -0.38562,-0.075 -1.29674,-1.1158 -1.37849,-1.5742 -0.0387,-0.2167 -0.0553,-12.8432 -0.037,-28.0588 l 0.0333,-27.6647 0.4632,-0.4756 c 0.38607,-0.3964 1.36731,-0.5813 1.75961,-0.5842 0.0482,-4e-4 -0.29526,13.0536 -0.29526,29.1581 0,23.3551 -0.0295,29.2776 -0.14603,29.2649 -0.0803,-0.01 -0.26001,-0.038 -0.39932,-0.065 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path472" d="m 620.42769,1013.2884 c -3.57448,-0.8725 -8.96012,-1.3788 -9.30569,-4.7082 l -0.67815,-2.0055 -0.25138,-4.2445 0.41829,-28.18567 c 0.29654,-19.98156 0.0411,-31.19328 0.50411,-32.91713 0.89622,-3.33689 2.97585,-6.44453 6.44362,-8.30431 2.42416,-1.3001 4.38417,-2.04911 12.31933,-2.04911 7.87316,0 9.30668,0.50275 11.63947,1.76142 3.17156,1.71124 4.95339,4.25793 5.90801,6.78394 1.14299,3.02444 0.95659,63.49706 -0.2043,66.28266 -1.21207,2.9084 -4.61574,6.4491 -8.13563,7.3377 -1.79168,0.4523 -6.47414,0.5577 -10.75587,0.4249 -3.25525,-0.101 -6.55619,0.1522 -7.90181,-0.1762 z m 0.80576,-24.14851 c 1.16322,-0.59784 3.35864,-1.93991 4.87872,-2.98238 2.69355,-1.84722 2.34692,-3.71595 2.76767,-2.38687 0.63441,2.00401 4.72774,5.3999 7.58335,4.8628 4.05952,-0.76353 5.0585,-2.82168 5.0585,-10.42179 v -6.53615 h -11.56483 l -11.51834,-0.0293 -4.7e-4,2.21816 0.0337,2.30803 4.63541,-0.0188 c 2.73527,-0.0111 4.24552,-0.44405 4.73547,-0.17155 0.39185,0.21794 0.0185,1.05358 -0.0712,1.68697 -0.14172,1.00046 -0.53695,2.34895 -3.53063,4.29524 -4.24127,2.7574 -5.67341,3.26403 -5.67341,5.70376 0,2.93489 -0.17135,2.93009 2.66607,1.47192 z m 8.72451,-20.28022 c 0.99255,-0.85681 2.35557,-3.3221 3.20525,-5.79732 1.14206,-3.32696 1.57736,-4.85966 2.57572,-4.85966 1.01595,0 1.82378,0.89997 1.98484,2.8501 0.17554,2.12547 -0.11777,2.73658 -1.58921,3.40873 -1.04809,0.47877 -1.79454,1.18693 -1.5773,1.75451 0.19578,0.5115 0.35596,1.50192 0.35596,2.20091 0,2.45771 4.7924,0.83849 6.32761,-2.13792 1.93784,-3.75702 0.66824,-10.20362 -2.32592,-11.81016 -2.08149,-1.11685 -5.66885,-0.79036 -7.54137,0.68637 -1.06893,0.84298 -1.92531,2.93981 -2.5499,5.09386 -1.30345,4.49527 -2.63948,5.88742 -4.17433,5.29693 -2.96077,-1.13908 -2.57455,-6.88848 0.56458,-7.67838 1.60085,-0.40282 2.28581,-2.23765 1.18075,-3.98616 -0.8873,-1.40395 -4.41318,-0.29463 -6.33262,1.99237 -1.36577,1.62731 -1.66572,2.67452 -1.64657,5.7486 0.0129,2.06736 0.41734,4.47138 0.8988,5.34228 1.94785,3.52339 7.593,4.52842 10.64371,1.89494 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00c8e8;fill-opacity:.992157;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path474" d="m 632.81036,983.17958 c -0.63556,-0.67826 -0.71845,-1.13691 -0.71845,-3.9753 v -3.20858 h 2.64339 2.64339 v 3.10243 c 0,2.63704 -0.10273,3.23338 -0.68483,3.97531 -0.91474,1.16589 -2.84114,1.21855 -3.8835,0.10614 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path476" d="m 614.90041,611.55893 c -5.47818,-3.70126 -5.46194,-5.62841 -5.47319,-39.94991 -0.01,-29.83751 0.23875,-32.42084 2.03054,-35.3673 2.73782,-4.50213 9.7432,-6.34849 18.29821,-6.34849 8.55502,0 14.93848,1.49439 17.6763,5.99652 1.78955,2.94276 1.41474,6.84185 1.41806,36.21097 0.003,28.17503 0.0839,31.98162 -1.47142,34.88922 -2.76995,5.17816 -6.88103,7.15268 -17.83149,7.15268 -8.29531,0 -11.8731,-0.70953 -14.64701,-2.58369 z m 8.18551,-25.73237 v -5.15343 h 9.34579 9.34579 v -2.81096 -2.81096 h -11.68224 -11.68224 v 7.96439 c 0,7.87069 -0.17512,7.83539 2.13383,7.83539 2.209,0 2.53907,-0.1521 2.53907,-5.02443 z m 7.19177,-16.60471 c 0.18831,-0.0366 0.45055,-0.54459 0.6657,-0.86103 0.6596,-0.97009 1.35497,-2.74044 1.9953,-4.67326 1.56982,-4.73845 3.62862,-5.98608 4.17546,-2.25932 0.17631,1.20159 -0.48112,2.61937 -1.34586,2.95206 -1.97767,0.76085 -1.99781,5.98598 -0.0231,5.98598 2.81061,0 6.03228,-4.36968 6.03228,-8.18181 0,-2.26738 -0.66708,-3.89433 -1.4774,-5.16066 -1.05092,-1.64231 -2.52443,-2.58631 -4.9728,-2.58631 -4.07241,0 -5.67625,1.85418 -7.32959,7.01759 -1.35947,4.24563 -2.76574,4.90543 -4.63024,3.03612 -1.76893,-1.77348 -2.21107,-4.65285 0.27445,-5.44376 1.94089,-0.6176 3.84262,-4.09021 2.19133,-5.11339 -0.54505,-0.33773 -2.20902,-0.10822 -3.69771,0.51 -2.80301,1.16403 -4.21198,4.73237 -4.21865,8.18117 -0.005,2.38104 0.56756,4.70512 2.18461,6.14168 2.68538,2.38566 6.4958,1.17087 9.91016,0.5067 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path480" d="m 583.49685,1194.3213 c -2.63205,-2.6388 -2.64339,-4.417 -2.64339,-414.70449 l 0.91025,-380.56509 0.0768,-32.0953 2.17287,-2.77511 c 2.35098,-3.00257 4.18121,-2.02246 45.18478,-2.02246 39.9348,0 42.75186,0.15622 45.67967,2.53317 l 2.95718,2.71194 0.16306,412.16132 -0.67534,412.51752 -2.4449,2.3556 c -2.71646,2.6173 -5.74931,2.5331 -45.92889,2.5331 -41.04641,0 -42.91748,-0.1091 -45.45206,-2.6502 z m 81.84368,-7.4058 3.14423,-4.037 0.0827,-66.2535 -0.39676,-66.5434 -2.26148,-3.3325 -3.88235,-2.7418 -32.27071,-0.7473 -32.79612,1.1063 -3.61057,2.1462 -3.24416,3.2525 v 66.7245 c 0,51.3889 0.37971,67.2017 1.65212,68.8007 3.62406,4.5542 6.83181,4.9751 38.22774,5.0155 l 30.77046,-0.8736 z m -24.61354,-173.581 c 7.9414,-2.7755 8.14807,-3.0866 8.14807,-41.16306 0,-32.95752 -0.10203,-35.06928 -2.67771,-37.65159 -1.48289,-1.48673 -4.16023,-2.90576 -5.99586,-3.60546 -4.95757,-1.88972 -17.0157,-1.44776 -22.15047,0.7032 -8.08162,3.38542 -8.9198,5.00242 -8.9198,40.79416 0,20.04755 0.002,33.57605 0.88389,35.22855 2.69585,5.0502 9.31002,6.769 18.65804,6.7743 4.79831,0 9.81254,-0.2968 12.05384,-1.0801 z m -1.58398,-140.068 c 5.13925,-3.46846 7.09546,-8.3228 6.85914,-13.07417 -0.16881,-3.39392 -1.37155,-6.53272 -4.41417,-9.45525 -6.97318,-6.69795 -19.07399,-5.59067 -24.94988,1.89858 -3.21578,4.09873 -3.22084,12.29018 -0.22077,16.5844 4.76762,6.82428 15.50209,8.92162 22.72568,4.04644 z m -1.36978,-61.94554 c 2.03057,-1.08953 2.55651,-2.80695 2.55651,-8.34813 0,-3.83703 -0.71372,-7.69196 -1.58604,-8.56653 -0.87232,-0.87457 -4.9167,-1.59012 -8.98752,-1.59012 -4.07082,0 -8.11521,0.71555 -8.98753,1.59012 -2.57798,2.58462 -2.032,15.24407 0.72693,16.85513 3.02779,1.76807 13.02528,1.80463 16.27765,0.0595 z m 0.46587,-39.18559 c 3.0003,-1.1543 3.0003,-15.78846 0,-16.94275 -3.66595,-1.41039 -15.82543,-0.86346 -17.47045,0.7858 -0.87232,0.87456 -1.58603,4.33307 -1.58603,7.68557 0,3.35251 0.71371,6.81101 1.58603,7.68558 1.64502,1.64926 13.8045,2.19618 17.47045,0.7858 z m 0,-39.75299 c 3.0003,-1.15429 3.0003,-15.78845 0,-16.94275 -3.66595,-1.41038 -15.82543,-0.86346 -17.47045,0.7858 -0.87232,0.87457 -1.58603,4.33307 -1.58603,7.68558 0,3.3525 0.71371,6.81101 1.58603,7.68557 1.64502,1.64926 13.8045,2.19619 17.47045,0.7858 z m 0.5046,-39.21368 c 0.87232,-0.87457 1.58604,-4.72951 1.58604,-8.56653 0,-8.09257 -1.7702,-9.71984 -10.57356,-9.71984 -8.80337,0 -10.57356,1.62727 -10.57356,9.71984 0,3.83702 0.71371,7.69196 1.58603,8.56653 0.87232,0.87457 4.91671,1.59012 8.98753,1.59012 4.07082,0 8.1152,-0.71555 8.98752,-1.59012 z m 6.9047,-82.58433 3.07071,-4.493 0.86249,-33.57673 c 0.56571,-22.02292 -0.51063,-35.24838 -1.42808,-36.96705 -2.15439,-4.03588 -9.35774,-6.42677 -19.34616,-6.42125 -10.21122,0.005 -16.75549,3.01486 -18.90955,8.69506 -0.70882,1.86912 -1.28875,17.83614 -1.28875,35.48223 0,27.49791 0.30761,32.52415 2.15212,35.16432 3.58912,5.1374 9.29638,6.89527 20.679,6.36923 9.16778,-0.42368 10.69887,-0.88197 14.20822,-4.25281 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path486" d="m 594.24699,1187.7985 c -1.15909,-0.1861 -2.79951,-1.1442 -3.68761,-2.2365 -1.49488,-1.8388 -1.31131,-8.5525 -1.33055,-68.6798 -0.0137,-42.7931 0.73515,-65.8381 1.58418,-66.8831 3.33535,-4.1049 5.06117,-6.6424 37.3562,-6.6424 19.85047,0 32.4974,1.49 33.95204,2.1545 1.22428,0.5593 4.03684,3.0392 4.89282,4.492 1.41138,2.3954 0.57113,8.6669 0.57113,67.039 v 64.367 l -1.93649,3.9919 -4.71377,2.9045 -30.90991,1.6993 c -20.82649,1.1449 -30.73945,-1.3974 -32.14976,-1.6239 z m 48.27939,-26.876 9.82832,-16.6722 -10.49871,-1.2375 c -6.93861,-0.8179 -18.12085,-0.1436 -24.74598,0 l -11.47394,0.261 12.08666,19.2791 c 6.72092,10.7203 12.32443,15.8272 12.69104,15.4321 0.3666,-0.3951 5.92627,-6.5684 12.11261,-17.0625 z m -0.87571,-43.3626 c 6.55374,-10.4749 10.57311,-17.3167 10.57311,-17.6433 0,-0.3266 -9.16284,-0 -22.78434,-0 -13.62149,0 -21.69277,-0.5851 -21.69277,-0.3178 0,0.5187 19.89711,32.7103 21.45728,34.6835 0.50934,0.6442 -2.27865,3.5495 0.11007,1.4228 1.38644,-1.2344 5.78291,-7.6659 12.33665,-18.1408 z m 1.13238,-46.0729 c 6.22721,-9.9106 9.27066,-15.806 9.27066,-16.0734 0,-0.2673 -9.26032,-0.7017 -22.88182,-0.7017 -13.62149,0 -24.20351,-0.744 -24.20351,-0.5285 0,0.3071 12.54336,18.6285 23.50069,35.8728 1.17961,1.8564 -2.07666,-0.013 -1.06964,-1.0847 0.66128,-0.7037 9.15641,-7.5738 15.38362,-17.4845 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path488" d="m 627.22564,1086.2996 c -1.36595,-2.1565 -6.28035,-9.9327 -10.92087,-17.2805 l -8.43732,-13.3596 21.71147,-0.1218 c 11.9413,-0.067 21.793,-0.04 21.89266,0.06 0.16849,0.1689 -20.53294,33.2929 -21.37902,34.2082 -0.21085,0.2281 -1.50096,-1.3497 -2.86692,-3.5061 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path490" d="m 618.93991,1117.4616 c -5.9568,-9.4452 -10.74845,-17.2554 -10.6481,-17.356 0.10035,-0.1006 9.87754,-0.1281 21.7271,-0.061 l 21.54464,0.1219 -10.771,17.1 c -5.92405,9.405 -10.82749,17.1603 -10.89655,17.2341 -0.069,0.074 -4.99929,-7.5937 -10.95609,-17.0389 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path492" d="m 627.34816,1175.0783 c -1.29113,-2.0355 -6.20112,-9.8147 -10.91108,-17.2872 l -8.56357,-13.5863 21.70844,-0.1218 c 11.93964,-0.067 21.76048,0.1196 21.89378,0.064 1.66501,-0.694 -20.53797,33.3157 -21.38241,34.2108 -0.2266,0.2401 -1.40744,-1.1705 -2.74516,-3.2795 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path494" d="m 705.333,475.35062 0.58572,-25.61496 h 2.58935 c 1.42413,0 3.07073,-0.1852 3.6591,-0.41156 6.23384,-2.39832 6.66628,-39.81075 0.51622,-44.66085 -0.98323,-0.7754 -2.60578,-1.09079 -4.08546,-1.11196 l -3.02606,-0.0433 0.17046,-24.49951 c 0.17521,-25.18178 -0.45706,-26.64286 -3.3757,-33.56049 -0.60015,-1.42246 -0.95981,-2.71801 -0.79924,-2.87899 0.73296,-0.73484 6.77569,9.79438 11.3051,19.6987 8.03987,17.58051 12.92059,24.16575 20.92458,28.23212 5.97386,3.03498 10.12842,3.56131 28.19456,3.57187 l 16.75248,0.01 2.24689,2.25266 c 1.28725,1.29057 2.24478,2.91766 2.24196,3.80967 -0.006,1.78302 -4.60673,10.12411 -8.86443,16.06984 -5.1397,7.17741 -13.21804,16.43802 -27.76099,31.82387 -25.38008,26.85109 -32.85153,36.30476 -38.78153,49.07044 l -2.48145,7.83399 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path496" d="m 551.50149,411.19136 c -0.98602,-0.57578 -1.10996,-1.3398 -1.10661,-6.82131 0.002,-2.873 0.0677,-5.46502 0.14652,-5.76006 0.20727,-0.77576 1.25515,-1.22041 2.87607,-1.22041 h 1.41347 v 7.0274 7.02739 l -1.46028,-0.007 c -0.80316,-0.004 -1.64428,-0.11456 -1.86917,-0.24589 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path498" d="m 705.29823,426.52862 v -21.6925 l 2.74532,0.0832 c 3.12768,0.0948 3.89424,0.4293 4.72483,2.06157 0.61397,1.20659 1.76821,5.63906 2.33099,8.95136 1.27555,7.50746 1.05966,16.78021 -0.57067,24.51085 -1.52786,7.24475 -1.97566,7.77797 -6.53195,7.77797 h -2.69852 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path500" d="m 584.73878,305.9748 c 0.003,-2.26451 1.14147,-4.16777 2.76325,-4.61938 1.23234,-0.34316 46.09771,-0.32639 47.35227,0.0177 0.6001,0.16459 1.31857,0.65313 2.00748,1.36501 1.06534,1.10085 1.37105,1.89697 1.3778,3.58804 l 0.003,0.64418 h -26.75233 -26.75234 l 10e-4,-0.99555 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path502" d="m 744.76749,392.34624 c -7.37403,-1.15256 -12.25912,-3.51316 -17.18139,-8.30249 -4.19,-4.07684 -9.97636,-11.23159 -14.15429,-20.84415 -6.80877,-15.6656 -12.32942,-19.2518 -16.1565,-24.99405 -0.5827,-0.8743 -3.10009,-5.66604 -4.55833,-7.29974 -3.50425,-3.92592 -5.49316,-5.94965 -6.99245,-7.1149 -0.67792,-0.52688 -2.15819,-0.77779 -2.10637,-0.82975 0.1682,-0.16863 10.68177,1.9607 15.83895,3.44149 6.54031,1.87794 9.83649,2.91531 21.26168,6.69147 24.21778,8.00427 37.13651,11.3397 48.9486,12.63781 1.92757,0.21183 4.08294,0.48465 4.78972,0.60624 4.01962,0.69158 8.00385,4.57809 8.87032,8.65275 0.19483,0.9162 0.25245,4.67159 0.19948,13.00069 l -0.0745,11.71234 -0.63074,1.34936 c -0.80435,1.72076 -2.07559,3.36646 -5.20034,6.73215 -1.37555,1.48161 -2.82564,3.19454 -3.22244,3.80651 l -0.72144,1.11267 -13.45364,-0.0227 c -9.97413,-0.0168 -13.9716,-0.10364 -15.45634,-0.33571 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path926" d="m 626.42004,812.0638 c -3.0151,-0.30334 -4.96457,-1.13982 -5.58976,-2.2103 -1.31153,-2.24565 -1.63054,-9.94619 -0.65837,-13.08723 0.61716,-1.99402 1.1237,-2.59841 3.95631,-3.1346 3.07565,-0.5822 10.37998,-0.38743 12.68678,0.34496 1.50914,0.47914 1.69385,0.57767 2.14224,1.78531 0.74868,2.0164 1.22658,7.31549 0.8778,10.29605 -0.36136,3.08801 -0.86268,4.19746 -2.35622,4.92047 -2.0881,1.01083 -7.02388,1.49128 -11.05878,1.08534 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path928" d="m 626.45483,772.42523 c -1.19582,-0.13489 -3.06338,-0.4663 -3.83508,-0.72229 -1.34222,-0.44525 -1.84952,-0.79471 -2.34633,-2.1889 -0.75897,-2.1299 -0.65153,-9.67076 0.10744,-11.80066 0.64277,-1.8038 1.39271,-2.22659 4.72627,-2.66451 2.84021,-0.37312 11.47273,-0.10592 12.66771,0.35154 1.51479,0.57988 2.20815,3.48226 2.20178,8.48923 -0.004,3.1328 -0.28379,5.81187 -0.98109,6.87608 -0.21326,0.32548 -1.09366,1.1394 -1.83309,1.33166 -1.62821,0.42336 -7.87645,0.64719 -10.70761,0.32785 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path930" d="m 626.45219,732.49906 c -1.25777,-0.13165 -3.14347,-0.41083 -3.92609,-0.67038 -1.36508,-0.45271 -1.72145,-0.63254 -2.21967,-2.03069 -0.75897,-2.1299 -0.78566,-9.66466 -0.0267,-11.79456 0.64277,-1.8038 1.59031,-2.26853 4.92387,-2.70646 2.84021,-0.37311 11.2883,-0.0856 12.48328,0.3719 1.51479,0.57988 2.27239,3.48197 2.26602,8.48895 -0.004,3.1328 -0.58408,6.09459 -1.28138,7.1588 -0.21517,0.32839 -0.84775,0.6853 -1.5938,0.87529 -1.65266,0.42087 -7.69669,0.6137 -10.62554,0.30715 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:.264985;stroke-opacity:1" id="path932" d="m 625.65956,693.89955 c -0.97518,-0.13612 -2.55333,-0.0903 -3.32293,-0.34698 -1.37509,-0.45857 -1.53415,-0.83609 -2.02375,-2.39853 -0.34888,-1.1134 -0.57835,-2.85799 -0.67551,-5.5487 -0.2167,-6.00139 0.52022,-7.93082 3.07167,-9.20691 1.28365,-0.64201 1.83934,-1.06269 7.10382,-1.06269 5.37865,0 5.54929,0.20323 7.00626,0.91889 1.84975,0.90844 2.42826,1.87471 2.83202,4.71762 0.53225,3.74752 -0.17476,11.16443 -1.26107,12.14752 -1.12933,1.02204 -8.85213,1.32114 -12.73051,0.77978 z"/><path id="path489" d="m 379.06905,101.33936 h 13.1901 l 0.037,-8.25531 h 14.1068 c 3.694,0 4.8671,3.29254 4.8671,8.2606 v 75.70196 c 0,3.53235 -3.4085,6.31095 -6.4405,6.31095 h -9.5226 c -2.5944,0 -2.7443,-2.75044 -3.0117,-5.11156 v -5.02502 h -13.0052 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path491" d="M 392.26755,173.06935 V 101.88171" style="fill:#4d4d4d;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path493" d="m 320.74985,56.29539 v 15.94604 h 43.5888 V 56.01064 c 0,-2.09826 -1.8726,-3.04523 -3.5597,-3.4883 -12.173,-3.19604 -25.2766,-3.03408 -36.8326,0 -1.8219,0.47838 -3.1965,1.67683 -3.1965,3.77305 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path495" d="m 278.71645,200.68211 c -1.8116,5.3094 -14.3159,15.23177 -26.804,17.54252 0,3.02085 2.1746,7.20824 6.6781,7.20824 h 42.9453 c 9.0444,0 6.7685,24.00009 -7.8827,24.00009 h -14.8228 c -30.7958,10.32445 -58.299,10.53516 -88.3562,0 h -15.6167 c -13.60575,0 -16.40685,-23.78104 -7.81066,-23.78104 h 42.12586 c 6.109,0 8.9689,-3.48568 8.6104,-7.02445 -10.9644,-3.70415 -20.7546,-8.55799 -26.2816,-17.58519 v -3.35273 h 87.2518 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84474px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path497" d="m 274.17465,197.4005 c 0,0.25865 0,6.33998 0,6.33998 0,2.6468 2.5651,3.68761 5.8562,3.68761 17.7306,0.98444 39.2718,0.92676 57.4315,0 3.0517,0 6.0443,-1.82692 6.0104,-3.78467 v -7.73095 h -69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path499" d="m 258.08445,225.33728 h -45.0418"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.4781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path501" d="m 355.50055,191.92715 v 11.14596 c 0,0.96002 -0.737,2.03381 -1.3112,2.03381 h -23.0257 c -0.7228,0 -1.5998,-1.11889 -1.5998,-2.48132 v -10.77963 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path503" d="m 252.26535,218.07198 h -35.7635"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84684px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path505" d="m 128.69523,197.40389 c 0,0.25924 0,6.35443 0,6.35443 0,2.65284 2.56501,3.69602 5.85597,3.69602 17.73073,0.98669 39.27175,0.92888 57.43165,0 3.0517,0 6.0443,-1.83107 6.0102,-3.7933 v -7.74857 h -69.29782 z"/><path id="path509" d="m 91.14151,199.65348 c -8.52966,0 -24.99089,-16.61076 -24.99089,-25.55625 v -58.65862 c 4.57443,-17.00507 13.35533,-35.47833 41.84537,-41.00408 4.97535,0 7.55529,-4.59359 7.55529,-7.40352 26.96999,-35.0496 56.25477,-53.08707 86.30587,-65.49263 h 63.6397 c 27.3731,12.02627 42.6345,29.98675 54.6313,49.5466 V 61.9055 c 0,4.46695 3.7756,9.11203 8.7178,9.11203 h 52.8878 v 128.70726 z" style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path511" d="M 100.1578,95.57843 H 327.54875 C 327.43015,49.18358 304.14675,1.15062 259.36955,1.15062 L 195.76105,1.8971 C 133.48741,13.03019 120.68895,56.85936 100.1578,95.57843 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path513" d="m 81.49442,126.18349 h 247.95873 v 27.99243 c 0,9.45565 -12.3167,23.51364 -23.9962,23.51364 H 97.49165 c -12.6963,0 -22.09152,-12.0229 -22.09152,-21.64746 0,-11.5947 -1.02012,-29.85861 6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path519" d="m 216.49175,61.4392 v -1.87954 l 5.5759,-6.74897 c 3.0668,-3.71194 5.5759,-6.75827 5.5759,-6.76966 0,-0.0114 -2.2283,-0.0205 -4.9515,-0.0205 h -4.9514 v -1.75092 -1.75094 h 7.7716 7.7718 v 1.61419 1.61418 l -5.8379,7.04557 -5.8376,7.04554 6.0529,0.0114 6.0532,0.0114 v 1.7297 1.72968 h -8.6113 -8.6116 v -1.87951 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0335108;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4218" d="M 236.52525,52.97079 V 42.61137 h 2.6255 2.6254 v 8.6079 8.60791 h 6.5824 6.5825 v 1.75151 1.75152 h -9.2079 -9.2079 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0325267;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4220" d="m 227.42615,152.06817 v -10.42336 h 2.4583 2.4584 v 8.66103 8.66102 h 6.1635 6.1634 v 1.76236 1.76232 h -8.6218 -8.6218 z"/></svg>
\ No newline at end of file diff --git a/src/Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg b/src/Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg new file mode 100644 index 00000000..c073c9c0 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Controller_JoyConPair.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000 1300" xml:space="preserve"><metadata id="metadata161"/><style id="style2" type="text/css">.st0{opacity:.1}.st1{fill:#02c5e5}.st2{fill:#ff5f55}.st3{fill:#fff}</style><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/><g id="layer1"><g id="g344" transform="translate(-64,299.7467)"><path id="path66-7" d="m 413.1,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 V 207 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 v 79.2 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 269.7 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 V 716 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 157.2 c 0,3.6 -2.9,6.5 -6.5,6.5 z M 405.2,65.7 c -3,0 -5.5,2.4 -5.5,5.5 v 828.9 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 742.9 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 340.1 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path68-5" d="m 399.3,858.9 h -11.2 c -0.3,0 -0.5,-0.2 -0.5,-0.5 V 72 c 0,-0.3 0.2,-0.5 0.5,-0.5 h 11.2 c 0.3,0 0.5,0.2 0.5,0.5 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -10.7,-1 h 10.2 V 72.5 h -10.2 z" class="st3" style="fill:#000"/><path id="path70-3" d="M 382.1,1000 H 275.9 C 158.9,1000 64,905.2 64,788.1 c 0,0 0,0 0,0 V 220.9 C 64,104.1 159.1,9.1 275.9,9.1 h 106.2 c 3.6,0 6.5,2.9 6.5,6.5 v 978 c 0,3.5 -2.9,6.4 -6.5,6.4 z M 275.9,10.1 C 159.6,10.1 65,104.7 65,220.9 V 788.1 C 65,904.4 159.6,999 275.9,999 h 106.2 c 3,0 5.5,-2.4 5.5,-5.5 v -978 c 0,-3 -2.4,-5.5 -5.5,-5.5 H 275.9 Z" class="st3" style="fill:#000"/><path id="path98" d="m 413.1,717.1 h -4.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -79.5 c 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path id="path100" d="m 413.1,314.3 h -4.2 c -0.6,0 -1,-0.4 -1,-1 v -79.5 c 0,-0.6 0.4,-1 1,-1 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z" class="st1" style="fill:#000"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1144" d="M 257.24031,997.87141 C 231.00562,994.85925 207.29188,989.42604 182.14949,976.89078 160.25417,965.97443 141.01707,951.17849 124.7007,934.38991 92.385223,901.13922 70.993413,856.60594 65.658526,807.7016 65.28629,804.28935 65.60032,777.25611 65.321787,735.45113 64.265473,576.90901 64.42116,214.87541 65.832698,201.04147 c 1.806274,-17.70261 6.06302,-36.49109 12.012095,-52.35867 2.796862,-7.4599 7.091312,-15.77684 10.715421,-23.13845 C 119.94788,61.78692 180.7783,21.164531 250.9852,11.961211 269.16651,9.5778481 384.12059,8.7019738 386.44913,11.030497 c 0.15343,0.153425 0.87429,2.31235 1.04555,7.011277 0.40459,11.1005 0.35029,35.996153 1.26274,79.381547 0.6886,32.741359 -0.0274,76.313339 0.10052,132.519699 0.15984,70.25759 -1.57659,160.16298 -1.57659,274.77051 0,484.50248 1.44371,491.1849 -0.86873,492.42248 -0.32431,0.17356 -2.47056,1.663 -5.33883,1.8051 -21.9107,1.08549 -119.24063,-0.54237 -120.56646,-0.6946 z"/><polygon id="polygon80" points="237.9 448.9 225.8 469.9 250 469.9" class="st1" transform="matrix(1.1037134,0,0,1.0523169,-24.636066,-24.267048)" style="fill:#333;stroke:#000;stroke-width:.927894;stroke-opacity:1"/><polygon id="polygon82" points="250 605.9 237.9 626.9 225.8 605.9" class="st1" transform="matrix(1.0574383,0,0,1.0316716,-13.259456,-19.457378)" style="fill:#333;stroke:#000;stroke-width:.957418;stroke-opacity:1"/><polygon id="polygon84" points="169.9 525.8 148.9 537.9 169.9 550" class="st1" transform="matrix(1.0443863,0,0,1.1036462,-7.5389156,-55.555947)" style="fill:#333;stroke:#000;stroke-width:.931439;stroke-opacity:1"/><polygon id="polygon86" points="326.9 537.9 305.9 550 305.9 525.8" class="st1" transform="matrix(1.2181479,0,0,1.1364095,-67.797686,-73.39984)" style="fill:#333;stroke:#000;stroke-width:.849928;stroke-opacity:1"/><path id="path102" d="m 81.300444,139.3 c -0.3,0 -0.5,-0.1 -0.7,-0.3 l -3.4,-3.4 c -2,-2 -2.6,-5.1 -1.5,-7.8 C 110.50044,50.1 187.70044,0.1 272.90044,0 h 51.2 c 3.8,0 6.9,3.1 7,7 v 2.6 c 0,0.6 -0.4,1 -1,1 h -54.2 c -84.5,-0.1 -160.8,50.4 -193.699996,128.1 -0.1,0.3 -0.4,0.5 -0.7,0.6 -0.1,0 -0.2,0 -0.2,0 z M 272.90044,2 c -84.4,0.1 -160.9,49.7 -195.399996,126.7 -0.8,1.9 -0.4,4.1 1.1,5.5 l 2.4,2.4 C 114.60044,58.8 191.30044,8.5 276.00044,8.6 h 53.2 V 7 c 0,-2.7 -2.2,-5 -5,-5 z" class="st1" style="fill:#000"/><path id="path104" d="m 359.60044,116.1 h -46.9 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 46.9 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 z m -46.9,-17.6 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 46.9 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 z" class="st1" style="fill:#000"/><path id="path106" d="m 237.90044,502.9 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path108" d="m 237.90044,649.8 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.3 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.2,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 0,-20.2 -16.3,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path110" d="m 311.40044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path112" d="m 164.50044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st1" style="fill:#000"/><path id="path114" d="m 314.10044,753.7 h -45 c -5.5,0 -9.9,-4.4 -9.9,-9.9 v -45 c 0,-5.5 4.4,-9.9 9.9,-9.9 h 45 c 5.5,0 9.9,4.4 9.9,9.9 v 45 c 0,5.5 -4.5,9.9 -9.9,9.9 z m -45,-62.8 c -4.4,0 -7.9,3.6 -7.9,7.9 v 45 c 0,4.4 3.6,7.9 7.9,7.9 h 45 c 4.4,0 7.9,-3.6 7.9,-7.9 v -45 c 0,-4.4 -3.6,-7.9 -7.9,-7.9 z" class="st1" style="fill:#000"/><path id="path116" d="m 291.60044,741.7 c -11.3,0 -20.4,-9.2 -20.4,-20.4 0,-11.3 9.2,-20.4 20.4,-20.4 11.3,0 20.4,9.2 20.4,20.4 0,0 0,0 0,0 0,11.3 -9.1,20.4 -20.4,20.4 z m 0,-38.9 c -10.2,0 -18.4,8.3 -18.4,18.4 0,10.1 8.3,18.4 18.4,18.4 10.2,0 18.4,-8.3 18.4,-18.4 0,-10.1 -8.2,-18.3 -18.4,-18.4 z" class="st1" style="fill:#000"/><path id="path118" d="m 174.80044,260.2 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st1" style="fill:#000"/><path id="path120" d="m 234.60044,338.9 v 0 c -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 V 338 c -0.1,0.5 -0.6,0.9 -1.1,0.9 z m -71,-72 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st1" style="fill:#000"/><path id="path122" d="m 241.30044,338.9 c -0.6,0 -1,-0.4 -1,-1 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.5,71.4 -73.1,73.1 z m 59.7,-72 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 11.2 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st1" style="fill:#000"/><path id="path124" d="m 313.30044,260.2 h -12.3 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1.1 -0.9,1.1 0,0 0,0 0,0 z m -71,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.2,-37.4 -32.7,-67.9 -70,-70 z" class="st1" style="fill:#000"/><path id="path126" d="m 237.90044,339 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 h -12.3 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0.1 -2.2,0.1 -3.4,0.1 z m -2.3,-2 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 h -11.4 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 z" class="st1" style="fill:#000"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path179" d="m 158.02789,574.27925 c -14.73064,-3.25266 -24.85554,-12.70578 -29.04419,-27.11717 -0.98592,-3.39218 -1.21679,-6.26957 -0.93511,-11.65556 0.33774,-6.4583 0.67944,-7.76803 3.52546,-13.51272 11.35216,-22.91431 40.68588,-27.928 58.61532,-10.01846 19.42229,19.40073 11.99924,51.86436 -13.89781,60.78009 -5.19354,1.788 -13.81105,2.50701 -18.26367,1.52382 z m 12.59864,-36.29462 c 0,-7.35074 -0.18108,-13.36496 -0.40241,-13.36496 -0.89601,0 -23.32454,13.1809 -22.99291,13.51259 0.66445,0.66458 22.24473,13.11359 22.82266,13.1657 0.31497,0.0284 0.57266,-5.96261 0.57266,-13.31333 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path181" d="m 232.50517,500.57091 c -6.91699,-0.86484 -15.04235,-4.99807 -20.4853,-10.42051 -14.58513,-14.53016 -14.55979,-36.85709 0.0584,-51.42015 23.0282,-22.94142 62.26853,-6.95317 62.26853,25.37095 0,10.34881 -3.46897,18.75364 -10.723,25.98031 -8.34032,8.30891 -19.22192,11.97685 -31.1186,10.4894 z m 18.58209,-30.69278 c -0.91811,-2.38357 -12.79282,-22.35099 -13.28879,-22.34521 -0.45143,0.005 -5.88471,9.05299 -11.95805,19.91302 l -2.0157,3.60439 h 13.85703 c 12.18288,0 13.80248,-0.14161 13.40551,-1.1722 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999997;stroke-opacity:1" id="path185" d="m 229.21434,646.98161 c -12.9232,-3.46654 -23.15418,-13.73508 -26.52403,-26.62142 -5.92248,-22.64757 11.58541,-45.21876 35.15949,-45.32763 7.44717,-0.0344 11.29183,0.91312 18.09999,4.46071 16.90217,8.80735 23.84898,30.39169 15.40753,47.87245 -7.54225,15.61868 -25.6403,24.04261 -42.14298,19.61589 z M 245.434,616.92014 c 3.65424,-6.30197 6.48622,-11.61534 6.29329,-11.8075 -0.19293,-0.19216 -6.40658,-0.25572 -13.80812,-0.14123 l -13.45735,0.20814 6.66623,11.58776 c 3.66642,6.37327 6.89025,11.59297 7.16405,11.59935 0.27381,0.006 3.48766,-5.14457 7.1419,-11.44652 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path187" d="m 307.85537,574.24407 c -0.34478,-0.0389 -1.62711,-0.27075 -2.84962,-0.51537 -11.23844,-2.24892 -20.9226,-9.70179 -26.17378,-20.1432 -2.82839,-5.62398 -4.20289,-12.18393 -3.75883,-17.93953 1.14218,-14.80435 11.33006,-27.74217 25.61809,-32.53303 8.75405,-2.93529 18.04495,-2.18507 26.72988,2.15843 8.69225,4.34715 15.48783,12.11097 18.64346,21.29973 5.25881,15.31297 -0.71552,32.17026 -14.73029,41.56334 -5.99457,4.01773 -13.35804,6.28235 -20.18834,6.20884 -1.46502,-0.0157 -2.94577,-0.0604 -3.29057,-0.0993 z m -0.66719,-23.08553 c 0.71175,-0.35815 3.02697,-1.62049 5.14496,-2.80516 8.66766,-4.84825 15.63944,-9.1681 16.21592,-10.0477 0.27948,-0.42642 0.28078,-0.49758 0.0166,-0.90068 -0.86957,-1.32678 -21.50733,-13.52937 -22.8817,-13.52937 -0.25925,0 -0.5656,0.11351 -0.68079,0.25225 -0.41371,0.49837 -0.59707,4.78502 -0.59431,13.89388 0.003,9.06159 0.17803,13.03427 0.59744,13.53951 0.32082,0.38645 0.78324,0.3011 2.18189,-0.40273 z"/><path style="fill:#333;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path189" d="m 287.96017,739.09726 c -1.01606,-0.21912 -2.9756,-0.9477 -4.35453,-1.61905 -2.09414,-1.01956 -2.88115,-1.59464 -4.77748,-3.49097 -1.89792,-1.89791 -2.4703,-2.68159 -3.48941,-4.77748 -2.66648,-5.48389 -2.66607,-10.55714 10e-4,-16.08572 1.0133,-2.10022 1.56326,-2.85257 3.48092,-4.76199 3.62968,-3.61405 7.72755,-5.3398 12.70198,-5.34921 8.35146,-0.0158 15.68299,5.71579 17.81213,13.92506 0.52326,2.01754 0.54009,6.16569 0.0339,8.34799 -1.47072,6.34008 -6.30854,11.44929 -12.69973,13.41212 -2.44922,0.7522 -6.26202,0.92699 -8.70906,0.39925 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path191" d="m 267.23012,751.2862 c -1.59942,-0.43597 -2.94763,-1.29847 -4.05871,-2.59652 -1.81264,-2.11766 -1.73429,-0.87988 -1.73429,-27.39725 0,-26.73402 -0.0972,-25.30688 1.87658,-27.54923 0.58306,-0.66239 1.71204,-1.51487 2.55332,-1.92799 l 1.5081,-0.74058 h 24.1534 24.15339 l 1.77672,0.87468 c 1.25727,0.61895 2.04823,1.23027 2.70544,2.091 1.78729,2.34073 1.72742,1.33094 1.64816,27.80036 -0.0712,23.78487 -0.0733,23.86757 -0.63865,25.09049 -0.72339,1.56486 -2.26169,3.10316 -3.93043,3.93043 l -1.30842,0.64864 -23.75199,0.0516 c -18.21394,0.0396 -24.03192,-0.0247 -24.95262,-0.27565 z m 27.28995,-9.68076 c 10.60326,-1.53286 18.09097,-10.66806 17.50501,-21.35655 -0.18432,-3.36213 -0.66908,-5.27077 -2.04745,-8.06138 -4.59235,-9.29756 -15.46557,-13.67756 -25.3079,-10.19463 -2.76161,0.97725 -4.68871,2.16763 -7.02836,4.34145 -3.05146,2.83517 -5.11688,6.34636 -6.04249,10.27217 -0.50715,2.151 -0.50715,7.22087 0,9.37186 0.92171,3.90925 2.95421,7.3745 6.0133,10.25221 2.20884,2.07787 4.16469,3.31668 6.72144,4.2573 3.40627,1.25315 6.72782,1.61756 10.18645,1.11757 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1082" d="m 235.77295,330.34531 c 0,-6.0203 -0.0462,-6.51813 -0.73076,-7.87124 -1.06164,-2.09851 -2.95253,-3.39477 -5.65313,-3.87537 -15.06064,-2.68022 -27.49575,-10.15006 -36.51861,-21.93692 -4.96934,-6.49162 -8.83069,-15.11098 -10.3887,-23.18981 -0.83474,-4.3284 -1.3998,-5.65891 -2.97647,-7.00848 -1.7724,-1.51711 -3.30405,-1.79252 -9.96885,-1.79252 h -5.86461 v -2.11107 -2.11107 h 6.26944 c 6.12912,0 6.30805,-0.0192 7.9945,-0.85963 2.44443,-1.21811 3.32179,-2.74063 4.22338,-7.32906 4.56927,-23.25403 22.39532,-40.97679 45.63214,-45.36773 4.16129,-0.78634 5.57438,-1.57205 6.90818,-3.84114 0.9048,-1.53927 0.91186,-1.5954 1.02116,-8.12677 l 0.11006,-6.57679 h 2.0822 2.0822 v 6.27497 c 0,6.20191 0.0104,6.29547 0.89315,8.03629 1.32629,2.61551 2.65075,3.37644 7.56606,4.34684 19.37922,3.82593 35.08856,16.98397 42.28514,35.41774 1.04383,2.67375 1.9437,5.93165 3.31831,12.01372 0.58905,2.60627 1.67368,4.16462 3.60307,5.17675 1.1513,0.60396 1.95144,0.68258 7.85861,0.77219 l 6.57679,0.0998 v 2.0925 2.09249 h -6.26944 c -6.12912,0 -6.30805,0.0192 -7.9945,0.85963 -2.20181,1.09721 -3.39863,2.90223 -3.90849,5.89474 -4.06097,23.83452 -22.22419,42.32715 -45.97159,46.8053 -4.2535,0.8021 -5.71797,1.66037 -6.96502,4.08193 -0.79329,1.54043 -0.83455,1.89301 -0.94026,8.03533 l -0.11057,6.42419 h -2.08169 -2.0817 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1084" d="m 163.78864,257.28223 c 0.0926,-0.49123 0.26012,-1.9162 0.37218,-3.1666 0.34565,-3.85681 1.73866,-10.12043 3.27937,-14.74553 8.02141,-24.0797 28.10082,-42.70464 52.74332,-48.92282 3.12397,-0.78829 7.58171,-1.54879 11.2861,-1.92544 l 2.02988,-0.20639 v 5.8726 c 0,8.54266 -0.3854,9.15422 -6.53853,10.37563 -18.42711,3.65779 -33.66767,15.25204 -41.92018,31.89074 -2.55007,5.14144 -4.14587,10.08856 -5.47376,16.9691 -0.45828,2.3746 -1.81844,3.9985 -3.71595,4.43649 -0.71452,0.16493 -3.75876,0.30335 -6.76499,0.30761 l -5.46587,0.008 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1086" d="m 229.76452,336.39384 c -26.99792,-3.04756 -50.79328,-21.35759 -60.92173,-46.87799 -2.38214,-6.00221 -4.22117,-13.35788 -4.67827,-18.71196 -0.11259,-1.31887 -0.27512,-2.73804 -0.36117,-3.1537 l -0.15645,-0.75574 6.32279,0.10618 c 5.78597,0.0972 6.39885,0.16304 7.21874,0.77582 1.58067,1.18137 2.03872,2.1715 2.89278,6.25312 1.21968,5.82894 2.45374,9.35857 5.18759,14.8375 2.85902,5.72977 5.67403,9.77885 9.85937,14.18161 8.62003,9.0678 19.6967,15.16512 31.73111,17.46684 3.63419,0.69508 4.63135,1.16546 5.80819,2.73983 0.6132,0.82034 0.6781,1.4276 0.77012,7.20628 0.0943,5.92221 0.0643,6.30785 -0.48717,6.26798 -0.32321,-0.0233 -1.75687,-0.17446 -3.1859,-0.33577 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1088" d="m 299.6703,257.71116 c -2.39043,-0.853 -2.81858,-1.58503 -3.81252,-6.51855 -3.66786,-18.20579 -15.40436,-33.45997 -31.99138,-41.57986 -4.81668,-2.35792 -8.58209,-3.67044 -13.47836,-4.69819 -4.72195,-0.99115 -6.17077,-1.58672 -7.05619,-2.9006 -0.70499,-1.04613 -0.73853,-1.38133 -0.73853,-7.38107 0,-3.45685 0.11517,-6.28518 0.25593,-6.28518 0.14076,0 1.93111,0.20926 3.97855,0.46502 11.96867,1.4951 22.85594,5.62979 32.79042,12.45291 4.36974,3.00118 7.416,5.6069 11.57682,9.90259 9.30395,9.60553 15.50823,20.66713 18.77966,33.48224 0.93232,3.65217 2.12151,10.886 2.12151,12.90514 0,0.58643 -0.30132,0.619 -5.60245,0.60551 -3.82949,-0.01 -5.98886,-0.15214 -6.82346,-0.44996 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1090" d="m 242.3249,330.46177 c 0.097,-5.7735 0.163,-6.38655 0.77566,-7.20629 1.18269,-1.58243 2.17182,-2.02925 6.33209,-2.86041 23.48707,-4.69236 41.89612,-23.31363 46.43689,-46.97223 0.66775,-3.47916 1.14738,-4.47847 2.71006,-5.64639 0.81991,-0.6128 1.43277,-0.67865 7.22079,-0.77584 l 6.32483,-0.10621 -0.19591,1.73011 c -1.19107,10.51857 -3.29919,17.9842 -7.45853,26.41337 -11.17834,22.65366 -32.93361,38.14197 -57.96776,41.26919 -2.04744,0.25577 -3.84896,0.46502 -4.00338,0.46502 -0.15442,0 -0.23305,-2.83964 -0.17474,-6.31032 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1092" d="m 311.60253,113.45766 c -0.55307,-0.55307 -0.67321,-1.83753 -0.67321,-7.19731 0,-4.50308 0.15925,-6.68335 0.51409,-7.03819 0.38766,-0.38766 6.43841,-0.5141 24.60307,-0.5141 21.32785,0 24.16614,0.0772 24.76219,0.67322 0.55166,0.55166 0.67322,1.82364 0.67322,7.0445 0,6.09825 -0.0408,6.39986 -0.95215,7.03819 -0.83385,0.58406 -3.89051,0.66691 -24.60307,0.66691 -20.92962,0 -23.72838,-0.0775 -24.32414,-0.67322 z"/><path style="fill:#000;fill-opacity:1;stroke:#4d4d4d;stroke-width:.999998" id="path1094" d="m 78.977784,134.18912 c -2.35328,-2.74929 -2.18932,-3.66269 2.26682,-12.62797 C 92.012734,99.89682 104.871,81.96966 121.771,65.058734 153.11752,33.69194 193.3541,12.833792 237.03838,5.305545 252.10894,2.708387 253.57756,2.630423 291.07604,2.43687 l 34.76922,-0.179466 1.35092,1.207149 c 0.9677,0.864713 1.41875,1.712966 1.59003,2.990242 l 0.23911,1.783092 -33.78877,0.194148 c -36.2509,0.208295 -38.76527,0.335101 -53.2555,2.685802 -38.392,6.2282 -72.8916,22.039868 -103.29303,47.340693 -6.79226,5.652686 -19.46547,18.33117 -25.22484,25.23531 -8.3636,10.02603 -16.479016,21.67655 -22.544486,32.36489 -3.07683,5.42188 -9.61802,18.64996 -9.61802,19.45027 0,0.91062 -0.80534,0.45303 -2.32289,-1.31988 z"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1150" d="m 398.44844,615.98373 c 0,-216.02489 -0.0215,-633.986049 0.12697,-525.973599 0.14845,108.012439 0.29139,614.347419 0.14294,722.359859 -0.0401,29.20619 -0.0907,43.20012 -0.12499,45.04791 -0.0926,4.98585 -0.14492,-83.82167 -0.14492,-241.43417 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1152" d="m 400.62988,903.164 c -1.48283,-2.11702 -0.83255,-44.16773 -0.83255,-417.61555 0,-373.44781 -0.81158,-415.197415 0.67125,-417.31444 1.37591,-1.964385 3.40896,-2.252646 8.48523,-2.252646 1.77094,0 3.84166,-0.08796 5.42907,0.210876 1.40618,0.264716 3.16687,2.038026 3.49464,2.365798 0.49522,0.495217 0.3217,4.318356 0.43962,16.36819 0.1111,11.353396 -0.22256,28.989262 -0.22256,55.337332 0,44.70634 0.60945,61.76349 0.136,69.7887 -0.25741,4.36328 -1.18492,6.13499 -1.9011,8.04917 -1.16098,3.10304 -3.86364,8.15599 -5.61012,10.90989 l -3.1754,5.00708 0.39853,40.34769 c 0.37154,37.61503 -0.21444,39.05077 1.63547,41.67417 1.08842,1.5435 2.94744,6.13491 4.62112,9.33312 l 3.04306,5.81494 1.31284,7.9315 -0.0707,19.78753 -0.10737,15.79956 -0.21131,97.91413 c -0.20099,93.13106 1.25117,126.69008 -0.28021,141.09354 -0.44236,4.16066 -1.62132,6.51589 -2.28217,8.50207 -0.90516,2.72046 -2.09268,4.90784 -3.84656,7.82045 l -3.66064,6.0791 0.3792,15.57297 0.11069,25.0662 c 0.11714,26.5248 0.58051,40.42685 1.28995,40.8653 0.59597,0.36833 2.69223,4.04112 4.32574,8.44952 l 3.32256,8.96672 1.09731,9.02354 -0.19118,15.86739 -0.18943,57.8651 c -0.2026,61.8851 0.4238,84.47685 -0.4696,85.55336 -0.77641,0.93553 -4.47782,2.42762 -8.42197,2.42762 -5.161,0 -7.33923,-0.63936 -8.71946,-2.60992 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1154" d="M 389.22472,464.93186 V 72.687962 h 4.22905 4.22904 V 464.93186 L 398.8,857.9 393.4746,858.08261 388.6,857.9 Z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1156" d="m 409.89998,273.33293 v -38.63294 h 3.04188 c 1.74435,0 3.58682,0.88543 4.31941,2.07573 1.73761,2.82321 1.73761,70.29119 0,73.11439 -0.73259,1.19032 -2.57506,2.07573 -4.31941,2.07573 h -3.04188 z"/><path style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1158" d="m 409.89998,676.164 v -38.66403 h 3.04381 c 1.74545,0 3.58909,0.88613 4.32215,2.07741 1.7387,2.82547 1.7387,70.34777 0,73.17325 -0.73306,1.19129 -2.5767,2.0774 -4.32215,2.0774 h -3.04381 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502-3"/></g><g id="g315" transform="translate(56.713,299.7467)"><g id="g64" class="st0"><path id="path36" d="m 597.9,233.9 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path38" d="m 597.9,636.6 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path40" d="m 929,134.9 -3.4,3.4 C 892.4,60.3 815.8,9.6 730.9,9.6 H 676.7 V 7 c 0,-3.3 2.7,-6 6,-6 0,0 0,0 0,0 h 51.2 c 84.8,0 161.7,49.8 196.4,127.2 1,2.3 0.5,4.9 -1.3,6.7 z" class="st2"/><path id="path42" d="M 679.5,94.5 V 82.8 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 -1.3,3 -3,3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,1.3 3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 v 0 -11.7 c 0,-1.6 1.3,-3 3,-3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 0,0 0,0 0,0 v -11.7 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.7,0 -3,-1.4 -3,-3 0,0 0,0 0,0 z" class="st2"/><circle id="circle44" cx="768.9" cy="333.9" r="37.5" class="st2"/><circle id="circle46" cx="768.9" cy="187.1" r="37.5" class="st2"/><circle id="circle48" cx="842.3" cy="260.5" r="37.5" class="st2"/><circle id="circle50" cx="695.5" cy="260.5" r="37.5" class="st2"/><circle id="circle52" cx="715" cy="721.3" r="27.9" class="st2"/><path id="path54" d="m 765.6,460.3 v 12.3 c 0,3 -2.2,5.5 -5.2,5.9 -25.2,3.7 -45,23.5 -48.7,48.7 -0.4,2.9 -2.9,5.1 -5.9,5.2 h -12.3 c 1.7,-39.1 33,-70.4 72.1,-72.1 z" class="st2"/><path id="path56" d="m 765.6,598.8 v 12.3 c -39.1,-1.7 -70.3,-33 -72.1,-72 h 12.3 c 3,0 5.5,2.2 5.9,5.2 3.7,25.2 23.5,45 48.7,48.7 3,0.3 5.2,2.8 5.2,5.8 z" class="st2"/><path id="path58" d="m 844.3,539 c -1.7,39.1 -33,70.3 -72.1,72 v -12.3 c 0,-3 2.2,-5.5 5.2,-5.9 25.2,-3.7 45,-23.5 48.7,-48.7 0.4,-2.9 2.9,-5.1 5.9,-5.2 z" class="st2"/><path id="path60" d="M 844.3,532.4 H 832 c -3,0 -5.5,-2.2 -5.9,-5.2 -3.7,-25.2 -23.5,-45 -48.7,-48.7 -2.9,-0.4 -5.1,-2.9 -5.2,-5.9 v -12.3 c 39.1,1.7 70.4,33 72.1,72.1 z" class="st2"/><path id="path62" d="m 844.4,535.7 c 0,1.1 0,2.2 -0.1,3.3 H 832 c -3,0 -5.5,2.2 -5.9,5.2 -3.7,25.2 -23.5,45 -48.7,48.7 -2.9,0.4 -5.1,2.9 -5.2,5.9 v 12.3 c -1.1,0.1 -2.2,0.1 -3.3,0.1 -1.1,0 -2.2,0 -3.3,-0.1 v -12.3 c 0,-3 -2.2,-5.5 -5.2,-5.9 -25.2,-3.7 -45,-23.5 -48.7,-48.7 -0.4,-2.9 -2.9,-5.1 -5.9,-5.2 h -12.3 c -0.1,-1.1 -0.1,-2.2 -0.1,-3.3 0,-1.1 0,-2.2 0.1,-3.3 h 12.3 c 3,0 5.5,-2.2 5.9,-5.2 3.7,-25.2 23.5,-45 48.7,-48.7 2.9,-0.4 5.1,-2.9 5.2,-5.9 v -12.3 c 1.1,-0.1 2.2,-0.1 3.3,-0.1 1.1,0 2.2,0 3.3,0.1 v 12.3 c 0,3 2.2,5.5 5.2,5.9 25.2,3.7 45,23.5 48.7,48.7 0.4,2.9 2.9,5.1 5.9,5.2 h 12.3 c 0,1.1 0.1,2.2 0.1,3.3 z" class="st2"/></g><path id="path72" d="m 601.6,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 742.9 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 v -79.2 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 340.1 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 V 234 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 1.06259,276.29779 1.22068,552.59764 0,828.9 -0.1,3.6 -3,6.5 -6.5,6.5 z M 593.7,65.7 c -3,0 -5.5,2.4 -5.5,5.5 V 207 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 269.7 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 157.2 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path74" d="m 618.8,858.9 h -11.3 c -0.3,0 -0.5,-0.2 -0.5,-0.5 v 0 l 0.75749,-786.429231 c 2.9e-4,-0.3 0.2,-0.5 0.5,-0.5 h 11.3 C 619.85749,71.470769 619.3,71.7 619.3,72 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -9.93686,-1 H 618.3 l 0.75749,-785.429231 h -10.3 l 1.00926,8.753045 c -0.5826,256.113716 4.51479,511.751226 -1.08804,768.299606 -0.0608,2.78307 0.24763,5.59331 0.18443,8.37658 z" class="st3" style="fill:#000"/><path id="path76" d="m 730.68234,1000.2542 h -106.2 c -3.6,0 -6.5,-2.89995 -6.5,-6.49995 V 15.754249 c 0,-3.6 2.9,-6.5000003 6.5,-6.5000003 h 106.2 c 116.8,0 211.9,95.1000013 211.9,211.9000013 v 567.2 c 0,117 -94.8,211.89995 -211.9,211.89995 0,0 0,0 0,0 z m -106.2,-989.899951 c -3,0 -5.5,2.4 -5.5,5.5 V 993.85425 c 0,3 2.4,5.5 5.5,5.5 h 106.2 c 116.3,0 210.9,-94.6 210.9,-210.9 v -567.3 c 0,-116.3 -94.6,-210.900001 -210.9,-210.900001 z" class="st3" style="fill:#000"/><path id="path128" d="m 597.9,314.3 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 v 79.5 c 0,0.7 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path id="path130" d="m 597.9,717.1 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 V 716 c 0,0.6 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#000005;stroke-width:1.00051;stroke-opacity:.956863" id="path1240" d="m 748.76734,998.67923 c 26.61833,-2.35509 50.50138,-9.19997 75.94584,-21.76611 5.0911,-2.51431 10.04483,-5.20072 14.85582,-8.05153 19.10445,-11.32055 36.26919,-27.08285 49.59754,-41.73902 25.48932,-28.02866 45.45624,-70.0817 51.37605,-116.52411 0.084,-0.65912 0.3966,-4.2662 0.37335,-6.75389 -0.0641,-6.85752 0.64519,-20.00285 0.80157,-38.33851 0.66141,-77.55489 1.0938,-244.03988 1.06613,-376.43674 -0.0211,-101.20234 -0.3111,-182.48746 -0.97305,-188.91287 -2.68737,-26.08933 -9.30087,-49.05862 -20.7698,-72.13549 C 889.27628,64.106475 828.08674,20.577545 757.0364,11.351548 745.67399,9.8761207 696.33771,9.7004055 660.43479,10.025388 c -7.73693,0.07003 -14.06771,-0.081483 -20.13516,0.05607 -7.4696,0.169301 -12.89971,-0.06855 -16.20341,0.248963 -1.72548,0.165835 -3.02594,0.790181 -3.22758,0.989913 -0.10173,0.100777 -1.42468,1.382777 -1.53437,3.347983 -0.28881,5.173999 -0.25578,17.11445 -0.43762,38.051844 -0.0367,4.233968 -0.0729,8.833333 -0.10824,13.815332 -0.035,4.930626 0.13264,10.123636 0.0992,15.820541 -0.0515,8.771897 0.12426,18.558756 0.0715,29.251086 -0.0484,9.8101 -0.24503,20.49671 0.002,32.01614 0.19247,8.97238 0.20413,18.37601 0.1562,28.43632 -0.072,15.10409 0.59165,31.14878 0.32443,48.96901 -0.22457,14.97582 0.11579,29.98781 -0.0372,46.92447 -0.10009,11.07577 0.0792,22.61567 -0.021,34.60622 -0.0602,7.20067 -0.008,14.53968 -0.0794,22.07309 -0.49593,52.10724 -0.0184,112.20821 -0.0184,180.33298 0,254.31464 -0.31499,376.10005 -0.0496,435.15254 0.0344,7.66703 -0.1971,14.45107 -0.13045,20.14913 0.0257,2.19566 -0.0445,4.29755 -0.0184,6.23195 0.0449,3.31894 -0.0346,6.64265 0.013,9.25764 0.0534,2.93004 -0.065,5.80443 -0.006,7.96224 0.13585,4.98798 0.0957,8.09705 0.27441,10.03685 0.26175,2.84095 1.26489,3.57892 1.56035,3.82606 0.21876,0.18298 1.30179,0.92883 3.07939,1.08771 4.53273,0.40514 14.55751,0.34773 27.08968,0.22654 9.86391,-0.0954 21.28116,-0.23028 32.79643,-0.21023 32.13223,0.0559 65.23405,0.25492 64.87309,-0.006 z"/><path id="path78" d="m 715,763.2 c -23.1,0 -41.9,-18.7 -41.9,-41.9 0,-23.2 18.7,-41.9 41.9,-41.9 23.2,0 41.9,18.7 41.9,41.9 v 0 c -0.1,23.1 -18.8,41.8 -41.9,41.9 z m 0,-82.8 c -22.6,0 -40.9,18.3 -40.9,40.9 0,22.6 18.3,40.9 40.9,40.9 22.6,0 40.9,-18.3 40.9,-40.9 v 0 C 755.8,698.7 737.6,680.4 715,680.4 Z" class="st3" style="fill:#000"/><path id="path88" d="m 782.2,203.2 h -5.5 L 769.05805,192.28414 761.1,203.2 h -5.4 l 10.6,-16.3 -9.8,-15.6 h 5.2 l 7.43748,10.56391 L 776.4,171.3 h 5 l -9.8,15.4 z" class="st2" style="fill:#fff;fill-opacity:1"/><path id="path90" d="m 709.2,244.5 -11.6,20.6 v 11.4 h -4.4 V 265 l -11.6,-20.5 h 5.3 l 6.4,11.7 2.08146,2.98786 L 697.8,256.6 l 6.4,-12.1 z" class="st2" style="fill:#fff"/><path id="path92" d="m 855.9,276.5 h -4.7 l -2.2,-7 -12.36339,0.32833 L 833.4,276.5 h -4.5 L 838.82682,241.29573 845.5,244.5 Z m -8.73488,-11.27058 -4.88343,-14.5941 -4.58555,14.81187 z" class="st2" style="fill:#fff"/><path id="path94" d="m 779.4,340.4 c 0,1.4 -0.3,2.8 -0.9,4.1 -0.6,1.2 -1.5,2.2 -2.5,3 -1.2,0.9 -2.6,1.5 -4,1.9 -1.7,0.4 -3.4,0.7 -5.2,0.6 h -8.4 v -32 h 9.2 c 7.1,0 10.7,2.6 10.7,7.8 0,1.6 -0.4,3.1 -1.2,4.5 -1,1.4 -1.00535,2.3267 -2.60535,2.8267 0.9,0.2 0.30535,0.3733 1.10535,0.7733 0.8,0.4 1.5,0.9 2,1.5 0.6,0.6 1.1,1.4 1.4,2.2 0.2,0.8 0.4,1.8 0.4,2.8 z m -5.7,-14.1 c 0,-0.6 -0.1,-1.3 -0.3,-1.8 -0.2,-0.6 -0.6,-1.1 -1,-1.5 -0.6,-0.5 -1.3,-0.8 -2,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 10 h 4.4 c 0.9,0 1.8,-0.1 2.7,-0.3 0.8,-0.2 1.5,-0.5 2.1,-1 0.6,-0.4 1,-1 1.3,-1.7 0.4,-0.7 0.5,-1.5 0.5,-2.3 z m 1.1,14.2 c 0,-0.8 -0.2,-1.5 -0.5,-2.2 -0.4,-0.7 -0.9,-1.2 -1.5,-1.7 -0.7,-0.5 -1.5,-0.8 -2.4,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 11 h 4.6 c 2.5,0 4.4,-0.5 5.6,-1.4 1.3,-1 2,-2.6 1.9,-4.3 z" class="st2" style="fill:#fff"/><path id="path132" d="m 925.6,139.3 c -0.1,0 -0.1,0 -0.2,0 -0.3,-0.1 -0.6,-0.3 -0.7,-0.6 C 891.7,61 815.4,10.5 730.9,10.6 h -54.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 V 7 c 0,-3.8 3.1,-6.9 7,-7 h 51.2 c 85.2,0.1 162.4,50.1 197.3,127.8 1.2,2.6 0.6,5.7 -1.5,7.8 l -3.4,3.4 c -0.2,0.2 -0.5,0.3 -0.7,0.3 z M 677.7,8.6 h 53.2 c 84.7,-0.1 161.3,50.2 195,128 l 2.4,-2.4 v 0 c 1.5,-1.4 1.9,-3.6 1.1,-5.5 C 894.8,51.7 818.3,2.1 733.9,2 h -51.2 c -2.7,0 -5,2.2 -5,5 z" class="st2" style="fill:#000"/><path id="path134" d="m 676.5,133.7 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 118 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 V 82.8 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2 -1.8,3.8 -4,3.8 z M 647.2,98.5 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 82.8 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2.2 -1.8,4 -4,4 z" class="st2" style="fill:#000"/><path id="path136" d="m 768.9,372.4 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path138" d="m 768.9,225.5 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path140" d="m 842.3,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.2 -17.2,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.1 -16.3,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path142" d="m 695.5,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.2 -17.3,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.20703,36.19743 36.40703,36.19743 C 715.50703,296.69743 732,280.7 732,260.5 731.9,240.4 715.6,224 695.5,224 Z" class="st2" style="fill:#000"/><path id="path144" d="m 715,750.2 c -16,0 -28.9,-13 -28.9,-28.9 0,-15.9 13,-28.9 28.9,-28.9 16,0 28.9,13 28.9,28.9 0,0 0,0 0,0 0,16 -12.9,28.9 -28.9,28.9 z m 0,-55.9 c -14.9,0 -26.9,12.1 -26.9,26.9 0,14.8 12.1,26.9 26.9,26.9 14.9,0 26.9,-12.1 26.9,-26.9 0,-14.8 -12,-26.8 -26.9,-26.9 z" class="st2" style="fill:#000"/><path id="path146" d="m 705.8,533.4 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st2" style="fill:#000"/><path id="path148" d="m 765.6,612.1 c 0,0 -0.1,0 0,0 -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 12.3 c -0.1,0.4 -0.6,0.9 -1.1,0.9 0,0 0,0 0,0 z m -71,-72.1 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st2" style="fill:#000"/><path id="path150" d="m 772.2,612.1 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.4,71.3 -73.1,73.1 0.1,0 0.1,0 0,0 z M 832,540 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 V 610 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st2" style="fill:#000"/><path id="path152" d="M 844.3,533.4 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1 -0.9,1.1 0,0 0,0 0,0 z m -71.1,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.1,-37.4 -32.6,-67.9 -70,-70 z" class="st2" style="fill:#000"/><path id="path154" d="m 768.9,612.2 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 H 832 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0 -2.2,0.1 -3.4,0.1 z m -2.3,-2.1 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 11.3 z" class="st2" style="fill:#000"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1462" d="m 686.27756,295.45757 c -6.3268,-1.65761 -11.32251,-3.90411 -16.49956,-9.07174 -7.7249,-7.71084 -11.28942,-16.94502 -10.84116,-27.69713 0.56274,-13.49806 8.02922,-25.02897 20.03386,-30.95782 10.51307,-5.1922 22.55435,-5.30046 32.66309,-0.26666 7.93543,3.95157 12.83197,10.03322 16.62983,17.97347 5.18792,10.84649 4.24806,24.40322 -2.39714,34.5766 -4.99743,7.65076 -13.48676,13.69608 -22.04004,15.69491 -4.81862,1.12607 -12.72306,1.01273 -17.54888,-0.25163 z m 11.6608,-24.5355 v -5.81067 l 5.62044,-9.96942 c 3.09124,-5.48319 5.62044,-10.21511 5.62044,-10.51538 0,-0.30027 -1.15454,-0.54595 -2.56564,-0.54595 h -2.56564 l -4.20029,8.09641 c -2.67942,5.1648 -4.33588,7.8298 -4.57474,7.3601 -0.20594,-0.40496 -2.13104,-4.04835 -4.27799,-8.0964 l -3.90356,-7.36011 h -2.87335 c -1.58035,0 -2.87336,0.12781 -2.87336,0.28402 0,0.1562 2.64964,4.96636 5.88808,10.68923 l 5.88809,10.40522 v 5.63681 5.63682 h 2.40876 2.40876 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1464" d="m 762.70726,222.86949 c 0,-0.31779 -3.67998,-0.84661 -5.68279,-1.60232 -2.94688,-1.11193 -5.893,-2.63216 -7.96131,-4.01553 -6.91015,-4.62179 -11.71459,-10.88088 -14.5402,-18.94258 -1.34575,-3.83954 -2.05596,-5.2027 -2.05596,-11.44945 0,-6.24676 0.71021,-7.1825 2.05596,-11.02204 3.87774,-11.0635 11.80142,-19.0577 22.76847,-22.97107 4.25097,-1.51687 5.14759,-2.2896 11.56025,-2.2896 6.41266,0 7.33188,0.77273 11.58285,2.2896 14.51853,5.18065 24.01748,17.63258 24.67097,32.86862 0.45428,10.5913 -2.7416,19.49589 -10.18797,26.91404 -7.55957,7.53093 -14.42052,10.69917 -24.62686,10.98514 -3.38565,0.0949 -6.8474,-0.62298 -7.58341,-0.76478 z m 2.38607,-25.68467 c 4.25443,-7.14961 3.37755,-7.25493 8.20926,0.98595 l 3.05431,5.20938 3.12152,0.01 3.12152,0.01 -1.22963,-2.0073 c -0.6763,-1.10401 -3.07664,-4.86619 -5.3341,-8.36039 l -4.10446,-6.35309 4.75516,-7.43514 c 2.61533,-4.08932 4.75516,-7.56602 4.75516,-7.72599 0,-0.15996 -1.24936,-0.21804 -2.77636,-0.12905 l -2.77635,0.16179 -3.10726,5.05393 c -1.70899,2.77966 -3.29562,5.24229 -3.52585,5.47251 -0.23022,0.23022 -1.93136,-2.10426 -3.78031,-5.18775 l -3.36174,-5.60633 h -2.95881 -2.95881 l 1.22685,2.0073 c 0.67476,1.10402 2.8714,4.62127 4.88142,7.81612 l 3.65457,5.80881 -4.85255,7.43415 c -2.66891,4.08878 -4.99211,7.79781 -5.16268,8.24229 -0.25287,0.65897 0.2216,0.80814 2.57051,0.80814 h 2.88063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1466" d="m 834.9366,296.44624 c -6.69858,-0.99593 -15.58735,-5.79462 -20.80585,-12.87465 -3.02683,-4.10655 -6.22101,-10.66585 -7.26537,-15.67097 -2.76322,-13.24277 2.63571,-27.85526 13.26894,-35.91309 19.99373,-15.15118 48.09433,-6.6877 56.44101,16.99918 1.86188,5.28381 2.98287,13.31429 1.68043,19.16849 -1.50813,6.77877 -4.86668,12.85647 -10.19438,18.15862 -5.26572,5.24048 -9.89475,7.95133 -16.43315,9.62357 -4.85615,1.24199 -12.03259,1.20154 -16.69163,0.50885 z m -0.17393,-23.059 1.06927,-3.3455 6.50377,-0.1501 6.50377,-0.1501 0.98735,3.36178 0.98735,3.36179 2.51591,0.16314 c 1.8243,0.1183 2.51592,-0.0335 2.51592,-0.55237 0,-0.39353 -2.29576,-7.75345 -5.10169,-16.35537 l -5.10169,-15.63986 h -3.1506 -3.1506 l -5.20854,15.65695 c -2.86469,8.61132 -5.31927,15.95804 -5.45462,16.32605 -0.17576,0.47789 0.50564,0.6691 2.38452,0.6691 h 2.6306 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1468" d="m 763.70798,369.86416 c -8.12397,-1.27623 -14.23623,-3.96267 -20.56659,-10.26395 -3.76197,-3.74468 -5.37393,-6.19207 -7.19215,-9.96045 -7.60051,-15.75262 -2.96024,-33.08108 10.77538,-44.10464 6.3567,-5.10159 13.61954,-7.5924 22.13836,-7.5924 29.9337,0 46.67982,33.83863 28.70945,58.01278 -2.79638,3.76175 -6.27683,7.45135 -10.51135,9.84091 -7.04064,3.97306 -15.70093,5.26986 -23.3531,4.06775 z m 11.20335,-21.38348 c 3.07353,-1.75995 4.52918,-4.20847 4.57675,-7.69846 0.0443,-3.24643 -1.27165,-5.85301 -3.49954,-6.93201 l -1.49389,-0.72351 1.60877,-1.54129 c 1.87307,-1.79453 2.80455,-4.70189 2.3305,-7.27407 -0.92747,-5.03237 -3.68485,-6.33408 -13.45172,-6.35026 l -7.09246,-0.0118 v 16.10974 16.10973 l 7.3601,-0.18515 c 6.6513,-0.16732 7.58173,-0.31206 9.66149,-1.50296 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1470" d="m 762.70726,326.44188 v -4.88945 l 3.72999,0.26688 c 4.16057,0.29769 6.24901,1.33706 6.7575,3.36306 0.94714,3.77369 -1.80659,6.14376 -7.14199,6.14695 l -3.3455,0.002 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1496" d="m 837.54718,264.82028 c 0,-0.76372 4.25204,-14.10124 4.62716,-14.51418 0.17889,-0.19692 1.32644,2.82483 2.55012,6.715 1.22368,3.89017 2.33144,7.35074 2.46168,7.69016 0.18748,0.48856 -0.7918,0.61711 -4.70107,0.61711 -3.25732,0 -4.93789,-0.17292 -4.93789,-0.50809 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1498" d="m 763.06218,340.74443 v -5.12084 h 3.61513 c 4.59667,0 6.58099,0.93645 7.49973,3.5393 0.55274,1.56594 0.54465,2.04231 -0.0591,3.47983 -0.97646,2.32493 -3.07062,3.22256 -7.51823,3.22256 h -3.53752 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1500" d="m 766.92321,602.64753 c -0.29048,-8.92659 -0.82524,-9.72678 -10.1321,-11.86299 -21.0747,-4.8373 -37.20457,-20.14213 -42.61333,-41.34602 -0.55002,-2.15622 -1.08744,-5.19544 -1.08744,-5.87916 0,-0.68371 -1.0064,-2.24952 -2.23643,-3.47956 l -2.34864,-1.94853 -6.86019,-0.2879 h -6.97241 v -1.97332 -1.97332 h 5.94109 c 6.60342,0 9.93688,-1.00153 11.20212,-3.36564 0.44261,-0.82703 1.50127,-3.93512 2.00022,-6.97425 2.67764,-16.30961 14.91214,-30.68661 29.48362,-37.96428 4.71573,-2.35525 11.36654,-4.65443 15.50589,-5.36038 6.61875,-1.12879 8.22218,-3.61509 8.22218,-12.74947 v -5.94109 h 1.97332 1.97332 v 6.89625 c 0,6.61611 0.0735,6.97475 1.80888,8.82901 1.46262,1.5628 3.90685,1.70471 9.49139,3.0655 20.40883,4.97306 35.28463,20.46042 40.71665,40.14848 0.78813,2.85653 1.76467,6.36883 2.17007,7.80511 1.22789,4.35011 3.85392,5.61076 11.68766,5.61076 h 6.48046 v 1.97332 1.97332 h -6.6104 c -6.95598,0 -9.89025,0.84134 -10.81193,3.1001 -0.2638,0.64649 -1.27295,4.60779 -2.13571,8.03332 -5.38972,21.39923 -21.27622,36.72039 -42.13505,41.53173 -9.94989,2.29507 -10.66202,3.14671 -10.66202,12.75068 v 6.28151 h -1.91345 -1.91345 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502-6"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1504" d="m 695.45795,526.49678 c 1.75282,-15.26781 8.92367,-31.22618 20.42144,-42.95218 11.95352,-12.1908 27.52102,-19.18005 45.72176,-21.6406 l 2.79554,-0.37793 v 6.18375 c 0,7.93282 -0.12396,8.86863 -6.84011,10.24498 -22.30129,4.57023 -41.81316,22.08888 -46.1026,44.18863 -1.7607,9.07134 -2.35691,9.12221 -11.11415,9.12221 h -5.42936 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1506" d="M 754.53008,608.24817 C 722.31091,601.3332 698.78801,575.33696 695.1389,542.61223 l -0.23838,-2.13776 h 6.36187 c 6.88754,0 6.85298,0.0191 7.74616,1.01913 1.26613,1.41754 1.51209,3.83358 2.42978,7.89599 4.79388,21.22157 24.19052,39.13835 46.58676,43.98208 6.89875,1.49203 6.3716,2.73181 6.3716,10.28576 v 5.88328 l -2.13776,-0.0463 c -1.17577,-0.0255 -4.65375,-0.58628 -7.72885,-1.24626 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1508" d="m 773.33996,603.05325 c -0.28949,-7.25738 0.97796,-8.25157 5.32662,-8.99716 4.85038,-0.83162 11.1113,-2.92244 16.31659,-5.44891 15.80304,-7.67023 27.12455,-21.98721 31.55746,-39.907 0.97744,-3.95125 1.56987,-7.24086 2.2486,-7.73716 0.71733,-0.52453 3.90303,-0.48855 7.84997,-0.48855 h 6.21369 l -0.43161,3.7822 c -3.78834,33.19719 -31.7798,61.26383 -64.82878,65.00289 l -3.98698,0.45108 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1510" d="m 828.66155,529.84176 c -1.17591,-1.07273 -1.30676,-2.96446 -2.112,-6.72672 -4.37909,-20.45999 -18.95972,-36.61709 -39.28934,-43.53733 -2.43875,-0.83016 -5.8241,-1.71782 -7.52299,-1.97259 -1.88233,-0.28227 -3.85602,-0.56229 -4.78314,-1.4894 -1.37609,-1.3761 -1.34856,-2.61232 -1.34856,-8.254 v -6.23739 l 2.46665,0.33127 c 18.99503,2.55107 32.67768,9.21103 45.44487,22.12006 10.43139,10.54728 17.44069,23.80984 20.16018,38.14583 0.547,2.88355 0.99455,6.09813 0.99455,7.14349 v 1.90066 h -5.88329 c -5.18197,0 -6.69797,-0.12032 -8.12693,-1.42388 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999999;stroke-opacity:1" id="path1512" d="m 663.62068,131.03319 c -0.53326,-0.58925 -0.625,-1.69704 -0.625,-7.54707 v -6.85645 l -1.10115,-1.23333 -1.10115,-1.23332 -7.11278,-0.10646 c -4.06806,-0.0609 -6.47681,0.46167 -7.5734,-0.16401 -1.35335,-0.7722 -0.86115,-3.06574 -0.86115,-7.62988 0,-4.68262 0.12554,-6.289149 0.5353,-6.850301 0.49015,-0.671243 1.10329,-0.741434 7.26979,-0.832236 3.70397,-0.05454 7.12214,-0.18656 7.59593,-0.293374 0.47378,-0.106815 1.19541,-0.741963 1.60361,-1.411441 0.66219,-1.086052 0.74232,-1.921972 0.74358,-7.756551 8.2e-4,-3.782617 0.16622,-6.847257 0.39235,-7.269795 0.3648,-0.681634 0.8563,-0.730476 7.35092,-0.730476 6.49462,0 6.98613,0.04884 7.35092,0.730476 0.22614,0.422538 0.39154,3.487178 0.39236,7.269795 10e-4,5.834579 0.0814,6.670499 0.74358,7.756551 0.4082,0.669478 1.12983,1.304626 1.60361,1.411441 0.47379,0.106814 3.89196,0.238833 7.59593,0.293374 6.1665,0.0908 6.77964,0.160993 7.26979,0.832236 0.40976,0.561152 0.5353,2.167681 0.5353,6.850301 0,4.82187 0.7369,7.18936 -0.88407,7.88102 -1.15658,0.4935 -3.76592,-0.14378 -7.55048,-0.0871 l -7.11278,0.10646 -1.10115,1.23332 -1.10115,1.23333 v 6.92207 c 0,6.22636 -0.0694,6.98488 -0.69062,7.54707 -0.58568,0.53003 -1.66715,0.62501 -7.11685,0.62501 -5.74601,0 -6.49238,-0.0731 -7.05124,-0.69063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.00067" id="path1514" d="m 709.8986,726.4428 v -5.25741 h 5.30749 5.20734 v 5.25741 5.25742 h -5.20734 -5.30749 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1518" d="m 709.32587,761.61376 c -14.84534,-2.33618 -27.22151,-12.34303 -32.43644,-26.22673 -7.52289,-20.0282 2.33277,-43.0312 22.02756,-51.41208 6.07171,-2.58375 7.95693,-3.52014 15.69808,-3.49043 6.50926,0.025 7.91106,0.60374 11.25868,1.62027 14.44352,4.38591 24.64194,14.87492 28.58676,29.40132 0.78714,2.89856 1.10607,5.2416 1.09829,10.74202 -0.008,5.44704 -0.33673,6.15425 -1.11435,9.04799 -4.75273,17.68623 -20.04274,29.95104 -38.0751,30.54176 -2.55811,0.0838 -5.72767,-0.0171 -7.04348,-0.22412 z m 12.01917,-11.94961 c 11.93985,-2.6283 21.26602,-13.04595 22.49006,-25.12213 2.18282,-21.53536 -18.13115,-37.7028 -38.52104,-30.65805 -4.17709,1.44319 -6.99053,3.28712 -10.81791,7.09005 -2.821,2.80297 -3.81838,4.14269 -5.32568,7.15366 -2.55937,5.1126 -3.29841,8.68914 -3.02322,14.63061 0.31524,6.80606 2.15585,11.73401 6.30752,16.88741 6.75846,8.38917 18.22621,12.36591 28.89027,10.01845 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1520" d="m 591.47251,714.31134 c -1.32743,-0.80942 -2.29002,-0.92179 -2.47367,-5.31313 -0.18144,-4.33862 0.062,-13.48601 0.062,-32.6299 0,-32.80523 -0.46981,-35.19682 0.63005,-36.25656 0.0664,-0.064 0.1032,-0.14627 0.16097,-0.21975 1.14169,-1.45141 2.68891,-2.12685 4.87199,-2.12685 h 1.91275 v 38.63637 38.63636 l -1.98864,-0.002 c -1.28887,-7.5e-4 -2.40626,-0.25607 -3.17548,-0.72512 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1522" d="m 592.87653,312.11027 c -0.50555,-0.0951 -1.32392,-0.43812 -1.8186,-0.76224 -0.77901,-0.51042 -1.53827,-0.76694 -1.82846,-2.70306 -0.48349,-3.2259 -0.1686,-11.38158 -0.1686,-35.10181 0,-19.2629 -0.52222,-28.34633 -0.3807,-32.53262 0.0922,-2.72597 0.77878,-3.23422 1.00023,-3.60909 0.93375,-1.58064 2.4287,-2.28781 4.83664,-2.28781 h 2.11959 V 273.75 312.38636 l -1.42045,-0.0516 c -0.78125,-0.0284 -1.83409,-0.1294 -2.33965,-0.22451 z"/><path style="opacity:1;fill:#000;fill-opacity:.956863;stroke:#4d4d4d;stroke-width:1" id="path1524" d="M 921.31509,126.45258 C 911.22775,105.90097 899.41123,89.210741 883.15837,72.558198 848.342,36.885643 804.48862,15.547979 753.51164,9.4762173 748.44895,8.8732107 740.43487,8.6841876 712.59008,8.5110262 L 677.96414,8.2956939 V 6.8885761 c 0,-0.9784616 0.0131,-2.9650392 1.40163,-3.6743483 l 2.12353,-1.1288295 30.378,0.2249304 c 16.92737,0.1253367 33.54939,0.2176979 37.00428,0.4846569 50.75274,3.9216602 97.06468,24.5817024 133.31418,59.4722764 17.58138,16.922285 31.48259,35.738975 42.78184,57.909488 4.28368,8.40514 4.87972,10.05538 4.25358,11.77682 -0.41652,1.14511 -2.66192,4.17147 -3.17716,4.12934 -0.14438,-0.0118 -2.24836,-4.57649 -4.72893,-9.63033 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1530" d="m 590.08186,903.77298 c -0.55877,-0.54988 -1.70743,-1.18329 -1.55645,-5.03977 0.26239,-6.70193 -0.21555,-27.16243 -0.13871,-79.12435 l 0.29646,-82.56455 2.57494,-6.44666 7.90468,-15.05275 0.10278,-39.42573 L 598.9,636.5 l -7.10988,-13.23431 -2.91024,-7.69331 -0.38184,-7.29025 0.0879,-48.02714 -0.10334,-22.13198 0.0966,-34.13422 0.0553,-10.47634 0.0117,-10.49224 -0.0696,-8.60257 0.0161,-25.57403 -0.005,-19.35155 -0.14968,-27.48393 0.0746,-21.58573 -0.0172,-11.0146 0.10416,-19.60547 -0.0482,-10.22715 0.54617,-5.68471 1.91706,-5.78584 2.96237,-5.52269 5.28838,-9.81904 V 273.28018 L 598.9,233.7 l -5.2812,-9.75149 -2.68351,-5.33049 -1.81693,-5.13665 -0.73664,-7.59716 0.23713,-13.31736 -0.12377,-12.24771 -0.0136,-11.08368 -0.0374,-10.84778 0.0307,-9.87039 0.01,-6.53596 0.018,-2.90392 0.0682,-17.39197 0.0306,-21.51034 -10e-4,-10.808249 -0.0542,-8.443665 0.017,-5.12553 -0.22211,-5.939713 2.2004,-3.055633 L 593.7,65.7 l 3.21783,0.0589 c 1.41548,0.02591 2.72523,0.05679 3.94006,0.2405 0.8633,0.130547 1.83634,0.127121 2.58513,0.398351 0.99296,0.35967 1.67802,1.018584 2.03567,1.315407 0.20827,0.172853 1.21427,1.722556 1.32566,4.747437 0.0757,2.056368 -0.0202,4.681671 -0.01,8.332014 0.0118,4.09125 0.083,9.689119 0.0361,16.361518 -0.0703,10.012523 -0.0176,23.117313 -0.0816,40.379883 -0.0488,13.18104 0.19588,28.6727 0.14409,46.98667 -0.17752,62.76594 -0.24767,157.98682 -0.2362,300.97578 l 0.0334,416.2456 -1.26287,1.82282 c -1.80326,2.60281 -12.60786,2.90243 -15.34573,0.2081 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1532" d="M 609.12095,465.08874 V 72.721096 h 4.31173 4.31173 V 465.08874 857.45638 h -4.31173 -4.31173 z"/><ellipse id="path3879" cx="714.884" cy="721.067" rx="40.267" ry="40.271" style="fill:#999595;fill-opacity:1;stroke:#000;stroke-width:2.39278;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><ellipse style="fill:#3a3d40;fill-opacity:1;stroke:#000;stroke-width:2.72654;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path3881" cx="714.948" cy="721.389" rx="34.057" ry="34.486"/><path id="path96" d="m 715,694.3 -26.77014,26.41636 h 7.64861 v 22.52766 h 38.51622 v -22.52766 h 7.23886 z m 7.78519,40.89843 h -15.16064 v -14.48207 h 15.16064 z" class="st2" style="fill:#000;stroke-width:1.35332"/></g><path id="path4136" d="m 680.8329,101.33936 h -13.19009 l -0.0372,-8.255307 h -14.10678 c -3.694,0 -4.86707,3.292534 -4.86707,8.260597 v 75.70196 c 0,3.53235 3.40852,6.31095 6.44045,6.31095 h 9.52259 c 2.5944,0 2.74434,-2.75044 3.01169,-5.11156 v -5.02502 h 13.00529 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4138" d="M 667.63443,173.06935 V 101.88171" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path4158" d="m 739.15217,56.29539 v 15.946041 h -43.5888 V 56.010642 c 0,-2.098267 1.87258,-3.045238 3.55963,-3.488308 12.17302,-3.196036 25.27663,-3.034074 36.83267,0 1.82189,0.478381 3.1965,1.676837 3.1965,3.773056 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4146" d="m 781.18551,200.84448 c 1.81167,5.59747 14.31597,16.05818 26.80398,18.49431 0,3.18475 -2.17456,7.59933 -6.67803,7.59933 h -42.94533 c -9.04439,0 -6.76848,25.30224 7.88272,25.30224 h 14.82275 c 30.79579,10.88463 58.29906,11.10676 88.35628,0 h 15.61665 c 13.60575,0 16.40685,-25.0713 7.81066,-25.0713 h -42.12588 c -6.10893,0 -8.96884,-3.67481 -8.61035,-7.40557 10.9644,-3.90513 20.75456,-9.02232 26.28159,-18.53931 v -3.53463 h -87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.97231;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4154" d="m 785.72736,197.61379 c 0,0.29572 0,7.24873 0,7.24873 0,3.02618 -2.56512,4.21618 -5.85626,4.21618 -17.73054,1.12554 -39.27177,1.0596 -57.43145,0 -3.05168,0 -6.04433,-2.08878 -6.01039,-4.32715 v -8.83908 h 69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4148" d="m 801.81755,226.83735 h 45.04178"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.1477;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4142" d="m 704.71423,192.24653 v 12.01609 c 0,1.03496 1.44365,2.19259 2.56837,2.19259 h 45.10268 c 1.41577,0 3.13375,-1.20624 3.13375,-2.67504 v -11.62115 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4150" d="m 807.6366,219.17785 h 35.76351"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.96467;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4144" d="m 931.20675,197.60063 c 0,0.29344 0,7.19268 0,7.19268 0,3.00278 -2.56501,4.18358 -5.85597,4.18358 -17.73073,1.11684 -39.27172,1.05141 -57.43168,0 -3.05166,0 -6.04429,-2.07262 -6.01013,-4.29369 v -8.77073 h 69.29778 z"/><path id="path4160" d="m 858.45697,197.63487 c 0,0.29939 0,7.33855 0,7.33855 0,3.06368 -2.56511,4.26842 -5.85601,4.26842 -17.73077,1.1395 -39.27177,1.07274 -57.4317,0 -3.05168,0 -6.0443,-2.11465 -6.01014,-4.38077 v -8.9486 h 69.29785 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.9845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4140" d="m 968.76047,199.65348 c 8.52966,0 24.99089,-16.61076 24.99089,-25.55625 v -58.65862 c -4.57443,-17.00507 -13.35533,-35.478328 -41.84537,-41.00408 -4.97535,0 -7.55529,-4.593593 -7.55529,-7.403519 C 917.38071,31.981408 888.09597,13.94394 858.0448,1.5383817 H 794.40512 C 767.03205,13.564651 751.77061,31.525124 739.77382,51.084979 v 10.820524 c 0,4.466942 -3.77561,9.112021 -8.71777,9.112021 H 678.16828 V 199.72479 Z" style="fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path4166" d="M 959.74418,95.578426 H 732.35325 C 732.47179,49.183575 755.75521,1.15062 800.53245,1.15062 l 63.60853,0.7464785 c 62.27359,11.1330875 75.07205,54.9622645 95.6032,93.6813275 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4168" d="M 978.40756,126.18349 H 730.44883 v 27.99243 c 0,9.45565 12.31669,23.51364 23.99616,23.51364 h 207.96534 c 12.6963,0 22.09152,-12.0229 22.09152,-21.64746 0,-11.5947 1.02012,-29.85861 -6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4232" d="m 815.30427,152.06817 v -10.42123 l 4.83314,5.9e-4 c 2.65811,3.3e-4 5.22066,0.0205 5.69422,0.0424 2.06412,0.0999 3.36854,0.38224 4.26309,0.92274 1.37392,0.83011 2.28986,2.29536 2.52187,4.03406 0.0698,0.53061 0.0278,1.70342 -0.0814,2.19391 -0.3657,1.6476 -1.32187,2.879 -2.82086,3.63292 -0.57443,0.2889 -1.45224,0.5764 -2.13805,0.70022 -0.28454,0.0512 -0.51679,0.1037 -0.51608,0.11614 6.8e-4,0.0137 0.15343,0.11316 0.3387,0.22298 0.59653,0.35375 1.21864,0.8364 1.75031,1.3583 0.86316,0.8471 1.40854,1.61519 3.70213,5.21324 0.77646,1.21827 1.44017,2.25774 1.4746,2.30996 l 0.0626,0.0949 h -2.53768 -2.53792 l -1.69473,-2.47872 c -3.18932,-4.66409 -3.60893,-5.21082 -4.38563,-5.71206 -0.59814,-0.38608 -1.12447,-0.49152 -2.64298,-0.52955 l -1.02243,-0.0258 v 4.37299 4.37295 h -2.13132 -2.13132 v -10.42122 z m 10.52829,-1.70253 c 0.90687,-0.11613 1.36601,-0.31747 1.80747,-0.79267 0.44566,-0.47955 0.62444,-0.99717 0.62444,-1.80829 0,-1.12302 -0.42359,-1.86219 -1.30232,-2.27314 -0.68255,-0.31921 -0.57259,-0.31053 -4.17686,-0.33119 l -3.21837,-0.0182 v 2.66568 2.66571 l 2.87406,-0.0205 c 2.26803,-0.0161 2.98311,-0.0346 3.39158,-0.087 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4234" d="M 824.38936,52.916016 V 42.513284 l 5.50031,0.01822 c 5.86555,0.01821 5.99551,0.02347 7.21251,0.236844 0.72764,0.127791 1.2063,0.273954 1.73262,0.529704 0.56119,0.272632 0.92919,0.536857 1.3444,0.965169 0.6865,0.708209 1.17119,1.612413 1.4232,2.655056 0.10465,0.436493 0.11392,0.546291 0.11623,1.401798 6.9e-4,0.725362 -0.0233,1.008267 -0.0743,1.294521 -0.49307,2.372679 -2.15713,3.863382 -4.92053,4.408664 -0.52052,0.102747 -0.58004,0.12279 -0.5089,0.173128 0.044,0.0312 0.27805,0.18384 0.51935,0.338992 1.26535,0.81414 2.04879,1.63119 3.24347,3.383274 0.43519,0.6382 3.38993,5.242662 3.43201,5.348069 0.0233,0.04234 -0.49075,0.05101 -2.51118,0.04215 l -2.53257,-0.0114 -1.89628,-2.766293 c -2.70088,-3.939608 -3.00426,-4.356325 -3.57776,-4.912496 -0.79112,-0.767048 -1.35952,-0.94266 -3.17329,-0.980344 L 828.653,54.61555 v 4.3512 4.351165 h -2.13132 -2.13131 v -10.4027 z m 10.29044,-1.663034 c 0.70021,-0.07582 1.02521,-0.153763 1.4046,-0.337001 0.60955,-0.294507 1.03662,-0.843043 1.20307,-1.545677 0.0907,-0.379282 0.0884,-1.172853 -0.002,-1.51464 -0.27525,-1.037227 -1.09727,-1.677094 -2.30428,-1.793635 -0.22549,-0.02279 -1.74122,-0.03988 -3.36922,-0.04055 l -2.96011,-0.0016 v 2.663058 2.663038 l 2.78783,-0.02279 c 1.66078,-0.01369 2.97079,-0.0419 3.23998,-0.07107 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4236" d="m 804.36779,61.4392 v -1.87954 l 5.57588,-6.748973 c 3.06678,-3.711938 5.57589,-6.758273 5.57589,-6.769663 0,-0.0114 -2.22827,-0.02049 -4.95147,-0.02049 h -4.95146 v -1.750915 -1.750941 h 7.7716 7.77183 v 1.614195 1.614171 l -5.83789,7.045572 -5.83763,7.045547 6.05291,0.0114 6.05316,0.0114 v 1.729694 1.729685 h -8.6113 -8.61152 v -1.879513 z"/><path id="path489" d="m 314.06908,101.33936 h 13.19009 l 0.0372,-8.255307 h 14.10678 c 3.694,0 4.86707,3.292534 4.86707,8.260597 v 75.70196 c 0,3.53235 -3.40852,6.31095 -6.44045,6.31095 h -9.52259 c -2.5944,0 -2.74434,-2.75044 -3.01169,-5.11156 v -5.02502 H 314.2902 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path491" d="M 327.26755,173.06935 V 101.88171" style="fill:#4d4d4d;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path493" d="m 255.74981,56.29539 v 15.946041 h 43.5888 V 56.010642 c 0,-2.098267 -1.87258,-3.045238 -3.55963,-3.488308 -12.17302,-3.196036 -25.27663,-3.034074 -36.83267,0 -1.82189,0.478381 -3.1965,1.676837 -3.1965,3.773056 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path495" d="m 213.71647,200.68211 c -1.81167,5.3094 -14.31597,15.23177 -26.80398,17.54252 0,3.02085 2.17456,7.20824 6.67803,7.20824 h 42.94533 c 9.04439,0 6.76848,24.00009 -7.88272,24.00009 h -14.82275 c -30.79579,10.32445 -58.29906,10.53516 -88.35628,0 h -15.61665 c -13.60575,0 -16.40685,-23.78104 -7.81066,-23.78104 h 42.12588 c 6.10893,0 8.96884,-3.48568 8.61035,-7.02445 -10.9644,-3.70415 -20.75456,-8.55799 -26.28159,-17.58519 v -3.35273 h 87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84474px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path497" d="m 209.17462,197.4005 c 0,0.25865 0,6.33998 0,6.33998 0,2.6468 2.56512,3.68761 5.85626,3.68761 17.73054,0.98444 39.27177,0.92676 57.43145,0 3.05168,0 6.04433,-1.82692 6.01039,-3.78467 v -7.73095 h -69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path499" d="M 193.08443,225.33728 H 148.04265"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.4781px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path501" d="m 290.50058,191.92715 v 11.14596 c 0,0.96002 -0.73701,2.03381 -1.3112,2.03381 h -23.02573 c -0.72278,0 -1.59984,-1.11889 -1.59984,-2.48132 v -10.77963 z"/><path style="fill:none;stroke:#000;stroke-width:2.09975px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path503" d="M 187.26538,218.07198 H 151.50187"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.84684px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path505" d="m 63.69523,197.40389 c 0,0.25924 0,6.35443 0,6.35443 0,2.65284 2.56501,3.69602 5.85597,3.69602 17.73073,0.98669 39.27172,0.92888 57.43168,0 3.05166,0 6.04429,-1.83107 6.01013,-3.7933 v -7.74857 H 63.69523 Z"/><path id="path509" d="m 26.14151,199.65348 c -8.52966,0 -24.99089,-16.61076 -24.99089,-25.55625 V 115.43861 C 5.72505,98.43354 14.50595,79.960282 42.99599,74.43453 c 4.97535,0 7.55529,-4.593593 7.55529,-7.403519 26.96999,-35.049603 56.25473,-53.087071 86.3059,-65.4926293 h 63.63968 c 27.37307,12.0262693 42.63451,29.9867423 54.6313,49.5465973 v 10.820524 c 0,4.466942 3.77561,9.112021 8.71777,9.112021 H 316.7337 V 199.72479 Z" style="fill:#00bbdb;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path511" d="M 35.1578,95.578426 H 262.54873 C 262.43019,49.183575 239.14677,1.15062 194.36953,1.15062 L 130.761,1.8970985 C 68.48741,13.030186 55.68895,56.859363 35.1578,95.578426 Z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path513" d="m 16.49442,126.18349 h 247.95873 v 27.99243 c 0,9.45565 -12.31669,23.51364 -23.99616,23.51364 H 32.49165 c -12.6963,0 -22.09152,-12.0229 -22.09152,-21.64746 0,-11.5947 -1.02012,-29.85861 6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path519" d="m 151.49179,61.4392 v -1.87954 l 5.57588,-6.748973 c 3.06678,-3.711938 5.57589,-6.758273 5.57589,-6.769663 0,-0.0114 -2.22827,-0.02049 -4.95147,-0.02049 h -4.95146 v -1.750915 -1.750941 h 7.7716 7.77183 v 1.614195 1.614171 l -5.83789,7.045572 -5.83763,7.045547 6.05291,0.0114 6.05316,0.0114 v 1.729694 1.729685 h -8.6113 -8.61152 v -1.879513 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0335108;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4218" d="M 171.52526,52.970786 V 42.611364 h 2.62547 2.62545 v 8.607904 8.607907 h 6.5824 6.58243 v 1.751518 1.751517 h -9.20788 -9.20787 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0325267;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4220" d="m 162.42612,152.06817 v -10.42336 h 2.45836 2.45836 v 8.66103 8.66102 h 6.16349 6.16346 v 1.76236 1.76232 h -8.62185 -8.62182 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path979" d="m 724.21326,200.03615 v 6.10386 h 9.9129 V 199.759 Z"/></g></svg>
\ No newline at end of file diff --git a/src/Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg b/src/Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg new file mode 100644 index 00000000..f4f12514 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Controller_JoyConRight.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" id="Layer_1" width="1000.8" height="1300" x="0" y="0" version="1.1" viewBox="0 0 1000.8 1300" xml:space="preserve"><metadata id="metadata85"/><style id="style2" type="text/css">.st0{opacity:.1}.st2{fill:#fff}</style><style id="style2-6" type="text/css">.st0{opacity:.1}.st2{fill:#ff5f55}.st3{fill:#fff}</style><path style="fill:#ff5f53;fill-opacity:1;stroke-width:.176777" id="path139" d="m 336.48913,612.01334 c -4.48491,-0.96172 -17.26511,-2.20937 -14.21934,-5.20076 l -1.59612,-5.33256 4.69156,-28.97943 c -21.87609,0.35049 0.88574,-29.59975 1.14094,-31.15228 0.67186,-4.0867 0.63712,-6.98639 4.0089,-9.33254 4.31967,-3.0057 6.13876,-6.05239 15.39769,-6.04934 6.18575,0.002 6.23657,4.51842 7.63527,4.8094 2.83752,0.59027 9.26915,0.22171 11.12017,2.22098 1.29357,1.39718 -1.70326,4.54462 -1.05568,6.52843 l 0.45372,1.38995 3.01931,28.03144 c 2.5809,23.96121 -1.28772,28.6331 -1.52389,30.69067 -0.50713,4.41767 -1.36999,7.75168 -2.71808,9.24386 -0.75196,0.83233 -6.13557,2.17746 -7.4235,2.75447 -0.6956,0.31163 -1.65288,2.59566 -4.83555,2.70854 -6.19176,0.21959 -12.78623,-2.05009 -14.09542,-2.33083 z m 7.03011,-22.69305 c 2.05969,-1.10868 2.82647,-2.34895 4.0826,-6.60361 0.94044,-3.18536 1.27937,-3.92467 2.00093,-4.36459 0.80192,-0.48891 1.26549,-0.45046 1.96409,0.16291 0.71152,0.62473 1.00895,1.51574 1.00895,3.02259 0,1.56253 -0.45686,2.45036 -1.57367,3.05821 -0.47337,0.25764 -0.98442,0.46843 -1.13567,0.46843 -0.46699,0 -0.51735,0.31657 -0.38564,2.42443 l 0.12741,2.03924 0.99608,-0.11707 c 1.81227,-0.21299 3.67586,-1.28059 4.58801,-2.62833 0.73213,-1.08177 1.05118,-2.01238 1.28038,-3.73464 0.52157,-3.91942 -0.80021,-7.14962 -3.48153,-8.50821 -0.95096,-0.48184 -1.18331,-0.52396 -2.89025,-0.52396 -1.61522,0 -1.95941,0.0547 -2.65165,0.42127 -2.42724,1.2854 -3.01034,2.27706 -4.76741,8.10775 -0.81484,2.70397 -1.68257,3.5027 -3.32487,3.06047 -0.81096,-0.21836 -1.7952,-1.15122 -2.09882,-1.98922 -0.27463,-0.75801 -0.29371,-2.48144 -0.0369,-3.33844 0.11098,-0.37041 0.44343,-0.96663 0.73878,-1.32494 0.5549,-0.6732 2.03724,-1.48499 2.71713,-1.48802 0.21302,-8.8e-4 0.44057,-0.0879 0.50566,-0.19321 0.0651,-0.10531 0.0206,-1.09911 -0.0989,-2.20844 l -0.21726,-2.01697 -0.73033,0.1088 c -1.04346,0.15545 -2.73301,0.73031 -3.56485,1.21291 -1.00575,0.5835 -2.3307,2.05885 -2.82441,3.14502 -0.60372,1.32822 -0.8601,3.09117 -0.73888,5.08087 0.2291,3.76062 1.69285,6.01606 4.59237,7.07626 0.73645,0.26928 1.31213,0.32792 2.86609,0.29196 1.83004,-0.0424 2.0098,-0.0801 3.05264,-0.64147 z m 12.41532,-19.9635 v -2.27241 l -4.3514,-0.0924 c -4.61309,-0.098 -4.53528,-0.082 -4.77362,-0.9766 -0.38253,-1.43579 0.87656,-2.86072 4.54388,-5.14234 1.30429,-0.81146 2.86862,-1.78392 3.47629,-2.16102 l 1.10485,-0.68564 v -2.47936 c 0,-1.37252 -0.0718,-2.47937 -0.16095,-2.47937 -0.2065,0 -2.12366,1.07629 -5.14235,2.88691 -1.67092,1.00223 -2.71254,1.76796 -3.47394,2.55381 l -1.08745,1.12238 -0.2181,-0.6741 c -0.55224,-1.70685 -1.65782,-3.08363 -3.04416,-3.79088 -0.90425,-0.46132 -2.76434,-0.67068 -4.28507,-0.4823 -2.32805,0.28839 -4.02881,1.54469 -4.62261,3.41459 -0.2868,0.90314 -0.54591,5.91584 -0.57837,11.18885 l -0.0144,2.34229 h 11.3137 11.31371 z"/><g id="g315" transform="translate(0,300.03245)"><g id="g64" class="st0"><path id="path36" d="m 597.9,233.9 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path38" d="m 597.9,636.6 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z" class="st2"/><path id="path40" d="m 929,134.9 -3.4,3.4 C 892.4,60.3 815.8,9.6 730.9,9.6 H 676.7 V 7 c 0,-3.3 2.7,-6 6,-6 0,0 0,0 0,0 h 51.2 c 84.8,0 161.7,49.8 196.4,127.2 1,2.3 0.5,4.9 -1.3,6.7 z" class="st2"/><path id="path42" d="M 679.5,94.5 V 82.8 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 -1.3,3 -3,3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,1.3 3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 v 0 -11.7 c 0,-1.6 1.3,-3 3,-3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 0,0 0,0 0,0 v -11.7 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.7,0 -3,-1.4 -3,-3 0,0 0,0 0,0 z" class="st2"/><circle id="circle44" cx="768.9" cy="333.9" r="37.5" class="st2"/><circle id="circle46" cx="768.9" cy="187.1" r="37.5" class="st2"/><circle id="circle48" cx="842.3" cy="260.5" r="37.5" class="st2"/><circle id="circle50" cx="695.5" cy="260.5" r="37.5" class="st2"/><circle id="circle52" cx="715" cy="721.3" r="27.9" class="st2"/><path id="path54" d="m 765.6,460.3 v 12.3 c 0,3 -2.2,5.5 -5.2,5.9 -25.2,3.7 -45,23.5 -48.7,48.7 -0.4,2.9 -2.9,5.1 -5.9,5.2 h -12.3 c 1.7,-39.1 33,-70.4 72.1,-72.1 z" class="st2"/><path id="path56" d="m 765.6,598.8 v 12.3 c -39.1,-1.7 -70.3,-33 -72.1,-72 h 12.3 c 3,0 5.5,2.2 5.9,5.2 3.7,25.2 23.5,45 48.7,48.7 3,0.3 5.2,2.8 5.2,5.8 z" class="st2"/><path id="path58" d="m 844.3,539 c -1.7,39.1 -33,70.3 -72.1,72 v -12.3 c 0,-3 2.2,-5.5 5.2,-5.9 25.2,-3.7 45,-23.5 48.7,-48.7 0.4,-2.9 2.9,-5.1 5.9,-5.2 z" class="st2"/><path id="path60" d="M 844.3,532.4 H 832 c -3,0 -5.5,-2.2 -5.9,-5.2 -3.7,-25.2 -23.5,-45 -48.7,-48.7 -2.9,-0.4 -5.1,-2.9 -5.2,-5.9 v -12.3 c 39.1,1.7 70.4,33 72.1,72.1 z" class="st2"/><path id="path62" d="m 844.4,535.7 c 0,1.1 0,2.2 -0.1,3.3 H 832 c -3,0 -5.5,2.2 -5.9,5.2 -3.7,25.2 -23.5,45 -48.7,48.7 -2.9,0.4 -5.1,2.9 -5.2,5.9 v 12.3 c -1.1,0.1 -2.2,0.1 -3.3,0.1 -1.1,0 -2.2,0 -3.3,-0.1 v -12.3 c 0,-3 -2.2,-5.5 -5.2,-5.9 -25.2,-3.7 -45,-23.5 -48.7,-48.7 -0.4,-2.9 -2.9,-5.1 -5.9,-5.2 h -12.3 c -0.1,-1.1 -0.1,-2.2 -0.1,-3.3 0,-1.1 0,-2.2 0.1,-3.3 h 12.3 c 3,0 5.5,-2.2 5.9,-5.2 3.7,-25.2 23.5,-45 48.7,-48.7 2.9,-0.4 5.1,-2.9 5.2,-5.9 v -12.3 c 1.1,-0.1 2.2,-0.1 3.3,-0.1 1.1,0 2.2,0 3.3,0.1 v 12.3 c 0,3 2.2,5.5 5.2,5.9 25.2,3.7 45,23.5 48.7,48.7 0.4,2.9 2.9,5.1 5.9,5.2 h 12.3 c 0,1.1 0.1,2.2 0.1,3.3 z" class="st2"/></g><path id="path72" d="m 601.6,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 742.9 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 v -79.2 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 340.1 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 V 234 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 1.06259,276.29779 1.22068,552.59764 0,828.9 -0.1,3.6 -3,6.5 -6.5,6.5 z M 593.7,65.7 c -3,0 -5.5,2.4 -5.5,5.5 V 207 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 269.7 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 157.2 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z" class="st3" style="fill:#000"/><path id="path74" d="m 618.8,858.9 h -11.3 c -0.3,0 -0.5,-0.2 -0.5,-0.5 v 0 l 0.75749,-786.429231 c 2.9e-4,-0.3 0.2,-0.5 0.5,-0.5 h 11.3 C 619.85749,71.470769 619.3,71.7 619.3,72 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -9.93686,-1 H 618.3 l 0.75749,-785.429231 h -10.3 l 1.00926,8.753045 c -0.5826,256.113716 4.51479,511.751226 -1.08804,768.299606 -0.0608,2.78307 0.24763,5.59331 0.18443,8.37658 z" class="st3" style="fill:#000"/><path id="path76" d="m 730.68234,1000.2542 h -106.2 c -3.6,0 -6.5,-2.89995 -6.5,-6.49995 V 15.754249 c 0,-3.6 2.9,-6.5000003 6.5,-6.5000003 h 106.2 c 116.8,0 211.9,95.1000013 211.9,211.9000013 v 567.2 c 0,117 -94.8,211.89995 -211.9,211.89995 0,0 0,0 0,0 z m -106.2,-989.899951 c -3,0 -5.5,2.4 -5.5,5.5 V 993.85425 c 0,3 2.4,5.5 5.5,5.5 h 106.2 c 116.3,0 210.9,-94.6 210.9,-210.9 v -567.3 c 0,-116.3 -94.6,-210.900001 -210.9,-210.900001 z" class="st3" style="fill:#000"/><path id="path128" d="m 597.9,314.3 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 v 79.5 c 0,0.7 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path id="path130" d="m 597.9,717.1 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 V 716 c 0,0.6 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z" class="st2" style="fill:#000"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#000005;stroke-width:1.00051;stroke-opacity:.956863" id="path1240" d="m 748.76734,998.67923 c 26.61833,-2.35509 50.50138,-9.19997 75.94584,-21.76611 5.0911,-2.51431 10.04483,-5.20072 14.85582,-8.05153 19.10445,-11.32055 36.26919,-27.08285 49.59754,-41.73902 25.48932,-28.02866 45.45624,-70.0817 51.37605,-116.52411 0.084,-0.65912 0.3966,-4.2662 0.37335,-6.75389 -0.0641,-6.85752 0.64519,-20.00285 0.80157,-38.33851 0.66141,-77.55489 1.0938,-244.03988 1.06613,-376.43674 -0.0211,-101.20234 -0.3111,-182.48746 -0.97305,-188.91287 -2.68737,-26.08933 -9.30087,-49.05862 -20.7698,-72.13549 C 889.27628,64.106475 828.08674,20.577545 757.0364,11.351548 745.67399,9.8761207 696.33771,9.7004055 660.43479,10.025388 c -7.73693,0.07003 -14.06771,-0.081483 -20.13516,0.05607 -7.4696,0.169301 -12.89971,-0.06855 -16.20341,0.248963 -1.72548,0.165835 -3.02594,0.790181 -3.22758,0.989913 -0.10173,0.100777 -1.42468,1.382777 -1.53437,3.347983 -0.28881,5.173999 -0.25578,17.11445 -0.43762,38.051844 -0.0367,4.233968 -0.0729,8.833333 -0.10824,13.815332 -0.035,4.930626 0.13264,10.123636 0.0992,15.820541 -0.0515,8.771897 0.12426,18.558756 0.0715,29.251086 -0.0484,9.8101 -0.24503,20.49671 0.002,32.01614 0.19247,8.97238 0.20413,18.37601 0.1562,28.43632 -0.072,15.10409 0.59165,31.14878 0.32443,48.96901 -0.22457,14.97582 0.11579,29.98781 -0.0372,46.92447 -0.10009,11.07577 0.0792,22.61567 -0.021,34.60622 -0.0602,7.20067 -0.008,14.53968 -0.0794,22.07309 -0.49593,52.10724 -0.0184,112.20821 -0.0184,180.33298 0,254.31464 -0.31499,376.10005 -0.0496,435.15254 0.0344,7.66703 -0.1971,14.45107 -0.13045,20.14913 0.0257,2.19566 -0.0445,4.29755 -0.0184,6.23195 0.0449,3.31894 -0.0346,6.64265 0.013,9.25764 0.0534,2.93004 -0.065,5.80443 -0.006,7.96224 0.13585,4.98798 0.0957,8.09705 0.27441,10.03685 0.26175,2.84095 1.26489,3.57892 1.56035,3.82606 0.21876,0.18298 1.30179,0.92883 3.07939,1.08771 4.53273,0.40514 14.55751,0.34773 27.08968,0.22654 9.86391,-0.0954 21.28116,-0.23028 32.79643,-0.21023 32.13223,0.0559 65.23405,0.25492 64.87309,-0.006 z"/><path id="path78" d="m 715,763.2 c -23.1,0 -41.9,-18.7 -41.9,-41.9 0,-23.2 18.7,-41.9 41.9,-41.9 23.2,0 41.9,18.7 41.9,41.9 v 0 c -0.1,23.1 -18.8,41.8 -41.9,41.9 z m 0,-82.8 c -22.6,0 -40.9,18.3 -40.9,40.9 0,22.6 18.3,40.9 40.9,40.9 22.6,0 40.9,-18.3 40.9,-40.9 v 0 C 755.8,698.7 737.6,680.4 715,680.4 Z" class="st3" style="fill:#000"/><path id="path88" d="m 782.2,203.2 h -5.5 L 769.05805,192.28414 761.1,203.2 h -5.4 l 10.6,-16.3 -9.8,-15.6 h 5.2 l 7.43748,10.56391 L 776.4,171.3 h 5 l -9.8,15.4 z" class="st2" style="fill:#fff;fill-opacity:1"/><path id="path90" d="m 709.2,244.5 -11.6,20.6 v 11.4 h -4.4 V 265 l -11.6,-20.5 h 5.3 l 6.4,11.7 2.08146,2.98786 L 697.8,256.6 l 6.4,-12.1 z" class="st2" style="fill:#fff"/><path id="path92" d="m 855.9,276.5 h -4.7 l -2.2,-7 -12.36339,0.32833 L 833.4,276.5 h -4.5 L 838.82682,241.29573 845.5,244.5 Z m -8.73488,-11.27058 -4.88343,-14.5941 -4.58555,14.81187 z" class="st2" style="fill:#fff"/><path id="path94" d="m 779.4,340.4 c 0,1.4 -0.3,2.8 -0.9,4.1 -0.6,1.2 -1.5,2.2 -2.5,3 -1.2,0.9 -2.6,1.5 -4,1.9 -1.7,0.4 -3.4,0.7 -5.2,0.6 h -8.4 v -32 h 9.2 c 7.1,0 10.7,2.6 10.7,7.8 0,1.6 -0.4,3.1 -1.2,4.5 -1,1.4 -1.00535,2.3267 -2.60535,2.8267 0.9,0.2 0.30535,0.3733 1.10535,0.7733 0.8,0.4 1.5,0.9 2,1.5 0.6,0.6 1.1,1.4 1.4,2.2 0.2,0.8 0.4,1.8 0.4,2.8 z m -5.7,-14.1 c 0,-0.6 -0.1,-1.3 -0.3,-1.8 -0.2,-0.6 -0.6,-1.1 -1,-1.5 -0.6,-0.5 -1.3,-0.8 -2,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 10 h 4.4 c 0.9,0 1.8,-0.1 2.7,-0.3 0.8,-0.2 1.5,-0.5 2.1,-1 0.6,-0.4 1,-1 1.3,-1.7 0.4,-0.7 0.5,-1.5 0.5,-2.3 z m 1.1,14.2 c 0,-0.8 -0.2,-1.5 -0.5,-2.2 -0.4,-0.7 -0.9,-1.2 -1.5,-1.7 -0.7,-0.5 -1.5,-0.8 -2.4,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 11 h 4.6 c 2.5,0 4.4,-0.5 5.6,-1.4 1.3,-1 2,-2.6 1.9,-4.3 z" class="st2" style="fill:#fff"/><path id="path132" d="m 925.6,139.3 c -0.1,0 -0.1,0 -0.2,0 -0.3,-0.1 -0.6,-0.3 -0.7,-0.6 C 891.7,61 815.4,10.5 730.9,10.6 h -54.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 V 7 c 0,-3.8 3.1,-6.9 7,-7 h 51.2 c 85.2,0.1 162.4,50.1 197.3,127.8 1.2,2.6 0.6,5.7 -1.5,7.8 l -3.4,3.4 c -0.2,0.2 -0.5,0.3 -0.7,0.3 z M 677.7,8.6 h 53.2 c 84.7,-0.1 161.3,50.2 195,128 l 2.4,-2.4 v 0 c 1.5,-1.4 1.9,-3.6 1.1,-5.5 C 894.8,51.7 818.3,2.1 733.9,2 h -51.2 c -2.7,0 -5,2.2 -5,5 z" class="st2" style="fill:#000"/><path id="path134" d="m 676.5,133.7 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 118 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 V 82.8 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2 -1.8,3.8 -4,3.8 z M 647.2,98.5 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 82.8 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2.2 -1.8,4 -4,4 z" class="st2" style="fill:#000"/><path id="path136" d="m 768.9,372.4 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path138" d="m 768.9,225.5 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path140" d="m 842.3,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.2 -17.2,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.1 -16.3,-36.5 -36.5,-36.5 z" class="st2" style="fill:#000"/><path id="path142" d="m 695.5,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.2 -17.3,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.20703,36.19743 36.40703,36.19743 C 715.50703,296.69743 732,280.7 732,260.5 731.9,240.4 715.6,224 695.5,224 Z" class="st2" style="fill:#000"/><path id="path144" d="m 715,750.2 c -16,0 -28.9,-13 -28.9,-28.9 0,-15.9 13,-28.9 28.9,-28.9 16,0 28.9,13 28.9,28.9 0,0 0,0 0,0 0,16 -12.9,28.9 -28.9,28.9 z m 0,-55.9 c -14.9,0 -26.9,12.1 -26.9,26.9 0,14.8 12.1,26.9 26.9,26.9 14.9,0 26.9,-12.1 26.9,-26.9 0,-14.8 -12,-26.8 -26.9,-26.9 z" class="st2" style="fill:#000"/><path id="path146" d="m 705.8,533.4 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z" class="st2" style="fill:#000"/><path id="path148" d="m 765.6,612.1 c 0,0 -0.1,0 0,0 -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 12.3 c -0.1,0.4 -0.6,0.9 -1.1,0.9 0,0 0,0 0,0 z m -71,-72.1 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z" class="st2" style="fill:#000"/><path id="path150" d="m 772.2,612.1 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.4,71.3 -73.1,73.1 0.1,0 0.1,0 0,0 z M 832,540 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 V 610 c 37.4,-2.2 67.8,-32.6 70,-70 z" class="st2" style="fill:#000"/><path id="path152" d="M 844.3,533.4 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1 -0.9,1.1 0,0 0,0 0,0 z m -71.1,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.1,-37.4 -32.6,-67.9 -70,-70 z" class="st2" style="fill:#000"/><path id="path154" d="m 768.9,612.2 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 H 832 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0 -2.2,0.1 -3.4,0.1 z m -2.3,-2.1 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 11.3 z" class="st2" style="fill:#000"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1462" d="m 686.27756,295.45757 c -6.3268,-1.65761 -11.32251,-3.90411 -16.49956,-9.07174 -7.7249,-7.71084 -11.28942,-16.94502 -10.84116,-27.69713 0.56274,-13.49806 8.02922,-25.02897 20.03386,-30.95782 10.51307,-5.1922 22.55435,-5.30046 32.66309,-0.26666 7.93543,3.95157 12.83197,10.03322 16.62983,17.97347 5.18792,10.84649 4.24806,24.40322 -2.39714,34.5766 -4.99743,7.65076 -13.48676,13.69608 -22.04004,15.69491 -4.81862,1.12607 -12.72306,1.01273 -17.54888,-0.25163 z m 11.6608,-24.5355 v -5.81067 l 5.62044,-9.96942 c 3.09124,-5.48319 5.62044,-10.21511 5.62044,-10.51538 0,-0.30027 -1.15454,-0.54595 -2.56564,-0.54595 h -2.56564 l -4.20029,8.09641 c -2.67942,5.1648 -4.33588,7.8298 -4.57474,7.3601 -0.20594,-0.40496 -2.13104,-4.04835 -4.27799,-8.0964 l -3.90356,-7.36011 h -2.87335 c -1.58035,0 -2.87336,0.12781 -2.87336,0.28402 0,0.1562 2.64964,4.96636 5.88808,10.68923 l 5.88809,10.40522 v 5.63681 5.63682 h 2.40876 2.40876 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1464" d="m 762.70726,222.86949 c 0,-0.31779 -3.67998,-0.84661 -5.68279,-1.60232 -2.94688,-1.11193 -5.893,-2.63216 -7.96131,-4.01553 -6.91015,-4.62179 -11.71459,-10.88088 -14.5402,-18.94258 -1.34575,-3.83954 -2.05596,-5.2027 -2.05596,-11.44945 0,-6.24676 0.71021,-7.1825 2.05596,-11.02204 3.87774,-11.0635 11.80142,-19.0577 22.76847,-22.97107 4.25097,-1.51687 5.14759,-2.2896 11.56025,-2.2896 6.41266,0 7.33188,0.77273 11.58285,2.2896 14.51853,5.18065 24.01748,17.63258 24.67097,32.86862 0.45428,10.5913 -2.7416,19.49589 -10.18797,26.91404 -7.55957,7.53093 -14.42052,10.69917 -24.62686,10.98514 -3.38565,0.0949 -6.8474,-0.62298 -7.58341,-0.76478 z m 2.38607,-25.68467 c 4.25443,-7.14961 3.37755,-7.25493 8.20926,0.98595 l 3.05431,5.20938 3.12152,0.01 3.12152,0.01 -1.22963,-2.0073 c -0.6763,-1.10401 -3.07664,-4.86619 -5.3341,-8.36039 l -4.10446,-6.35309 4.75516,-7.43514 c 2.61533,-4.08932 4.75516,-7.56602 4.75516,-7.72599 0,-0.15996 -1.24936,-0.21804 -2.77636,-0.12905 l -2.77635,0.16179 -3.10726,5.05393 c -1.70899,2.77966 -3.29562,5.24229 -3.52585,5.47251 -0.23022,0.23022 -1.93136,-2.10426 -3.78031,-5.18775 l -3.36174,-5.60633 h -2.95881 -2.95881 l 1.22685,2.0073 c 0.67476,1.10402 2.8714,4.62127 4.88142,7.81612 l 3.65457,5.80881 -4.85255,7.43415 c -2.66891,4.08878 -4.99211,7.79781 -5.16268,8.24229 -0.25287,0.65897 0.2216,0.80814 2.57051,0.80814 h 2.88063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1466" d="m 834.9366,296.44624 c -6.69858,-0.99593 -15.58735,-5.79462 -20.80585,-12.87465 -3.02683,-4.10655 -6.22101,-10.66585 -7.26537,-15.67097 -2.76322,-13.24277 2.63571,-27.85526 13.26894,-35.91309 19.99373,-15.15118 48.09433,-6.6877 56.44101,16.99918 1.86188,5.28381 2.98287,13.31429 1.68043,19.16849 -1.50813,6.77877 -4.86668,12.85647 -10.19438,18.15862 -5.26572,5.24048 -9.89475,7.95133 -16.43315,9.62357 -4.85615,1.24199 -12.03259,1.20154 -16.69163,0.50885 z m -0.17393,-23.059 1.06927,-3.3455 6.50377,-0.1501 6.50377,-0.1501 0.98735,3.36178 0.98735,3.36179 2.51591,0.16314 c 1.8243,0.1183 2.51592,-0.0335 2.51592,-0.55237 0,-0.39353 -2.29576,-7.75345 -5.10169,-16.35537 l -5.10169,-15.63986 h -3.1506 -3.1506 l -5.20854,15.65695 c -2.86469,8.61132 -5.31927,15.95804 -5.45462,16.32605 -0.17576,0.47789 0.50564,0.6691 2.38452,0.6691 h 2.6306 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1468" d="m 763.70798,369.86416 c -8.12397,-1.27623 -14.23623,-3.96267 -20.56659,-10.26395 -3.76197,-3.74468 -5.37393,-6.19207 -7.19215,-9.96045 -7.60051,-15.75262 -2.96024,-33.08108 10.77538,-44.10464 6.3567,-5.10159 13.61954,-7.5924 22.13836,-7.5924 29.9337,0 46.67982,33.83863 28.70945,58.01278 -2.79638,3.76175 -6.27683,7.45135 -10.51135,9.84091 -7.04064,3.97306 -15.70093,5.26986 -23.3531,4.06775 z m 11.20335,-21.38348 c 3.07353,-1.75995 4.52918,-4.20847 4.57675,-7.69846 0.0443,-3.24643 -1.27165,-5.85301 -3.49954,-6.93201 l -1.49389,-0.72351 1.60877,-1.54129 c 1.87307,-1.79453 2.80455,-4.70189 2.3305,-7.27407 -0.92747,-5.03237 -3.68485,-6.33408 -13.45172,-6.35026 l -7.09246,-0.0118 v 16.10974 16.10973 l 7.3601,-0.18515 c 6.6513,-0.16732 7.58173,-0.31206 9.66149,-1.50296 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1470" d="m 762.70726,326.44188 v -4.88945 l 3.72999,0.26688 c 4.16057,0.29769 6.24901,1.33706 6.7575,3.36306 0.94714,3.77369 -1.80659,6.14376 -7.14199,6.14695 l -3.3455,0.002 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1496" d="m 837.54718,264.82028 c 0,-0.76372 4.25204,-14.10124 4.62716,-14.51418 0.17889,-0.19692 1.32644,2.82483 2.55012,6.715 1.22368,3.89017 2.33144,7.35074 2.46168,7.69016 0.18748,0.48856 -0.7918,0.61711 -4.70107,0.61711 -3.25732,0 -4.93789,-0.17292 -4.93789,-0.50809 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999998;stroke-opacity:1" id="path1498" d="m 763.06218,340.74443 v -5.12084 h 3.61513 c 4.59667,0 6.58099,0.93645 7.49973,3.5393 0.55274,1.56594 0.54465,2.04231 -0.0591,3.47983 -0.97646,2.32493 -3.07062,3.22256 -7.51823,3.22256 h -3.53752 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#1a1a1a;stroke-width:1;stroke-opacity:1" id="path1500" d="m 766.92321,602.64753 c -0.29048,-8.92659 -0.82524,-9.72678 -10.1321,-11.86299 -21.0747,-4.8373 -37.20457,-20.14213 -42.61333,-41.34602 -0.55002,-2.15622 -1.08744,-5.19544 -1.08744,-5.87916 0,-0.68371 -1.0064,-2.24952 -2.23643,-3.47956 l -2.34864,-1.94853 -6.86019,-0.2879 h -6.97241 v -1.97332 -1.97332 h 5.94109 c 6.60342,0 9.93688,-1.00153 11.20212,-3.36564 0.44261,-0.82703 1.50127,-3.93512 2.00022,-6.97425 2.67764,-16.30961 14.91214,-30.68661 29.48362,-37.96428 4.71573,-2.35525 11.36654,-4.65443 15.50589,-5.36038 6.61875,-1.12879 8.22218,-3.61509 8.22218,-12.74947 v -5.94109 h 1.97332 1.97332 v 6.89625 c 0,6.61611 0.0735,6.97475 1.80888,8.82901 1.46262,1.5628 3.90685,1.70471 9.49139,3.0655 20.40883,4.97306 35.28463,20.46042 40.71665,40.14848 0.78813,2.85653 1.76467,6.36883 2.17007,7.80511 1.22789,4.35011 3.85392,5.61076 11.68766,5.61076 h 6.48046 v 1.97332 1.97332 h -6.6104 c -6.95598,0 -9.89025,0.84134 -10.81193,3.1001 -0.2638,0.64649 -1.27295,4.60779 -2.13571,8.03332 -5.38972,21.39923 -21.27622,36.72039 -42.13505,41.53173 -9.94989,2.29507 -10.66202,3.14671 -10.66202,12.75068 v 6.28151 h -1.91345 -1.91345 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1502"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1504" d="m 695.45795,526.49678 c 1.75282,-15.26781 8.92367,-31.22618 20.42144,-42.95218 11.95352,-12.1908 27.52102,-19.18005 45.72176,-21.6406 l 2.79554,-0.37793 v 6.18375 c 0,7.93282 -0.12396,8.86863 -6.84011,10.24498 -22.30129,4.57023 -41.81316,22.08888 -46.1026,44.18863 -1.7607,9.07134 -2.35691,9.12221 -11.11415,9.12221 h -5.42936 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1506" d="M 754.53008,608.24817 C 722.31091,601.3332 698.78801,575.33696 695.1389,542.61223 l -0.23838,-2.13776 h 6.36187 c 6.88754,0 6.85298,0.0191 7.74616,1.01913 1.26613,1.41754 1.51209,3.83358 2.42978,7.89599 4.79388,21.22157 24.19052,39.13835 46.58676,43.98208 6.89875,1.49203 6.3716,2.73181 6.3716,10.28576 v 5.88328 l -2.13776,-0.0463 c -1.17577,-0.0255 -4.65375,-0.58628 -7.72885,-1.24626 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1508" d="m 773.33996,603.05325 c -0.28949,-7.25738 0.97796,-8.25157 5.32662,-8.99716 4.85038,-0.83162 11.1113,-2.92244 16.31659,-5.44891 15.80304,-7.67023 27.12455,-21.98721 31.55746,-39.907 0.97744,-3.95125 1.56987,-7.24086 2.2486,-7.73716 0.71733,-0.52453 3.90303,-0.48855 7.84997,-0.48855 h 6.21369 l -0.43161,3.7822 c -3.78834,33.19719 -31.7798,61.26383 -64.82878,65.00289 l -3.98698,0.45108 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1510" d="m 828.66155,529.84176 c -1.17591,-1.07273 -1.30676,-2.96446 -2.112,-6.72672 -4.37909,-20.45999 -18.95972,-36.61709 -39.28934,-43.53733 -2.43875,-0.83016 -5.8241,-1.71782 -7.52299,-1.97259 -1.88233,-0.28227 -3.85602,-0.56229 -4.78314,-1.4894 -1.37609,-1.3761 -1.34856,-2.61232 -1.34856,-8.254 v -6.23739 l 2.46665,0.33127 c 18.99503,2.55107 32.67768,9.21103 45.44487,22.12006 10.43139,10.54728 17.44069,23.80984 20.16018,38.14583 0.547,2.88355 0.99455,6.09813 0.99455,7.14349 v 1.90066 h -5.88329 c -5.18197,0 -6.69797,-0.12032 -8.12693,-1.42388 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:.999999;stroke-opacity:1" id="path1512" d="m 663.62068,131.03319 c -0.53326,-0.58925 -0.625,-1.69704 -0.625,-7.54707 v -6.85645 l -1.10115,-1.23333 -1.10115,-1.23332 -7.11278,-0.10646 c -4.06806,-0.0609 -6.47681,0.46167 -7.5734,-0.16401 -1.35335,-0.7722 -0.86115,-3.06574 -0.86115,-7.62988 0,-4.68262 0.12554,-6.289149 0.5353,-6.850301 0.49015,-0.671243 1.10329,-0.741434 7.26979,-0.832236 3.70397,-0.05454 7.12214,-0.18656 7.59593,-0.293374 0.47378,-0.106815 1.19541,-0.741963 1.60361,-1.411441 0.66219,-1.086052 0.74232,-1.921972 0.74358,-7.756551 8.2e-4,-3.782617 0.16622,-6.847257 0.39235,-7.269795 0.3648,-0.681634 0.8563,-0.730476 7.35092,-0.730476 6.49462,0 6.98613,0.04884 7.35092,0.730476 0.22614,0.422538 0.39154,3.487178 0.39236,7.269795 10e-4,5.834579 0.0814,6.670499 0.74358,7.756551 0.4082,0.669478 1.12983,1.304626 1.60361,1.411441 0.47379,0.106814 3.89196,0.238833 7.59593,0.293374 6.1665,0.0908 6.77964,0.160993 7.26979,0.832236 0.40976,0.561152 0.5353,2.167681 0.5353,6.850301 0,4.82187 0.7369,7.18936 -0.88407,7.88102 -1.15658,0.4935 -3.76592,-0.14378 -7.55048,-0.0871 l -7.11278,0.10646 -1.10115,1.23332 -1.10115,1.23333 v 6.92207 c 0,6.22636 -0.0694,6.98488 -0.69062,7.54707 -0.58568,0.53003 -1.66715,0.62501 -7.11685,0.62501 -5.74601,0 -6.49238,-0.0731 -7.05124,-0.69063 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1.00067" id="path1514" d="m 709.8986,726.4428 v -5.25741 h 5.30749 5.20734 v 5.25741 5.25742 h -5.20734 -5.30749 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1" id="path1518" d="m 709.32587,761.61376 c -14.84534,-2.33618 -27.22151,-12.34303 -32.43644,-26.22673 -7.52289,-20.0282 2.33277,-43.0312 22.02756,-51.41208 6.07171,-2.58375 7.95693,-3.52014 15.69808,-3.49043 6.50926,0.025 7.91106,0.60374 11.25868,1.62027 14.44352,4.38591 24.64194,14.87492 28.58676,29.40132 0.78714,2.89856 1.10607,5.2416 1.09829,10.74202 -0.008,5.44704 -0.33673,6.15425 -1.11435,9.04799 -4.75273,17.68623 -20.04274,29.95104 -38.0751,30.54176 -2.55811,0.0838 -5.72767,-0.0171 -7.04348,-0.22412 z m 12.01917,-11.94961 c 11.93985,-2.6283 21.26602,-13.04595 22.49006,-25.12213 2.18282,-21.53536 -18.13115,-37.7028 -38.52104,-30.65805 -4.17709,1.44319 -6.99053,3.28712 -10.81791,7.09005 -2.821,2.80297 -3.81838,4.14269 -5.32568,7.15366 -2.55937,5.1126 -3.29841,8.68914 -3.02322,14.63061 0.31524,6.80606 2.15585,11.73401 6.30752,16.88741 6.75846,8.38917 18.22621,12.36591 28.89027,10.01845 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1520" d="m 591.47251,714.31134 c -1.32743,-0.80942 -2.29002,-0.92179 -2.47367,-5.31313 -0.18144,-4.33862 0.062,-13.48601 0.062,-32.6299 0,-32.80523 -0.46981,-35.19682 0.63005,-36.25656 0.0664,-0.064 0.1032,-0.14627 0.16097,-0.21975 1.14169,-1.45141 2.68891,-2.12685 4.87199,-2.12685 h 1.91275 v 38.63637 38.63636 l -1.98864,-0.002 c -1.28887,-7.5e-4 -2.40626,-0.25607 -3.17548,-0.72512 z"/><path style="opacity:1;fill:#ff5f55;fill-opacity:.956863;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1522" d="m 592.87653,312.11027 c -0.50555,-0.0951 -1.32392,-0.43812 -1.8186,-0.76224 -0.77901,-0.51042 -1.53827,-0.76694 -1.82846,-2.70306 -0.48349,-3.2259 -0.1686,-11.38158 -0.1686,-35.10181 0,-19.2629 -0.52222,-28.34633 -0.3807,-32.53262 0.0922,-2.72597 0.77878,-3.23422 1.00023,-3.60909 0.93375,-1.58064 2.4287,-2.28781 4.83664,-2.28781 h 2.11959 V 273.75 312.38636 l -1.42045,-0.0516 c -0.78125,-0.0284 -1.83409,-0.1294 -2.33965,-0.22451 z"/><path style="opacity:1;fill:#000;fill-opacity:.956863;stroke:#4d4d4d;stroke-width:1" id="path1524" d="M 921.31509,126.45258 C 911.22775,105.90097 899.41123,89.210741 883.15837,72.558198 848.342,36.885643 804.48862,15.547979 753.51164,9.4762173 748.44895,8.8732107 740.43487,8.6841876 712.59008,8.5110262 L 677.96414,8.2956939 V 6.8885761 c 0,-0.9784616 0.0131,-2.9650392 1.40163,-3.6743483 l 2.12353,-1.1288295 30.378,0.2249304 c 16.92737,0.1253367 33.54939,0.2176979 37.00428,0.4846569 50.75274,3.9216602 97.06468,24.5817024 133.31418,59.4722764 17.58138,16.922285 31.48259,35.738975 42.78184,57.909488 4.28368,8.40514 4.87972,10.05538 4.25358,11.77682 -0.41652,1.14511 -2.66192,4.17147 -3.17716,4.12934 -0.14438,-0.0118 -2.24836,-4.57649 -4.72893,-9.63033 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1530" d="m 590.08186,903.77298 c -0.55877,-0.54988 -1.70743,-1.18329 -1.55645,-5.03977 0.26239,-6.70193 -0.21555,-27.16243 -0.13871,-79.12435 l 0.29646,-82.56455 2.57494,-6.44666 7.90468,-15.05275 0.10278,-39.42573 L 598.9,636.5 l -7.10988,-13.23431 -2.91024,-7.69331 -0.38184,-7.29025 0.0879,-48.02714 -0.10334,-22.13198 0.0966,-34.13422 0.0553,-10.47634 0.0117,-10.49224 -0.0696,-8.60257 0.0161,-25.57403 -0.005,-19.35155 -0.14968,-27.48393 0.0746,-21.58573 -0.0172,-11.0146 0.10416,-19.60547 -0.0482,-10.22715 0.54617,-5.68471 1.91706,-5.78584 2.96237,-5.52269 5.28838,-9.81904 V 273.28018 L 598.9,233.7 l -5.2812,-9.75149 -2.68351,-5.33049 -1.81693,-5.13665 -0.73664,-7.59716 0.23713,-13.31736 -0.12377,-12.24771 -0.0136,-11.08368 -0.0374,-10.84778 0.0307,-9.87039 0.01,-6.53596 0.018,-2.90392 0.0682,-17.39197 0.0306,-21.51034 -10e-4,-10.808249 -0.0542,-8.443665 0.017,-5.12553 -0.22211,-5.939713 2.2004,-3.055633 L 593.7,65.7 l 3.21783,0.0589 c 1.41548,0.02591 2.72523,0.05679 3.94006,0.2405 0.8633,0.130547 1.83634,0.127121 2.58513,0.398351 0.99296,0.35967 1.67802,1.018584 2.03567,1.315407 0.20827,0.172853 1.21427,1.722556 1.32566,4.747437 0.0757,2.056368 -0.0202,4.681671 -0.01,8.332014 0.0118,4.09125 0.083,9.689119 0.0361,16.361518 -0.0703,10.012523 -0.0176,23.117313 -0.0816,40.379883 -0.0488,13.18104 0.19588,28.6727 0.14409,46.98667 -0.17752,62.76594 -0.24767,157.98682 -0.2362,300.97578 l 0.0334,416.2456 -1.26287,1.82282 c -1.80326,2.60281 -12.60786,2.90243 -15.34573,0.2081 z"/><path style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1;stroke-opacity:1" id="path1532" d="M 609.12095,465.08874 V 72.721096 h 4.31173 4.31173 V 465.08874 857.45638 h -4.31173 -4.31173 z"/><ellipse id="path3879" cx="714.884" cy="721.067" rx="40.267" ry="40.271" style="fill:#999595;fill-opacity:1;stroke:#000;stroke-width:2.39278;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><ellipse style="fill:#3a3d40;fill-opacity:1;stroke:#000;stroke-width:2.72654;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path3881" cx="714.948" cy="721.389" rx="34.057" ry="34.486"/><path id="path96" d="m 715,694.3 -26.77014,26.41636 h 7.64861 v 22.52766 h 38.51622 v -22.52766 h 7.23886 z m 7.78519,40.89843 h -15.16064 v -14.48207 h 15.16064 z" class="st2" style="fill:#000;stroke-width:1.35332"/></g><ellipse id="ellipse382" cx="344.639" cy="859.606" rx="15.571" ry="14.069" style="fill:#2e2f31;fill-opacity:1;stroke:#000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path384" d="m 443.0983,809.82781 v 45.80985" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path386" d="m 436.0092,815.74618 v 36.37333" style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path388" d="m 355.92023,980.61127 c -0.159,2.38632 -0.9339,4.18348 -2.3494,5.44717 -1.0538,0.94086 -2.4969,1.60298 -4.1869,1.92092 -0.3864,0.0726 -1.0871,0.1771 -1.0975,0.16314 0,-0.005 -0.093,-0.85306 -0.2017,-1.88773 -0.1082,-1.03464 -0.2053,-1.93454 -0.2156,-1.9998 -0.018,-0.10426 -0.01,-0.11846 0.052,-0.11846 0.1214,0 0.6621,-0.12294 1.0604,-0.24083 1.8948,-0.56173 2.9076,-1.69881 3.1357,-3.52037 0.053,-0.4186 0.023,-1.49252 -0.051,-1.88234 -0.1958,-1.02944 -0.6378,-1.79009 -1.336,-2.30018 -0.5453,-0.39839 -0.9906,-0.54269 -1.6797,-0.54425 -0.4911,0 -0.7649,0.0565 -1.0906,0.22816 -0.224,0.11845 -0.5342,0.39899 -0.7138,0.64552 -0.4284,0.5885 -0.6382,1.17335 -1.3991,3.89925 -0.4752,1.70296 -0.7598,2.51481 -1.1909,3.39834 -0.584,1.19653 -1.3563,2.06447 -2.414,2.7127 -0.5828,0.35721 -1.3337,0.64064 -2.0474,0.7727 -0.3392,0.0631 -0.4902,0.0716 -1.1851,0.0709 -0.6888,-7.5e-4 -0.842,-0.01 -1.1342,-0.0703 -1.7103,-0.34894 -3.1451,-1.32436 -3.9859,-2.70946 -0.3778,-0.62245 -0.6928,-1.42824 -0.8702,-2.22642 -0.3894,-1.7521 -0.3112,-4.07304 0.1924,-5.71076 0.2323,-0.7556 0.6307,-1.54303 1.0637,-2.10262 0.2976,-0.38477 1.0376,-1.06011 1.4626,-1.33492 0.6802,-0.43973 1.5737,-0.79266 2.4151,-0.95396 0.4254,-0.0815 0.9688,-0.14541 1.2361,-0.14541 h 0.1571 l 2e-4,0.18183 c 2e-4,0.0998 0.039,0.97141 0.087,1.93652 0.048,0.96511 0.086,1.80485 0.086,1.86617 l 10e-5,0.11137 -0.3029,0.0565 c -0.6791,0.12626 -1.358,0.40173 -1.7702,0.71779 -0.8027,0.61542 -1.1472,1.52476 -1.1467,3.02784 3e-4,0.9899 0.1461,1.66912 0.5004,2.33009 0.4111,0.76692 0.8552,1.07989 1.5814,1.1146 0.5403,0.0263 0.9144,-0.092 1.2917,-0.40687 0.6036,-0.50373 1.0028,-1.42843 1.6845,-3.90103 0.5306,-1.92496 0.7696,-2.6569 1.1769,-3.6043 0.7236,-1.68302 1.723,-2.76077 3.1653,-3.41339 0.8627,-0.39031 1.6574,-0.56193 2.8045,-0.60571 1.3619,-0.0523 2.6128,0.24529 3.8083,0.90462 1.3364,0.73709 2.2925,1.87859 2.8381,3.38818 0.4756,1.31608 0.6841,3.06752 0.5698,4.78495 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path390" d="m 344.68166,571.55323 -11.22758,0.0524 0.0282,-4.64898 c 0.0146,-2.39871 0.018,-4.79751 0.034,-5.29725 0.1201,-2.99844 0.50834,-4.47151 1.80242,-5.57094 1.43938,-1.29933 3.86276,-1.68857 6.05962,-1.28878 1.22398,0.1999 2.1495,0.86284 2.97159,1.66242 0.75529,0.79959 1.34588,1.99896 1.58337,3.29829 0.053,0.29984 0.0886,0.10698 0.12964,0.007 0.026,0 0.17696,-0.007 0.36596,-0.20693 0.79258,-1.09943 1.50437,-1.8495 2.85325,-2.64909 0.78279,-0.49974 1.13628,-0.74914 4.08763,-2.44826 l 2.49546,-1.39927 0.01,2.39875 c 0,1.99896 -2e-4,2.4987 -0.034,2.4987 -0.023,0 -1.34447,0.89954 -2.93445,1.79907 -4.59312,2.79854 -5.0351,3.37378 -5.57969,3.97346 -0.54019,0.69964 -0.66221,0.81512 -0.69151,2.41429 l 0.48716,0.75844 4.08351,0.26903 4.69846,0.0106 -0.0199,2.16917 0.0199,2.25025 -11.13382,-0.0473 z m -1.74891,-9.39408 c -0.041,-0.69963 -0.114,-1.29932 -0.18719,-1.49922 -0.2217,-0.79958 -0.88159,-1.39927 -1.75178,-1.59917 -0.32459,-0.1 -1.14798,-0.1 -1.50817,-0.1 -0.87379,0.1 -1.48218,0.49974 -1.85017,1.19938 -0.3531,0.69964 -0.3777,0.99948 -0.3791,4.69756 l -7e-4,2.4987 h 2.85636 2.85645 v -2.2988 c 0,-1.29933 -0.018,-2.59865 -0.036,-2.8985 z" style="fill:#000;stroke:#000;stroke-width:.0133722;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path392" d="m 333.0763,580.70071 c 0.2699,-3.09839 1.47058,-5.09735 3.82724,-6.39667 0.94539,-0.49974 2.47236,-0.99948 3.66664,-1.09943 h 0.2144 l 0.021,0.1 c 0.037,0.19989 0.41959,3.89797 0.40439,3.89797 -0.01,0 -0.17189,0.1 -0.36389,0.1 -0.1921,0 -0.53819,0.0999 -0.76929,0.1999 -1.79067,0.49974 -2.78005,1.59916 -3.10355,3.19833 -0.099,0.49974 -0.1074,1.59917 -0.015,2.19886 0.1217,0.69964 0.322,1.19938 0.62179,1.59917 0.41149,0.59969 0.98798,0.99948 1.60627,1.19938 0.3497,0.0999 1.05159,0.19989 1.39958,0.0999 0.68299,-0.19989 1.12958,-0.49974 1.53758,-1.29932 0.28619,-0.49974 0.48609,-1.09943 1.12488,-3.39823 0.58179,-2.09891 0.89518,-2.99845 1.46878,-3.99793 0.54769,-0.99948 1.29527,-1.69911 2.25086,-2.2988 1.01618,-0.59969 2.16996,-0.89953 3.44104,-0.79959 1.09519,0 2.11077,0.29985 3.03455,0.89954 0.67949,0.39979 1.15789,0.79958 1.62308,1.49922 0.94818,1.29932 1.41878,2.99844 1.41828,5.09735 -5e-4,2.39875 -0.5283,4.19782 -1.61348,5.59709 -0.28049,0.29984 -0.87698,0.89953 -1.25648,1.09943 -1.02518,0.69963 -2.17746,1.09942 -3.55564,1.19937 -0.2116,0 -0.38909,0 -0.39449,0 -0.015,0 -0.2131,-4.09787 -0.2004,-4.09787 0.01,0 0.1496,-0.0999 0.31999,-0.0999 0.96079,-0.1999 1.73388,-0.59969 2.16607,-1.09943 0.33459,-0.3998 0.56069,-0.89954 0.68789,-1.49922 0.1015,-0.49974 0.1113,-1.69912 0.018,-2.19886 -0.1453,-0.89953 -0.46589,-1.59917 -0.92189,-1.99896 -0.48339,-0.49974 -1.31478,-0.59969 -1.98367,-0.29985 -0.30419,0.0999 -0.66298,0.3998 -0.87728,0.69964 -0.397,0.59969 -0.77619,1.69912 -1.28808,3.59813 -0.61799,2.19886 -1.08688,3.49818 -1.64607,4.49766 -0.90499,1.59917 -2.40657,2.59865 -4.21394,2.99844 -0.65499,0.1 -1.14148,0.1 -1.88937,0.1 -0.52549,0 -0.75938,0 -1.08948,-0.1 -1.82277,-0.39979 -3.39374,-1.29932 -4.32833,-2.69859 -0.65799,-0.99948 -1.07878,-2.19886 -1.27778,-3.79803 -0.053,-0.39979 -0.097,-2.2988 -0.063,-2.6986 v 0 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path394" d="m 344.34473,966.1041 h -11.2417 v -2.07865 -2.07863 h 9.3507 9.3505 v -5.19669 -5.19663 h 1.8911 1.8912 v 7.27527 7.27533 z" style="fill:#000;stroke:#000;stroke-width:.0135255;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path396" d="m 409.8518,320.05567 -2.8025,-2.94026 -2.1084,-1.796 -3.8978,-2.62047 -4.9398,-2.55642 -3.8113,-1.26102 -3.8729,-0.82355 -1.3897,-0.20254 -2.8884,-0.16657 h -57.7923 l -1.5715,0.14912 -1.7697,0.23885 -1.7748,0.23784 -2.7296,0.54225 -2.3129,0.60501 -2.4432,0.75415 -2.944,0.94164 -2.1288,0.90223 -3.8498,1.71494 -2.7574,1.53514 -2.1058,1.19382 -3.235,2.15931 -2.4201,1.63397 -1.436,1.20278 -1.896,1.44906 -3.2118,2.6021 -2.4228,2.54068 -4.259,4.68887 -2.5995,3.24851 -1.6774,2.6235 -1.271,2.18323 -1.9119,3.72736 -0.727,1.6468 -1.1613,2.96158 -0.6623,2.59781 -0.7848,3.27106 -0.3398,2.68009 -0.048,2.38299 v 3.99567 2.84426 875.03454 l 0.1638,2.4919 0.3452,3.3929 1.2989,4.7686 1.2397,3.7743 3.6049,7.2541 2.5738,4.0559 2.4685,3.1987 1.4819,1.9751 2.6694,2.8626 3.0699,3.022 2.1765,1.9253 4.0187,3.1181 4.1145,2.8537 2.3075,1.2731 3.5235,1.8455 3.6903,1.6798 4.1541,1.4538 3.7259,1.1675 3.6825,0.7441 3.285,0.4416 3.0789,0.2674 h 56.728 l 2.2738,-0.2161 3.6621,-0.6453 2.1372,-0.5088 2.6035,-0.8999 3.7077,-1.5118 3.7208,-1.891 3.1188,-1.9598 2.4944,-2.0592 3.0857,-2.8789 3.1141,-3.8291 2.3879,-3.9155 1.3793,-3.2339 1.0698,-2.9013 0.8145,-3.3519 0.4154,-3.6021 0.024,-2.1424 V 343.15522 l -0.2807,-2.93341 -0.6388,-3.84483 -1.3177,-4.25655 -1.5322,-3.68324 -2.5337,-4.45711 -1.9699,-2.57666 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path398" d="m 395.3929,1180.0491 v 6.0661 l 0.2504,2.2569 -0.22889,0.3633 0.0188,0.4323 0.0368,0.983 -1.0319,1.3186 -1.91624,1.5403 -1.8286,1.4972 -2.1313,1.0814 -1.9039,0.5267 -1.6018,0.1436 h -79.7814 l -1.9951,-0.4092 -2.2181,-0.8515 -1.5437,-0.8939 -1.324,-1.0482 -0.8339,-0.9964 -0.9297,-1.4644 -0.5711,-1.0947 -0.331,-0.8522 -0.2214,-1.445 v -0.9701 -816.23528 l 0.1524,-0.78853 0.1354,-0.61772 0.2239,-0.77581 0.2629,-0.76027 0.5285,-1.02162 0.7718,-1.1054 0.9507,-1.04883 1.5188,-1.1948 1.1498,-0.70115 1.3513,-0.54994 1.7628,-0.48373 1.567,-0.17203 h 79.0926 l 1.0991,0.0989 1.3891,0.27672 2.2207,0.74493 1.1905,0.67498 1.4954,1.14485 0.8938,0.8516 1.1289,1.64893 0.7411,1.63916 0.386,1.57396 0.05,1.06242 c -0.0804,114.31284 -0.10418,228.63693 -0.0983,342.96694 0.008,155.52282 0.0712,311.05662 0.12178,466.58792 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path400" d="m 280.0489,334.04973 -2.8746,2.16498 -1.3945,1.27122 -1.1064,1.18868 -1.3392,1.49729 -1.3821,1.73597 -1.1375,1.54737 -1.1471,1.61493 -1.7633,2.77824 -1.1335,1.98857 -0.9191,1.69028 -1.3324,2.59146 -1.1121,2.32402 -1.5658,3.3824 -0.6357,1.21716 -0.7728,1.8524 -0.7249,1.7502 -0.989,2.11092 -1.0447,2.26153 -0.86,1.70122 -0.7487,1.45807 -0.7784,1.50072 -1.1616,2.03112 -0.6994,1.16648 -1.3216,2.11047 -1.1613,1.58472 -0.9183,1.1248 -1.4672,1.69512 -1.42,1.41779 -1.9934,1.72491 -2.2557,1.72298 -2.1512,1.20455 -1.3718,0.68514 -3.115,1.23076 -4.1538,1.06111 -3.0868,0.4675 -3.2213,0.30214 h -28.4829 l -0.9465,0.0522 -0.9784,0.35707 -1.1635,0.4739 -0.9822,0.69974 -1.0146,1.07545 -0.9282,1.35489 -0.6502,1.7225 -0.1277,1.59156 0.296,1.44131 0.7415,1.59064 1.9905,3.44769 2.4225,4.15209 2.3354,3.53006 1.3741,1.96135 1.2426,1.70362 1.4133,1.82618 1.3411,1.74059 2.1466,2.65906 1.9723,2.30436 1.0859,1.37163 2.4142,2.76344 1.3089,1.52486 3.0336,3.39354 1.5816,1.80314 1.3444,1.31094 2.4631,2.62274 1.0462,1.088 4.8462,5.01965 3.6011,3.76598 1.7432,1.82423 2.1054,2.24013 6.0616,6.47629 2.3937,2.58723 2.014,2.19763 1.6282,1.85126 1.1405,1.25224 1.6465,1.98007 1.726,2.18054 1.5288,1.91466 1.2553,1.47803 1.1294,1.5201 1.6519,2.24592 1.1514,1.59813 1.313,1.80747 1.0891,1.73386 1.8619,2.95681 1.9716,3.31485 1.215,2.46611 1.3695,2.68245 0.9533,2.4215 1.0707,2.90707 0.7627,2.01532 h 0.6246"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path402" d="m 419.6848,525.27774 h 3.3148 l 1.2108,0.19587 1.4197,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4607,1.28829 0.064,0.91052 0.1581,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.069,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3265,4.36272 -0.1216,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.2805,0.22452 h -4.5718 -0.1723 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path404" d="m 419.7599,446.71674 h 3.3148 l 1.2108,0.19587 1.4197,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4608,1.28829 0.064,0.91052 0.158,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.07,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3264,4.36272 -0.1217,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.2805,0.22452 h -4.5717 -0.1724 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path406" d="m 419.3182,991.21629 0.7067,0.005 1.1504,0.26365 0.9444,0.76195 0.3328,0.70813 v 46.67098 l -0.351,0.8325 -1.1666,0.8966 -0.7662,0.1774 -0.7976,-0.036 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path408" d="m 292.23542,321.94382 -2.85482,0.19193 -3.5205,0.79532 -3.2999,0.79136 -3.3568,0.85492 -10.5848,3.04972 -8.2427,2.61122 -6.9829,2.30208 -8.1913,2.71333 -6.855,2.11775 -7.5618,2.21755 -3.0235,0.89028 -3.0148,0.78091 -2.5919,0.65281 -4.3968,1.00847 -3.4498,0.73028 -4.1489,0.73001 -5.6739,0.74708 -2.2602,0.25755 -2.5162,0.19354 -1.5131,0.53719 -1.7144,0.82362 -1.1537,0.80424 -0.8192,0.61627 -1.0935,1.16923 -1.2892,1.65867 -1.0363,2.0311 -0.4006,1.59894 -0.1889,1.03517 v 22.38615 l 0.1909,1.30564 0.4958,1.40886 0.8296,1.64975 0.8332,1.21754 1.2656,1.51781 1.473,1.67519 1.7472,1.806 1.5258,1.66687 1.0269,1.42626 0.5157,0.92256"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path410" d="m 419.5504,789.12692 1.0104,0.39157 1.2284,0.93414 1.2742,1.0266 1.3335,1.34755 1.3498,1.58941 1.4074,1.79596 1.068,1.4886 0.8509,1.19973 0.8928,1.39146 0.9973,1.62576 0.6021,1.24333 0.8025,1.68804 0.9324,1.96316 0.9148,2.22486 0.6262,1.90738 0.5734,2.0049 0.5948,2.79681 0.1489,0.35893 1.1814,-0.13758 0.9744,-0.18453 1.2915,-0.53944 1.0017,-0.68907 1.1544,-0.99535 0.604,-0.85004 0.4934,-1.12029 0.3702,-1.37331 v -45.33419 l 0.2034,-1.17653 0.748,-1.09495 0.8786,-0.84648 1.1084,-0.65922 1.6277,-0.61299 1.9995,-0.31181 2.419,-0.0432 3.3419,0.50976 2.789,1.02605 1.7576,0.92574 1.4806,0.99459 2.1054,1.92583 1.357,1.78977 0.7746,1.80358 0.5382,2.14337 0.1755,1.82459 v 15.36545 l 0.7426,2.32837 0.8151,3.04194 0.6637,2.10231 1.4461,5.39684 0.1081,0.54415 0.3624,1.61807 0.4384,2.00735 0.5281,2.58998 0.5111,2.93668 0.532,3.40847 0.5218,3.68177 0.2738,2.55863 0.1742,1.97306 0.125,1.76412 0.1687,2.52444 0.093,2.5116 0.1008,2.95717 0.032,3.58916 -0.1372,3.61839 -0.1588,3.45509"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path412" d="m 419.5504,878.18361 1.0104,-0.39157 1.2284,-0.93414 1.2742,-1.0266 1.3335,-1.34755 1.3498,-1.58941 1.4074,-1.79596 1.068,-1.4886 0.8509,-1.19973 0.8928,-1.39146 0.9973,-1.62576 0.6021,-1.24333 0.8025,-1.68804 0.9324,-1.96316 0.9148,-2.22486 0.6262,-1.90738 0.5734,-2.0049 0.5948,-2.79681 0.1489,-0.35893 1.1814,0.13758 0.9744,0.18453 1.2915,0.53944 1.0017,0.68907 1.1544,0.99535 0.604,0.85004 0.4934,1.12029 0.3702,1.37331 v 45.33419 l 0.2034,1.17653 0.748,1.09495 0.8786,0.84648 1.1084,0.65922 1.6277,0.61299 1.9995,0.31181 2.419,0.0432 3.3419,-0.50976 2.789,-1.02605 1.7576,-0.92574 1.4806,-0.99459 2.1054,-1.92583 1.357,-1.78977 0.7746,-1.80358 0.5382,-2.14337 0.1755,-1.82459 v -15.36545 l 0.7426,-2.32837 0.8151,-3.04194 0.6637,-2.10231 1.4461,-5.39684 0.1081,-0.54415 0.3624,-1.61807 0.4384,-2.00735 0.5281,-2.58998 0.5111,-2.93668 0.532,-3.40847 0.5218,-3.68177 0.2738,-2.55863 0.1742,-1.97306 0.125,-1.76412 0.1687,-2.52444 0.093,-2.5116 0.1008,-2.95717 0.032,-3.58916 -0.1372,-3.61839 -0.1588,-3.45509"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path414" d="m 345.6694,529.78706 h -6.1466 l -2.0406,0.16173 -1.1253,0.1953 -1.5748,0.44867 -1.3791,0.53886 -1.4965,0.74967 -1.1637,0.77396 -1.2064,0.95657 -1.075,1.06404 -1.1014,1.41493 -0.594,1.14722 -0.5358,1.29229 -0.5077,1.36813 -0.1092,1.5301 -0.019,1.06031 v 58.69762 l 0.1365,1.11638 0.2065,0.99097 0.3274,0.9147 0.2958,0.88818 0.5023,0.98607 0.7034,1.07023 0.7271,0.83072 1.1425,1.22917 0.9548,0.84847 1.1231,0.73807 1.3029,0.76185 1.5781,0.61856 1.753,0.41994 1.6248,0.25206 1.9291,0.0355 12.21761,-0.15231 1.24069,0.009 1.4416,-0.26481 1.209,-0.3538 1.3406,-0.58952 1.2548,-0.64457 0.9072,-0.5388 1.0383,-0.81994 0.7108,-0.73783 0.6713,-0.63536 1.2672,-1.78476 1.0821,-2.39096 0.4226,-1.73078 0.032,-1.77014 v -58.93942 l -0.1414,-0.90899 -0.2101,-0.66149 -0.2984,-1.07142 -0.4418,-1.07685 -0.4733,-1.01774 -0.3698,-0.61491 -0.9962,-1.35072 -0.9572,-1.00027 -0.9422,-0.8506 -0.8825,-0.60388 -1.188,-0.67727 -1.3389,-0.66409 -0.8725,-0.3618 -0.9794,-0.32179 -0.9048,-0.1841 -1.4328,-0.23747 -0.4669,-0.0583 -1.0123,-0.0549 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path416" d="m 345.6694,929.08474 h -6.1466 l -2.0406,0.16173 -1.1253,0.1953 -1.5748,0.44867 -1.3791,0.53886 -1.4965,0.74967 -1.1637,0.77396 c -0.40213,0.31886 -0.80427,-0.0101 -1.2064,0.95657 -1.1612,-0.13384 -0.80827,0.40421 -1.2124,0.60632 l -1.03457,1.59803 -0.52343,1.42184 -0.5358,1.29229 -0.5077,1.36813 -0.1092,1.5301 -0.019,1.06031 v 58.69758 l 0.1365,1.1164 0.2065,0.991 0.3274,0.9147 0.2958,0.8882 0.5023,0.986 0.7034,1.0703 0.7271,0.8307 1.1425,1.2292 0.9548,0.8484 1.1231,0.7381 1.3029,0.7618 1.5781,0.6186 0.84467,0.2023 0.90833,0.2176 1.6248,0.2521 1.9291,0.035 h 12.2138 l 1.2445,-0.1435 1.4416,-0.2648 1.209,-0.3538 1.3406,-0.5895 1.2548,-0.6446 0.9072,-0.5388 1.0383,-0.8199 0.7108,-0.7378 0.6713,-0.6354 1.2672,-1.7847 1.0821,-2.391 0.4226,-1.7308 0.032,-1.77012 v -58.93942 l -0.1414,-0.90899 -0.2101,-0.66149 -0.2984,-1.07142 -0.4418,-1.07685 -0.4733,-1.01774 -0.3698,-0.61491 -0.9962,-1.35072 -0.9572,-1.00027 -0.9422,-0.8506 -0.8825,-0.60388 -1.188,-0.67727 -1.3389,-0.66409 -0.8725,-0.3618 -0.9794,-0.32179 -0.9048,-0.1841 -1.4328,-0.23747 -0.4669,-0.0583 -1.0123,-0.0549 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path426" d="m 269.3709,404.13671 h -4.9495 l -1.0113,0.19773 -1.022,0.65678 -0.7694,0.84217 -0.623,1.27551 -0.4117,1.3715 -0.6037,2.17152 -0.5303,2.14305 -0.3827,1.9667 -0.3142,1.95063 -0.2528,2.01116 -0.2212,2.18086 -0.1418,2.35493 -0.046,2.05813 0.034,2.89349 0.1866,2.92296 0.2597,3.11808 0.3257,2.74124 0.4726,2.4298 0.3837,2.06422 0.6228,2.42502 0.4876,1.70136 0.5673,1.13322 0.656,0.75539 0.7893,0.54624 0.78,0.31802 0.8271,0.091 h 5.1673 0.2296 v -44.33098 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path428" d="m 419.3062,396.58247 h 3.3623 l 0.9525,0.25724 0.8868,0.75004 0.3797,1.09319 v 10.77754 l -0.3997,0.99826 -0.4739,0.71234 -0.6363,0.44149 -0.5074,0.1596 h -3.3662 -0.2116 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path430" d="m 368.2112,1052.977 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path432" d="m 368.2112,1097.1347 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path434" d="m 368.2112,1141.3197 h -46.6816 l 23.3408,36.9165 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path436" d="m 343.5847,1042.2128 h -27.013 l -1.8698,0.2799 -1.342,0.3586 -1.606,0.6627 -1.1661,0.7504 -1.1412,0.8758 -0.7833,0.8235 -0.7034,0.7948 -0.6319,1.1103 -0.4797,0.9867 -0.3453,1.0256 -0.2487,1.1948 -0.069,0.83 v 125.1345 l 0.052,0.8702 0.1667,1.0482 0.4222,1.1949 0.7328,1.4918 0.8537,1.1485 1.4176,1.3519 1.1779,0.9169 1.5965,0.8574 1.9127,0.6145 1.7443,0.195 h 57.292 l 1.482,-0.1169 1.5379,-0.379 1.0258,-0.4189 1.0471,-0.555 0.7983,-0.4851 1.0868,-0.8153 1.1798,-1.2764 0.6871,-0.9185 0.4367,-0.7747 0.3972,-0.7651 0.3643,-1.035 0.1713,-0.7948 0.086,-1.2186 v -125.1426 l -0.076,-1.0984 -0.204,-0.9502 -0.2266,-0.7979 -0.3429,-0.7631 -0.7969,-1.4695 -0.8643,-1.1417 -1.3636,-1.2219 -1.4025,-0.9472 -0.7682,-0.4017 -1.6691,-0.5921 -1.312,-0.2496 -1.4844,-0.1821 -1.158,0.01 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path438" d="m 390.4523,307.66577 v -3.14841 l -0.3715,-1.45506 -0.7559,-1.06735 -1.1876,-0.97885 -1.7025,-0.48365 h -45.228 l -1.5835,0.18859 -1.2132,0.58802 -0.8602,0.6336 -0.6208,0.61481 -0.7767,1.21911 -0.2726,1.3989 v 2.48519 z"/><path style="fill:none;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path440" d="m 419.68509,599.75674 h 3.3148 l 1.2108,0.19587 1.41971,0.53011 1.5704,0.97007 0.9319,0.98029 0.8244,1.30095 0.4607,1.28829 0.064,0.91052 0.1581,2.35685 0.2578,3.05672 0.2171,3.22797 0.2039,3.98205 0.1256,3.05298 0.1452,4.34265 0.086,5.4517 v 13.88157 l -0.1562,2.15427 -0.069,2.19292 -0.2028,3.00598 -0.2269,2.94631 -0.169,2.82951 -0.3265,4.36272 -0.1216,1.92949 -0.121,1.18236 -0.3083,1.24744 -0.7538,1.13179 -1.0196,0.99385 -1.5458,0.79964 -1.28051,0.22452 h -4.5718 -0.1723 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path506" d="m 420.36151,634.93249 v -34.75633 l 2.0263,0.23815 c 2.75467,0.32376 4.80203,1.57598 5.69709,3.48449 1.06072,2.26176 1.52361,9.71023 1.72256,27.71794 0.14637,13.24854 0.0672,17.02245 -0.52828,25.19166 -0.77583,10.64303 -0.85918,10.95183 -3.29112,12.19251 -0.89452,0.45635 -2.06849,0.68792 -3.48749,0.68792 h -2.13906 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path508" d="m 420.36151,560.56402 v -34.75143 l 1.85933,0.15785 c 2.39951,0.20371 4.31925,1.13642 5.48512,2.66497 0.83656,1.09678 0.97668,1.7388 1.39976,6.41356 0.25858,2.85712 0.56214,12.52586 0.67458,21.48608 0.1781,14.19187 0.11309,17.54027 -0.50447,25.983 l -0.70891,9.69168 -1.16519,1.20216 c -1.30344,1.34481 -2.86398,1.89866 -5.35797,1.90159 l -1.68225,0.002 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path510" d="m 420.36151,481.93505 v -34.75712 l 1.92371,0.19854 c 2.49155,0.25715 4.263,1.11778 5.41822,2.63234 1.41345,1.85314 1.85463,7.51526 2.10513,27.01756 0.17647,13.73942 0.10561,18.07268 -0.42766,26.14973 -0.46732,7.07821 -0.78975,9.98262 -1.19916,10.80185 -0.79619,1.59315 -3.17954,2.71422 -5.77033,2.71422 h -2.04991 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path512" d="m 447.5015,906.00098 c -1.8715,-0.70661 -2.9819,-1.7154 -3.3712,-3.06268 -0.2644,-0.9154 -0.3472,-22.05223 -0.2745,-70.13291 l 0.1041,-68.8226 1.2946,-1.18645 c 2.041,-1.87038 4.9744,-2.37787 9.1933,-1.59049 4.2243,0.78838 8.8238,4.07342 10.363,7.40147 0.6902,1.49247 0.7677,2.40752 0.9325,11.01292 l 0.1796,9.38522 1.7041,5.81417 c 7.6872,26.22849 7.7031,50.97284 0.05,77.62707 l -1.8918,6.58875 -0.1107,9.17132 -0.1107,9.17132 -1.0625,1.92041 c -1.2599,2.27718 -3.7071,4.33173 -6.8926,5.78647 -1.902,0.86861 -2.8591,1.06811 -5.6666,1.18115 -2.0013,0.0806 -3.8109,-0.0275 -4.4404,-0.26514 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path514" d="m 441.6385,852.73071 c -0.5999,-0.72278 -2.3597,-1.63125 -3.6993,-1.9097 l -1.06248,-0.22083 -0.092,-16.88205 -0.092,-16.88205 1.50858,-0.39612 c 0.8297,-0.21787 2.1062,-0.86942 2.8367,-1.4479 l 1.3281,-1.05178 v 19.67251 c 0,10.81988 -0.06,19.67251 -0.1337,19.67251 -0.074,0 -0.3409,-0.24956 -0.594,-0.55459 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path516" d="m 420.05417,833.61702 v -43.39693 l 0.79594,0.42597 c 0.43776,0.23429 1.60747,1.27059 2.59935,2.30289 4.51391,4.69789 9.10684,12.69355 10.93014,19.02792 l 0.9034,3.1385 v 18.51411 18.51411 l -0.90522,3.13851 c -1.92215,6.6643 -6.56913,14.65718 -11.23693,19.32767 -1.32154,1.3223 -2.55667,2.40418 -2.74474,2.40418 -0.21796,0 -0.34194,-15.73501 -0.34194,-43.39693 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path524" d="m 313.99198,1292.8085 c -0.96622,-0.2545 -2.10487,-0.9559 -3.09247,-1.3094 -1.70548,-0.6104 -3.38805,-1.3678 -5.04339,-2.0839 -13.35521,-5.7781 -24.71137,-15.7518 -30.37881,-29.3689 l -5.07081,-12.1835 0.21567,-447.85593 -1.68502,-452.83955 5.21819,-6.82435 c 6.70736,-8.77188 19.17143,-19.4178 30.32839,-25.75165 12.83574,-7.28691 20.41017,-6.77706 55.40112,-6.27587 29.89918,0.42825 32.28987,-0.2527 38.18687,2.89292 7.63586,4.07316 15.0438,13.06457 18.54681,20.55351 0.66444,1.42047 1.68556,3.4563 2.05056,13.27608 1.04826,28.20251 0.44492,121.62908 -0.18564,457.03992 l -0.066,459.79922 -0.81036,6.3982 -3.45262,8.1963 c -1.76025,4.1787 -8.98897,10.0118 -12.10386,12.1705 -10.15801,7.0395 -14.51748,6.4392 -48.74484,6.3559 -20.03132,-0.049 -28.55486,0.083 -34.44933,-1.0022 -1.84725,-0.34 1.41291,0.4661 -0.16387,0.051 z m 78.87474,-99.2762 3.27873,-3.0802 v -65.5066 l -0.2424,-215.7738 0.25427,-68.97059 0.0331,-61.49435 c 0.11334,-210.56388 -0.50479,-313.30624 -0.8914,-364.08471 -0.35613,-46.77635 -0.40721,-49.50115 -1.95288,-50.80192 l -2.99002,-2.51629 -44.14324,-1.50348 -43.58958,0.51399 -4.70273,2.60905 -3.53443,3.53443 v 412.25021 412.25016 l 2.86193,2.7659 c 2.93271,2.8342 4.77438,2.8884 47.72015,2.8884 43.86243,0 44.67543,-0.052 47.8985,-3.0802 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path526" d="m 264.23721,492.50948 c -4.04844,-8.33293 -16.624,-23.7182 -35.08385,-43.12156 -26.81029,-28.1806 -38.94038,-44.27168 -38.0073,-50.84946 0.2392,-1.68623 1.46532,-4.24344 5.12049,-5.01886 3.19131,-0.67702 8.11058,0.35187 17.45091,-0.0198 23.39935,-0.93118 25.92443,-0.22204 34.18969,-9.37069 2.82569,-3.12771 9.72884,-13.68396 13.55981,-21.88811 2.0257,-4.33811 4.05045,-8.45316 5.51052,-10.90389 0.76226,-1.27947 1.07024,-2.31363 1.47031,-2.76411 0.28284,-0.31849 0.76027,-0.22269 0.8214,-0.25623 1.85097,-1.01578 0.12781,12.83353 -0.1142,27.83216 l 0.24214,24.66349 -0.68216,2.60676 h -3.52801 c -5.21935,0 -7.63511,7.05409 -7.62545,22.26651 0.0108,17.00318 1.77689,22.92697 7.15611,24.00281 l 4.16908,0.83382 v 23.90572 c 0,13.14815 0.49174,29.00863 0.25743,29.00863 -0.23432,0 -3.28323,-7.58512 -4.90692,-10.92716 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path528" d="m 295.1401,1185.4149 c -3.06937,-3.2672 5.67849,-7.7931 8.85227,-71.9607 l 3.14349,-63.5553 0.59066,-4.8296 c 0.52648,-4.3049 8.30627,-3.402 38.30164,-3.402 25.86749,0 38.24755,-2.2189 38.03519,0.9698 l 3.45868,11.3714 -2.79167,59.5757 3.06297,66.1632 -6.74309,5.9725 c -2.39371,2.1201 -8.12035,2.5912 -34.16751,2.5912 -30.89856,0 -48.7031,0.3392 -51.74263,-2.8962 z m 60.60873,-26.4444 c 6.3449,-10.045 11.38379,-15.7341 11.38379,-16.2306 0,-0.4966 -8.67254,-0.2057 -22.30766,-0.2057 -13.63512,0 -20.98513,-0.1734 -20.98513,0.1875 0,1.9194 20.33259,34.7155 21.23584,34.1572 0.58838,-0.3636 4.32826,-7.8634 10.67316,-17.9084 z m 1.57196,-45.1746 c 6.02548,-9.6095 10.68997,-15.7918 10.34635,-16.1355 -0.34362,-0.3436 -10.16328,-1.4002 -23.54772,-1.1865 l -22.58982,0.6608 12.33804,18.1627 c 12.12402,17.8476 11.33234,16.5866 12.68919,15.1005 0.93353,-1.0226 4.73849,-6.9926 10.76396,-16.602 z m -4.74836,-38.5533 c 6.72239,-10.6062 12.20345,-20.4597 11.88264,-20.7805 -0.32082,-0.3208 -6.79848,0.016 -20.13412,-0.1191 l -20.97842,-0.2121 10.503,17.5628 c 6.49171,10.8554 11.17262,15.0769 11.09751,17.0875 -0.008,0.2094 0.90699,-2.9325 7.62939,-13.5386 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path530" d="m 195.38552,386.2328 c -4.58371,-5.30681 -4.27509,-6.14052 -4.27509,-19.98524 0,-17.24523 1.72279,-19.61607 15.05755,-21.23724 9.67784,-1.17658 22.06465,-2.66101 54.5917,-14.7228 13.93049,-5.16576 29.54685,-8.05337 29.95931,-7.6409 0.41247,0.41246 -7.82477,7.64243 -12.70328,12.40148 -7.11384,6.93963 -10.0361,11.45679 -15.83597,23.5081 -9.7373,20.23271 -12.31671,25.43301 -19.9502,29.92064 -5.8988,3.46784 -9.64568,4.83664 -24.46127,4.50485 l -16.87996,-0.37801 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path532" d="m 260.25826,445.73518 c -0.87612,-2.14266 -2.24387,-11.42662 -2.30953,-18.43896 -0.0789,-8.42481 0.5889,-15.94359 2.95394,-19.86196 1.46407,-2.42565 4.20484,-2.8223 5.93526,-3.15555 0.81862,-0.15765 2.20028,-0.94768 2.77122,0.7176 1.00427,2.92917 0.90932,10.69905 0.90932,23.15575 0,20.49599 0.29677,21.57233 -2.45639,21.57233 -1.7985,0 -6.80502,-1.5465 -7.80382,-3.98921 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path534" d="m 335.78812,307.06698 c 0,-1.77848 0.75861,-5.19179 4.31531,-6.11265 4.01911,-1.04059 12.44741,0.017 24.70426,0.21676 11.74082,0.19135 18.48536,-0.47698 21.97918,0.38297 2.88441,0.70995 3.12648,3.58747 3.31976,4.59386 0.43963,2.28916 -2.61413,0.94 -26.90979,0.94 -14.47139,0 -27.40872,0.6628 -27.40872,-0.0209 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path536" d="m 424.74041,404.13845 c 8.8e-4,-3.58112 0.0807,-4.98041 0.17728,-3.10952 0.0966,1.87089 0.0959,4.8009 -0.002,6.51113 -0.0975,1.71024 -0.17656,0.17952 -0.17569,-3.40161 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#000;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path538" d="m 420.0381,404.10822 v -6.7918 l 1.87821,0.15545 1.87822,0.15545 0.14568,5.50942 c 0.1916,7.24582 0.0477,7.76327 -2.15865,7.76327 h -1.74346 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path548" d="m 334.02423,1070.9922 -10.6817,-16.8613 10.97722,-0.1953 c 6.03746,-0.1074 15.72027,-0.1074 21.51734,0 l 10.54013,0.1953 -10.29748,16.2913 c -5.66361,8.9602 -10.53965,16.5478 -10.83564,16.8613 -0.296,0.3136 -5.34494,-7.0175 -11.21987,-16.2913 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path550" d="m 334.02948,1115.1625 -10.82491,-17.1159 11.04619,-0.1953 c 6.07541,-0.1074 15.82454,-0.1074 21.66473,0 l 10.61853,0.1953 -10.74364,16.9996 c -5.90901,9.3498 -10.78693,17.052 -10.83982,17.1159 -0.0529,0.064 -4.96738,-7.5858 -10.92108,-16.9996 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path552" d="m 334.13106,1159.4901 -10.61146,-16.8195 10.88868,-0.1953 c 5.98878,-0.1074 15.60026,-0.1074 21.35885,0 l 10.47016,0.1953 -10.39596,16.468 c -5.71779,9.0575 -10.55411,16.6262 -10.74739,16.8195 -0.19329,0.1933 -5.12658,-7.2173 -10.96288,-16.468 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path572" d="m 420.0231,1016.5918 c 0,-20.55693 0.0782,-24.48013 0.48787,-24.48013 1.26302,0 1.28964,0.54348 1.19693,24.43313 l -0.0911,23.4691 -0.79685,0.529 -0.79686,0.5291 z"/><path style="fill:#ff5f53;fill-opacity:1;stroke:#1a1a1a;stroke-width:.25;stroke-opacity:1" id="path987" d="m 336.33885,1011.7736 c -0.4903,-0.1025 -1.34011,-0.499 -1.86387,-0.5891 -2.10906,-0.3631 -4.24247,-1.0485 -6.03886,-2.8281 -2.21068,-2.1901 -2.45772,-4.2576 -2.92495,-7.2201 -0.0644,-0.4083 -0.33547,-3.32902 -0.7219,-7.96551 -0.47191,-5.66195 -0.26588,-14.13412 -0.22086,-24.07743 l 0.13273,-29.31033 2.1854,-3.07209 c 1.68451,-2.36796 2.85286,-4.8002 5.70807,-6.16483 3.14456,-1.50292 4.3061,-1.05628 13.1741,-0.94462 7.32026,0.0922 8.2212,0.0618 9.5738,0.56462 4.38444,1.62985 7.57683,5.059 8.6811,9.18385 0.22909,0.85573 0.41962,8.86488 0.21397,32.35897 l -0.056,30.50887 -0.83085,2.4841 c -0.94256,2.8179 -3.22521,4.2492 -5.91157,5.5336 -1.13944,0.5447 -2.59573,1.1447 -3.33637,1.2835 -1.10922,0.2079 -5.88727,0.4361 -10.04355,0.3913 -2.3498,-0.025 -3.61164,0.2383 -5.14351,0.029 -0.87269,-0.1194 -0.99665,0.165 -1.3228,0.097 z m 13.30469,-23.7451 c 2.76719,-0.58714 4.69699,-2.04661 5.74377,-4.34391 0.47551,-1.04356 0.57052,-1.68351 0.57531,-3.875 0.009,-4.20728 -1.02802,-6.30701 -3.78078,-7.65381 -2.39779,-1.17313 -5.79519,-0.86226 -7.69553,0.70416 -1.16483,0.96015 -1.85705,2.35288 -3.009,6.05403 -1.00853,3.24035 -1.41582,4.0427 -2.17437,4.28345 -1.5805,0.50163 -2.90029,-1.36574 -2.62256,-3.71068 0.19465,-1.64357 0.66036,-2.28932 2.02759,-2.81147 1.12124,-0.4282 1.13535,-0.44797 1.13263,-1.58714 -0.002,-0.63445 -0.0725,-1.57541 -0.15771,-2.09104 -0.13433,-0.81269 -0.24453,-0.9375 -0.82772,-0.9375 -2.30578,0 -4.85058,1.92056 -5.66126,4.27257 -0.69366,2.01248 -0.63686,5.68454 0.11372,7.35243 1.14973,2.55483 2.92227,3.72494 5.66589,3.74023 1.40395,0.008 2.00379,-0.11802 2.99769,-0.62888 1.9043,-0.97879 2.69476,-2.2324 3.99147,-6.3301 1.20414,-3.80517 1.74731,-4.65625 2.9717,-4.65625 0.97546,0 2.09342,0.64567 2.49633,1.44174 1.35565,2.67848 0.17187,5.70204 -2.55195,6.51812 -0.93521,0.2802 -1.0352,0.38787 -1.03324,1.11268 0.003,0.96835 0.28627,3.42746 0.39535,3.42746 0.0428,0 0.67403,-0.12649 1.40267,-0.28109 z m 5.94981,-29.21891 v -7.5 h -2 -2 v 5.25 5.25 h -9.25 -9.25 v 2.25 2.25 h 11.25 11.25 z"/><path style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;stop-color:#000;stop-opacity:1" id="path504" d="m 300.85,1194.9934 c -1.71731,-0.8472 -4.91972,-2.1462 -5.54391,-3.5161 -0.83944,-1.8424 0.86542,-110.6107 0.86542,-412.9166 0,-355.43486 -2.26943,-409.5887 -1.00378,-412.03621 2.62275,-5.07184 6.80299,-6.80795 52.50153,-5.38304 l 40.5665,0.52575 3.70004,2.69699 2.40356,3.70288 v 409.59752 c 0,267.41961 0.6532,377.35501 0.22653,405.85801 -0.0462,3.0834 0.15924,4.3842 0.0303,5.658 -0.0851,0.8402 -0.5067,2.1372 -0.56245,2.2596 -2.45684,5.3924 -4.14164,3.9318 -48.47815,3.9071 -34.72063,-0.019 -42.05298,0.9547 -44.70561,-0.3539 z m 80.27252,-10.4604 c 2.12921,-1.989 3.21222,-4.1353 3.6646,-7.2624 0.35319,-2.4415 0.50577,-32.4911 0.33906,-66.777 l -0.30309,-62.3379 -1.817,-4.7667 -4.72991,-1.7818 -30.78478,-0.3127 c -34.35748,-0.3489 -37.22985,0.016 -40.34521,5.1254 -1.88189,3.0863 -1.95191,5.545 -1.95552,68.6629 l -0.004,65.4619 3.40582,3.4058 3.40582,3.4059 h 33.05076 33.05075 z m -22.91983,-173.0609 c 1.57682,-0.8154 3.84958,-2.6835 5.00011,-4.1461 2.02772,-2.5779 2.08689,-3.5907 2.08689,-36.43981 l -0.69949,-33.99855 -2.38805,-3.40626 c -3.72994,-4.24816 -8.21239,-5.25265 -18.24178,-5.26006 -5.84642,-0.004 -8.30481,0.20024 -11.76537,1.9453 -7.84443,3.95572 -7.97242,4.60298 -7.97242,40.31894 0,34.66614 0.41247,35.72854 7.12185,40.21074 2.99392,2.0001 4.44288,2.362 13.60803,2.362 7.24014,0 11.25811,-0.556 13.25023,-1.5862 z m -5.95573,-138.90396 c 6.10086,-3.11739 8.53502,-6.75988 8.53502,-12.77184 0,-8.4223 -5.95352,-14.17655 -15.26265,-14.7518 -7.02351,-0.43401 -12.57208,2.34255 -15.43573,7.72419 -7.14597,13.42935 8.05461,27.00867 22.16336,19.79945 z m 1.45148,-63.42988 c 1.10087,-1.10086 1.57412,-3.48865 1.57412,-7.94215 0,-8.51585 -1.07862,-9.51627 -10.26023,-9.51627 -9.38389,0 -10.77573,1.20668 -10.77573,9.34222 0,8.48897 1.31434,9.69032 10.60168,9.69032 5.28806,0 7.7177,-0.43166 8.86016,-1.57412 z m 0.37207,-38.69473 c 0.69725,-0.69725 1.20205,-4.03875 1.20205,-7.9569 0,-8.44376 -1.52314,-9.87359 -10.51798,-9.87359 -8.88853,0 -10.51798,1.47199 -10.51798,9.50153 0,8.65087 1.00564,9.53101 10.89005,9.53101 4.68578,0 8.21631,-0.4745 8.94386,-1.20205 z m -0.62982,-39.52257 c 2.44013,-2.20828 2.62327,-13.43508 0.25775,-15.80059 -2.26592,-2.26593 -15.101,-2.20499 -17.62997,0.0837 -2.48085,2.24514 -2.59975,12.86248 -0.17405,15.54285 2.27669,2.51572 14.82125,2.64015 17.54627,0.17404 z m -0.1057,-38.44592 c 1.6168,-0.86529 1.93757,-2.13749 1.93757,-7.6844 0,-9.02878 -1.23743,-10.31119 -9.94949,-10.31119 -9.51513,0 -11.08647,1.3467 -11.08647,9.50153 0,8.51102 1.08671,9.53101 10.15453,9.53101 3.85346,0 7.8782,-0.46663 8.94386,-1.03695 z m 4.89747,-81.8069 c 5.473,-3.60783 6.98335,-3.06909 7.02174,-39.48044 0.0344,-32.65824 -0.45612,-33.68452 -2.485,-36.2638 -1.3225,-1.68128 -2.16617,-2.68325 -3.79664,-3.53269 -2.85079,-1.4852 -6.79655,-1.97333 -14.0201,-1.97333 -9.16515,0 -9.82283,0.81199 -12.81675,2.81203 -6.85365,4.57854 -7.27471,4.72625 -6.9653,40.5757 0.2612,30.26439 -0.11042,32.144 1.7811,34.65729 3.82743,5.08555 5.86745,5.85717 18.30393,5.87882 9.72787,0.0169 10.49635,-1.03831 12.97702,-2.67358 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.373293;stroke-opacity:1" id="path989" d="m 337.67662,692.88512 c -2.67305,-0.96309 -3.2939,-2.84605 -3.09019,-9.37193 0.17168,-5.49938 0.64108,-6.64523 3.20441,-7.82229 1.52187,-0.69884 2.42425,-0.79766 7.30307,-0.79982 6.75767,-0.003 7.98061,0.38279 9.09592,2.86921 0.61253,1.3655 0.72342,2.47625 0.73034,7.31525 0.007,5.38513 -0.0388,5.75973 -0.82685,6.67489 -0.62002,0.71994 -1.40826,1.06314 -3.06165,1.33297 -3.40014,0.55493 -11.60256,0.43314 -13.35505,-0.19828 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.370491;stroke-opacity:1" id="path991" d="m 339.04414,731.97109 c -3.60561,-0.93726 -4.48264,-2.73045 -4.45483,-9.10842 0.0218,-5.00727 0.73904,-7.15345 2.73101,-8.17253 1.29271,-0.66135 2.19762,-0.74953 7.69168,-0.74953 8.49855,0 8.96303,0.26628 9.77396,5.60339 0.32491,2.13833 0.32915,3.61396 0.0172,5.9992 -0.53103,4.06091 -1.10757,5.18233 -3.09269,6.01548 -2.09206,0.87802 -9.89752,1.13216 -12.66637,0.41241 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.365528;stroke-opacity:1" id="path993" d="m 337.75825,770.7391 c -2.54567,-0.94315 -3.11216,-2.48804 -3.09149,-8.43076 0.028,-8.05586 1.30547,-9.15871 10.57454,-9.12914 4.14079,0.0132 5.1614,0.13044 6.36851,0.73158 2.63337,1.31141 2.92902,2.08079 3.06977,7.98827 0.13827,5.8041 -0.24296,8.00904 -1.50624,8.71158 -1.28401,0.71409 -13.55834,0.81639 -15.41509,0.12847 z"/><path style="fill:#333;fill-opacity:1;stroke:#333;stroke-width:.370789;stroke-opacity:1" id="path995" d="m 340.25178,810.31175 c -2.30728,-0.35082 -4.07035,-1.26307 -4.79602,-2.48153 -0.63065,-1.05893 -0.72313,-1.90705 -0.72313,-6.63222 0,-8.75452 0.4422,-9.15459 10.11842,-9.15459 9.55452,0 9.93447,0.34222 9.93447,8.94819 0,8.55026 -0.56098,9.15949 -8.62352,9.3653 -2.64352,0.0675 -5.30312,0.0472 -5.91022,-0.0451 z"/><path id="path4136" d="m 620.05176,101.33936 h -13.19009 l -0.0372,-8.25531 h -14.10678 c -3.694,0 -4.86707,3.29254 -4.86707,8.2606 v 75.70196 c 0,3.53235 3.40852,6.31095 6.44045,6.31095 h 9.52259 c 2.5944,0 2.74434,-2.75044 3.01169,-5.11156 v -5.02502 h 13.00529 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4138" d="M 606.85329,173.06935 V 101.88171" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#000;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="path4158" d="m 678.37103,56.29539 v 15.94604 h -43.5888 V 56.01064 c 0,-2.09826 1.87258,-3.04523 3.55963,-3.4883 12.17302,-3.19604 25.27663,-3.03408 36.83267,0 1.82189,0.47838 3.1965,1.67683 3.1965,3.77305 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4146" d="m 720.40437,200.84448 c 1.81167,5.59747 14.31597,16.05818 26.80398,18.49431 0,3.18475 -2.17456,7.59933 -6.67803,7.59933 h -42.94533 c -9.04439,0 -6.76848,25.30224 7.88272,25.30224 h 14.82275 c 30.79579,10.88463 58.29906,11.10676 88.35628,0 h 15.61665 c 13.60575,0 16.40685,-25.0713 7.81066,-25.0713 h -42.12588 c -6.10893,0 -8.96884,-3.67481 -8.61035,-7.40557 10.9644,-3.90513 20.75456,-9.02232 26.28159,-18.53931 v -3.53463 h -87.25178 z"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.97231;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4154" d="m 724.94622,197.61379 c 0,0.29572 0,7.24873 0,7.24873 0,3.02618 -2.56512,4.21618 -5.85626,4.21618 -17.73054,1.12554 -39.27177,1.0596 -57.43145,0 -3.05168,0 -6.04433,-2.08878 -6.01039,-4.32715 v -8.83908 h 69.2981 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4148" d="m 741.03641,226.83735 h 45.04178"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.1477;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4142" d="m 643.93309,192.24653 v 12.01609 c 0,1.03496 1.44365,2.19259 2.56837,2.19259 h 45.10268 c 1.41577,0 3.13375,-1.20624 3.13375,-2.67504 v -11.62115 z"/><path style="fill:none;stroke:#000;stroke-width:2.15573;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4150" d="m 746.85546,219.17785 h 35.76351"/><path style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.96467;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4144" d="m 870.42561,197.60063 c 0,0.29344 0,7.19268 0,7.19268 0,3.00278 -2.56501,4.18358 -5.85597,4.18358 -17.73073,1.11684 -39.27172,1.05141 -57.43168,0 -3.05166,0 -6.04429,-2.07262 -6.01013,-4.29369 v -8.77073 h 69.29778 z"/><path id="path4160" d="m 797.67583,197.63487 c 0,0.29939 0,7.33855 0,7.33855 0,3.06368 -2.56511,4.26842 -5.85601,4.26842 -17.73077,1.1395 -39.27177,1.07274 -57.4317,0 -3.05168,0 -6.0443,-2.11465 -6.01014,-4.38077 v -8.9486 h 69.29785 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:1.9845;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/><path id="path4140" d="m 907.97933,199.65348 c 8.52966,0 24.99089,-16.61076 24.99089,-25.55625 v -58.65862 c -4.57443,-17.00507 -13.35533,-35.47833 -41.84537,-41.00408 -4.97535,0 -7.55529,-4.59359 -7.55529,-7.40352 -26.96999,-35.0496 -56.25473,-53.08707 -86.3059,-65.49263 h -63.63968 c -27.37307,12.02627 -42.63451,29.98675 -54.6313,49.5466 V 61.9055 c 0,4.46695 -3.77561,9.11203 -8.71777,9.11203 h -52.88777 v 128.70726 z" style="fill:#ff5f53;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"/><path id="path4166" d="M 898.96304,95.57843 H 671.57211 c 0.11854,-46.39485 23.40196,-94.42781 68.1792,-94.42781 l 63.60853,0.74648 c 62.27359,11.13309 75.07205,54.96226 95.6032,93.68133 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path id="path4168" d="M 917.62642,126.18349 H 669.66769 v 27.99243 c 0,9.45565 12.31669,23.51364 23.99616,23.51364 h 207.96534 c 12.6963,0 22.09152,-12.0229 22.09152,-21.64746 0,-11.5947 1.02012,-29.85861 -6.09429,-29.85861 z" style="fill:#1a1a1a;fill-opacity:1;stroke:#000;stroke-width:2.30124px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4232" d="m 754.52313,152.06817 v -10.42123 l 4.83314,5.9e-4 c 2.65811,3.3e-4 5.22066,0.0205 5.69422,0.0424 2.06412,0.0999 3.36854,0.38224 4.26309,0.92274 1.37392,0.83011 2.28986,2.29536 2.52187,4.03406 0.0698,0.53061 0.0278,1.70342 -0.0814,2.19391 -0.3657,1.6476 -1.32187,2.879 -2.82086,3.63292 -0.57443,0.2889 -1.45224,0.5764 -2.13805,0.70022 -0.28454,0.0512 -0.51679,0.1037 -0.51608,0.11614 6.8e-4,0.0137 0.15343,0.11316 0.3387,0.22298 0.59653,0.35375 1.21864,0.8364 1.75031,1.3583 0.86316,0.8471 1.40854,1.61519 3.70213,5.21324 0.77646,1.21827 1.44017,2.25774 1.4746,2.30996 l 0.0626,0.0949 h -2.53768 -2.53792 l -1.69473,-2.47872 c -3.18932,-4.66409 -3.60893,-5.21082 -4.38563,-5.71206 -0.59814,-0.38608 -1.12447,-0.49152 -2.64298,-0.52955 l -1.02243,-0.0258 v 4.37299 4.37295 h -2.13132 -2.13132 v -10.42122 z m 10.52829,-1.70253 c 0.90687,-0.11613 1.36601,-0.31747 1.80747,-0.79267 0.44566,-0.47955 0.62444,-0.99717 0.62444,-1.80829 0,-1.12302 -0.42359,-1.86219 -1.30232,-2.27314 -0.68255,-0.31921 -0.57259,-0.31053 -4.17686,-0.33119 l -3.21837,-0.0182 v 2.66568 2.66571 l 2.87406,-0.0205 c 2.26803,-0.0161 2.98311,-0.0346 3.39158,-0.087 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4234" d="M 763.60822,52.91602 V 42.51329 l 5.50031,0.0182 c 5.86555,0.0182 5.99551,0.0235 7.21251,0.23684 0.72764,0.12779 1.2063,0.27395 1.73262,0.5297 0.56119,0.27264 0.92919,0.53686 1.3444,0.96517 0.6865,0.70821 1.17119,1.61242 1.4232,2.65506 0.10465,0.43649 0.11392,0.54629 0.11623,1.4018 6.9e-4,0.72536 -0.0233,1.00826 -0.0743,1.29452 -0.49307,2.37268 -2.15713,3.86338 -4.92053,4.40866 -0.52052,0.10275 -0.58004,0.12279 -0.5089,0.17313 0.044,0.0312 0.27805,0.18384 0.51935,0.33899 1.26535,0.81414 2.04879,1.63119 3.24347,3.38328 0.43519,0.6382 3.38993,5.24266 3.43201,5.34806 0.0233,0.0423 -0.49075,0.051 -2.51118,0.0421 l -2.53257,-0.0114 -1.89628,-2.76629 c -2.70088,-3.93961 -3.00426,-4.35632 -3.57776,-4.91249 -0.79112,-0.76705 -1.35952,-0.94266 -3.17329,-0.98035 l -1.06565,-0.0228 v 4.3512 4.35117 h -2.13132 -2.13131 v -10.4027 z m 10.29044,-1.66304 c 0.70021,-0.0758 1.02521,-0.15376 1.4046,-0.337 0.60955,-0.2945 1.03662,-0.84304 1.20307,-1.54567 0.0907,-0.37929 0.0884,-1.17286 -0.002,-1.51464 -0.27525,-1.03723 -1.09727,-1.6771 -2.30428,-1.79364 -0.22549,-0.0228 -1.74122,-0.0399 -3.36922,-0.0406 l -2.96011,-0.002 v 2.66306 2.66304 l 2.78783,-0.0228 c 1.66078,-0.0137 2.97079,-0.0419 3.23998,-0.0711 v 0 z"/><path style="fill:#b3b3b3;fill-opacity:1;stroke:#000;stroke-width:.0426219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" id="path4236" d="m 743.58665,61.4392 v -1.87954 l 5.57588,-6.74897 c 3.06678,-3.71194 5.57589,-6.75827 5.57589,-6.76966 0,-0.0114 -2.22827,-0.0205 -4.95147,-0.0205 h -4.95146 v -1.75092 -1.75094 h 7.7716 7.77183 v 1.61419 1.61418 l -5.83789,7.04557 -5.83763,7.04554 6.05291,0.0114 6.05316,0.0114 v 1.7297 1.72968 h -8.6113 -8.61152 v -1.87951 z"/><path style="fill:#ff5f53;fill-opacity:1;stroke-width:.176777" id="path141" d="m 337.37689,564.16039 c 0.004,-3.45814 0.214,-4.28994 1.21089,-4.80544 1.18361,-0.61208 3.0461,-0.20122 3.8108,0.84064 0.33284,0.45348 0.37167,0.7949 0.42717,3.75651 l 0.0611,3.25769 h -2.7569 -2.7569 z"/></svg>
\ No newline at end of file diff --git a/src/Ryujinx.UI.Common/Resources/Controller_ProCon.svg b/src/Ryujinx.UI.Common/Resources/Controller_ProCon.svg new file mode 100644 index 00000000..f5380f3a --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Controller_ProCon.svg @@ -0,0 +1,132 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 27.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<svg version="1.1" id="Layer_1" xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1050 1050.5" + style="enable-background:new 0 0 1050 1050.5;" xml:space="preserve"> +<style type="text/css"> + .st0{fill:#20221F;} + .st1{fill:#3B3B3B;} + .st2{fill:#121212;} + .st3{fill:#444542;} + .st4{fill:#FFFFFF;} + .st5{fill:#444542;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;} + .st6{fill:#454644;} + .st7{fill:#454644;stroke:#FFFFFF;stroke-width:2;stroke-miterlimit:10;} + .st8{fill:#3B3C3A;} + .st9{font-family:'Helvetica-Bold';} + .st10{font-size:40px;} + .st11{fill:#0D0D0A;} +</style> +<g id="Front"> + <path id="Right_Grip_00000028282943321285403220000008369785803052272051_" class="st0" d="M766,850.5 + c34,28.2,27.6,35.9,68.5,108.5c36.7,74.7,64.4,104.4,125.1,84.1v0c95.3-57.9,59.3-145.3,43.6-275.2c-10-60.6-35.6-190.3-35.6-190.3 + L766,850.5z"/> + <path id="Left_Grip" class="st0" d="M82.3,577.6c0,0-25.6,129.7-35.6,190.3C31,897.8-5,985.1,90.3,1043v0 + c60.8,20.3,88.4-9.4,125.1-84.1c40.9-72.7,34.5-80.3,68.5-108.5L82.3,577.6z"/> + <path id="Right_Bumper_00000006710349871522532470000011078040965381267594_" class="st1" d="M676.3,378.4 + c10.1-4.3,39.7-22.5,58.7-19.7c59.5,0.9,166.7,17.7,172.6,81.2"/> + <path id="Left_Bumper_00000024680414077879639570000011759596763560342154_" class="st1" d="M142.4,439.9 + c5.9-63.4,113-80.2,172.6-81.2c19-2.8,48.6,15.4,58.7,19.7"/> + <path id="Background_00000141418846164053065470000016150094984198570163_" class="st2" d="M766,850.5 + c35.5-30.8,68.5-74.7,96-113.5c26.9-36.3,94.7-136.7,105.6-159.3c0-2.4-6.3-30.1-12.8-56.2C919.1,361.9,702.2,378.1,525,378.1 + c-177.4,0-394.1-16.2-429.9,143.3c-6.5,26-12.8,53.8-12.8,56.2c10.9,22.6,78.8,123,105.6,159.3c27.5,38.8,60.5,82.8,96,113.5"/> + <g id="Directional_Pad"> + <path id="Background_00000032628022449190479560000015279211462520783249_" class="st3" d="M466.2,683.5h-40c-2.8,0-5-2.2-5-5v-40 + c0-2.8-2.2-5-5-5h-30c-2.8,0-5,2.2-5,5v40c0,2.8-2.2,5-5,5h-40c-2.8,0-5,2.2-5,5v30c0,2.8,2.2,5,5,5h40c2.8,0,5,2.2,5,5v40 + c0,2.8,2.2,5,5,5h30c2.8,0,5-2.2,5-5v-40c0-2.8,2.2-5,5-5h40c2.8,0,5-2.2,5-5v-30C471.2,685.8,469,683.5,466.2,683.5z"/> + <g id="Arrows"> + <g> + <polygon class="st4" points="393.7,746 408.7,746 401.2,761 "/> + </g> + <g> + <polygon class="st4" points="358.7,696 358.7,711 343.7,703.5 "/> + </g> + <g> + <polygon class="st4" points="408.7,661 393.7,661 401.2,646 "/> + </g> + <g> + <polygon class="st4" points="443.7,711 443.7,696 458.7,703.5 "/> + </g> + </g> + </g> + <g id="R_Thumbstick_00000152226188525111835500000011838297421350334865_"> + <circle id="Background_00000035532849542660068350000006517224202948159422_" class="st0" cx="650.6" cy="703.5" r="55"/> + <circle id="Stick" class="st5" cx="650.6" cy="703.5" r="45"/> + </g> + <g id="L_Thumbstick_00000047032468231999382210000005512347386782594484_"> + <circle id="Background_00000182502673988292164000000007125719133096369561_" class="st0" cx="240.2" cy="564.8" r="55"/> + <circle id="Stick_00000075121990265259598900000000214370239054002365_" class="st5" cx="240.2" cy="564.8" r="45"/> + </g> + <g id="Minus_Button"> + <circle id="_Background_00000120554951013892796430000015877571645746699662_" class="st6" cx="401" cy="489.3" r="22.5"/> + <polyline id="Plus_00000039131319101621183460000006196023733899658629_" class="st4" points="386.2,491.8 386.2,486.8 + 416.2,486.8 416.2,491.8 "/> + </g> + <g id="Plus_Button"> + <circle id="_Background" class="st6" cx="650.4" cy="489.6" r="22.5"/> + <polygon id="Plus" class="st4" points="665.6,487.1 653.1,487.1 653.1,474.4 648.1,474.4 648.1,487.1 635.6,487.1 635.6,492.1 + 648.1,492.1 648.1,504.4 653.1,504.4 653.1,492.1 665.6,492.1 "/> + </g> + <g id="Home_Button_00000029758737660217614780000001403165237001195407_"> + <circle id="_Background_00000132788487854287834010000009548421243227981499_" class="st6" cx="605.4" cy="564.8" r="22.5"/> + <path id="Home" class="st4" d="M605.4,549.8l-15,15h5v15h20v-15h5L605.4,549.8z M610.4,574.8h-10v-10h10V574.8z"/> + </g> + <g id="Capture_Button_00000105394663133565750060000017455731898661404072_"> + <path class="st6" d="M468.6,586.5h-30c-2.8,0-5-2.2-5-5v-29.5c0-2.8,2.2-5,5-5h30c2.8,0,5,2.2,5,5v29.5 + C473.6,584.2,471.4,586.5,468.6,586.5z"/> + <circle class="st7" cx="453.6" cy="566.7" r="15"/> + </g> + <g id="Buttons_00000023239109225132251950000005218343074279628213_"> + <g id="A_Button"> + <circle id="Background_00000006699118933065716380000004636085088820886913_" class="st8" cx="863.9" cy="564.8" r="35"/> + <text transform="matrix(1 0 0 1 849.4224 578.6607)" class="st4 st9 st10">A</text> + </g> + <g id="X_Button"> + <circle id="Background_00000083074713085756701790000016893839312974798515_" class="st8" cx="793.9" cy="494.8" r="35"/> + <text transform="matrix(1 0 0 1 780.5266 508.6604)" class="st4 st9 st10">X</text> + </g> + <g id="Y_Button_00000100344340438574137780000014238704828967683973_"> + <circle id="Background_00000137100455694543496620000011124722786613194377_" class="st8" cx="723.9" cy="564.8" r="35"/> + <text transform="matrix(1 0 0 1 710.5263 578.661)" class="st4 st9 st10">Y</text> + </g> + <g id="B_Button_00000041994261956088037220000013468634544777304733_"> + <circle id="Background_00000096038108578846046800000001873940014252420514_" class="st8" cx="793.9" cy="634.8" r="35"/> + <text transform="matrix(1 0 0 1 780.9706 648.6605)" class="st4 st9 st10">B</text> + </g> + </g> +</g> +<g id="Top_Down"> + <path id="Left_Grip_00000026131988385328425370000016677941743356253314_" class="st0" d="M219.2,78.5 + c-12.5-17.6-25.9-42.3-45.6-58.6C153.5,3.3,112.1-4.7,87.1,5.8c-13.9,5.8-33.4,33.1-42.7,52.8C33.9,80.9,30.4,109.9,32,141.4 + c1.2,25.1,5.3,51.7,14.2,78.6c0,0,14.3,53.8,42.8,80.8c11.2,10.6,35,26.6,35,26.6l116-217.5C240,109.9,224.6,86.2,219.2,78.5z"/> + <path id="Right_Grip_00000016782759094708820330000002450847065936193693_" class="st0" d="M828.6,78.5 + c12.5-17.6,25.9-42.3,45.6-58.6c20.1-16.6,61.4-24.5,86.5-14.1c13.9,5.8,33.4,33.1,42.7,52.8c10.5,22.3,13.9,51.3,12.4,82.8 + c-1.2,25.1-5.3,51.7-14.2,78.6c0,0-14.3,53.8-42.8,80.8c-11.2,10.6-35,26.6-35,26.6l-116-217.5C807.8,109.9,823.2,86.2,828.6,78.5z + "/> + <path id="Background_00000169534857628063347190000007586592143875928969_" class="st11" d="M866,122.2 + c66.3,18.7,85.1,128.8,69,186c-2.5,54.2-148.9,15.3-265.1,31.2c-41.1,1.7-91.8,2.4-145.9,2.3c-54.1,0-104.8-0.6-145.9-2.3 + c-116.2-15.9-262.6,23.1-265.1-31.2c-16.1-57.1,2.6-167.3,69-186l60.5-18.8l38.9-1.9c40.2,0.1,142.8,0,242.7,0 + c99.9,0,202.4,0.1,242.7,0l38.9,1.9L866,122.2z"/> + <g id="ZL_Trigger_00000005254517714433203260000014117442438696169895_"> + <path id="Background_00000111870097528015387240000017384507710402295183_" class="st1" d="M145.9,239.2 + c15.2-97.4,38.1-147.2,141.7-137c8.2,16.4,43.3,83,50.6,105.7C280.6,227.2,204.7,225.6,145.9,239.2z"/> + <text id="ZL_Trigger" transform="matrix(1.0139 0 0 1 218.3906 179.3992)" class="st4 st9 st10">ZL</text> + </g> + <g id="ZR_Trigger"> + <path id="Background_00000133526766189752063450000016781240006605114763_" class="st1" d="M716.2,207.9 + c7.4-22.7,42.5-89.3,50.6-105.7c103.7-10.2,126.5,39.6,141.7,137C849.8,225.6,773.8,227.2,716.2,207.9z"/> + + <text id="ZL_Trigger_00000000206350378518266660000001315160307759857328_" transform="matrix(1.0139 0 0 1 784.2356 179.3992)" class="st4 st9 st10">ZR</text> + </g> + <g id="R_Trigger_00000085939413106284991650000014018840000393673094_"> + <path id="Background" class="st1" d="M664,318.5c7-10.1,27.8-78.4,45.4-78.7C1040.8,243.7,897.1,334,664,318.5z"/> + <text id="R_Trigger" transform="matrix(1 0 0 1 769.6461 292.8947)" class="st4 st9 st10">R</text> + </g> + <g id="L_Trigger"> + <path id="Background_00000043427985111927735300000011910735497762731703_" class="st1" d="M340.6,238.6 + c17.6,0.3,38.4,68.6,45.4,78.7C152.9,332.8,9.2,242.6,340.6,238.6z"/> + + <text id="R_Trigger_00000092444210070373642420000009814634285137007748_" transform="matrix(1 0 0 1 253.7327 291.7279)" class="st4 st9 st10">L</text> + </g> +</g> +</svg> diff --git a/src/Ryujinx.UI.Common/Resources/Icon_NCA.png b/src/Ryujinx.UI.Common/Resources/Icon_NCA.png Binary files differnew file mode 100644 index 00000000..feae77b9 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Icon_NCA.png diff --git a/src/Ryujinx.UI.Common/Resources/Icon_NRO.png b/src/Ryujinx.UI.Common/Resources/Icon_NRO.png Binary files differnew file mode 100644 index 00000000..3a9da621 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Icon_NRO.png diff --git a/src/Ryujinx.UI.Common/Resources/Icon_NSO.png b/src/Ryujinx.UI.Common/Resources/Icon_NSO.png Binary files differnew file mode 100644 index 00000000..16de84be --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Icon_NSO.png diff --git a/src/Ryujinx.UI.Common/Resources/Icon_NSP.png b/src/Ryujinx.UI.Common/Resources/Icon_NSP.png Binary files differnew file mode 100644 index 00000000..4f98e22e --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Icon_NSP.png diff --git a/src/Ryujinx.UI.Common/Resources/Icon_XCI.png b/src/Ryujinx.UI.Common/Resources/Icon_XCI.png Binary files differnew file mode 100644 index 00000000..f9c34f47 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Icon_XCI.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Amiibo.png b/src/Ryujinx.UI.Common/Resources/Logo_Amiibo.png Binary files differnew file mode 100644 index 00000000..cbee8037 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_Amiibo.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Discord_Dark.png b/src/Ryujinx.UI.Common/Resources/Logo_Discord_Dark.png Binary files differnew file mode 100644 index 00000000..baececa9 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_Discord_Dark.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Discord_Light.png b/src/Ryujinx.UI.Common/Resources/Logo_Discord_Light.png Binary files differnew file mode 100644 index 00000000..25fc892d --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_Discord_Light.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Dark.png b/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Dark.png Binary files differnew file mode 100644 index 00000000..50b81752 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Dark.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Light.png b/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Light.png Binary files differnew file mode 100644 index 00000000..95bc742b --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_GitHub_Light.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Dark.png b/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Dark.png Binary files differnew file mode 100644 index 00000000..9a521e3f --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Dark.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Light.png b/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Light.png Binary files differnew file mode 100644 index 00000000..44da0ac4 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_Patreon_Light.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png b/src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png Binary files differnew file mode 100644 index 00000000..0e8da15e --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_Ryujinx.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Dark.png b/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Dark.png Binary files differnew file mode 100644 index 00000000..66962e7d --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Dark.png diff --git a/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Light.png b/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Light.png Binary files differnew file mode 100644 index 00000000..040ca169 --- /dev/null +++ b/src/Ryujinx.UI.Common/Resources/Logo_Twitter_Light.png diff --git a/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj b/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj new file mode 100644 index 00000000..387e998b --- /dev/null +++ b/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj @@ -0,0 +1,68 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <TargetFramework>net8.0</TargetFramework> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + + <ItemGroup> + <None Remove="Resources\Controller_JoyConLeft.svg" /> + <None Remove="Resources\Controller_JoyConPair.svg" /> + <None Remove="Resources\Controller_JoyConRight.svg" /> + <None Remove="Resources\Controller_ProCon.svg" /> + <None Remove="Resources\Icon_NCA.png" /> + <None Remove="Resources\Icon_NRO.png" /> + <None Remove="Resources\Icon_NSO.png" /> + <None Remove="Resources\Icon_NSP.png" /> + <None Remove="Resources\Icon_XCI.png" /> + <None Remove="Resources\Logo_Amiibo.png" /> + <None Remove="Resources\Logo_Discord.png" /> + <None Remove="Resources\Logo_GitHub.png" /> + <None Remove="Resources\Logo_Patreon.png" /> + <None Remove="Resources\Logo_Ryujinx.png" /> + <None Remove="Resources\Logo_Twitter.png" /> + </ItemGroup> + + <ItemGroup> + <EmbeddedResource Include="Resources\Controller_JoyConLeft.svg" /> + <EmbeddedResource Include="Resources\Controller_JoyConPair.svg" /> + <EmbeddedResource Include="Resources\Controller_JoyConRight.svg" /> + <EmbeddedResource Include="Resources\Controller_ProCon.svg" /> + <EmbeddedResource Include="Resources\Icon_NCA.png" /> + <EmbeddedResource Include="Resources\Icon_NRO.png" /> + <EmbeddedResource Include="Resources\Icon_NSO.png" /> + <EmbeddedResource Include="Resources\Icon_NSP.png" /> + <EmbeddedResource Include="Resources\Icon_XCI.png" /> + <EmbeddedResource Include="Resources\Logo_Amiibo.png" /> + <EmbeddedResource Include="Resources\Logo_Ryujinx.png" /> + <EmbeddedResource Include="Resources\Logo_Discord_Dark.png" /> + <EmbeddedResource Include="Resources\Logo_Discord_Light.png" /> + <EmbeddedResource Include="Resources\Logo_GitHub_Dark.png" /> + <EmbeddedResource Include="Resources\Logo_GitHub_Light.png" /> + <EmbeddedResource Include="Resources\Logo_Patreon_Dark.png" /> + <EmbeddedResource Include="Resources\Logo_Patreon_Light.png" /> + <EmbeddedResource Include="Resources\Logo_Twitter_Dark.png" /> + <EmbeddedResource Include="Resources\Logo_Twitter_Light.png" /> + </ItemGroup> + + <ItemGroup Condition="'$(RuntimeIdentifier)' == 'linux-x64' OR '$(RuntimeIdentifier)' == 'linux-arm64' OR '$(RuntimeIdentifier)' == ''"> + <EmbeddedResource Include="..\..\distribution\linux\shortcut-template.desktop" /> + </ItemGroup> + + <ItemGroup Condition="'$(RuntimeIdentifier)' == 'osx-x64' OR '$(RuntimeIdentifier)' == 'osx-arm64' OR '$(RuntimeIdentifier)' == ''"> + <EmbeddedResource Include="..\..\distribution\macos\shortcut-template.plist" /> + <EmbeddedResource Include="..\..\distribution\macos\shortcut-launch-script.sh" /> + </ItemGroup> + + <ItemGroup> + <PackageReference Include="DiscordRichPresence" /> + <PackageReference Include="securifybv.ShellLink" /> + </ItemGroup> + + <ItemGroup> + <ProjectReference Include="..\Ryujinx.Common\Ryujinx.Common.csproj" /> + <ProjectReference Include="..\Ryujinx.HLE\Ryujinx.HLE.csproj" /> + <ProjectReference Include="..\Ryujinx.Graphics.Vulkan\Ryujinx.Graphics.Vulkan.csproj" /> + </ItemGroup> + +</Project> diff --git a/src/Ryujinx.UI.Common/SystemInfo/LinuxSystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/LinuxSystemInfo.cs new file mode 100644 index 00000000..c7fe05a0 --- /dev/null +++ b/src/Ryujinx.UI.Common/SystemInfo/LinuxSystemInfo.cs @@ -0,0 +1,85 @@ +using Ryujinx.Common.Logging; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Runtime.Versioning; + +namespace Ryujinx.UI.Common.SystemInfo +{ + [SupportedOSPlatform("linux")] + class LinuxSystemInfo : SystemInfo + { + internal LinuxSystemInfo() + { + string cpuName = GetCpuidCpuName(); + + if (cpuName == null) + { + var cpuDict = new Dictionary<string, string>(StringComparer.Ordinal) + { + ["model name"] = null, + ["Processor"] = null, + ["Hardware"] = null, + }; + + ParseKeyValues("/proc/cpuinfo", cpuDict); + + cpuName = cpuDict["model name"] ?? cpuDict["Processor"] ?? cpuDict["Hardware"] ?? "Unknown"; + } + + var memDict = new Dictionary<string, string>(StringComparer.Ordinal) + { + ["MemTotal"] = null, + ["MemAvailable"] = null, + }; + + ParseKeyValues("/proc/meminfo", memDict); + + // Entries are in KiB + ulong.TryParse(memDict["MemTotal"]?.Split(' ')[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong totalKiB); + ulong.TryParse(memDict["MemAvailable"]?.Split(' ')[0], NumberStyles.Integer, CultureInfo.InvariantCulture, out ulong availableKiB); + + CpuName = $"{cpuName} ; {LogicalCoreCount} logical"; + RamTotal = totalKiB * 1024; + RamAvailable = availableKiB * 1024; + } + + private static void ParseKeyValues(string filePath, Dictionary<string, string> itemDict) + { + if (!File.Exists(filePath)) + { + Logger.Error?.Print(LogClass.Application, $"File \"{filePath}\" not found"); + + return; + } + + int count = itemDict.Count; + + using StreamReader file = new(filePath); + + string line; + while ((line = file.ReadLine()) != null) + { + string[] kvPair = line.Split(':', 2, StringSplitOptions.TrimEntries); + + if (kvPair.Length < 2) + { + continue; + } + + string key = kvPair[0]; + + if (itemDict.TryGetValue(key, out string value) && value == null) + { + itemDict[key] = kvPair[1]; + + if (--count <= 0) + { + break; + } + } + } + } + } +} diff --git a/src/Ryujinx.UI.Common/SystemInfo/MacOSSystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/MacOSSystemInfo.cs new file mode 100644 index 00000000..36deaf35 --- /dev/null +++ b/src/Ryujinx.UI.Common/SystemInfo/MacOSSystemInfo.cs @@ -0,0 +1,164 @@ +using Ryujinx.Common.Logging; +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; +using System.Text; + +namespace Ryujinx.UI.Common.SystemInfo +{ + [SupportedOSPlatform("macos")] + partial class MacOSSystemInfo : SystemInfo + { + internal MacOSSystemInfo() + { + if (SysctlByName("kern.osversion", out string buildRevision) != 0) + { + buildRevision = "Unknown Build"; + } + + OsDescription = $"macOS {Environment.OSVersion.Version} ({buildRevision}) ({RuntimeInformation.OSArchitecture})"; + + string cpuName = GetCpuidCpuName(); + + if (cpuName == null && SysctlByName("machdep.cpu.brand_string", out cpuName) != 0) + { + cpuName = "Unknown"; + } + + ulong totalRAM = 0; + + if (SysctlByName("hw.memsize", ref totalRAM) != 0) // Bytes + { + totalRAM = 0; + } + + CpuName = $"{cpuName} ; {LogicalCoreCount} logical"; + RamTotal = totalRAM; + RamAvailable = GetVMInfoAvailableMemory(); + } + + static ulong GetVMInfoAvailableMemory() + { + var port = mach_host_self(); + + uint pageSize = 0; + var result = host_page_size(port, ref pageSize); + + if (result != 0) + { + Logger.Error?.Print(LogClass.Application, $"Failed to query Available RAM. host_page_size() error = {result}"); + return 0; + } + + const int Flavor = 4; // HOST_VM_INFO64 + uint count = (uint)(Marshal.SizeOf<VMStatistics64>() / sizeof(int)); // HOST_VM_INFO64_COUNT + VMStatistics64 stats = new(); + result = host_statistics64(port, Flavor, ref stats, ref count); + + if (result != 0) + { + Logger.Error?.Print(LogClass.Application, $"Failed to query Available RAM. host_statistics64() error = {result}"); + return 0; + } + + return (ulong)(stats.FreeCount + stats.InactiveCount) * pageSize; + } + + private const string SystemLibraryName = "libSystem.dylib"; + + [LibraryImport(SystemLibraryName, SetLastError = true)] + private static partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, IntPtr oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize); + + private static int SysctlByName(string name, IntPtr oldValue, ref ulong oldSize) + { + if (sysctlbyname(name, oldValue, ref oldSize, IntPtr.Zero, 0) == -1) + { + int err = Marshal.GetLastWin32Error(); + + Logger.Error?.Print(LogClass.Application, $"Cannot retrieve '{name}'. Error Code {err}"); + + return err; + } + + return 0; + } + + private static int SysctlByName<T>(string name, ref T oldValue) + { + unsafe + { + ulong oldValueSize = (ulong)Unsafe.SizeOf<T>(); + + return SysctlByName(name, (IntPtr)Unsafe.AsPointer(ref oldValue), ref oldValueSize); + } + } + + private static int SysctlByName(string name, out string oldValue) + { + oldValue = default; + + ulong strSize = 0; + + int res = SysctlByName(name, IntPtr.Zero, ref strSize); + + if (res == 0) + { + byte[] rawData = new byte[strSize]; + + unsafe + { + fixed (byte* rawDataPtr = rawData) + { + res = SysctlByName(name, (IntPtr)rawDataPtr, ref strSize); + } + + if (res == 0) + { + oldValue = Encoding.ASCII.GetString(rawData); + } + } + } + + return res; + } + + [LibraryImport(SystemLibraryName, SetLastError = true)] + private static partial uint mach_host_self(); + + [LibraryImport(SystemLibraryName, SetLastError = true)] + private static partial int host_page_size(uint host, ref uint out_page_size); + + [StructLayout(LayoutKind.Sequential, Pack = 8)] + struct VMStatistics64 + { + public uint FreeCount; + public uint ActiveCount; + public uint InactiveCount; + public uint WireCount; + public ulong ZeroFillCount; + public ulong Reactivations; + public ulong Pageins; + public ulong Pageouts; + public ulong Faults; + public ulong CowFaults; + public ulong Lookups; + public ulong Hits; + public ulong Purges; + public uint PurgeableCount; + public uint SpeculativeCount; + public ulong Decompressions; + public ulong Compressions; + public ulong Swapins; + public ulong Swapouts; + public uint CompressorPageCount; + public uint ThrottledCount; + public uint ExternalPageCount; + public uint InternalPageCount; + public ulong TotalUncompressedPagesInCompressor; + } + + [LibraryImport(SystemLibraryName, SetLastError = true)] + private static partial int host_statistics64(uint hostPriv, int hostFlavor, ref VMStatistics64 hostInfo64Out, ref uint hostInfo64OutCnt); + } +} diff --git a/src/Ryujinx.UI.Common/SystemInfo/SystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/SystemInfo.cs new file mode 100644 index 00000000..38728b9c --- /dev/null +++ b/src/Ryujinx.UI.Common/SystemInfo/SystemInfo.cs @@ -0,0 +1,79 @@ +using Ryujinx.Common.Logging; +using Ryujinx.UI.Common.Helper; +using System; +using System.Runtime.InteropServices; +using System.Runtime.Intrinsics.X86; +using System.Text; + +namespace Ryujinx.UI.Common.SystemInfo +{ + public class SystemInfo + { + public string OsDescription { get; protected set; } + public string CpuName { get; protected set; } + public ulong RamTotal { get; protected set; } + public ulong RamAvailable { get; protected set; } + protected static int LogicalCoreCount => Environment.ProcessorCount; + + protected SystemInfo() + { + OsDescription = $"{RuntimeInformation.OSDescription} ({RuntimeInformation.OSArchitecture})"; + CpuName = "Unknown"; + } + + private static string ToGBString(ulong bytesValue) => (bytesValue == 0) ? "Unknown" : ValueFormatUtils.FormatFileSize((long)bytesValue, ValueFormatUtils.FileSizeUnits.Gibibytes); + + public void Print() + { + Logger.Notice.Print(LogClass.Application, $"Operating System: {OsDescription}"); + Logger.Notice.Print(LogClass.Application, $"CPU: {CpuName}"); + Logger.Notice.Print(LogClass.Application, $"RAM: Total {ToGBString(RamTotal)} ; Available {ToGBString(RamAvailable)}"); + } + + public static SystemInfo Gather() + { + if (OperatingSystem.IsWindows()) + { + return new WindowsSystemInfo(); + } + else if (OperatingSystem.IsLinux()) + { + return new LinuxSystemInfo(); + } + else if (OperatingSystem.IsMacOS()) + { + return new MacOSSystemInfo(); + } + + Logger.Error?.Print(LogClass.Application, "SystemInfo unsupported on this platform"); + + return new SystemInfo(); + } + + // x86 exposes a 48 byte ASCII "CPU brand" string via CPUID leaves 0x80000002-0x80000004. + internal static string GetCpuidCpuName() + { + if (!X86Base.IsSupported) + { + return null; + } + + // Check if CPU supports the query + if ((uint)X86Base.CpuId(unchecked((int)0x80000000), 0).Eax < 0x80000004) + { + return null; + } + + int[] regs = new int[12]; + + for (uint i = 0; i < 3; ++i) + { + (regs[4 * i], regs[4 * i + 1], regs[4 * i + 2], regs[4 * i + 3]) = X86Base.CpuId((int)(0x80000002 + i), 0); + } + + string name = Encoding.ASCII.GetString(MemoryMarshal.Cast<int, byte>(regs)).Replace('\0', ' ').Trim(); + + return string.IsNullOrEmpty(name) ? null : name; + } + } +} diff --git a/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs b/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs new file mode 100644 index 00000000..bf49c2a6 --- /dev/null +++ b/src/Ryujinx.UI.Common/SystemInfo/WindowsSystemInfo.cs @@ -0,0 +1,87 @@ +using Ryujinx.Common.Logging; +using System; +using System.Management; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; + +namespace Ryujinx.UI.Common.SystemInfo +{ + [SupportedOSPlatform("windows")] + partial class WindowsSystemInfo : SystemInfo + { + internal WindowsSystemInfo() + { + CpuName = $"{GetCpuidCpuName() ?? GetCpuNameWMI()} ; {LogicalCoreCount} logical"; // WMI is very slow + (RamTotal, RamAvailable) = GetMemoryStats(); + } + + private static (ulong Total, ulong Available) GetMemoryStats() + { + MemoryStatusEx memStatus = new(); + if (GlobalMemoryStatusEx(ref memStatus)) + { + return (memStatus.TotalPhys, memStatus.AvailPhys); // Bytes + } + + Logger.Error?.Print(LogClass.Application, $"GlobalMemoryStatusEx failed. Error {Marshal.GetLastWin32Error():X}"); + + return (0, 0); + } + + private static string GetCpuNameWMI() + { + ManagementObjectCollection cpuObjs = GetWMIObjects("root\\CIMV2", "SELECT * FROM Win32_Processor"); + + if (cpuObjs != null) + { + foreach (var cpuObj in cpuObjs) + { + return cpuObj["Name"].ToString().Trim(); + } + } + + return Environment.GetEnvironmentVariable("PROCESSOR_IDENTIFIER").Trim(); + } + + [StructLayout(LayoutKind.Sequential)] + private struct MemoryStatusEx + { + public uint Length; + public uint MemoryLoad; + public ulong TotalPhys; + public ulong AvailPhys; + public ulong TotalPageFile; + public ulong AvailPageFile; + public ulong TotalVirtual; + public ulong AvailVirtual; + public ulong AvailExtendedVirtual; + + public MemoryStatusEx() + { + Length = (uint)Marshal.SizeOf<MemoryStatusEx>(); + } + } + + [LibraryImport("kernel32.dll", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static partial bool GlobalMemoryStatusEx(ref MemoryStatusEx lpBuffer); + + private static ManagementObjectCollection GetWMIObjects(string scope, string query) + { + try + { + return new ManagementObjectSearcher(scope, query).Get(); + } + catch (PlatformNotSupportedException ex) + { + Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}"); + } + catch (COMException ex) + { + Logger.Error?.Print(LogClass.Application, $"WMI isn't available : {ex.Message}"); + } + + return null; + } + } +} diff --git a/src/Ryujinx.UI.Common/UserError.cs b/src/Ryujinx.UI.Common/UserError.cs new file mode 100644 index 00000000..706971ef --- /dev/null +++ b/src/Ryujinx.UI.Common/UserError.cs @@ -0,0 +1,39 @@ +namespace Ryujinx.UI.Common +{ + /// <summary> + /// Represent a common error that could be reported to the user by the emulator. + /// </summary> + public enum UserError + { + /// <summary> + /// No error to report. + /// </summary> + Success = 0x0, + + /// <summary> + /// No keys are present. + /// </summary> + NoKeys = 0x1, + + /// <summary> + /// No firmware is installed. + /// </summary> + NoFirmware = 0x2, + + /// <summary> + /// Firmware parsing failed. + /// </summary> + /// <remarks>Most likely related to keys.</remarks> + FirmwareParsingFailed = 0x3, + + /// <summary> + /// No application was found at the given path. + /// </summary> + ApplicationNotFound = 0x4, + + /// <summary> + /// An unknown error. + /// </summary> + Unknown = 0xDEAD, + } +} |
