Compare commits

..

1 Commits

Author SHA1 Message Date
dependabot[bot]
00a86f8fc2 ci: bump actions/github-script from 6 to 7
Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 16:10:59 +00:00
326 changed files with 1364 additions and 49129 deletions

View File

@@ -13,7 +13,7 @@ updates:
- package-ecosystem: nuget
directory: /
open-pull-requests-limit: 10
open-pull-requests-limit: 5
schedule:
interval: daily
labels:
@@ -22,19 +22,3 @@ updates:
- marysaka
commit-message:
prefix: nuget
groups:
Avalonia:
patterns:
- "*Avalonia*"
Silk.NET:
patterns:
- "Silk.NET*"
OpenTK:
patterns:
- "OpenTK*"
SixLabors:
patterns:
- "SixLabors*"
NUnit:
patterns:
- "NUnit*"

View File

@@ -79,21 +79,21 @@ jobs:
if: github.event_name == 'pull_request' && matrix.os == 'ubuntu-latest'
- name: Upload Ryujinx artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
path: publish
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
path: publish_sdl2_headless
if: github.event_name == 'pull_request' && matrix.os != 'macOS-latest'
- name: Upload Ryujinx.Ava artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-${{ matrix.RELEASE_ZIP_OS_NAME }}
path: publish_ava
@@ -144,14 +144,14 @@ jobs:
./distribution/macos/create_macos_build_headless.sh . publish_tmp_headless publish_headless ./distribution/macos/entitlements.xml "${{ env.RYUJINX_BASE_VERSION }}" "${{ steps.git_short_hash.outputs.result }}" "${{ matrix.configuration }}" "-p:ExtraDefineConstants=DISABLE_UPDATER"
- name: Upload Ryujinx.Ava artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: ava-ryujinx-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_ava/*.tar.gz"
if: github.event_name == 'pull_request'
- name: Upload Ryujinx.Headless.SDL2 artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: sdl2-ryujinx-headless-${{ matrix.configuration }}-${{ env.RYUJINX_BASE_VERSION }}+${{ steps.git_short_hash.outputs.result }}-macos_universal
path: "publish_headless/*.tar.gz"

View File

@@ -63,7 +63,7 @@ jobs:
- name: Upload report
if: failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v3
with:
name: dotnet-format
path: ./*-report.json

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT) }}
steps:
- uses: actions/github-script@v6
- uses: actions/github-script@v7
with:
script: |
const {owner, repo} = context.repo;

View File

@@ -34,7 +34,7 @@ jobs:
shell: bash
- name: Create tag
uses: actions/github-script@v6
uses: actions/github-script@v7
with:
script: |
github.rest.git.createRef({

View File

@@ -3,35 +3,34 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Avalonia" Version="11.0.7" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.7" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.7" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.7" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.7" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.10" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.10" />
<PackageVersion Include="Avalonia" Version="11.0.5" />
<PackageVersion Include="Avalonia.Controls.DataGrid" Version="11.0.5" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.5" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.5" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.5" />
<PackageVersion Include="Avalonia.Svg" Version="11.0.0.3" />
<PackageVersion Include="Avalonia.Svg.Skia" Version="11.0.0.3" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="Concentus" Version="1.1.7" />
<PackageVersion Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageVersion Include="DynamicData" Version="8.3.27" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.5" />
<PackageVersion Include="DynamicData" Version="7.14.2" />
<PackageVersion Include="FluentAvaloniaUI" Version="2.0.4" />
<PackageVersion Include="GtkSharp.Dependencies" Version="1.1.1" />
<PackageVersion Include="GtkSharp.Dependencies.osx" Version="0.0.5" />
<PackageVersion Include="jp2masa.Avalonia.Flexbox" Version="0.3.0-beta.4" />
<PackageVersion Include="LibHac" Version="0.19.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
<PackageVersion Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.2.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.7.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.0" />
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
<PackageVersion Include="NetCoreServer" Version="8.0.7" />
<PackageVersion Include="NetCoreServer" Version="7.0.0" />
<PackageVersion Include="NUnit" Version="3.13.3" />
<PackageVersion Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageVersion Include="OpenTK.Core" Version="4.8.2" />
<PackageVersion Include="OpenTK.Graphics" Version="4.8.2" />
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.2" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.2" />
<PackageVersion Include="OpenTK.Core" Version="4.8.1" />
<PackageVersion Include="OpenTK.Graphics" Version="4.8.1" />
<PackageVersion Include="OpenTK.Audio.OpenAL" Version="4.8.1" />
<PackageVersion Include="OpenTK.Windowing.GraphicsLibraryFramework" Version="4.8.1" />
<PackageVersion Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" />
<PackageVersion Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build13" />
<PackageVersion Include="Ryujinx.Graphics.Vulkan.Dependencies.MoltenVK" Version="1.2.0" />
@@ -46,7 +45,8 @@
<PackageVersion Include="SixLabors.ImageSharp" Version="1.0.4" />
<PackageVersion Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta11" />
<PackageVersion Include="SPB" Version="0.0.4-build28" />
<PackageVersion Include="System.Drawing.Common" Version="8.0.1" />
<PackageVersion Include="System.Drawing.Common" Version="8.0.0" />
<PackageVersion Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
<PackageVersion Include="System.IO.Hashing" Version="8.0.0" />
<PackageVersion Include="System.Management" Version="8.0.0" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.0.2-rc1-fb78016" />

View File

@@ -1,8 +0,0 @@
#!/bin/sh
launch_arch="$(uname -m)"
if [ "$(sysctl -in sysctl.proc_translated)" = "1" ]
then
launch_arch="arm64"
fi
arch -$launch_arch {0} {1}

View File

@@ -9,7 +9,7 @@ namespace ARMeilleure.Common
/// Represents a table of guest address to a value.
/// </summary>
/// <typeparam name="TEntry">Type of the value</typeparam>
public unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
unsafe class AddressTable<TEntry> : IDisposable where TEntry : unmanaged
{
/// <summary>
/// Represents a level in an <see cref="AddressTable{TEntry}"/>.

View File

@@ -517,10 +517,7 @@ namespace ARMeilleure.Decoders
SetA64("0x00111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_V, InstEmit.Sqrshrn_V, OpCodeSimdShImm.Create);
SetA64("0111111100>>>xxx100011xxxxxxxxxx", InstName.Sqrshrun_S, InstEmit.Sqrshrun_S, OpCodeSimdShImm.Create);
SetA64("0x10111100>>>xxx100011xxxxxxxxxx", InstName.Sqrshrun_V, InstEmit.Sqrshrun_V, OpCodeSimdShImm.Create);
SetA64("010111110>>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Si, InstEmit.Sqshl_Si, OpCodeSimdShImm.Create);
SetA64("0>001110<<1xxxxx010011xxxxxxxxxx", InstName.Sqshl_V, InstEmit.Sqshl_V, OpCodeSimdReg.Create);
SetA64("0000111100>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Vi, InstEmit.Sqshl_Vi, OpCodeSimdShImm.Create);
SetA64("010011110>>>>xxx011101xxxxxxxxxx", InstName.Sqshl_Vi, InstEmit.Sqshl_Vi, OpCodeSimdShImm.Create);
SetA64("0101111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_S, InstEmit.Sqshrn_S, OpCodeSimdShImm.Create);
SetA64("0x00111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_V, InstEmit.Sqshrn_V, OpCodeSimdShImm.Create);
SetA64("0111111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_S, InstEmit.Sqshrun_S, OpCodeSimdShImm.Create);

View File

@@ -116,7 +116,7 @@ namespace ARMeilleure.Instructions
}
else if (shift >= eSize)
{
if (op.RegisterSize == RegisterSize.Simd64)
if ((op.RegisterSize == RegisterSize.Simd64))
{
Operand res = context.VectorZeroUpper64(GetVec(op.Rd));
@@ -359,16 +359,6 @@ namespace ARMeilleure.Instructions
}
}
public static void Sqshl_Si(ArmEmitterContext context)
{
EmitShlImmOp(context, signedDst: true, ShlRegFlags.Signed | ShlRegFlags.Scalar | ShlRegFlags.Saturating);
}
public static void Sqshl_Vi(ArmEmitterContext context)
{
EmitShlImmOp(context, signedDst: true, ShlRegFlags.Signed | ShlRegFlags.Saturating);
}
public static void Sqshrn_S(ArmEmitterContext context)
{
if (Optimizations.UseAdvSimd)
@@ -1603,99 +1593,6 @@ namespace ARMeilleure.Instructions
Saturating = 1 << 3,
}
private static void EmitShlImmOp(ArmEmitterContext context, bool signedDst, ShlRegFlags flags = ShlRegFlags.None)
{
bool scalar = flags.HasFlag(ShlRegFlags.Scalar);
bool signed = flags.HasFlag(ShlRegFlags.Signed);
bool saturating = flags.HasFlag(ShlRegFlags.Saturating);
OpCodeSimdShImm op = (OpCodeSimdShImm)context.CurrOp;
Operand res = context.VectorZero();
int elems = !scalar ? op.GetBytesCount() >> op.Size : 1;
for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtract(context, op.Rn, index, op.Size, signed);
Operand e = !saturating
? EmitShlImm(context, ne, GetImmShl(op), op.Size)
: EmitShlImmSatQ(context, ne, GetImmShl(op), op.Size, signed, signedDst);
res = EmitVectorInsert(context, res, e, index, op.Size);
}
context.Copy(GetVec(op.Rd), res);
}
private static Operand EmitShlImm(ArmEmitterContext context, Operand op, int shiftLsB, int size)
{
int eSize = 8 << size;
Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
Operand res = context.AllocateLocal(OperandType.I64);
if (shiftLsB >= eSize)
{
Operand shl = context.ShiftLeft(op, Const(shiftLsB));
context.Copy(res, shl);
}
else
{
Operand zeroL = Const(0L);
context.Copy(res, zeroL);
}
return res;
}
private static Operand EmitShlImmSatQ(ArmEmitterContext context, Operand op, int shiftLsB, int size, bool signedSrc, bool signedDst)
{
int eSize = 8 << size;
Debug.Assert(op.Type == OperandType.I64);
Debug.Assert(eSize == 8 || eSize == 16 || eSize == 32 || eSize == 64);
Operand lblEnd = Label();
Operand res = context.Copy(context.AllocateLocal(OperandType.I64), op);
if (shiftLsB >= eSize)
{
context.Copy(res, signedSrc
? EmitSignedSignSatQ(context, op, size)
: EmitUnsignedSignSatQ(context, op, size));
}
else
{
Operand shl = context.ShiftLeft(op, Const(shiftLsB));
if (eSize == 64)
{
Operand sarOrShr = signedSrc
? context.ShiftRightSI(shl, Const(shiftLsB))
: context.ShiftRightUI(shl, Const(shiftLsB));
context.Copy(res, shl);
context.BranchIf(lblEnd, sarOrShr, op, Comparison.Equal);
context.Copy(res, signedSrc
? EmitSignedSignSatQ(context, op, size)
: EmitUnsignedSignSatQ(context, op, size));
}
else
{
context.Copy(res, signedSrc
? EmitSignedSrcSatQ(context, shl, size, signedDst)
: EmitUnsignedSrcSatQ(context, shl, size, signedDst));
}
}
context.MarkLabel(lblEnd);
return res;
}
private static void EmitShlRegOp(ArmEmitterContext context, ShlRegFlags flags = ShlRegFlags.None)
{
bool scalar = flags.HasFlag(ShlRegFlags.Scalar);

View File

@@ -384,9 +384,7 @@ namespace ARMeilleure.Instructions
Sqrshrn_V,
Sqrshrun_S,
Sqrshrun_V,
Sqshl_Si,
Sqshl_V,
Sqshl_Vi,
Sqshrn_S,
Sqshrn_V,
Sqshrun_S,

View File

@@ -4,5 +4,7 @@ namespace ARMeilleure.Memory
{
IJitMemoryBlock Allocate(ulong size);
IJitMemoryBlock Reserve(ulong size);
ulong GetPageSize();
}
}

View File

@@ -8,7 +8,6 @@ namespace ARMeilleure.Memory
void Commit(ulong offset, ulong size);
void MapAsRw(ulong offset, ulong size);
void MapAsRx(ulong offset, ulong size);
void MapAsRwx(ulong offset, ulong size);
}

View File

@@ -31,7 +31,7 @@ namespace ARMeilleure.Memory
HostMappedUnsafe,
}
public static class MemoryManagerTypeExtensions
static class MemoryManagerTypeExtensions
{
public static bool IsHostMapped(this MemoryManagerType type)
{

View File

@@ -2,7 +2,7 @@ using System;
namespace ARMeilleure.Memory
{
public class ReservedRegion
class ReservedRegion
{
public const int DefaultGranularity = 65536; // Mapping granularity in Windows.

View File

@@ -5,7 +5,7 @@ using System.Runtime.Versioning;
namespace ARMeilleure.Native
{
[SupportedOSPlatform("macos")]
static partial class JitSupportDarwin
internal static partial class JitSupportDarwin
{
[LibraryImport("libarmeilleure-jitsupport", EntryPoint = "armeilleure_jit_memcpy")]
public static partial void Copy(IntPtr dst, IntPtr src, ulong n);

View File

@@ -1,14 +1,63 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using ARMeilleure.Translation;
using ARMeilleure.Translation.Cache;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal
{
public static class NativeSignalHandlerGenerator
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SignalHandlerRange
{
public const int MaxTrackedRanges = 8;
public int IsActive;
public nuint RangeAddress;
public nuint RangeEndAddress;
public IntPtr ActionPointer;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct SignalHandlerConfig
{
/// <summary>
/// The byte offset of the faulting address in the SigInfo or ExceptionRecord struct.
/// </summary>
public int StructAddressOffset;
/// <summary>
/// The byte offset of the write flag in the SigInfo or ExceptionRecord struct.
/// </summary>
public int StructWriteOffset;
/// <summary>
/// The sigaction handler that was registered before this one. (unix only)
/// </summary>
public nuint UnixOldSigaction;
/// <summary>
/// The type of the previous sigaction. True for the 3 argument variant. (unix only)
/// </summary>
public int UnixOldSigaction3Arg;
public SignalHandlerRange Range0;
public SignalHandlerRange Range1;
public SignalHandlerRange Range2;
public SignalHandlerRange Range3;
public SignalHandlerRange Range4;
public SignalHandlerRange Range5;
public SignalHandlerRange Range6;
public SignalHandlerRange Range7;
}
public static class NativeSignalHandler
{
private delegate void UnixExceptionHandler(int sig, IntPtr info, IntPtr ucontext);
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
private delegate int VectoredExceptionHandler(IntPtr exceptionInfo);
private const int MaxTrackedRanges = 8;
private const int StructAddressOffset = 0;
private const int StructWriteOffset = 4;
@@ -21,10 +70,125 @@ namespace ARMeilleure.Signal
private const uint EXCEPTION_ACCESS_VIOLATION = 0xc0000005;
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite, int rangeStructSize, ulong pageSize)
{
ulong pageMask = pageSize - 1;
private static ulong _pageSize;
private static ulong _pageMask;
private static readonly IntPtr _handlerConfig;
private static IntPtr _signalHandlerPtr;
private static IntPtr _signalHandlerHandle;
private static readonly object _lock = new();
private static bool _initialized;
static NativeSignalHandler()
{
_handlerConfig = Marshal.AllocHGlobal(Unsafe.SizeOf<SignalHandlerConfig>());
ref SignalHandlerConfig config = ref GetConfigRef();
config = new SignalHandlerConfig();
}
public static void Initialize(IJitMemoryAllocator allocator)
{
JitCache.Initialize(allocator);
}
public static void InitializeSignalHandler(ulong pageSize, Func<IntPtr, IntPtr, IntPtr> customSignalHandlerFactory = null)
{
if (_initialized)
{
return;
}
lock (_lock)
{
if (_initialized)
{
return;
}
_pageSize = pageSize;
_pageMask = pageSize - 1;
ref SignalHandlerConfig config = ref GetConfigRef();
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateUnixSignalHandler(_handlerConfig));
if (customSignalHandlerFactory != null)
{
_signalHandlerPtr = customSignalHandlerFactory(UnixSignalHandlerRegistration.GetSegfaultExceptionHandler().sa_handler, _signalHandlerPtr);
}
var old = UnixSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
config.UnixOldSigaction = (nuint)(ulong)old.sa_handler;
config.UnixOldSigaction3Arg = old.sa_flags & 4;
}
else
{
config.StructAddressOffset = 40; // ExceptionInformation1
config.StructWriteOffset = 32; // ExceptionInformation0
_signalHandlerPtr = Marshal.GetFunctionPointerForDelegate(GenerateWindowsSignalHandler(_handlerConfig));
if (customSignalHandlerFactory != null)
{
_signalHandlerPtr = customSignalHandlerFactory(IntPtr.Zero, _signalHandlerPtr);
}
_signalHandlerHandle = WindowsSignalHandlerRegistration.RegisterExceptionHandler(_signalHandlerPtr);
}
_initialized = true;
}
}
private static unsafe ref SignalHandlerConfig GetConfigRef()
{
return ref Unsafe.AsRef<SignalHandlerConfig>((void*)_handlerConfig);
}
public static unsafe bool AddTrackedRegion(nuint address, nuint endAddress, IntPtr action)
{
var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
for (int i = 0; i < MaxTrackedRanges; i++)
{
if (ranges[i].IsActive == 0)
{
ranges[i].RangeAddress = address;
ranges[i].RangeEndAddress = endAddress;
ranges[i].ActionPointer = action;
ranges[i].IsActive = 1;
return true;
}
}
return false;
}
public static unsafe bool RemoveTrackedRegion(nuint address)
{
var ranges = &((SignalHandlerConfig*)_handlerConfig)->Range0;
for (int i = 0; i < MaxTrackedRanges; i++)
{
if (ranges[i].IsActive == 1 && ranges[i].RangeAddress == address)
{
ranges[i].IsActive = 0;
return true;
}
}
return false;
}
private static Operand EmitGenericRegionCheck(EmitterContext context, IntPtr signalStructPtr, Operand faultAddress, Operand isWrite)
{
Operand inRegionLocal = context.AllocateLocal(OperandType.I32);
context.Copy(inRegionLocal, Const(0));
@@ -32,7 +196,7 @@ namespace ARMeilleure.Signal
for (int i = 0; i < MaxTrackedRanges; i++)
{
ulong rangeBaseOffset = (ulong)(RangeOffset + i * rangeStructSize);
ulong rangeBaseOffset = (ulong)(RangeOffset + i * Unsafe.SizeOf<SignalHandlerRange>());
Operand nextLabel = Label();
@@ -46,12 +210,13 @@ namespace ARMeilleure.Signal
// Is the fault address within this tracked region?
Operand inRange = context.BitwiseAnd(
context.ICompare(faultAddress, rangeAddress, Comparison.GreaterOrEqualUI),
context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI));
context.ICompare(faultAddress, rangeEndAddress, Comparison.LessUI)
);
// Only call tracking if in range.
context.BranchIfFalse(nextLabel, inRange, BasicBlockFrequency.Cold);
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~pageMask));
Operand offset = context.BitwiseAnd(context.Subtract(faultAddress, rangeAddress), Const(~_pageMask));
// Call the tracking action, with the pointer's relative offset to the base address.
Operand trackingActionPtr = context.Load(OperandType.I64, Const((ulong)signalStructPtr + rangeBaseOffset + 20));
@@ -62,7 +227,7 @@ namespace ARMeilleure.Signal
// Tracking action should be non-null to call it, otherwise assume false return.
context.BranchIfFalse(skipActionLabel, trackingActionPtr);
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(pageSize), isWrite);
Operand result = context.Call(trackingActionPtr, OperandType.I32, offset, Const(_pageSize), isWrite);
context.Copy(inRegionLocal, result);
context.MarkLabel(skipActionLabel);
@@ -104,7 +269,8 @@ namespace ARMeilleure.Signal
Operand esr = context.Load(OperandType.I64, context.Add(ctxPtr, Const(EsrOffset)));
return context.BitwiseAnd(esr, Const(0x40ul));
}
else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
const ulong ErrOffset = 4; // __es.__err
Operand err = context.Load(OperandType.I64, context.Add(ctxPtr, Const(ErrOffset)));
@@ -144,7 +310,8 @@ namespace ARMeilleure.Signal
Operand esr = context.Load(OperandType.I64, context.Add(auxPtr, Const(8ul)));
return context.BitwiseAnd(esr, Const(0x40ul));
}
else if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
{
const int ErrOffset = 192; // uc_mcontext.gregs[REG_ERR]
Operand err = context.Load(OperandType.I64, context.Add(ucontextPtr, Const(ErrOffset)));
@@ -155,7 +322,7 @@ namespace ARMeilleure.Signal
throw new PlatformNotSupportedException();
}
public static byte[] GenerateUnixSignalHandler(IntPtr signalStructPtr, int rangeStructSize, ulong pageSize)
private static UnixExceptionHandler GenerateUnixSignalHandler(IntPtr signalStructPtr)
{
EmitterContext context = new();
@@ -168,7 +335,7 @@ namespace ARMeilleure.Signal
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite, rangeStructSize, pageSize);
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
Operand endLabel = Label();
@@ -200,10 +367,10 @@ namespace ARMeilleure.Signal
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<UnixExceptionHandler>();
}
public static byte[] GenerateWindowsSignalHandler(IntPtr signalStructPtr, int rangeStructSize, ulong pageSize)
private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr)
{
EmitterContext context = new();
@@ -232,7 +399,7 @@ namespace ARMeilleure.Signal
Operand isWrite = context.ICompareNotEqual(writeFlag, Const(0L)); // Normalize to 0/1.
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite, rangeStructSize, pageSize);
Operand isInRegion = EmitGenericRegionCheck(context, signalStructPtr, faultAddress, isWrite);
Operand endLabel = Label();
@@ -254,7 +421,7 @@ namespace ARMeilleure.Signal
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Code;
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq, RuntimeInformation.ProcessArchitecture).Map<VectoredExceptionHandler>();
}
}
}

View File

@@ -1,7 +1,7 @@
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Cpu.Signal
namespace ARMeilleure.Signal
{
static partial class UnixSignalHandlerRegistration
{

View File

@@ -2,7 +2,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using Ryujinx.Common.Memory.PartialUnmaps;
using System;
using System.Runtime.InteropServices;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Signal
@@ -10,28 +10,8 @@ namespace ARMeilleure.Signal
/// <summary>
/// Methods to handle signals caused by partial unmaps. See the structs for C# implementations of the methods.
/// </summary>
internal static partial class WindowsPartialUnmapHandler
internal static class WindowsPartialUnmapHandler
{
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
[LibraryImport("kernel32.dll", SetLastError = true)]
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
private static IntPtr _getCurrentThreadIdPtr;
public static IntPtr GetCurrentThreadIdFunc()
{
if (_getCurrentThreadIdPtr == IntPtr.Zero)
{
IntPtr handle = LoadLibrary("kernel32.dll");
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
}
return _getCurrentThreadIdPtr;
}
public static Operand EmitRetryFromAccessViolation(EmitterContext context)
{
IntPtr partialRemapStatePtr = PartialUnmapState.GlobalState;
@@ -40,7 +20,7 @@ namespace ARMeilleure.Signal
// Get the lock first.
EmitNativeReaderLockAcquire(context, IntPtr.Add(partialRemapStatePtr, PartialUnmapState.PartialUnmapLockOffset));
IntPtr getCurrentThreadId = GetCurrentThreadIdFunc();
IntPtr getCurrentThreadId = WindowsSignalHandlerRegistration.GetCurrentThreadIdFunc();
Operand threadId = context.Call(Const((ulong)getCurrentThreadId), OperandType.I32);
Operand threadIndex = EmitThreadLocalMapIntGetOrReserve(context, localCountsPtr, threadId, Const(0));
@@ -157,6 +137,17 @@ namespace ARMeilleure.Signal
return context.Add(structsPtr, context.SignExtend32(OperandType.I64, offset));
}
#pragma warning disable IDE0051 // Remove unused private member
private static void EmitThreadLocalMapIntRelease(EmitterContext context, IntPtr threadLocalMapPtr, Operand threadId, Operand index)
{
Operand offset = context.Multiply(index, Const(sizeof(int)));
Operand idsPtr = Const((ulong)IntPtr.Add(threadLocalMapPtr, ThreadLocalMap<int>.ThreadIdsOffset));
Operand idPtr = context.Add(idsPtr, context.SignExtend32(OperandType.I64, offset));
context.CompareAndSwap(idPtr, threadId, Const(0));
}
#pragma warning restore IDE0051
private static void EmitAtomicAddI32(EmitterContext context, Operand ptr, Operand additive)
{
Operand loop = Label();

View File

@@ -0,0 +1,44 @@
using System;
using System.Runtime.InteropServices;
namespace ARMeilleure.Signal
{
unsafe partial class WindowsSignalHandlerRegistration
{
[LibraryImport("kernel32.dll")]
private static partial IntPtr AddVectoredExceptionHandler(uint first, IntPtr handler);
[LibraryImport("kernel32.dll")]
private static partial ulong RemoveVectoredExceptionHandler(IntPtr handle);
[LibraryImport("kernel32.dll", SetLastError = true, EntryPoint = "LoadLibraryA")]
private static partial IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
[LibraryImport("kernel32.dll", SetLastError = true)]
private static partial IntPtr GetProcAddress(IntPtr hModule, [MarshalAs(UnmanagedType.LPStr)] string procName);
private static IntPtr _getCurrentThreadIdPtr;
public static IntPtr RegisterExceptionHandler(IntPtr action)
{
return AddVectoredExceptionHandler(1, action);
}
public static bool RemoveExceptionHandler(IntPtr handle)
{
return RemoveVectoredExceptionHandler(handle) != 0;
}
public static IntPtr GetCurrentThreadIdFunc()
{
if (_getCurrentThreadIdPtr == IntPtr.Zero)
{
IntPtr handle = LoadLibrary("kernel32.dll");
_getCurrentThreadIdPtr = GetProcAddress(handle, "GetCurrentThreadId");
}
return _getCurrentThreadIdPtr;
}
}
}

View File

@@ -8,7 +8,7 @@ namespace ARMeilleure.Translation
/// </summary>
/// <typeparam name="TK">Key</typeparam>
/// <typeparam name="TV">Value</typeparam>
public class IntervalTree<TK, TV> where TK : IComparable<TK>
class IntervalTree<TK, TV> where TK : IComparable<TK>
{
private const int ArrayGrowthSize = 32;

View File

@@ -57,6 +57,9 @@ namespace ARMeilleure.Translation
private Thread[] _backgroundTranslationThreads;
private volatile int _threadCount;
// FIXME: Remove this once the init logic of the emulator will be redone.
public static readonly ManualResetEvent IsReadyForTranslation = new(false);
public Translator(IJitMemoryAllocator allocator, IMemoryManager memory, bool for64Bits)
{
_allocator = allocator;
@@ -73,9 +76,14 @@ namespace ARMeilleure.Translation
CountTable = new EntryTable<uint>();
Functions = new TranslatorCache<TranslatedFunction>();
FunctionTable = new AddressTable<ulong>(for64Bits ? _levels64Bit : _levels32Bit);
Stubs = new TranslatorStubs(FunctionTable);
Stubs = new TranslatorStubs(this);
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
if (memory.Type.IsHostMapped())
{
NativeSignalHandler.InitializeSignalHandler(allocator.GetPageSize());
}
}
public IPtcLoadState LoadDiskCache(string titleIdText, string displayVersion, bool enabled)
@@ -97,6 +105,8 @@ namespace ARMeilleure.Translation
{
if (Interlocked.Increment(ref _threadCount) == 1)
{
IsReadyForTranslation.WaitOne();
if (_ptc.State == PtcState.Enabled)
{
Debug.Assert(Functions.Count == 0);

View File

@@ -1,4 +1,3 @@
using ARMeilleure.Common;
using ARMeilleure.Instructions;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
@@ -15,11 +14,11 @@ namespace ARMeilleure.Translation
/// </summary>
class TranslatorStubs : IDisposable
{
private readonly Lazy<IntPtr> _slowDispatchStub;
private static readonly Lazy<IntPtr> _slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
private bool _disposed;
private readonly AddressTable<ulong> _functionTable;
private readonly Translator _translator;
private readonly Lazy<IntPtr> _dispatchStub;
private readonly Lazy<DispatcherFunction> _dispatchLoop;
private readonly Lazy<WrapperFunction> _contextWrapper;
@@ -84,14 +83,13 @@ namespace ARMeilleure.Translation
/// Initializes a new instance of the <see cref="TranslatorStubs"/> class with the specified
/// <see cref="Translator"/> instance.
/// </summary>
/// <param name="functionTable">Function table used to store pointers to the functions that the guest code will call</param>
/// <param name="translator"><see cref="Translator"/> instance to use</param>
/// <exception cref="ArgumentNullException"><paramref name="translator"/> is null</exception>
public TranslatorStubs(AddressTable<ulong> functionTable)
public TranslatorStubs(Translator translator)
{
ArgumentNullException.ThrowIfNull(functionTable);
ArgumentNullException.ThrowIfNull(translator);
_functionTable = functionTable;
_slowDispatchStub = new(GenerateSlowDispatchStub, isThreadSafe: true);
_translator = translator;
_dispatchStub = new(GenerateDispatchStub, isThreadSafe: true);
_dispatchLoop = new(GenerateDispatchLoop, isThreadSafe: true);
_contextWrapper = new(GenerateContextWrapper, isThreadSafe: true);
@@ -153,15 +151,15 @@ namespace ARMeilleure.Translation
context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())));
// Check if guest address is within range of the AddressTable.
Operand masked = context.BitwiseAnd(guestAddress, Const(~_functionTable.Mask));
Operand masked = context.BitwiseAnd(guestAddress, Const(~_translator.FunctionTable.Mask));
context.BranchIfTrue(lblFallback, masked);
Operand index = default;
Operand page = Const((long)_functionTable.Base);
Operand page = Const((long)_translator.FunctionTable.Base);
for (int i = 0; i < _functionTable.Levels.Length; i++)
for (int i = 0; i < _translator.FunctionTable.Levels.Length; i++)
{
ref var level = ref _functionTable.Levels[i];
ref var level = ref _translator.FunctionTable.Levels[i];
// level.Mask is not used directly because it is more often bigger than 32-bits, so it will not
// be encoded as an immediate on x86's bitwise and operation.
@@ -169,7 +167,7 @@ namespace ARMeilleure.Translation
index = context.BitwiseAnd(context.ShiftRightUI(guestAddress, Const(level.Index)), mask);
if (i < _functionTable.Levels.Length - 1)
if (i < _translator.FunctionTable.Levels.Length - 1)
{
page = context.Load(OperandType.I64, context.Add(page, context.ShiftLeft(index, Const(3))));
context.BranchIfFalse(lblFallback, page);
@@ -198,7 +196,7 @@ namespace ARMeilleure.Translation
/// Generates a <see cref="SlowDispatchStub"/>.
/// </summary>
/// <returns>Generated <see cref="SlowDispatchStub"/></returns>
private IntPtr GenerateSlowDispatchStub()
private static IntPtr GenerateSlowDispatchStub()
{
var context = new EmitterContext();
@@ -207,7 +205,8 @@ namespace ARMeilleure.Translation
Operand guestAddress = context.Load(OperandType.I64,
context.Add(nativeContext, Const((ulong)NativeContext.GetDispatchAddressOffset())));
Operand hostAddress = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), guestAddress);
MethodInfo getFuncAddress = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress));
Operand hostAddress = context.Call(getFuncAddress, guestAddress);
context.Tailcall(hostAddress, nativeContext);
var cfg = context.GetControlFlowGraph();

View File

@@ -31,7 +31,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
private const int Minus6dBInQ15 = (int)(0.501f * RawQ15One);
private const int Minus12dBInQ15 = (int)(0.251f * RawQ15One);
private static readonly long[] _defaultSurroundToStereoCoefficients = new long[4]
private static readonly int[] _defaultSurroundToStereoCoefficients = new int[4]
{
RawQ15One,
Minus3dBInQ15,
@@ -39,7 +39,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
Minus3dBInQ15,
};
private static readonly long[] _defaultStereoToMonoCoefficients = new long[2]
private static readonly int[] _defaultStereoToMonoCoefficients = new int[2]
{
Minus6dBInQ15,
Minus6dBInQ15,
@@ -62,23 +62,19 @@ namespace Ryujinx.Audio.Backends.CompatLayer
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static short DownMixStereoToMono(ReadOnlySpan<long> coefficients, short left, short right)
private static short DownMixStereoToMono(ReadOnlySpan<int> coefficients, short left, short right)
{
return (short)Math.Clamp((left * coefficients[0] + right * coefficients[1]) >> Q15Bits, short.MinValue, short.MaxValue);
return (short)((left * coefficients[0] + right * coefficients[1]) >> Q15Bits);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static short DownMixSurroundToStereo(ReadOnlySpan<long> coefficients, short back, short lfe, short center, short front)
private static short DownMixSurroundToStereo(ReadOnlySpan<int> coefficients, short back, short lfe, short center, short front)
{
return (short)Math.Clamp(
(coefficients[3] * back +
coefficients[2] * lfe +
coefficients[1] * center +
coefficients[0] * front + RawQ15HalfOne) >> Q15Bits, short.MinValue, short.MaxValue);
return (short)((coefficients[3] * back + coefficients[2] * lfe + coefficients[1] * center + coefficients[0] * front + RawQ15HalfOne) >> Q15Bits);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static short[] DownMixSurroundToStereo(ReadOnlySpan<long> coefficients, ReadOnlySpan<short> data)
private static short[] DownMixSurroundToStereo(ReadOnlySpan<int> coefficients, ReadOnlySpan<short> data)
{
int samplePerChannelCount = data.Length / SurroundChannelCount;
@@ -98,7 +94,7 @@ namespace Ryujinx.Audio.Backends.CompatLayer
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static short[] DownMixStereoToMono(ReadOnlySpan<long> coefficients, ReadOnlySpan<short> data)
private static short[] DownMixStereoToMono(ReadOnlySpan<int> coefficients, ReadOnlySpan<short> data)
{
int samplePerChannelCount = data.Length / StereoChannelCount;

View File

@@ -12,6 +12,7 @@ using Ryujinx.Ui.Common.Configuration;
using Ryujinx.Ui.Common.Helper;
using System;
using System.Diagnostics;
using System.IO;
namespace Ryujinx.Ava
{
@@ -89,6 +90,8 @@ namespace Ryujinx.Ava
try
{
string baseStyle = ConfigurationState.Instance.Ui.BaseStyle;
string themePath = ConfigurationState.Instance.Ui.CustomThemePath;
bool enableCustomTheme = ConfigurationState.Instance.Ui.EnableCustomTheme;
if (string.IsNullOrWhiteSpace(baseStyle))
{
@@ -103,6 +106,24 @@ namespace Ryujinx.Ava
"Dark" => ThemeVariant.Dark,
_ => ThemeVariant.Default,
};
if (enableCustomTheme)
{
if (!string.IsNullOrWhiteSpace(themePath))
{
try
{
var themeContent = File.ReadAllText(themePath);
var customStyle = AvaloniaRuntimeXamlLoader.Parse<IStyle>(themeContent);
Styles.Add(customStyle);
}
catch (Exception ex)
{
Logger.Error?.Print(LogClass.Application, $"Failed to Apply Custom Theme. Error: {ex.Message}");
}
}
}
}
catch (Exception)
{

View File

@@ -1,3 +1,4 @@
using ARMeilleure.Translation;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
@@ -915,6 +916,7 @@ namespace Ryujinx.Ava
{
Device.Gpu.SetGpuThread();
Device.Gpu.InitializeShaderCache(_gpuCancellationTokenSource.Token);
Translator.IsReadyForTranslation.Set();
_renderer.Window.ChangeVSyncMode(Device.EnableDeviceVsync);
@@ -978,7 +980,7 @@ namespace Ryujinx.Ava
ConfigurationState.Instance.Graphics.AspectRatio.Value.ToText(),
LocaleManager.Instance[LocaleKeys.Game] + $": {Device.Statistics.GetGameFrameRate():00.00} FPS ({Device.Statistics.GetGameFrameTime():00.00} ms)",
$"FIFO: {Device.Statistics.GetFifoPercent():00.00} %",
$"GPU: {_renderer.GetHardwareInfo().GpuDriver}"));
$"GPU: {_renderer.GetHardwareInfo().GpuVendor}"));
}
public async Task ShowExitPrompt()

View File

@@ -1,155 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1000 355.6" style="enable-background:new 0 0 1000 355.6;" xml:space="preserve">
<style type="text/css">
.st0{fill:#00BBDB;stroke:#000000;}
.st1{fill:#333333;stroke:#000000;stroke-width:0.93;}
.st2{fill:#333333;stroke:#000000;stroke-width:0.96;}
.st3{fill:#333333;stroke:#000000;stroke-width:0.85;}
.st4{fill:#1A1A1A;stroke:#000000;}
.st5{fill:#333333;stroke:#000000;}
.st6{fill:#1A1A1A;stroke:#1A1A1A;}
.st7{fill:#1A1A1A;stroke:#4D4D4D;}
.st8{stroke:#4D4D4D;}
.st9{stroke:#000000;}
</style>
<g id="g344">
<path id="path66-7" d="M906.6,6.5v7.9c0,3.6-2.9,6.4-6.5,6.5H71.2c-3.6,0-6.4-2.9-6.5-6.5V6.5c0-3.6,2.9-6.4,6.5-6.5L207,0
c4.9,0,9.6,1.2,14,3.4l13,6.7h79.2l13-6.7c4.3-2.2,9.1-3.4,13.9-3.4l269.7,0c4.9,0,9.6,1.2,14,3.4l13,6.7H716l13-6.7
c4.3-2.2,9.1-3.4,13.9-3.4l157.2,0C903.7,0,906.6,2.9,906.6,6.5L906.6,6.5L906.6,6.5z M65.7,14.4c0,3,2.4,5.5,5.5,5.5h828.9
c3,0,5.5-2.4,5.5-5.5V6.5c0-3-2.4-5.5-5.5-5.5H742.9c-4.7,0-9.3,1.1-13.5,3.3l-13.1,6.8c-0.1,0-0.2,0.1-0.2,0.1h-79.5
c-0.1,0-0.2,0-0.2-0.1l-13.1-6.8c-4.2-2.2-8.8-3.3-13.5-3.3H340.1c-4.7,0-9.3,1.1-13.5,3.3l-13.1,6.8c-0.1,0-0.2,0.1-0.2,0.1h-79.5
c-0.1,0-0.2,0-0.2-0.1l-13.1-6.8C216.3,2.1,211.7,1,207,1L71.2,1c-3,0-5.5,2.4-5.5,5.5L65.7,14.4L65.7,14.4z"/>
<path id="path68-5" d="M858.9,20.3v11.2c0,0.3-0.2,0.5-0.5,0.5H72c-0.3,0-0.5-0.2-0.5-0.5V20.3c0-0.3,0.2-0.5,0.5-0.5h786.4
C858.7,19.8,858.9,20,858.9,20.3z M857.9,31V20.8H72.5V31H857.9z"/>
<path id="path70-3" d="M1000,37.5v106.2c0,117-94.8,211.9-211.9,211.9l0,0H220.9c-116.8,0-211.8-95.1-211.8-211.9V37.5
c0-3.6,2.9-6.5,6.5-6.5h978C997.1,31,1000,33.9,1000,37.5L1000,37.5L1000,37.5z M10.1,143.7c0,116.3,94.6,210.9,210.8,210.9h567.2
C904.4,354.6,999,260,999,143.7V37.5c0-3-2.4-5.5-5.5-5.5h-978c-3,0-5.5,2.4-5.5,5.5v106.2L10.1,143.7L10.1,143.7z"/>
<path id="path98" d="M717.1,6.5v4.2c0,0.6-0.4,1-1,1l0,0h-79.5c-0.6,0-1-0.4-1-1V6.5c0-3.8,3.1-6.9,7-7h67.6
C714-0.5,717.1,2.6,717.1,6.5z M715.1,9.7V6.5c0-2.7-2.2-5-5-5h-67.6c-2.7,0-5,2.2-5,5v3.2H715.1z"/>
<path id="path100" d="M314.3,6.5v4.2c0,0.6-0.4,1-1,1h-79.5c-0.6,0-1-0.4-1-1V6.5c0-3.8,3.1-6.9,7-7h67.6
C311.2-0.5,314.3,2.6,314.3,6.5z M312.3,9.7V6.5c0-2.7-2.2-5-5-5h-67.6c-2.7,0-5,2.2-5,5v3.2H312.3z"/>
<path id="path1144" class="st0" d="M997.9,162.4c-3,26.2-8.5,49.9-21,75.1c-10.9,21.9-25.7,41.1-42.5,57.5
c-33.2,32.3-77.8,53.7-126.7,59c-3.4,0.4-30.5,0.1-72.2,0.3c-158.5,1.1-520.6,0.9-534.4-0.5c-17.7-1.8-36.5-6.1-52.4-12
c-7.5-2.8-15.8-7.1-23.1-10.7C61.8,299.6,21.2,238.8,12,168.6C9.6,150.4,8.7,35.5,11,33.1c0.1-0.1,2.3-0.9,7-1
c11.1-0.4,36-0.4,79.4-1.3c32.7-0.7,76.3,0,132.5-0.1c70.3-0.2,160.2,1.6,274.8,1.6c484.5,0,491.2-1.4,492.4,0.9
c0.2,0.3,1.7,2.5,1.8,5.3c1.1,21.9-0.5,119.2-0.7,120.6L997.9,162.4L997.9,162.4z"/>
<polygon id="polygon80" class="st1" points="470.2,195 470.2,168.3 448.1,181.7 "/>
<polygon id="polygon82" class="st2" points="627.3,181.3 605.6,194.1 605.6,168.5 "/>
<polygon id="polygon84" class="st1" points="538.1,271.6 551.5,249.7 524.7,249.7 "/>
<polygon id="polygon86" class="st3" points="551.6,114.8 524.1,114.8 537.9,89.2 "/>
<path id="path102" d="M139.3,338.3c0,0.3-0.1,0.5-0.3,0.7l-3.4,3.4c-2,2-5.1,2.6-7.8,1.5C50.1,309.1,0.1,231.9,0,146.7l0-51.2
c0-3.8,3.1-6.9,7-7h2.6c0.6,0,1,0.4,1,1v54.2C10.5,228.2,61,304.5,138.7,337.4c0.3,0.1,0.5,0.4,0.6,0.7L139.3,338.3L139.3,338.3z
M2,146.7c0.1,84.4,49.7,160.9,126.7,195.4c1.9,0.8,4.1,0.4,5.5-1.1l2.4-2.4C58.8,305,8.5,228.3,8.6,143.6V90.4H7c-2.7,0-5,2.2-5,5
L2,146.7L2,146.7z"/>
<path id="path104" d="M116.1,60v46.9c0,2.2-1.8,4-4,4h-11.7c-2.2,0-4-1.8-4-4V60c0-2.2,1.8-4,4-4h11.7
C114.3,56,116.1,57.8,116.1,60z M98.5,106.9c0,1.1,0.9,2,2,2h11.7c1.1,0,2-0.9,2-2V60c0-1.1-0.9-2-2-2h-11.7c-1.1,0-2,0.9-2,2
V106.9z"/>
<path id="path106" d="M502.9,181.7c0,21.2-17.2,38.5-38.5,38.5s-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5S502.9,160.4,502.9,181.7
L502.9,181.7z M428,181.7c0,20.1,16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5s-16.3-36.5-36.5-36.5S428,161.5,428,181.7L428,181.7z"/>
<path id="path108" d="M649.8,181.7c0,21.2-17.2,38.5-38.5,38.5s-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5S649.8,160.4,649.8,181.7
L649.8,181.7z M574.9,181.7c0,20.1,16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5s-16.3-36.5-36.5-36.5l0,0
C591.2,145.2,574.9,161.5,574.9,181.7L574.9,181.7z"/>
<path id="path110" d="M576.3,108.2c0,21.2-17.2,38.5-38.5,38.5s-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5l0,0
C559.1,69.8,576.3,87,576.3,108.2z M501.4,108.2c0,20.1,16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5s-16.3-36.5-36.5-36.5l0,0
C517.7,71.8,501.4,88.1,501.4,108.2L501.4,108.2L501.4,108.2z"/>
<path id="path112" d="M576.3,255.1c0,21.2-17.2,38.5-38.5,38.5s-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5l0,0
C559.1,216.7,576.3,233.9,576.3,255.1z M501.4,255.1c0,20.1,16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5s-16.3-36.5-36.5-36.5l0,0
C517.7,218.7,501.4,235,501.4,255.1L501.4,255.1L501.4,255.1z"/>
<path id="path114" d="M753.7,105.5v45c0,5.5-4.4,9.9-9.9,9.9h-45c-5.5,0-9.9-4.4-9.9-9.9v-45c0-5.5,4.4-9.9,9.9-9.9h45
C749.3,95.6,753.7,100.1,753.7,105.5z M690.9,150.5c0,4.4,3.6,7.9,7.9,7.9h45c4.4,0,7.9-3.6,7.9-7.9v-45c0-4.4-3.6-7.9-7.9-7.9h-45
c-4.4,0-7.9,3.6-7.9,7.9V150.5z"/>
<path id="path116" d="M741.7,128c0,11.3-9.2,20.4-20.4,20.4s-20.4-9.2-20.4-20.4s9.2-20.4,20.4-20.4l0,0
C732.6,107.6,741.7,116.7,741.7,128z M702.8,128c0,10.2,8.3,18.4,18.4,18.4s18.4-8.3,18.4-18.4s-8.3-18.4-18.4-18.4
S702.9,117.8,702.8,128z"/>
<path id="path118" d="M260.2,244.8v12.3c0,0.6-0.4,1-1,1l0,0c-39.6-1.7-71.3-33.4-73-73c0-0.3,0.1-0.5,0.3-0.7s0.4-0.3,0.7-0.3
h12.3c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9C257.6,238.4,260.2,241.3,260.2,244.8L260.2,244.8z M258.2,256v-11.2
c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-11.2C190.3,223.4,220.8,253.9,258.2,256L258.2,256z
"/>
<path id="path120" d="M338.9,185L338.9,185c-1.7,39.6-33.4,71.3-73,73c-0.6,0-1-0.4-1-1v-12.3c0-3.5,2.6-6.4,6-6.9
c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6H338C338.5,184,338.9,184.5,338.9,185L338.9,185z M266.9,256
c37.4-2.2,67.8-32.6,70-70h-11.2c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9V256L266.9,256z"/>
<path id="path122" d="M338.9,178.3c0,0.6-0.4,1-1,1h-12.3c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9
c-3.4-0.5-6-3.4-6-6.9v-12.3c0-0.6,0.4-1,1-1l0,0C305.5,107,337.2,138.7,338.9,178.3L338.9,178.3L338.9,178.3z M266.9,118.6
c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h11.2c-2.2-37.4-32.6-67.8-70-70V118.6z"/>
<path id="path124" d="M260.2,106.3v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-12.3
c-0.3,0-0.5-0.1-0.7-0.3s-0.3-0.5-0.3-0.7c1.7-39.6,33.4-71.3,73-73C259.7,105.3,260.2,105.7,260.2,106.3L260.2,106.3L260.2,106.3z
M188.2,177.3h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2
C220.8,109.5,190.3,140,188.2,177.3L188.2,177.3L188.2,177.3z"/>
<path id="path126" d="M339,181.7c0,1.2,0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9h-12.3c-2.5,0-4.6,1.8-4.9,4.3
c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1c-1.1,0.1-2.2,0.1-3.4,0.1s-2.3,0-3.4-0.1
c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3
c-0.5,0-1-0.4-1-0.9c-0.1-2.3-0.1-4.5,0-6.8c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6
c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1c1.1-0.1,2.2-0.1,3.4-0.1s2.3,0,3.4,0.1c0.5,0,0.9,0.5,0.9,1v12.3
c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3c0.5,0,1,0.4,1,0.9C339,179.4,339,180.5,339,181.7
L339,181.7z M337,184c0.1-1.5,0.1-3.1,0-4.7h-11.3c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3
h-4.6v11.4c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3c-0.1,1.5-0.1,3.1,0,4.7h11.3
c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v11.3h4.6v-11.3c0-3.5,2.6-6.4,6-6.9
c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6L337,184L337,184z"/>
<path id="path179" class="st4" d="M574.3,261.6c-3.2,14.7-12.7,24.9-27.1,29c-3.4,1-6.3,1.2-11.7,0.9c-6.5-0.3-7.8-0.7-13.5-3.5
c-22.9-11.4-27.9-40.7-10-58.6c19.4-19.4,51.9-12,60.8,13.9C574.5,248.5,575.3,257.1,574.3,261.6L574.3,261.6L574.3,261.6z
M538,249c-7.3,0-13.4,0.2-13.4,0.4c0,0.9,13.2,23.3,13.5,23c0.7-0.7,13.1-22.2,13.2-22.8C551.3,249.2,545.4,249,538,249L538,249
L538,249z"/>
<path id="path181" class="st4" d="M500.6,187.1c-0.9,6.9-5,15-10.4,20.5c-14.5,14.6-36.9,14.6-51.4-0.1c-22.9-23-7-62.3,25.4-62.3
c10.4,0,18.8,3.5,26,10.7C498.4,164.3,502.1,175.2,500.6,187.1L500.6,187.1L500.6,187.1z M469.9,168.5
c-2.4,0.9-22.4,12.8-22.4,13.3c0,0.4,9,5.9,19.9,12l3.6,2v-13.9C471,169.7,470.9,168.1,469.9,168.5L469.9,168.5L469.9,168.5z"/>
<path id="path185" class="st4" d="M647,190.4c-3.5,12.9-13.7,23.1-26.6,26.5c-22.7,5.9-45.2-11.6-45.3-35.2
c0-7.4,0.9-11.3,4.5-18.1c8.8-16.9,30.4-23.9,47.9-15.4C643,155.8,651.4,173.9,647,190.4L647,190.4L647,190.4z M616.9,174.2
c-6.3-3.6-11.6-6.5-11.8-6.3s-0.3,6.4-0.1,13.8l0.2,13.5l11.6-6.7c6.4-3.7,11.6-6.9,11.6-7.2C628.4,181.1,623.2,177.8,616.9,174.2
L616.9,174.2z"/>
<path id="path187" class="st4" d="M574.2,111.7c0,0.3-0.3,1.6-0.5,2.9c-2.2,11.2-9.7,20.9-20.1,26.2c-5.6,2.8-12.2,4.2-17.9,3.8
c-14.8-1.1-27.7-11.3-32.5-25.6c-2.9-8.8-2.2-18,2.2-26.7s12.1-15.5,21.3-18.6c15.3-5.3,32.2,0.7,41.6,14.7c4,6,6.3,13.4,6.2,20.2
C574.3,109.9,574.3,111.4,574.2,111.7L574.2,111.7L574.2,111.7z M551.1,112.4c-0.4-0.7-1.6-3-2.8-5.1c-4.8-8.7-9.2-15.6-10-16.2
c-0.4-0.3-0.5-0.3-0.9,0c-1.3,0.9-13.5,21.5-13.5,22.9c0,0.3,0.1,0.6,0.2,0.7c0.5,0.4,4.8,0.6,13.9,0.6c9.1,0,13-0.2,13.5-0.6
C551.9,114.3,551.8,113.8,551.1,112.4L551.1,112.4L551.1,112.4z"/>
<path id="path189" class="st5" d="M739.1,131.6c-0.2,1-1,3-1.6,4.4c-1,2.1-1.6,2.9-3.5,4.8c-1.9,1.9-2.7,2.5-4.8,3.5
c-5.5,2.7-10.6,2.7-16.1,0c-2.1-1-2.8-1.6-4.8-3.5c-3.6-3.6-5.3-7.7-5.3-12.7c0-8.4,5.7-15.7,13.9-17.8c2-0.5,6.2-0.5,8.3,0
c6.3,1.5,11.5,6.3,13.4,12.7C739.4,125.4,739.6,129.2,739.1,131.6L739.1,131.6L739.1,131.6z"/>
<path id="path191" class="st4" d="M751.3,152.4c-0.4,1.6-1.3,3-2.6,4.1c-2.1,1.8-0.9,1.7-27.4,1.7s-25.3,0.1-27.5-1.9
c-0.7-0.6-1.5-1.7-1.9-2.5l-0.7-1.5v-48.3l0.9-1.8c0.6-1.3,1.2-2,2.1-2.7c2.3-1.8,1.3-1.7,27.8-1.6c23.8,0.1,23.9,0.1,25.1,0.6
c1.6,0.7,3.1,2.3,3.9,3.9l0.7,1.3l0,23.8C751.6,145.6,751.5,151.4,751.3,152.4L751.3,152.4L751.3,152.4z M741.6,125.1
c-1.5-10.6-10.7-18.1-21.4-17.5c-3.4,0.2-5.3,0.7-8.1,2c-9.3,4.6-13.7,15.5-10.2,25.3c1,2.8,2.2,4.7,4.3,7c2.8,3,6.3,5.1,10.3,6
c2.2,0.5,7.2,0.5,9.4,0c3.9-0.9,7.4-3,10.2-6c2.1-2.2,3.3-4.2,4.3-6.7C741.7,131.9,742.1,128.5,741.6,125.1L741.6,125.1
L741.6,125.1z"/>
<path id="path1082" class="st6" d="M330.4,183.8c-6,0-6.5,0.1-7.9,0.7c-2.1,1.1-3.4,2.9-3.9,5.6c-2.7,15.1-10.1,27.5-21.9,36.5
c-6.5,5-15.1,8.8-23.2,10.4c-4.3,0.8-5.7,1.4-7,3c-1.5,1.8-1.8,3.3-1.8,10v5.9h-4.2v-6.3c0-6.1,0-6.3-0.9-8
c-1.2-2.4-2.7-3.3-7.3-4.2c-23.2-4.6-41-22.4-45.4-45.6c-0.8-4.2-1.6-5.6-3.8-6.9c-1.5-0.9-1.6-0.9-8.1-1l-6.6-0.1v-4.2h6.3
c6.2,0,6.3,0,8-0.9c2.6-1.3,3.4-2.6,4.4-7.6c3.8-19.4,17-35.1,35.4-42.3c2.7-1,5.9-1.9,12-3.3c2.6-0.6,4.2-1.7,5.2-3.6
c0.6-1.1,0.7-2,0.8-7.9l0.1-6.6h4.2v6.3c0,6.1,0,6.3,0.9,8c1.1,2.2,2.9,3.4,5.9,3.9c23.8,4.1,42.3,22.2,46.8,46
c0.8,4.2,1.7,5.7,4.1,7c1.5,0.8,1.9,0.8,8,0.9l6.4,0.1v4.2L330.4,183.8L330.4,183.8z"/>
<path id="path1084" class="st7" d="M257.3,255.8c-0.5-0.1-1.9-0.3-3.2-0.4c-3.9-0.4-10.1-1.7-14.8-3.3c-24.1-8-42.7-28.1-48.9-52.7
c-0.8-3.1-1.6-7.6-1.9-11.3l-0.2-2h5.9c8.5,0,9.1,0.4,10.4,6.5c3.7,18.4,15.2,33.7,31.9,41.9c5.1,2.6,10.1,4.1,17,5.5
c2.4,0.5,4,1.8,4.4,3.7c0.2,0.7,0.3,3.8,0.3,6.8v5.5L257.3,255.8L257.3,255.8z"/>
<path id="path1086" class="st7" d="M336.4,189.8c-3,27-21.4,50.8-46.9,60.9c-6,2.4-13.4,4.2-18.7,4.7c-1.3,0.1-2.7,0.3-3.1,0.4
l-0.8,0.2l0.1-6.3c0.1-5.8,0.2-6.4,0.8-7.2c1.2-1.6,2.2-2,6.2-2.9c5.8-1.2,9.4-2.4,14.8-5.2c5.7-2.9,9.8-5.7,14.2-9.9
c9.1-8.6,15.2-19.7,17.5-31.7c0.7-3.6,1.2-4.6,2.7-5.8c0.8-0.6,1.4-0.7,7.2-0.8c5.9-0.1,6.3-0.1,6.3,0.5
C336.7,187,336.6,188.4,336.4,189.8L336.4,189.8L336.4,189.8z"/>
<path id="path1088" class="st7" d="M257.7,119.9c-0.9,2.4-1.6,2.8-6.5,3.8c-18.2,3.7-33.5,15.4-41.6,32c-2.4,4.8-3.7,8.6-4.7,13.5
c-1,4.7-1.6,6.2-2.9,7.1c-1.1,0.7-1.4,0.7-7.4,0.7c-3.5,0-6.3-0.1-6.3-0.3s0.2-1.9,0.5-4c1.5-12,5.6-22.9,12.4-32.8
c3-4.4,5.6-7.4,9.9-11.6c9.6-9.3,20.7-15.5,33.5-18.8c3.6-0.9,10.9-2.1,12.9-2.1c0.6,0,0.6,0.3,0.6,5.6
C258.1,116.9,258,119.1,257.7,119.9L257.7,119.9L257.7,119.9z"/>
<path id="path1090" class="st7" d="M330.5,177.3c-5.8-0.1-6.4-0.2-7.2-0.8c-1.6-1.2-2-2.2-2.9-6.3c-4.7-23.5-23.3-41.9-47-46.4
c-3.5-0.7-4.5-1.1-5.6-2.7c-0.6-0.8-0.7-1.4-0.8-7.2l-0.1-6.3l1.7,0.2c10.5,1.2,18,3.3,26.4,7.5c22.6,11.2,38.1,32.9,41.3,58
c0.3,2.1,0.5,3.9,0.5,4S333.9,177.3,330.5,177.3L330.5,177.3L330.5,177.3z"/>
<path id="path1092" class="st4" d="M113.5,108c-0.6,0.5-1.8,0.7-7.2,0.7c-4.5,0-6.7-0.2-7-0.5c-0.4-0.4-0.5-6.4-0.5-24.6
c0-21.3,0.1-24.2,0.7-24.8c0.6-0.5,1.8-0.7,7-0.7c6.1,0,6.4,0,7,1c0.6,0.8,0.7,3.9,0.7,24.6S114,107.4,113.5,108z"/>
<path id="path1094" class="st8" d="M134.2,340.6c-2.8,2.4-3.7,2.2-12.6-2.3c-21.7-10.8-39.6-23.6-56.5-40.5
c-31.4-31.4-52.2-71.6-59.8-115.3c-2.6-15.1-2.7-16.5-2.9-54L2.3,93.7l1.2-1.4c0.9-1,1.7-1.4,3-1.6l1.8-0.2l0.2,33.8
c0.2,36.2,0.3,38.8,2.7,53.3c6.2,38.4,22,72.9,47.3,103.3c5.7,6.8,18.3,19.5,25.2,25.2c10,8.4,21.7,16.5,32.4,22.5
c5.4,3.1,18.7,9.6,19.5,9.6C136.4,338.3,136,339.1,134.2,340.6L134.2,340.6L134.2,340.6z"/>
<path id="path1150" class="st9" d="M616,21.1c-216,0-634,0-526-0.1c108-0.1,614.3-0.3,722.4-0.1c29.2,0,43.2,0.1,45,0.1
C862.4,21.1,773.6,21.1,616,21.1L616,21.1L616,21.1z"/>
<path id="path1152" class="st4" d="M903.2,19c-2.1,1.5-44.2,0.8-417.6,0.8S70.3,20.6,68.2,19.1c-2-1.4-2.2-3.4-2.2-8.5
c0-1.8-0.1-3.8,0.2-5.4c0.3-1.4,2-3.2,2.4-3.5c0.5-0.5,4.3-0.3,16.4-0.4c11.3-0.1,29,0.2,55.3,0.2c44.7,0,61.8-0.6,69.8-0.1
c4.4,0.3,6.1,1.2,8.1,1.9c3.1,1.2,8.2,3.9,10.9,5.6l5,3.2l40.4-0.4c37.6-0.4,39,0.2,41.7-1.6c1.5-1.1,6.1-3,9.3-4.6l5.8-3l7.9-1.3
l19.8,0.1l15.8,0.1l97.9,0.2c93.1,0.2,126.7-1.2,141.1,0.3c4.2,0.4,6.5,1.6,8.5,2.3c2.7,0.9,4.9,2.1,7.8,3.9l6.1,3.7l15.6-0.4
l25.1-0.1c26.5-0.1,40.4-0.6,40.9-1.3c0.4-0.6,4-2.7,8.5-4.3l9-3.3l9-1.1l15.9,0.2l57.9,0.2c61.9,0.2,84.5-0.4,85.5,0.5
c0.9,0.8,2.4,4.5,2.4,8.4C905.8,15.4,905.1,17.6,903.2,19L903.2,19L903.2,19z"/>
<path id="path1154" class="st4" d="M464.9,30.8l-5.2,0l-387-0.4v-8.5h392.2l393-1.1l0.2,5.3l-0.2,4.9L464.9,30.8L464.9,30.8z"/>
<path id="path1156" class="st0" d="M273.3,9.7h-38.6v-3c0-1.7,0.9-3.6,2.1-4.3c2.8-1.7,70.3-1.7,73.1,0c1.2,0.7,2.1,2.6,2.1,4.3v3
H273.3L273.3,9.7z"/>
<path id="path1158" class="st0" d="M676.2,9.7h-38.7v-3c0-1.8,0.9-3.6,2.1-4.3c2.8-1.7,70.3-1.7,73.2,0c1.2,0.7,2.1,2.6,2.1,4.3v3
H676.2L676.2,9.7z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,341 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1000 1000.2" style="enable-background:new 0 0 1000 1000.2;" xml:space="preserve">
<style type="text/css">
.st0{fill:#00BBDB;stroke:#000000;}
.st1{fill:#333333;stroke:#000000;stroke-width:0.93;}
.st2{fill:#333333;stroke:#000000;stroke-width:0.96;}
.st3{fill:#333333;stroke:#000000;stroke-width:0.85;}
.st4{fill:#1A1A1A;stroke:#000000;}
.st5{fill:#333333;stroke:#000000;}
.st6{fill:#1A1A1A;stroke:#1A1A1A;}
.st7{fill:#1A1A1A;stroke:#4D4D4D;}
.st8{stroke:#4D4D4D;}
.st9{stroke:#000000;}
.st10{opacity:0.1;}
.st11{fill:#FF5F55;}
.st12{fill:#FF5F53;}
.st13{fill:#FFFFFF;}
.st14{fill:#999595;stroke:#000000;stroke-width:2.39;stroke-linecap:round;stroke-linejoin:round;}
.st15{fill:#3A3D40;stroke:#000000;stroke-width:2.73;stroke-linecap:round;stroke-linejoin:round;}
</style>
<g id="layer1">
<g id="g344">
<path id="path66-7" d="M349.1,906.6h-7.9c-3.6,0-6.4-2.9-6.5-6.5V71.2c0-3.6,2.9-6.4,6.5-6.5h7.9c3.6,0,6.4,2.9,6.5,6.5V207
c0,4.9-1.2,9.6-3.4,14l-6.7,13v79.2l6.7,13c2.2,4.3,3.4,9.1,3.4,13.9v269.7c0,4.9-1.2,9.6-3.4,14l-6.7,13V716l6.7,13
c2.2,4.3,3.4,9.1,3.4,13.9v157.2C355.6,903.7,352.7,906.6,349.1,906.6L349.1,906.6L349.1,906.6z M341.2,65.7c-3,0-5.5,2.4-5.5,5.5
v828.9c0,3,2.4,5.5,5.5,5.5h7.9c3,0,5.5-2.4,5.5-5.5V742.9c0-4.7-1.1-9.3-3.3-13.5l-6.8-13.1c0-0.1-0.1-0.2-0.1-0.2v-79.5
c0-0.1,0-0.2,0.1-0.2l6.8-13.1c2.2-4.2,3.3-8.8,3.3-13.5V340.1c0-4.7-1.1-9.3-3.3-13.5l-6.8-13.1c0-0.1-0.1-0.2-0.1-0.2v-79.5
c0-0.1,0-0.2,0.1-0.2l6.8-13.1c2.2-4.2,3.3-8.8,3.3-13.5V71.2c0-3-2.4-5.5-5.5-5.5L341.2,65.7L341.2,65.7z"/>
<path id="path68-5" d="M335.3,858.9h-11.2c-0.3,0-0.5-0.2-0.5-0.5V72c0-0.3,0.2-0.5,0.5-0.5h11.2c0.3,0,0.5,0.2,0.5,0.5v786.4
C335.8,858.7,335.6,858.9,335.3,858.9z M324.6,857.9h10.2V72.5h-10.2V857.9z"/>
<path id="path70-3" d="M318.1,1000H211.9C94.9,1000,0,905.2,0,788.1l0,0V220.9C0,104.1,95.1,9.1,211.9,9.1h106.2
c3.6,0,6.5,2.9,6.5,6.5v978C324.6,997.1,321.7,1000,318.1,1000L318.1,1000L318.1,1000z M211.9,10.1C95.6,10.1,1,104.7,1,220.9
v567.2C1,904.4,95.6,999,211.9,999h106.2c3,0,5.5-2.4,5.5-5.5v-978c0-3-2.4-5.5-5.5-5.5H211.9L211.9,10.1L211.9,10.1z"/>
<path id="path98" d="M349.1,717.1h-4.2c-0.6,0-1-0.4-1-1l0,0v-79.5c0-0.6,0.4-1,1-1h4.2c3.8,0,6.9,3.1,7,7v67.6
C356.1,714,353,717.1,349.1,717.1z M345.9,715.1h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V715.1z"/>
<path id="path100" d="M349.1,314.3h-4.2c-0.6,0-1-0.4-1-1v-79.5c0-0.6,0.4-1,1-1h4.2c3.8,0,6.9,3.1,7,7v67.6
C356.1,311.2,353,314.3,349.1,314.3z M345.9,312.3h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V312.3z"/>
<path id="path1144" class="st0" d="M193.2,997.9c-26.2-3-49.9-8.5-75.1-21C96.2,966,77,951.2,60.7,934.4
C28.4,901.1,7,856.6,1.7,807.7c-0.4-3.4-0.1-30.5-0.3-72.2C0.3,576.9,0.4,214.9,1.8,201c1.8-17.7,6.1-36.5,12-52.4
c2.8-7.5,7.1-15.8,10.7-23.1C55.9,61.8,116.8,21.2,187,12c18.2-2.4,133.1-3.3,135.5-0.9c0.1,0.1,0.9,2.3,1,7
c0.4,11.1,0.4,36,1.3,79.4c0.7,32.7,0,76.3,0.1,132.5c0.2,70.3-1.6,160.2-1.6,274.8c0,484.5,1.4,491.2-0.9,492.4
c-0.3,0.2-2.5,1.7-5.3,1.8c-21.9,1.1-119.2-0.5-120.6-0.7L193.2,997.9L193.2,997.9z"/>
<polygon id="polygon80" class="st1" points="173.9,448.1 160.6,470.2 187.3,470.2 "/>
<polygon id="polygon82" class="st2" points="187.1,605.6 174.3,627.3 161.5,605.6 "/>
<polygon id="polygon84" class="st1" points="105.9,524.7 84,538.1 105.9,551.5 "/>
<polygon id="polygon86" class="st3" points="266.4,537.9 240.8,551.6 240.8,524.1 "/>
<path id="path102" d="M17.3,139.3c-0.3,0-0.5-0.1-0.7-0.3l-3.4-3.4c-2-2-2.6-5.1-1.5-7.8C46.5,50.1,123.7,0.1,208.9,0h51.2
c3.8,0,6.9,3.1,7,7v2.6c0,0.6-0.4,1-1,1h-54.2C127.4,10.5,51.1,61,18.2,138.7c-0.1,0.3-0.4,0.5-0.7,0.6L17.3,139.3L17.3,139.3z
M208.9,2C124.5,2.1,48,51.7,13.5,128.7c-0.8,1.9-0.4,4.1,1.1,5.5l2.4,2.4C50.6,58.8,127.3,8.5,212,8.6h53.2V7c0-2.7-2.2-5-5-5
L208.9,2L208.9,2z"/>
<path id="path104" d="M295.6,116.1h-46.9c-2.2,0-4-1.8-4-4v-11.7c0-2.2,1.8-4,4-4h46.9c2.2,0,4,1.8,4,4v11.7
C299.6,114.3,297.8,116.1,295.6,116.1z M248.7,98.5c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h46.9c1.1,0,2-0.9,2-2v-11.7
c0-1.1-0.9-2-2-2H248.7z"/>
<path id="path106" d="M173.9,502.9c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5S195.2,502.9,173.9,502.9
L173.9,502.9z M173.9,428c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5S194.1,428,173.9,428L173.9,428z"
/>
<path id="path108" d="M173.9,649.8c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5S195.2,649.8,173.9,649.8
L173.9,649.8z M173.9,574.9c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5l0,0
C210.4,591.2,194.1,574.9,173.9,574.9L173.9,574.9z"/>
<path id="path110" d="M247.4,576.3c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0
C285.8,559.1,268.6,576.3,247.4,576.3z M247.4,501.4c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5l0,0
C283.8,517.7,267.5,501.4,247.4,501.4L247.4,501.4L247.4,501.4z"/>
<path id="path112" d="M100.5,576.3c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0
C138.9,559.1,121.7,576.3,100.5,576.3z M100.5,501.4c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5s36.5-16.3,36.5-36.5l0,0
C136.9,517.7,120.6,501.4,100.5,501.4L100.5,501.4L100.5,501.4z"/>
<path id="path114" d="M250.1,753.7h-45c-5.5,0-9.9-4.4-9.9-9.9v-45c0-5.5,4.4-9.9,9.9-9.9h45c5.5,0,9.9,4.4,9.9,9.9v45
C260,749.3,255.5,753.7,250.1,753.7z M205.1,690.9c-4.4,0-7.9,3.6-7.9,7.9v45c0,4.4,3.6,7.9,7.9,7.9h45c4.4,0,7.9-3.6,7.9-7.9v-45
c0-4.4-3.6-7.9-7.9-7.9H205.1z"/>
<path id="path116" d="M227.6,741.7c-11.3,0-20.4-9.2-20.4-20.4s9.2-20.4,20.4-20.4s20.4,9.2,20.4,20.4l0,0
C248,732.6,238.9,741.7,227.6,741.7z M227.6,702.8c-10.2,0-18.4,8.3-18.4,18.4s8.3,18.4,18.4,18.4s18.4-8.3,18.4-18.4
S237.8,702.9,227.6,702.8z"/>
<path id="path118" d="M110.8,260.2H98.5c-0.6,0-1-0.4-1-1l0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3s0.3,0.4,0.3,0.7
v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C117.2,257.6,114.3,260.2,110.8,260.2L110.8,260.2z M99.6,258.2h11.2
c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2C132.2,190.3,101.7,220.8,99.6,258.2L99.6,258.2
z"/>
<path id="path120" d="M170.6,338.9L170.6,338.9c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1h12.3c3.5,0,6.4,2.6,6.9,6
c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9V338C171.6,338.5,171.1,338.9,170.6,338.9L170.6,338.9z M99.6,266.9
c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3H99.6L99.6,266.9z"
/>
<path id="path122" d="M177.3,338.9c-0.6,0-1-0.4-1-1v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6
h12.3c0.6,0,1,0.4,1,1l0,0C248.6,305.5,216.9,337.2,177.3,338.9L177.3,338.9L177.3,338.9z M237,266.9c-2.5,0-4.6,1.8-4.9,4.3
c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v11.2c37.4-2.2,67.8-32.6,70-70H237z"/>
<path id="path124" d="M249.3,260.2H237c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-12.3
c0-0.3,0.1-0.5,0.3-0.7s0.5-0.3,0.7-0.3c39.6,1.7,71.3,33.4,73,73C250.3,259.7,249.9,260.2,249.3,260.2L249.3,260.2L249.3,260.2z
M178.3,188.2v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h11.2
C246.1,220.8,215.6,190.3,178.3,188.2L178.3,188.2L178.3,188.2z"/>
<path id="path126" d="M173.9,339c-1.2,0-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9
c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3H98.5c-0.5,0-1-0.4-1-0.9c-0.1-1.1-0.1-2.2-0.1-3.4s0-2.3,0.1-3.4
c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1
c2.3-0.1,4.5-0.1,6.8,0c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3
c0.5,0,1,0.4,1,0.9c0.1,1.1,0.1,2.2,0.1,3.4s0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9H237c-2.5,0-4.6,1.8-4.9,4.3
c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1C176.2,339,175.1,339,173.9,339L173.9,339z
M171.6,337c1.5,0.1,3.1,0.1,4.7,0v-11.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h11.3v-4.6H237
c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3c-1.5-0.1-3.1-0.1-4.7,0v11.3
c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6H99.4v4.6h11.3c3.5,0,6.4,2.6,6.9,6
c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9L171.6,337L171.6,337z"/>
<path id="path179" class="st4" d="M94,574.3c-14.7-3.2-24.9-12.7-29-27.1c-1-3.4-1.2-6.3-0.9-11.7c0.3-6.5,0.7-7.8,3.5-13.5
c11.4-22.9,40.7-27.9,58.6-10c19.4,19.4,12,51.9-13.9,60.8C107.1,574.5,98.5,575.3,94,574.3L94,574.3L94,574.3z M106.6,538
c0-7.3-0.2-13.4-0.4-13.4c-0.9,0-23.3,13.2-23,13.5c0.7,0.7,22.2,13.1,22.8,13.2C106.4,551.3,106.6,545.4,106.6,538L106.6,538
L106.6,538z"/>
<path id="path181" class="st4" d="M168.5,500.6c-6.9-0.9-15-5-20.5-10.4c-14.6-14.5-14.6-36.9,0.1-51.4c23-22.9,62.3-7,62.3,25.4
c0,10.4-3.5,18.8-10.7,26C191.3,498.4,180.4,502.1,168.5,500.6L168.5,500.6L168.5,500.6z M187.1,469.9
c-0.9-2.4-12.8-22.4-13.3-22.4c-0.4,0-5.9,9-12,19.9l-2,3.6h13.9C185.9,471,187.5,470.9,187.1,469.9L187.1,469.9L187.1,469.9z"/>
<path id="path185" class="st4" d="M165.2,647c-12.9-3.5-23.1-13.7-26.5-26.6c-5.9-22.7,11.6-45.2,35.2-45.3
c7.4,0,11.3,0.9,18.1,4.5c16.9,8.8,23.9,30.4,15.4,47.9C199.8,643,181.7,651.4,165.2,647L165.2,647L165.2,647z M181.4,616.9
c3.6-6.3,6.5-11.6,6.3-11.8s-6.4-0.3-13.8-0.1l-13.5,0.2l6.7,11.6c3.7,6.4,6.9,11.6,7.2,11.6C174.5,628.4,177.8,623.2,181.4,616.9
L181.4,616.9z"/>
<path id="path187" class="st4" d="M243.9,574.2c-0.3,0-1.6-0.3-2.9-0.5c-11.2-2.2-20.9-9.7-26.2-20.1c-2.8-5.6-4.2-12.2-3.8-17.9
c1.1-14.8,11.3-27.7,25.6-32.5c8.8-2.9,18-2.2,26.7,2.2s15.5,12.1,18.6,21.3c5.3,15.3-0.7,32.2-14.7,41.6c-6,4-13.4,6.3-20.2,6.2
C245.7,574.3,244.2,574.3,243.9,574.2L243.9,574.2L243.9,574.2z M243.2,551.1c0.7-0.4,3-1.6,5.1-2.8c8.7-4.8,15.6-9.2,16.2-10
c0.3-0.4,0.3-0.5,0-0.9c-0.9-1.3-21.5-13.5-22.9-13.5c-0.3,0-0.6,0.1-0.7,0.2c-0.4,0.5-0.6,4.8-0.6,13.9c0,9.1,0.2,13,0.6,13.5
C241.3,551.9,241.8,551.8,243.2,551.1L243.2,551.1L243.2,551.1z"/>
<path id="path189" class="st5" d="M224,739.1c-1-0.2-3-1-4.4-1.6c-2.1-1-2.9-1.6-4.8-3.5c-1.9-1.9-2.5-2.7-3.5-4.8
c-2.7-5.5-2.7-10.6,0-16.1c1-2.1,1.6-2.8,3.5-4.8c3.6-3.6,7.7-5.3,12.7-5.3c8.4,0,15.7,5.7,17.8,13.9c0.5,2,0.5,6.2,0,8.3
c-1.5,6.3-6.3,11.5-12.7,13.4C230.2,739.4,226.4,739.6,224,739.1L224,739.1L224,739.1z"/>
<path id="path191" class="st4" d="M203.2,751.3c-1.6-0.4-3-1.3-4.1-2.6c-1.8-2.1-1.7-0.9-1.7-27.4s-0.1-25.3,1.9-27.5
c0.6-0.7,1.7-1.5,2.5-1.9l1.5-0.7h48.3l1.8,0.9c1.3,0.6,2,1.2,2.7,2.1c1.8,2.3,1.7,1.3,1.6,27.8c-0.1,23.8-0.1,23.9-0.6,25.1
c-0.7,1.6-2.3,3.1-3.9,3.9l-1.3,0.7l-23.8,0C210,751.6,204.2,751.5,203.2,751.3L203.2,751.3L203.2,751.3z M230.5,741.6
c10.6-1.5,18.1-10.7,17.5-21.4c-0.2-3.4-0.7-5.3-2-8.1c-4.6-9.3-15.5-13.7-25.3-10.2c-2.8,1-4.7,2.2-7,4.3c-3,2.8-5.1,6.3-6,10.3
c-0.5,2.2-0.5,7.2,0,9.4c0.9,3.9,3,7.4,6,10.2c2.2,2.1,4.2,3.3,6.7,4.3C223.7,741.7,227.1,742.1,230.5,741.6L230.5,741.6
L230.5,741.6z"/>
<path id="path1082" class="st6" d="M171.8,330.4c0-6-0.1-6.5-0.7-7.9c-1.1-2.1-2.9-3.4-5.6-3.9c-15.1-2.7-27.5-10.1-36.5-21.9
c-5-6.5-8.8-15.1-10.4-23.2c-0.8-4.3-1.4-5.7-3-7c-1.8-1.5-3.3-1.8-10-1.8h-5.9v-4.2h6.3c6.1,0,6.3,0,8-0.9
c2.4-1.2,3.3-2.7,4.2-7.3c4.6-23.2,22.4-41,45.6-45.4c4.2-0.8,5.6-1.6,6.9-3.8c0.9-1.5,0.9-1.6,1-8.1l0.1-6.6h4.2v6.3
c0,6.2,0,6.3,0.9,8c1.3,2.6,2.6,3.4,7.6,4.4c19.4,3.8,35.1,17,42.3,35.4c1,2.7,1.9,5.9,3.3,12c0.6,2.6,1.7,4.2,3.6,5.2
c1.1,0.6,2,0.7,7.9,0.8l6.6,0.1v4.2h-6.3c-6.1,0-6.3,0-8,0.9c-2.2,1.1-3.4,2.9-3.9,5.9c-4.1,23.8-22.2,42.3-46,46.8
c-4.2,0.8-5.7,1.7-7,4.1c-0.8,1.5-0.8,1.9-0.9,8l-0.1,6.4h-4.2L171.8,330.4L171.8,330.4z"/>
<path id="path1084" class="st7" d="M99.8,257.3c0.1-0.5,0.3-1.9,0.4-3.2c0.4-3.9,1.7-10.1,3.3-14.8c8-24.1,28.1-42.7,52.7-48.9
c3.1-0.8,7.6-1.6,11.3-1.9l2-0.2v5.9c0,8.5-0.4,9.1-6.5,10.4c-18.4,3.7-33.7,15.2-41.9,31.9c-2.6,5.1-4.1,10.1-5.5,17
c-0.5,2.4-1.8,4-3.7,4.4c-0.7,0.2-3.8,0.3-6.8,0.3h-5.5L99.8,257.3L99.8,257.3z"/>
<path id="path1086" class="st7" d="M165.8,336.4c-27-3-50.8-21.4-60.9-46.9c-2.4-6-4.2-13.4-4.7-18.7c-0.1-1.3-0.3-2.7-0.4-3.1
l-0.2-0.8l6.3,0.1c5.8,0.1,6.4,0.2,7.2,0.8c1.6,1.2,2,2.2,2.9,6.2c1.2,5.8,2.4,9.4,5.2,14.8c2.9,5.7,5.7,9.8,9.9,14.2
c8.6,9.1,19.7,15.2,31.7,17.5c3.6,0.7,4.6,1.2,5.8,2.7c0.6,0.8,0.7,1.4,0.8,7.2c0.1,5.9,0.1,6.3-0.5,6.3
C168.6,336.7,167.2,336.6,165.8,336.4L165.8,336.4L165.8,336.4z"/>
<path id="path1088" class="st7" d="M235.7,257.7c-2.4-0.9-2.8-1.6-3.8-6.5c-3.7-18.2-15.4-33.5-32-41.6c-4.8-2.4-8.6-3.7-13.5-4.7
c-4.7-1-6.2-1.6-7.1-2.9c-0.7-1.1-0.7-1.4-0.7-7.4c0-3.5,0.1-6.3,0.3-6.3s1.9,0.2,4,0.5c12,1.5,22.9,5.6,32.8,12.4
c4.4,3,7.4,5.6,11.6,9.9c9.3,9.6,15.5,20.7,18.8,33.5c0.9,3.6,2.1,10.9,2.1,12.9c0,0.6-0.3,0.6-5.6,0.6
C238.7,258.1,236.5,258,235.7,257.7L235.7,257.7L235.7,257.7z"/>
<path id="path1090" class="st7" d="M178.3,330.5c0.1-5.8,0.2-6.4,0.8-7.2c1.2-1.6,2.2-2,6.3-2.9c23.5-4.7,41.9-23.3,46.4-47
c0.7-3.5,1.1-4.5,2.7-5.6c0.8-0.6,1.4-0.7,7.2-0.8l6.3-0.1l-0.2,1.7c-1.2,10.5-3.3,18-7.5,26.4c-11.2,22.6-32.9,38.1-58,41.3
c-2.1,0.3-3.9,0.5-4,0.5S178.3,333.9,178.3,330.5L178.3,330.5L178.3,330.5z"/>
<path id="path1092" class="st4" d="M247.6,113.5c-0.5-0.6-0.7-1.8-0.7-7.2c0-4.5,0.2-6.7,0.5-7c0.4-0.4,6.4-0.5,24.6-0.5
c21.3,0,24.2,0.1,24.8,0.7c0.5,0.6,0.7,1.8,0.7,7c0,6.1,0,6.4-1,7c-0.8,0.6-3.9,0.7-24.6,0.7S248.2,114,247.6,113.5z"/>
<path id="path1094" class="st8" d="M15,134.2c-2.3-2.8-2.2-3.7,2.3-12.6C28,99.9,40.9,82,57.8,65.1C89.1,33.7,129.4,12.8,173,5.3
c15.1-2.6,16.5-2.7,54-2.9l34.8-0.2l1.4,1.2c1,0.9,1.4,1.7,1.6,3l0.2,1.8l-33.8,0.2C195,8.6,192.5,8.8,178,11.1
c-38.4,6.2-72.9,22-103.3,47.3c-6.8,5.7-19.5,18.3-25.2,25.2c-8.4,10-16.5,21.7-22.5,32.4c-3.1,5.4-9.6,18.7-9.6,19.5
C17.3,136.4,16.5,136,15,134.2L15,134.2L15,134.2z"/>
<path id="path1150" class="st9" d="M334.4,616c0-216,0-634,0.1-526c0.1,108,0.3,614.3,0.1,722.4c0,29.2-0.1,43.2-0.1,45
C334.5,862.4,334.5,773.6,334.4,616L334.4,616L334.4,616z"/>
<path id="path1152" class="st4" d="M336.6,903.2c-1.5-2.1-0.8-44.2-0.8-417.6S335,70.3,336.5,68.2c1.4-2,3.4-2.2,8.5-2.2
c1.8,0,3.8-0.1,5.4,0.2c1.4,0.3,3.2,2,3.5,2.4c0.5,0.5,0.3,4.3,0.4,16.4c0.1,11.3-0.2,29-0.2,55.3c0,44.7,0.6,61.8,0.1,69.8
c-0.3,4.4-1.2,6.1-1.9,8.1c-1.2,3.1-3.9,8.2-5.6,10.9l-3.2,5l0.4,40.4c0.4,37.6-0.2,39,1.6,41.7c1.1,1.5,3,6.1,4.6,9.3l3,5.8
l1.3,7.9l-0.1,19.8l-0.1,15.8l-0.2,97.9c-0.2,93.1,1.2,126.7-0.3,141.1c-0.4,4.2-1.6,6.5-2.3,8.5c-0.9,2.7-2.1,4.9-3.9,7.8
l-3.7,6.1l0.4,15.6l0.1,25.1c0.1,26.5,0.6,40.4,1.3,40.9c0.6,0.4,2.7,4,4.3,8.5l3.3,9l1.1,9l-0.2,15.9l-0.2,57.9
c-0.2,61.9,0.4,84.5-0.5,85.5c-0.8,0.9-4.5,2.4-8.4,2.4C340.2,905.8,338,905.1,336.6,903.2L336.6,903.2L336.6,903.2z"/>
<path id="path1154" class="st4" d="M325.2,464.9V72.7h8.5v392.2l1.1,393l-5.3,0.2l-4.9-0.2L325.2,464.9L325.2,464.9z"/>
<path id="path1156" class="st0" d="M345.9,273.3v-38.6h3c1.7,0,3.6,0.9,4.3,2.1c1.7,2.8,1.7,70.3,0,73.1c-0.7,1.2-2.6,2.1-4.3,2.1
h-3V273.3L345.9,273.3z"/>
<path id="path1158" class="st0" d="M345.9,676.2v-38.7h3c1.8,0,3.6,0.9,4.3,2.1c1.7,2.8,1.7,70.3,0,73.2c-0.7,1.2-2.6,2.1-4.3,2.1
h-3V676.2L345.9,676.2z"/>
</g>
<g id="g315">
<g id="g64" class="st10">
<path id="path36" class="st11" d="M654.6,233.9v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6h4.2V233.9z"/>
<path id="path38" class="st11" d="M654.6,636.6v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6L654.6,636.6L654.6,636.6z"/>
<path id="path40" class="st11" d="M985.7,134.9l-3.4,3.4C949.1,60.3,872.5,9.6,787.6,9.6h-54.2V7c0-3.3,2.7-6,6-6h51.2
C875.4,1,952.3,50.8,987,128.2C988,130.5,987.5,133.1,985.7,134.9L985.7,134.9L985.7,134.9z"/>
<path id="path42" class="st11" d="M736.2,94.5V82.8c0-1.6-1.3-3-3-3h-11.7c-1.6,0-3,1.3-3,3l0,0v11.7c0,1.6-1.3,3-3,3h-11.7
c-1.6,0-3,1.3-3,3l0,0v11.7c0,1.6,1.3,3,3,3h11.7c1.6,0,3,1.3,3,3l0,0v11.7c0,1.6,1.3,3,3,3h11.7c1.6,0,3-1.3,3-3l0,0v-11.7
c0-1.6,1.3-3,3-3h11.7c1.6,0,3-1.3,3-3l0,0v-11.7c0-1.6-1.3-3-3-3h-11.7C737.5,97.5,736.2,96.1,736.2,94.5L736.2,94.5z"/>
<circle id="circle44" class="st11" cx="825.6" cy="333.9" r="37.5"/>
<circle id="circle46" class="st11" cx="825.6" cy="187.1" r="37.5"/>
<circle id="circle48" class="st11" cx="899" cy="260.5" r="37.5"/>
<circle id="circle50" class="st11" cx="752.2" cy="260.5" r="37.5"/>
<circle id="circle52" class="st11" cx="771.7" cy="721.3" r="27.9"/>
<path id="path54" class="st11" d="M822.3,460.3v12.3c0,3-2.2,5.5-5.2,5.9c-25.2,3.7-45,23.5-48.7,48.7c-0.4,2.9-2.9,5.1-5.9,5.2
h-12.3C751.9,493.3,783.2,462,822.3,460.3L822.3,460.3L822.3,460.3z"/>
<path id="path56" class="st11" d="M822.3,598.8v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2
c3.7,25.2,23.5,45,48.7,48.7C820.1,593.3,822.3,595.8,822.3,598.8L822.3,598.8L822.3,598.8z"/>
<path id="path58" class="st11" d="M901,539c-1.7,39.1-33,70.3-72.1,72v-12.3c0-3,2.2-5.5,5.2-5.9c25.2-3.7,45-23.5,48.7-48.7
c0.4-2.9,2.9-5.1,5.9-5.2L901,539L901,539z"/>
<path id="path60" class="st11" d="M901,532.4h-12.3c-3,0-5.5-2.2-5.9-5.2c-3.7-25.2-23.5-45-48.7-48.7c-2.9-0.4-5.1-2.9-5.2-5.9
v-12.3C868,462,899.3,493.3,901,532.4L901,532.4L901,532.4z"/>
<path id="path62" class="st11" d="M901.1,535.7c0,1.1,0,2.2-0.1,3.3h-12.3c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7
c-2.9,0.4-5.1,2.9-5.2,5.9v12.3c-1.1,0.1-2.2,0.1-3.3,0.1s-2.2,0-3.3-0.1v-12.3c0-3-2.2-5.5-5.2-5.9c-25.2-3.7-45-23.5-48.7-48.7
c-0.4-2.9-2.9-5.1-5.9-5.2h-12.3c-0.1-1.1-0.1-2.2-0.1-3.3s0-2.2,0.1-3.3h12.3c3,0,5.5-2.2,5.9-5.2c3.7-25.2,23.5-45,48.7-48.7
c2.9-0.4,5.1-2.9,5.2-5.9v-12.3c1.1-0.1,2.2-0.1,3.3-0.1s2.2,0,3.3,0.1v12.3c0,3,2.2,5.5,5.2,5.9c25.2,3.7,45,23.5,48.7,48.7
c0.4,2.9,2.9,5.1,5.9,5.2H901C901,533.5,901.1,534.6,901.1,535.7L901.1,535.7z"/>
</g>
<path id="path72" d="M658.3,906.6h-7.9c-3.6,0-6.4-2.9-6.5-6.5V742.9c0-4.9,1.2-9.6,3.4-13.9l6.7-13v-79.2l-6.7-13
c-2.2-4.3-3.4-9.1-3.4-14V340.1c0-4.9,1.2-9.6,3.4-13.9l6.7-13V234l-6.7-13c-2.2-4.3-3.4-9.1-3.4-14V71.2c0-3.6,2.9-6.4,6.5-6.5
h7.9c3.6,0,6.4,2.9,6.5,6.5c1.1,276.3,1.2,552.6,0,828.9C664.7,903.7,661.8,906.6,658.3,906.6L658.3,906.6L658.3,906.6z
M650.4,65.7c-3,0-5.5,2.4-5.5,5.5V207c0,4.7,1.1,9.3,3.3,13.5l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2
l-6.8,13.1c-2.2,4.2-3.3,8.8-3.3,13.5v269.7c0,4.7,1.1,9.3,3.3,13.5l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2
l-6.8,13.1c-2.2,4.2-3.3,8.8-3.3,13.5v157.2c0,3,2.4,5.5,5.5,5.5h7.9c3,0,5.5-2.4,5.5-5.5V71.2c0-3-2.4-5.5-5.5-5.5L650.4,65.7
L650.4,65.7z"/>
<path id="path74" d="M675.5,858.9h-11.3c-0.3,0-0.5-0.2-0.5-0.5l0,0L664.5,72c0-0.3,0.2-0.5,0.5-0.5h11.3c0.3,0-0.3,0.2-0.3,0.5
v786.4C676,858.7,675.8,858.9,675.5,858.9z M665.6,857.9h9.4l0.8-785.4h-10.3l1,8.8c-0.6,256.1,4.5,511.8-1.1,768.3
C665.3,852.3,665.6,855.1,665.6,857.9L665.6,857.9z"/>
<path id="path76" d="M787.4,1000.2H681.2c-3.6,0-6.5-2.9-6.5-6.5v-978c0-3.6,2.9-6.5,6.5-6.5h106.2
c116.8,0,211.9,95.1,211.9,211.9v567.2C999.3,905.3,904.5,1000.2,787.4,1000.2L787.4,1000.2z M681.2,10.4c-3,0-5.5,2.4-5.5,5.5
v978c0,3,2.4,5.5,5.5,5.5h106.2c116.3,0,210.9-94.6,210.9-210.9V221.1c0-116.3-94.6-210.9-210.9-210.9L681.2,10.4z"/>
<path id="path128" d="M654.6,314.3h-4.2c-3.8,0-6.9-3.1-7-7v-67.6c0-3.8,3.1-6.9,7-7h4.2c0.6,0,1,0.4,1,1l0,0v79.5
C655.6,313.9,655.1,314.3,654.6,314.3L654.6,314.3z M650.4,234.8c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5h3.2v-77.5h-3.2V234.8z"/>
<path id="path130" d="M654.6,717.1h-4.2c-3.8,0-6.9-3.1-7-7v-67.6c0-3.8,3.1-6.9,7-7h4.2c0.6,0,1,0.4,1,1l0,0V716
C655.6,716.6,655.1,717.1,654.6,717.1L654.6,717.1z M650.4,637.6c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5h3.2v-77.5L650.4,637.6
L650.4,637.6z"/>
<path id="path1240" class="st12" d="M805.5,998.7c26.6-2.4,50.5-9.2,75.9-21.8c5.1-2.5,10-5.2,14.9-8
c19.1-11.3,36.3-27.1,49.6-41.7c25.5-28,45.5-70.1,51.4-116.5c0.1-0.7,0.4-4.3,0.4-6.8c-0.1-6.9,0.7-20,0.8-38.3
c0.7-77.5,1.1-244,1.1-376.4c0-101.2-0.3-182.5-1-188.9c-2.7-26.1-9.3-49.1-20.8-72.1c-31.8-63.9-93-107.4-164-116.7
c-11.4-1.5-60.7-1.6-96.6-1.3c-7.7,0.1-14.1-0.1-20.1,0.1c-7.5,0.2-12.9-0.1-16.2,0.2c-1.7,0.2-3,0.8-3.2,1
c-0.1,0.1-1.4,1.4-1.5,3.3c-0.3,5.2-0.3,17.1-0.4,38c0,4.2-0.1,8.8-0.1,13.8c0,4.9,0.1,10.1,0.1,15.8c-0.1,8.8,0.1,18.6,0.1,29.2
c0,9.8-0.2,20.5,0,32c0.2,9,0.2,18.4,0.2,28.4c-0.1,15.1,0.6,31.1,0.3,49c-0.2,15,0.1,30,0,46.9c-0.1,11.1,0.1,22.6,0,34.6
c-0.1,7.2,0,14.5-0.1,22.1c-0.5,52.1,0,112.2,0,180.3c0,254.3-0.3,376.1,0,435.2c0,7.7-0.2,14.5-0.1,20.2c0,2.2,0,4.3,0,6.2
c0,3.3,0,6.6,0,9.3c0,2.9-0.1,5.8,0,8c0.1,5,0.1,8.1,0.3,10c0.3,2.8,1.3,3.6,1.6,3.8c0.2,0.2,1.3,0.9,3.1,1.1
c4.5,0.4,14.6,0.3,27.1,0.2c9.9-0.1,21.3-0.2,32.8-0.2C772.7,998.8,805.8,999,805.5,998.7L805.5,998.7L805.5,998.7z"/>
<path id="path78" d="M771.7,763.2c-23.1,0-41.9-18.7-41.9-41.9s18.7-41.9,41.9-41.9c23.2,0,41.9,18.7,41.9,41.9l0,0
C813.5,744.4,794.8,763.1,771.7,763.2z M771.7,680.4c-22.6,0-40.9,18.3-40.9,40.9s18.3,40.9,40.9,40.9c22.6,0,40.9-18.3,40.9-40.9
l0,0C812.5,698.7,794.3,680.4,771.7,680.4z"/>
<path id="path88" class="st13" d="M838.9,203.2h-5.5l-7.6-10.9l-8,10.9h-5.4l10.6-16.3l-9.8-15.6h5.2l7.4,10.6l7.3-10.6h5
l-9.8,15.4L838.9,203.2L838.9,203.2z"/>
<path id="path90" class="st13" d="M765.9,244.5l-11.6,20.6v11.4h-4.4V265l-11.6-20.5h5.3l6.4,11.7l2.1,3l2.4-2.6l6.4-12.1H765.9
L765.9,244.5z"/>
<path id="path92" class="st13" d="M912.6,276.5h-4.7l-2.2-7l-12.4,0.3l-3.2,6.7h-4.5l9.9-35.2l6.7,3.2L912.6,276.5z M903.9,265.2
l-4.9-14.6l-4.6,14.8L903.9,265.2L903.9,265.2z"/>
<path id="path132" d="M982.3,139.3h-0.2c-0.3-0.1-0.6-0.3-0.7-0.6C948.4,61,872.1,10.5,787.6,10.6h-54.2c-0.6,0-1-0.4-1-1l0,0V7
c0-3.8,3.1-6.9,7-7h51.2C875.8,0.1,953,50.1,987.9,127.8c1.2,2.6,0.6,5.7-1.5,7.8L983,139C982.8,139.2,982.5,139.3,982.3,139.3
L982.3,139.3z M734.4,8.6h53.2c84.7-0.1,161.3,50.2,195,128l2.4-2.4l0,0c1.5-1.4,1.9-3.6,1.1-5.5C951.5,51.7,875,2.1,790.6,2
h-51.2c-2.7,0-5,2.2-5,5V8.6z"/>
<path id="path134" d="M733.2,133.7h-11.7c-2.2,0-4-1.8-4-4V118c0-1.1-0.9-2-2-2h-11.7c-2.2,0-4-1.8-4-4v-11.7c0-2.2,1.8-4,4-4
h11.7c1.1,0,2-0.9,2-2V82.8c0-2.2,1.8-4,4-4h11.7c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c2.2,0,4,1.8,4,4v11.7
c0,2.2-1.8,4-4,4h-11.7c-1.1,0-2,0.9-2,2v11.7C737.2,131.9,735.4,133.7,733.2,133.7z M703.9,98.5c-1.1,0-2,0.9-2,2v11.7
c0,1.1,0.9,2,2,2h11.7c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c1.1,0,2-0.9,2-2v-11.7c0-2.2,1.8-4,4-4H751c1.1,0,2-0.9,2-2
v-11.7c0-1.1-0.9-2-2-2h-11.7c-2.2,0-4-1.8-4-4V82.8c0-1.1-0.9-2-2-2h-11.7c-1.1,0-2,0.9-2,2v11.7c0,2.2-1.8,4-4,4H703.9z"/>
<path id="path136" d="M825.6,372.4c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.3,0,38.5,17.2,38.5,38.5
C864,355.2,846.8,372.4,825.6,372.4z M825.6,297.5c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5c20.2,0,36.5-16.3,36.5-36.5
C862,313.8,845.7,297.5,825.6,297.5z"/>
<path id="path138" d="M825.6,225.5c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.3,0,38.5,17.2,38.5,38.5
C864,208.3,846.8,225.5,825.6,225.5z M825.6,150.6c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5c20.2,0,36.5-16.3,36.5-36.5
C862,166.9,845.7,150.6,825.6,150.6z"/>
<path id="path140" d="M899,299c-21.2,0-38.5-17.2-38.5-38.5S877.7,222,899,222c21.3,0,38.5,17.2,38.5,38.5S920.3,298.9,899,299z
M899,224c-20.1,0-36.5,16.3-36.5,36.5S878.8,297,899,297c20.2,0,36.5-16.3,36.5-36.5S919.2,224,899,224z"/>
<path id="path142" d="M752.2,299c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.3,0,38.5,17.2,38.5,38.5
C790.6,281.7,773.4,298.9,752.2,299z M752.2,224c-20.1,0-36.5,16.3-36.5,36.5s16.2,36.2,36.4,36.2s36.6-16,36.6-36.2
C788.6,240.4,772.3,224,752.2,224z"/>
<path id="path144" d="M771.7,750.2c-16,0-28.9-13-28.9-28.9s13-28.9,28.9-28.9s28.9,13,28.9,28.9l0,0
C800.6,737.3,787.7,750.2,771.7,750.2z M771.7,694.3c-14.9,0-26.9,12.1-26.9,26.9s12.1,26.9,26.9,26.9s26.9-12.1,26.9-26.9
S786.6,694.4,771.7,694.3z"/>
<path id="path146" d="M762.5,533.4h-12.3c-0.6,0-1-0.4-1-1l0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3
c0.2,0.2,0.3,0.4,0.3,0.7v12.3c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C768.9,530.8,766,533.4,762.5,533.4z
M751.3,531.4h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2
C783.9,463.5,753.4,494,751.3,531.4z"/>
<path id="path148" d="M822.3,612.1C822.3,612.1,822.2,612.1,822.3,612.1c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1h12.3
c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v12.3C823.3,611.6,822.8,612.1,822.3,612.1L822.3,612.1
L822.3,612.1z M751.3,540c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6
c-0.3-2.5-2.4-4.3-4.9-4.3H751.3z"/>
<path id="path150" d="M828.9,612.1c-0.6,0-1-0.4-1-1l0,0v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9
c0.5-3.4,3.4-6,6.9-6H901c0.6,0,1,0.4,1,1l0,0C900.2,578.7,868.6,610.3,828.9,612.1C829,612.1,829,612.1,828.9,612.1L828.9,612.1
L828.9,612.1z M888.7,540c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9V610
c37.4-2.2,67.8-32.6,70-70H888.7z"/>
<path id="path152" d="M901,533.4h-12.3c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-12.3
c0-0.3,0.1-0.5,0.3-0.7c0.2-0.2,0.5-0.3,0.7-0.3c39.6,1.7,71.3,33.4,73,73C902,532.9,901.6,533.3,901,533.4L901,533.4L901,533.4z
M829.9,461.4v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h11.2
C897.8,494,867.3,463.5,829.9,461.4z"/>
<path id="path154" d="M825.6,612.2c-1.2,0-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9
c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3c-0.5,0-1-0.4-1-0.9c-0.1-1.1-0.1-2.2-0.1-3.4s0-2.3,0.1-3.4
c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1
c2.3-0.1,4.5-0.1,6.8,0c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3H901
c0.5,0,1,0.4,1,0.9c0.1,1.1,0.1,2.2,0.1,3.4s0,2.3-0.1,3.4c0,0.5-0.5,0.9-1,0.9h-12.3c-2.5,0-4.6,1.8-4.9,4.3
c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v12.3c0,0.5-0.4,1-0.9,1C827.9,612.1,826.8,612.2,825.6,612.2L825.6,612.2
L825.6,612.2z M823.3,610.1c1.5,0.1,3.1,0.1,4.7,0v-11.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6
h11.3v-4.6h-11.4c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3c-1.5-0.1-3.1-0.1-4.7,0v11.3
c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3v4.6h11.3c3.5,0,6.4,2.6,6.9,6
c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9L823.3,610.1L823.3,610.1L823.3,610.1z"/>
<path id="path1462" class="st4" d="M743,295.5c-6.3-1.7-11.3-3.9-16.5-9.1c-7.7-7.7-11.3-17-10.8-27.7c0.6-13.5,8-25,20-31
c10.5-5.2,22.6-5.3,32.7-0.3c7.9,3.9,12.8,10,16.6,18c5.2,10.8,4.2,24.4-2.4,34.6c-5,7.6-13.5,13.7-22,15.7
C755.7,296.8,747.8,296.7,743,295.5L743,295.5L743,295.5z"/>
<path id="path1464" class="st4" d="M819.4,222.9c0-0.3-3.7-0.9-5.7-1.6c-3-1.1-5.9-2.6-8-4c-6.9-4.6-11.7-10.9-14.5-18.9
c-1.3-3.8-2.1-5.2-2.1-11.4s0.7-7.2,2.1-11c3.9-11.1,11.8-19.1,22.8-23c4.2-1.5,5.2-2.3,11.6-2.3c6.4,0,7.3,0.8,11.6,2.3
c14.5,5.2,24,17.6,24.7,32.9c0.5,10.6-2.7,19.5-10.2,26.9c-7.6,7.5-14.4,10.7-24.6,11C823.6,223.7,820.2,223,819.4,222.9
L819.4,222.9L819.4,222.9z"/>
<path id="path1466" class="st4" d="M891.7,296.5c-6.7-1-15.6-5.8-20.8-12.9c-3-4.1-6.2-10.7-7.3-15.7
c-2.8-13.2,2.6-27.9,13.3-35.9c20-15.1,48.1-6.7,56.4,17c1.9,5.3,3,13.3,1.7,19.2c-1.5,6.8-4.9,12.9-10.2,18.2
c-5.3,5.2-9.9,8-16.4,9.6C903.5,297.2,896.3,297.2,891.7,296.5L891.7,296.5L891.7,296.5z"/>
<path id="path1468" class="st4" d="M820.4,369.9c-8.1-1.3-14.2-4-20.6-10.3c-3.8-3.7-5.4-6.2-7.2-10c-7.6-15.8-3-33.1,10.8-44.1
c6.4-5.1,13.6-7.6,22.1-7.6c29.9,0,46.7,33.8,28.7,58c-2.8,3.8-6.3,7.5-10.5,9.8C836.7,369.8,828.1,371.1,820.4,369.9L820.4,369.9
L820.4,369.9z"/>
<path id="path1500" class="st6" d="M823.6,602.7c-0.3-8.9-0.8-9.7-10.1-11.9c-21.1-4.8-37.2-20.1-42.6-41.3
c-0.6-2.2-1.1-5.2-1.1-5.9s-1-2.2-2.2-3.5l-2.3-2l-6.9-0.3h-7v-4h5.9c6.6,0,9.9-1,11.2-3.4c0.4-0.8,1.5-3.9,2-7
c2.7-16.3,14.9-30.7,29.5-38c4.7-2.4,11.4-4.6,15.5-5.4c6.6-1.1,8.2-3.6,8.2-12.8v-5.9h4v6.9c0,6.6,0.1,7,1.8,8.8
c1.5,1.6,3.9,1.7,9.5,3.1c20.4,5,35.3,20.5,40.7,40.1c0.8,2.9,1.8,6.4,2.2,7.8c1.2,4.3,3.8,5.6,11.7,5.6h6.5v4h-6.6
c-7,0-9.9,0.8-10.8,3.1c-0.3,0.7-1.3,4.6-2.1,8c-5.4,21.4-21.3,36.7-42.1,41.5c-9.9,2.3-10.7,3.2-10.7,12.8v6.3h-3.8L823.6,602.7
L823.6,602.7z"/>
<path id="path1504" class="st7" d="M752.2,526.5c1.8-15.3,8.9-31.2,20.4-43c11.9-12.2,27.5-19.2,45.7-21.6l2.8-0.4v6.2
c0,7.9-0.1,8.9-6.8,10.2c-22.3,4.6-41.8,22.1-46.1,44.2c-1.8,9.1-2.4,9.1-11.1,9.1h-5.4L752.2,526.5L752.2,526.5z"/>
<path id="path1506" class="st7" d="M811.2,608.2c-32.2-6.9-55.7-32.9-59.4-65.6l-0.2-2.1h6.4c6.9,0,6.8,0,7.8,1
c1.3,1.4,1.5,3.8,2.4,7.9c4.8,21.2,24.2,39.1,46.6,44c6.9,1.5,6.4,2.7,6.4,10.3v5.9l-2.1,0C817.8,609.5,814.3,608.9,811.2,608.2
L811.2,608.2L811.2,608.2z"/>
<path id="path1508" class="st7" d="M830,603c-0.3-7.3,1-8.2,5.3-9c4.8-0.8,11.1-2.9,16.3-5.5c15.8-7.7,27.1-22,31.6-39.9
c1-4,1.6-7.2,2.2-7.7c0.7-0.5,3.9-0.5,7.8-0.5h6.2l-0.4,3.8c-3.8,33.2-31.8,61.3-64.8,65l-4,0.5L830,603L830,603z"/>
<path id="path1510" class="st7" d="M885.4,529.8c-1.2-1.1-1.3-3-2.1-6.7c-4.4-20.5-19-36.6-39.3-43.5c-2.4-0.8-5.8-1.7-7.5-2
c-1.9-0.3-3.9-0.6-4.8-1.5c-1.4-1.4-1.3-2.6-1.3-8.2v-6.2l2.5,0.3c19,2.5,32.7,9.2,45.4,22.1c10.4,10.5,17.4,23.8,20.2,38.1
c0.6,2.9,1,6.1,1,7.1v1.9h-5.9C888.3,531.3,886.8,531.1,885.4,529.8L885.4,529.8L885.4,529.8z"/>
<path id="path1512" class="st4" d="M720.3,131c-0.5-0.6-0.6-1.7-0.6-7.6v-6.9l-1.1-1.2l-1.1-1.2l-7.1-0.1
c-4.1-0.1-6.5,0.5-7.6-0.2c-1.3-0.8-0.9-3.1-0.9-7.6s0.1-6.3,0.5-6.8c0.5-0.7,1.1-0.7,7.3-0.8c3.7-0.1,7.1-0.2,7.6-0.3
c0.5-0.1,1.2-0.7,1.6-1.4c0.7-1.1,0.7-1.9,0.7-7.8c0-3.8,0.2-6.8,0.4-7.3c0.4-0.7,0.9-0.7,7.3-0.7s7,0.1,7.3,0.7
c0.2,0.4,0.4,3.5,0.4,7.3c0,5.8,0.1,6.7,0.7,7.8c0.4,0.7,1.1,1.3,1.6,1.4s3.9,0.2,7.6,0.3c6.2,0.1,6.8,0.2,7.3,0.8
c0.4,0.6,0.5,2.2,0.5,6.8s0.7,7.2-0.9,7.9c-1.2,0.5-3.8-0.1-7.6-0.1l-7.1,0.1l-1.1,1.2l-1.1,1.2v6.9c0,6.2-0.1,7-0.7,7.6
c-0.6,0.5-1.7,0.6-7.1,0.6C721.7,131.7,720.9,131.6,720.3,131L720.3,131L720.3,131z"/>
<path id="path1514" class="st7" d="M766.6,726.4v-5.3h10.5v10.5h-10.5V726.4L766.6,726.4z"/>
<path id="path1518" class="st7" d="M766,761.6c-14.8-2.3-27.2-12.3-32.4-26.2c-7.5-20,2.3-43,22-51.4c6.1-2.6,8-3.5,15.7-3.5
c6.5,0,7.9,0.6,11.3,1.6c14.4,4.4,24.6,14.9,28.6,29.4c0.8,2.9,1.1,5.2,1.1,10.7c0,5.5-0.3,6.2-1.1,9c-4.8,17.7-20,30-38.1,30.5
C770.5,761.9,767.4,761.8,766,761.6L766,761.6L766,761.6z M778.1,749.7c11.9-2.6,21.3-13,22.5-25.1c2.2-21.5-18.1-37.7-38.5-30.7
c-4.2,1.4-7,3.3-10.8,7.1c-2.8,2.8-3.8,4.1-5.3,7.2c-2.6,5.1-3.3,8.7-3,14.6c0.3,6.8,2.2,11.7,6.3,16.9
C755.9,748,767.4,752,778.1,749.7L778.1,749.7L778.1,749.7z"/>
<path id="path1520" class="st9" d="M648.2,714.3c-1.3-0.8-2.3-0.9-2.5-5.3c-0.2-4.3,0.1-13.5,0.1-32.6c0-32.8-0.5-35.2,0.6-36.3
c0.1-0.1,0.1-0.2,0.2-0.2c1.1-1.5,2.7-2.1,4.9-2.1h1.9V715h-2C650.1,715,648.9,714.8,648.2,714.3L648.2,714.3L648.2,714.3z"/>
<path id="path1522" class="st9" d="M649.6,312.1c-0.5-0.1-1.3-0.4-1.8-0.8c-0.8-0.5-1.5-0.8-1.8-2.7c-0.5-3.2-0.2-11.4-0.2-35.1
c0-19.3-0.5-28.4-0.4-32.5c0.1-2.7,0.8-3.2,1-3.6c0.9-1.6,2.4-2.3,4.8-2.3h2.1v77.3l-1.4,0C651.2,312.3,650.1,312.2,649.6,312.1
L649.6,312.1L649.6,312.1z"/>
<path id="path1524" class="st8" d="M978,126.4c-10.1-20.6-21.9-37.2-38.2-53.9c-34.8-35.7-78.7-57-129.6-63.1
c-5.1-0.6-13.1-0.8-40.9-1l-34.6-0.2V6.9c0-1,0-3,1.4-3.7l2.1-1.1l30.4,0.2c16.9,0.1,33.6,0.2,37,0.5
c50.8,3.9,97.1,24.6,133.3,59.5c17.6,16.9,31.5,35.7,42.8,57.9c4.3,8.4,4.9,10.1,4.2,11.8c-0.4,1.1-2.7,4.2-3.2,4.1
C982.6,136.1,980.5,131.5,978,126.4L978,126.4L978,126.4z"/>
<path id="path1530" class="st4" d="M646.8,903.8c-0.6-0.5-1.7-1.2-1.6-5c0.3-6.7-0.2-27.2-0.1-79.1l0.3-82.6l2.6-6.5l7.9-15
l0.1-39.4l-0.4-39.6l-7.1-13.2l-2.9-7.7l-0.4-7.3l0.1-48l-0.1-22.1l0.1-34.1l0.1-10.5V483l-0.1-8.6l0-25.6v-19.4l-0.2-27.5
l0.1-21.6l0-11l0.1-19.6l0-10.2l0.5-5.7l1.9-5.8l3-5.5l5.3-9.8v-39.5l-0.4-39.6l-5.3-9.8l-2.7-5.3l-1.8-5.1l-0.7-7.6l0.2-13.3
l-0.1-12.2v-11.1l-0.1-10.9l0-9.9V142l0-2.9l0.1-17.4l0-21.5V89.4l-0.1-8.4l0-5.1l-0.2-5.9l2.2-3.1l3.2-1.1l3.2,0.1
c1.4,0,2.7,0.1,3.9,0.2c0.9,0.1,1.8,0.1,2.6,0.4c1,0.4,1.7,1,2,1.3c0.2,0.2,1.2,1.7,1.3,4.8c0.1,2.1,0,4.7,0,8.3
c0,4.1,0.1,9.7,0,16.4c-0.1,10,0,23.1-0.1,40.4c0,13.2,0.2,28.7,0.1,47c-0.2,62.8-0.2,158-0.2,301l0,416.2l-1.3,1.8
C660.4,906.2,649.5,906.5,646.8,903.8L646.8,903.8L646.8,903.8z"/>
<path id="path1532" class="st4" d="M665.8,465.1V72.7h8.6v784.7h-8.6V465.1L665.8,465.1z"/>
<ellipse id="path3879" class="st14" cx="771.6" cy="721.1" rx="40.3" ry="40.3"/>
<ellipse id="path3881" class="st15" cx="771.7" cy="721.4" rx="34.1" ry="34.5"/>
<path id="path96" d="M771.7,694.3l-26.8,26.4h7.7v22.5h38.5v-22.5h7.2L771.7,694.3L771.7,694.3z M779.5,735.2h-15.2v-14.5h15.2
V735.2z"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 32 KiB

View File

@@ -1,185 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 27.9.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 1000.4 356.1" style="enable-background:new 0 0 1000.4 356.1;" xml:space="preserve">
<style type="text/css">
.st0{opacity:0.1;}
.st1{fill:#FF5F55;}
.st2{fill:#FF5F53;}
.st3{fill:#FFFFFF;}
.st4{fill:#1A1A1A;stroke:#000000;}
.st5{fill:#1A1A1A;stroke:#1A1A1A;}
.st6{fill:#1A1A1A;stroke:#4D4D4D;}
.st7{stroke:#000000;}
.st8{stroke:#4D4D4D;}
.st9{fill:#999595;stroke:#000000;stroke-width:2.39;stroke-linecap:round;stroke-linejoin:round;}
.st10{fill:#3A3D40;stroke:#000000;stroke-width:2.73;stroke-linecap:round;stroke-linejoin:round;}
</style>
<g id="g315">
<g id="g64" class="st0">
<path id="path36" class="st1" d="M766.5,11.2H687V7c0-3.3,2.7-6,6-6h67.6c3.3,0,6,2.7,6,6L766.5,11.2L766.5,11.2z"/>
<path id="path38" class="st1" d="M363.8,11.2h-79.5V7c0-3.3,2.7-6,6-6h67.6c3.3,0,6,2.7,6,6L363.8,11.2L363.8,11.2z"/>
<path id="path40" class="st1" d="M865.5,342.3l-3.4-3.4c78-33.2,128.7-109.8,128.7-194.7V90h2.6c3.3,0,6,2.7,6,6v51.2
c0,84.8-49.8,161.7-127.2,196.4C869.9,344.6,867.3,344.1,865.5,342.3L865.5,342.3L865.5,342.3z"/>
<path id="path42" class="st1" d="M905.9,92.8h11.7c1.6,0,3-1.3,3-3V78.1c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3-1.3-3-3V60.4
c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3,1.3-3,3v11.7c0,1.6-1.3,3-3,3l0,0h-11.7c-1.6,0-3,1.3-3,3v11.7c0,1.6,1.3,3,3,3l0,0h11.7
c1.6,0,3,1.3,3,3v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3-1.3,3-3V95.8C902.9,94.1,904.3,92.8,905.9,92.8L905.9,92.8z"/>
<circle id="circle44" class="st1" cx="666.5" cy="182.2" r="37.5"/>
<circle id="circle46" class="st1" cx="813.3" cy="182.2" r="37.5"/>
<circle id="circle48" class="st1" cx="739.9" cy="255.6" r="37.5"/>
<circle id="circle50" class="st1" cx="739.9" cy="108.8" r="37.5"/>
<circle id="circle52" class="st1" cx="279.1" cy="128.3" r="27.9"/>
<path id="path54" class="st1" d="M540.1,178.9h-12.3c-3,0-5.5-2.2-5.9-5.2c-3.7-25.2-23.5-45-48.7-48.7c-2.9-0.4-5.1-2.9-5.2-5.9
v-12.3C507.1,108.5,538.4,139.8,540.1,178.9L540.1,178.9L540.1,178.9z"/>
<path id="path56" class="st1" d="M401.6,178.9h-12.3c1.7-39.1,33-70.3,72-72.1v12.3c0,3-2.2,5.5-5.2,5.9
c-25.2,3.7-45,23.5-48.7,48.7C407.1,176.7,404.6,178.9,401.6,178.9L401.6,178.9L401.6,178.9z"/>
<path id="path58" class="st1" d="M461.4,257.6c-39.1-1.7-70.3-33-72-72.1h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7
c2.9,0.4,5.1,2.9,5.2,5.9L461.4,257.6L461.4,257.6z"/>
<path id="path60" class="st1" d="M468,257.6v-12.3c0-3,2.2-5.5,5.2-5.9c25.2-3.7,45-23.5,48.7-48.7c0.4-2.9,2.9-5.1,5.9-5.2h12.3
C538.4,224.6,507.1,255.9,468,257.6L468,257.6L468,257.6z"/>
<path id="path62" class="st1" d="M464.7,257.7c-1.1,0-2.2,0-3.3-0.1v-12.3c0-3-2.2-5.5-5.2-5.9c-25.2-3.7-45-23.5-48.7-48.7
c-0.4-2.9-2.9-5.1-5.9-5.2h-12.3c-0.1-1.1-0.1-2.2-0.1-3.3s0-2.2,0.1-3.3h12.3c3,0,5.5-2.2,5.9-5.2c3.7-25.2,23.5-45,48.7-48.7
c2.9-0.4,5.1-2.9,5.2-5.9v-12.3c1.1-0.1,2.2-0.1,3.3-0.1s2.2,0,3.3,0.1v12.3c0,3,2.2,5.5,5.2,5.9c25.2,3.7,45,23.5,48.7,48.7
c0.4,2.9,2.9,5.1,5.9,5.2h12.3c0.1,1.1,0.1,2.2,0.1,3.3s0,2.2-0.1,3.3h-12.3c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7
c-2.9,0.4-5.1,2.9-5.2,5.9v12.3C466.9,257.6,465.8,257.7,464.7,257.7L464.7,257.7z"/>
</g>
<path id="path72" d="M93.8,14.9V7c0-3.6,2.9-6.4,6.5-6.5h157.2c4.9,0,9.6,1.2,13.9,3.4l13,6.7h79.2l13-6.7c4.3-2.2,9.1-3.4,14-3.4
h269.7c4.9,0,9.6,1.2,13.9,3.4l13,6.7h79.2l13-6.7c4.3-2.2,9.1-3.4,14-3.4h135.8c3.6,0,6.4,2.9,6.5,6.5v7.9c0,3.6-2.9,6.4-6.5,6.5
c-276.3,1.1-552.6,1.2-828.9,0C96.7,21.3,93.8,18.4,93.8,14.9L93.8,14.9L93.8,14.9z M934.7,7c0-3-2.4-5.5-5.5-5.5H793.4
c-4.7,0-9.3,1.1-13.5,3.3l-13.1,6.8c-0.1,0-0.1,0.1-0.2,0.1h-79.5c-0.1,0-0.2,0-0.2-0.1l-13.1-6.8c-4.2-2.2-8.8-3.3-13.5-3.3H390.6
c-4.7,0-9.3,1.1-13.5,3.3L364,11.6c-0.1,0-0.1,0.1-0.2,0.1h-79.5c-0.1,0-0.2,0-0.2-0.1L271,4.8c-4.2-2.2-8.8-3.3-13.5-3.3H100.3
c-3,0-5.5,2.4-5.5,5.5v7.9c0,3,2.4,5.5,5.5,5.5h828.9c3,0,5.5-2.4,5.5-5.5L934.7,7L934.7,7z"/>
<path id="path74" d="M141.5,32.1V20.8c0-0.3,0.2-0.5,0.5-0.5l0,0l786.4,0.8c0.3,0,0.5,0.2,0.5,0.5v11.3c0,0.3-0.2-0.3-0.5-0.3H142
C141.7,32.6,141.5,32.4,141.5,32.1z M142.5,22.2v9.4L928,32.4V22.1l-8.8,1c-256.1-0.6-511.8,4.5-768.3-1.1
C148.1,21.9,145.3,22.2,142.5,22.2L142.5,22.2z"/>
<path id="path76" d="M0.2,144V37.8c0-3.6,2.9-6.5,6.5-6.5h978c3.6,0,6.5,2.9,6.5,6.5V144c0,116.8-95.1,211.9-211.9,211.9H212.1
C95.1,355.9,0.2,261.1,0.2,144L0.2,144L0.2,144z M990.1,37.8c0-3-2.4-5.5-5.5-5.5H6.6c-3,0-5.5,2.4-5.5,5.5V144
c0,116.3,94.6,210.9,210.9,210.9h567.3c116.3,0,210.9-94.6,210.9-210.9L990.1,37.8L990.1,37.8z"/>
<path id="path128" d="M686.1,11.2V7c0-3.8,3.1-6.9,7-7h67.6c3.8,0,6.9,3.1,7,7v4.2c0,0.6-0.4,1-1,1l0,0h-79.5
C686.5,12.2,686.1,11.7,686.1,11.2L686.1,11.2z M765.6,7c0-2.7-2.2-5-5-5H693c-2.7,0-5,2.2-5,5v3.2h77.5L765.6,7L765.6,7z"/>
<path id="path130" d="M283.3,11.2V7c0-3.8,3.1-6.9,7-7h67.6c3.8,0,6.9,3.1,7,7v4.2c0,0.6-0.4,1-1,1l0,0h-79.5
C283.8,12.2,283.3,11.7,283.3,11.2L283.3,11.2z M362.8,7c0-2.7-2.2-5-5-5h-67.6c-2.7,0-5,2.2-5,5v3.2h77.5L362.8,7L362.8,7z"/>
<path id="path1240" class="st2" d="M1.8,162.1c2.4,26.6,9.2,50.5,21.8,76c2.5,5.1,5.2,10,8,14.9c11.3,19.1,27.1,36.3,41.7,49.6
c28,25.5,70.1,45.5,116.5,51.4c0.7,0.1,4.3,0.4,6.8,0.4c6.9-0.1,20,0.7,38.3,0.8c77.5,0.7,244,1.1,376.4,1.1
c101.2,0,182.5-0.3,188.9-1c26.1-2.7,49.1-9.3,72.1-20.8c63.9-31.8,107.4-93,116.7-164c1.5-11.4,1.6-60.7,1.3-96.6
c-0.1-7.7,0.1-14.1-0.1-20.1c-0.2-7.5,0.1-12.9-0.2-16.2c-0.2-1.7-0.8-3-1-3.2c-0.1-0.1-1.4-1.4-3.3-1.5c-5.2-0.3-17.1-0.3-38-0.4
c-4.2,0-8.8-0.1-13.8-0.1c-4.9,0-10.1,0.1-15.8,0.1c-8.8,0-18.6,0.1-29.2,0.1c-9.8,0-20.5-0.2-32,0c-9,0.2-18.4,0.2-28.4,0.2
c-15.1-0.1-31.1,0.6-49,0.3c-15-0.2-30,0.1-46.9,0c-11.1-0.1-22.6,0.1-34.6,0c-7.2-0.1-14.5,0-22.1-0.1c-52.1-0.5-112.2,0-180.3,0
c-254.3,0-376.1-0.3-435.2,0c-7.7,0-14.5-0.2-20.2-0.1c-2.2,0-4.3,0-6.2,0c-3.3,0-6.6,0-9.3,0c-2.9,0-5.8-0.1-8,0
c-5,0.1-8.1,0.1-10,0.3c-2.8,0.3-3.6,1.3-3.8,1.6c-0.2,0.2-0.9,1.3-1.1,3.1c-0.4,4.5-0.3,14.6-0.2,27.1c0.1,9.9,0.2,21.3,0.2,32.8
C1.7,129.3,1.5,162.4,1.8,162.1L1.8,162.1L1.8,162.1z"/>
<path id="path78" d="M237.2,128.3c0-23.1,18.7-41.9,41.9-41.9s41.9,18.7,41.9,41.9s-18.7,41.9-41.9,41.9l0,0
C256,170.1,237.3,151.4,237.2,128.3z M320,128.3c0-22.6-18.3-40.9-40.9-40.9s-40.9,18.3-40.9,40.9s18.3,40.9,40.9,40.9l0,0
C301.7,169.1,320,150.9,320,128.3z"/>
<path id="path92" class="st3" d="M723.9,269.2v-4.7l7-2.2l-0.3-12.4l-6.7-3.2v-4.5l35.2,9.9l-3.2,6.7L723.9,269.2z M735.2,260.5
l14.6-4.9L735,251L735.2,260.5L735.2,260.5z"/>
<path id="path132" d="M861.1,338.9v-0.2c0.1-0.3,0.3-0.6,0.6-0.7c77.7-33,128.2-109.3,128.1-193.8V90c0-0.6,0.4-1,1-1l0,0h2.6
c3.8,0,6.9,3.1,7,7v51.2c-0.1,85.2-50.1,162.4-127.8,197.3c-2.6,1.2-5.7,0.6-7.8-1.5l-3.4-3.4C861.2,339.4,861.1,339.1,861.1,338.9
L861.1,338.9z M991.8,91v53.2c0.1,84.7-50.2,161.3-128,195l2.4,2.4l0,0c1.4,1.5,3.6,1.9,5.5,1.1c77-34.6,126.6-111.1,126.7-195.5
V96c0-2.7-2.2-5-5-5H991.8z"/>
<path id="path134" d="M866.7,89.8V78.1c0-2.2,1.8-4,4-4h11.7c1.1,0,2-0.9,2-2V60.4c0-2.2,1.8-4,4-4h11.7c2.2,0,4,1.8,4,4v11.7
c0,1.1,0.9,2,2,2h11.5c2.2,0,4,1.8,4,4v11.7c0,2.2-1.8,4-4,4h-11.7c-1.1,0-2,0.9-2,2v11.7c0,2.2-1.8,4-4,4h-11.7c-2.2,0-4-1.8-4-4
V95.8c0-1.1-0.9-2-2-2h-11.7C868.5,93.8,866.7,92,866.7,89.8z M901.9,60.5c0-1.1-0.9-2-2-2h-11.7c-1.1,0-2,0.9-2,2v11.7
c0,2.2-1.8,4-4,4h-11.7c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h11.7c2.2,0,4,1.8,4,4v11.7c0,1.1,0.9,2,2,2h11.7c1.1,0,2-0.9,2-2
V95.9c0-2.2,1.8-4,4-4h11.7c1.1,0,2-0.9,2-2V78.2c0-1.1-0.9-2-2-2h-11.7c-2.2,0-4-1.8-4-4V60.5z"/>
<path id="path136" d="M628,182.2c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5s-17.2,38.5-38.5,38.5
C645.2,220.6,628,203.4,628,182.2z M702.9,182.2c0-20.1-16.3-36.5-36.5-36.5s-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5
C686.6,218.6,702.9,202.3,702.9,182.2z"/>
<path id="path138" d="M774.9,182.2c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5s-17.2,38.5-38.5,38.5
C792.1,220.6,774.9,203.4,774.9,182.2z M849.8,182.2c0-20.1-16.3-36.5-36.5-36.5c-20.2,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5
C833.5,218.6,849.8,202.3,849.8,182.2z"/>
<path id="path140" d="M701.4,255.6c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5s-17.2,38.5-38.5,38.5S701.5,276.9,701.4,255.6z
M776.4,255.6c0-20.1-16.3-36.5-36.5-36.5s-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5S776.4,275.8,776.4,255.6z"/>
<path id="path142" d="M701.4,108.8c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5s-17.2,38.5-38.5,38.5
C718.7,147.2,701.5,130,701.4,108.8z M776.4,108.8c0-20.1-16.3-36.5-36.5-36.5s-36.2,16.2-36.2,36.4s16,36.6,36.2,36.6
C760,145.2,776.4,128.9,776.4,108.8z"/>
<path id="path144" d="M250.2,128.3c0-16,13-28.9,28.9-28.9s28.9,13,28.9,28.9s-13,28.9-28.9,28.9l0,0
C263.1,157.2,250.2,144.3,250.2,128.3z M306.1,128.3c0-14.9-12.1-26.9-26.9-26.9s-26.9,12.1-26.9,26.9s12.1,26.9,26.9,26.9
S306,143.2,306.1,128.3z"/>
<path id="path146" d="M467,119.1v-12.3c0-0.6,0.4-1,1-1l0,0c39.6,1.7,71.3,33.4,73,73c0,0.3-0.1,0.5-0.3,0.7s-0.4,0.3-0.7,0.3
h-12.3c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9C469.6,125.5,467,122.6,467,119.1z M469,107.9v11.2
c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3H539C536.9,140.5,506.4,110,469,107.9z"/>
<path id="path148" d="M388.3,178.9C388.3,178.9,388.3,178.8,388.3,178.9c1.7-39.6,33.4-71.3,73-73c0.6,0,1,0.4,1,1v12.3
c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-12.3C388.8,179.9,388.3,179.4,388.3,178.9L388.3,178.9
L388.3,178.9z M460.4,107.9c-37.4,2.2-67.8,32.6-70,70h11.2c2.5,0,4.6-1.8,4.9-4.3c3.9-25.6,24-45.7,49.6-49.6
c2.5-0.3,4.3-2.4,4.3-4.9V107.9z"/>
<path id="path150" d="M388.3,185.5c0-0.6,0.4-1,1-1l0,0h12.3c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9
c3.4,0.5,6,3.4,6,6.9v12.3c0,0.6-0.4,1-1,1l0,0C421.7,256.8,390.1,225.2,388.3,185.5C388.3,185.6,388.3,185.6,388.3,185.5
L388.3,185.5L388.3,185.5z M460.4,245.3c0-2.5-1.8-4.6-4.3-4.9c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-11.2
c2.2,37.4,32.6,67.8,70,70V245.3z"/>
<path id="path152" d="M467,257.6v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h12.3
c0.3,0,0.5,0.1,0.7,0.3s0.3,0.5,0.3,0.7c-1.7,39.6-33.4,71.3-73,73C467.5,258.6,467.1,258.2,467,257.6L467,257.6L467,257.6z
M539,186.5h-11.2c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9v11.2
C506.4,254.4,536.9,223.9,539,186.5z"/>
<path id="path154" d="M388.2,182.2c0-1.2,0-2.3,0.1-3.4c0-0.5,0.5-0.9,1-0.9h12.3c2.5,0,4.6-1.8,4.9-4.3
c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-12.3c0-0.5,0.4-1,0.9-1c1.1-0.1,2.2-0.1,3.4-0.1s2.3,0,3.4,0.1
c0.5,0,0.9,0.5,0.9,1v12.3c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6c0.3,2.5,2.4,4.3,4.9,4.3h12.3c0.5,0,1,0.4,1,0.9
c0.1,2.3,0.1,4.5,0,6.8c0,0.5-0.5,0.9-1,0.9h-12.3c-2.5,0-4.6,1.8-4.9,4.3c-3.9,25.6-24,45.7-49.6,49.6c-2.5,0.3-4.3,2.4-4.3,4.9
v12.3c0,0.5-0.4,1-0.9,1c-1.1,0.1-2.2,0.1-3.4,0.1s-2.3,0-3.4-0.1c-0.5,0-0.9-0.5-0.9-1v-12.3c0-2.5-1.8-4.6-4.3-4.9
c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3h-12.3c-0.5,0-1-0.4-1-0.9C388.3,184.5,388.2,183.4,388.2,182.2L388.2,182.2
L388.2,182.2z M390.3,179.9c-0.1,1.5-0.1,3.1,0,4.7h11.3c3.5,0,6.4,2.6,6.9,6c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9
v11.3h4.6v-11.4c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9c0.5-3.4,3.4-6,6.9-6h11.3c0.1-1.5,0.1-3.1,0-4.7h-11.3
c-3.5,0-6.4-2.6-6.9-6c-3.7-24.7-23.1-44.2-47.9-47.9c-3.4-0.5-6-3.4-6-6.9v-11.3h-4.6V119c0,3.5-2.6,6.4-6,6.9
c-24.7,3.7-44.2,23.1-47.9,47.9c-0.5,3.4-3.4,6-6.9,6h-11.3V179.9L390.3,179.9z"/>
<path id="path1462" class="st4" d="M705,99.6c1.7-6.3,3.9-11.3,9.1-16.5c7.7-7.7,17-11.3,27.7-10.8c13.5,0.6,25,8,31,20
c5.2,10.5,5.3,22.5,0.3,32.7c-4,7.9-10,12.8-18,16.6c-10.8,5.2-24.4,4.2-34.6-2.4c-7.7-5-13.7-13.5-15.7-22
C703.6,112.3,703.7,104.4,705,99.6L705,99.6L705,99.6z"/>
<path id="path1464" class="st4" d="M777.6,176c0.3,0,0.9-3.7,1.6-5.7c1.1-3,2.6-5.9,4-8c4.6-6.9,10.9-11.7,18.9-14.5
c3.8-1.3,5.2-2.1,11.5-2.1s7.2,0.7,11,2.1c11.1,3.9,19.1,11.8,23,22.8c1.5,4.2,2.3,5.2,2.3,11.6s-0.8,7.3-2.3,11.6
c-5.2,14.5-17.6,24-32.9,24.7c-10.6,0.5-19.5-2.7-26.9-10.2c-7.5-7.6-10.7-14.4-11-24.6C776.7,180.2,777.4,176.7,777.6,176
L777.6,176L777.6,176z"/>
<path id="path1466" class="st4" d="M704,248.2c1-6.7,5.8-15.6,12.9-20.8c4.1-3,10.7-6.2,15.7-7.3c13.2-2.8,27.9,2.6,35.9,13.3
c15.2,20,6.7,48.1-17,56.4c-5.3,1.9-13.3,3-19.2,1.7c-6.8-1.5-12.9-4.9-18.2-10.2c-5.2-5.3-8-9.9-9.6-16.4
C703.3,260.1,703.3,252.9,704,248.2L704,248.2L704,248.2z"/>
<path id="path1468" class="st4" d="M630.6,177c1.3-8.1,4-14.2,10.3-20.6c3.7-3.8,6.2-5.4,10-7.2c15.8-7.6,33.1-3,44.1,10.8
c5.1,6.4,7.6,13.6,7.6,22.1c0,29.9-33.8,46.7-58,28.7c-3.8-2.8-7.5-6.3-9.8-10.5C630.7,193.3,629.4,184.7,630.6,177L630.6,177
L630.6,177z"/>
<path id="path1500" class="st5" d="M397.8,180.2c8.9-0.3,9.7-0.8,11.9-10.1c4.8-21.1,20.1-37.2,41.3-42.6c2.2-0.5,5.2-1.1,5.9-1.1
s2.2-1,3.5-2.2l2-2.3l0.3-6.9v-7h4v5.9c0,6.6,1,9.9,3.4,11.2c0.8,0.4,3.9,1.5,7,2c16.3,2.7,30.7,14.9,38,29.5
c2.4,4.7,4.6,11.4,5.4,15.5c1.1,6.6,3.6,8.2,12.8,8.2h5.9v4H532c-6.6,0-7,0.1-8.8,1.8c-1.6,1.5-1.7,3.9-3.1,9.5
c-5,20.4-20.5,35.3-40.2,40.7c-2.9,0.8-6.4,1.8-7.8,2.2c-4.3,1.2-5.6,3.8-5.6,11.7v6.5h-4V250c0-7-0.8-9.9-3.1-10.8
c-0.7-0.3-4.6-1.3-8-2.1c-21.4-5.4-36.7-21.3-41.5-42.1c-2.3-10-3.2-10.7-12.8-10.7h-6.3v-3.8L397.8,180.2L397.8,180.2z"/>
<path id="path1504" class="st6" d="M473.9,108.8c15.3,1.8,31.2,8.9,43,20.4c12.2,12,19.2,27.5,21.6,45.7l0.4,2.8h-6.2
c-7.9,0-8.9-0.1-10.2-6.8c-4.6-22.3-22.1-41.8-44.2-46.1c-9.1-1.8-9.1-2.4-9.1-11.1v-5.4L473.9,108.8L473.9,108.8z"/>
<path id="path1506" class="st6" d="M392.2,167.8c6.9-32.2,32.9-55.7,65.6-59.4l2.1-0.2v6.4c0,6.9,0,6.8-1,7.8
c-1.4,1.3-3.8,1.5-7.9,2.4c-21.2,4.8-39.1,24.2-44,46.6c-1.5,6.9-2.7,6.4-10.3,6.4h-5.9l0-2.1C391,174.4,391.5,170.9,392.2,167.8
L392.2,167.8L392.2,167.8z"/>
<path id="path1508" class="st6" d="M397.4,186.6c7.3-0.3,8.2,1,9,5.3c0.8,4.8,2.9,11.1,5.5,16.3c7.7,15.8,22,27.1,39.9,31.6
c4,1,7.2,1.6,7.7,2.2c0.5,0.7,0.5,3.9,0.5,7.8v6.2l-3.8-0.4c-33.2-3.8-61.3-31.8-65-64.8l-0.5-4L397.4,186.6L397.4,186.6z"/>
<path id="path1510" class="st6" d="M470.6,242c1.1-1.2,3-1.3,6.7-2.1c20.5-4.4,36.6-19,43.5-39.3c0.8-2.4,1.7-5.8,2-7.5
c0.3-1.9,0.6-3.9,1.5-4.8c1.4-1.4,2.6-1.3,8.2-1.3h6.2l-0.3,2.5c-2.5,19-9.2,32.7-22.1,45.4c-10.6,10.4-23.8,17.4-38.2,20.2
c-2.9,0.5-6.1,1-7.1,1h-1.9v-5.9C469.2,244.9,469.3,243.4,470.6,242L470.6,242L470.6,242z"/>
<path id="path1512" class="st4" d="M869.4,76.9c0.6-0.5,1.7-0.6,7.5-0.6h6.9l1.2-1.1l1.2-1.1l0.1-7.1c0.1-4.1-0.5-6.5,0.2-7.6
c0.8-1.3,3.1-0.9,7.6-0.9s6.3,0.1,6.8,0.5c0.7,0.5,0.7,1.1,0.8,7.3c0,3.7,0.2,7.1,0.3,7.6c0.1,0.5,0.7,1.2,1.4,1.6
c1.1,0.7,1.9,0.7,7.8,0.7c3.8,0,6.9,0.2,7.3,0.4c0.7,0.4,0.7,0.9,0.7,7.3s0,7-0.7,7.3c-0.4,0.2-3.5,0.4-7.3,0.4
c-5.8,0-6.7,0.1-7.8,0.7c-0.7,0.4-1.3,1.1-1.4,1.6s-0.2,3.9-0.3,7.6c-0.1,6.2-0.2,6.8-0.8,7.3c-0.6,0.4-2.2,0.5-6.8,0.5
c-4.7,0-7.2,0.7-7.9-0.9c-0.5-1.2,0.1-3.8,0.1-7.5l-0.1-7.1l-1.2-1.1l-1.2-1.1h-6.9c-6.2,0-7-0.1-7.5-0.7c-0.5-0.6-0.6-1.7-0.6-7.1
C868.7,78.2,868.8,77.5,869.4,76.9L869.4,76.9L869.4,76.9z"/>
<path id="path1514" class="st6" d="M274,123.2h5.3v10.5h-10.5v-10.5H274L274,123.2z"/>
<path id="path1518" class="st6" d="M238.8,122.6c2.3-14.8,12.3-27.2,26.2-32.4c20-7.5,43,2.3,51.4,22c2.6,6.1,3.5,8,3.5,15.7
c0,6.5-0.6,7.9-1.6,11.3c-4.4,14.4-14.9,24.6-29.4,28.6c-2.9,0.8-5.2,1.1-10.7,1.1c-5.5,0-6.2-0.3-9-1.1
c-17.7-4.8-29.9-20-30.5-38.1C238.5,127.1,238.6,124,238.8,122.6L238.8,122.6L238.8,122.6z M250.8,134.7
c2.6,11.9,13,21.3,25.1,22.5c21.5,2.2,37.7-18.1,30.7-38.5c-1.4-4.2-3.3-7-7.1-10.8c-2.8-2.8-4.1-3.8-7.2-5.3
c-5.1-2.6-8.7-3.3-14.6-3c-6.8,0.3-11.7,2.2-16.9,6.3C252.4,112.5,248.4,124,250.8,134.7L250.8,134.7L250.8,134.7z"/>
<path id="path1520" class="st7" d="M286.1,4.8c0.8-1.3,0.9-2.3,5.3-2.5c4.3-0.2,13.5,0.1,32.6,0.1c32.8,0,35.2-0.5,36.3,0.6
c0.1,0.1,0.2,0.1,0.2,0.2c1.5,1.1,2.1,2.7,2.1,4.9v1.9h-77.3v-2C285.4,6.6,285.7,5.5,286.1,4.8L286.1,4.8L286.1,4.8z"/>
<path id="path1522" class="st7" d="M688.3,6.2c0.1-0.5,0.4-1.3,0.8-1.8c0.5-0.8,0.8-1.5,2.7-1.8c3.2-0.5,11.4-0.2,35.1-0.2
c19.3,0,28.3-0.5,32.5-0.4c2.7,0.1,3.2,0.8,3.6,1c1.6,0.9,2.3,2.4,2.3,4.8v2.1h-77.3l0-1.4C688.1,7.7,688.2,6.7,688.3,6.2
L688.3,6.2L688.3,6.2z"/>
<path id="path1524" class="st8" d="M874,334.6c20.6-10.1,37.2-21.9,53.9-38.2c35.7-34.8,57-78.7,63.1-129.7
c0.6-5.1,0.8-13.1,1-40.9l0.2-34.6h1.4c1,0,3,0,3.7,1.4l1.1,2.1l-0.2,30.4c-0.1,16.9-0.2,33.5-0.5,37
c-3.9,50.8-24.6,97.1-59.5,133.3c-16.9,17.6-35.7,31.5-57.9,42.8c-8.4,4.3-10.1,4.9-11.8,4.2c-1.1-0.4-4.2-2.7-4.1-3.2
C864.4,339.2,869,337.1,874,334.6L874,334.6L874,334.6z"/>
<path id="path1530" class="st4" d="M96.7,3.4c0.5-0.6,1.2-1.7,5-1.6c6.7,0.3,27.2-0.2,79.1-0.1L263.4,2l6.5,2.6l15,7.9l39.4,0.1
l39.6-0.4l13.2-7.1l7.7-2.9l7.3-0.4l48,0.1l22.1-0.1l34.1,0.1l10.5,0.1h10.5l8.6-0.1l25.6,0h19.4l27.5-0.2L620,1.8l11,0l19.6,0.1
l10.2,0l5.7,0.5l5.8,1.9l5.5,3l9.8,5.3h39.5l39.6-0.4l9.8-5.3l5.3-2.7l5.1-1.8l7.6-0.7l13.3,0.2l12.2-0.1h11.1l10.9,0l9.9,0h6.5
l2.9,0l17.4,0.1l21.5,0h10.8l8.4-0.1l5.1,0l5.9-0.2l3.1,2.2l1.1,3.2l-0.1,3.2c0,1.4-0.1,2.7-0.2,3.9c-0.1,0.9-0.1,1.8-0.4,2.6
c-0.4,1-1,1.7-1.3,2c-0.2,0.2-1.7,1.2-4.8,1.3c-2.1,0.1-4.7,0-8.3,0c-4.1,0-9.7,0.1-16.4,0c-10-0.1-23.1,0-40.4-0.1
c-13.2,0-28.7,0.2-47,0.1c-62.8-0.2-158-0.2-301-0.2L98.7,20l-1.8-1.3C94.3,16.9,94,6.1,96.7,3.4L96.7,3.4L96.7,3.4z"/>
<path id="path1532" class="st4" d="M535.4,22.4h392.4V31H143v-8.6H535.4L535.4,22.4z"/>
<ellipse id="path3879" class="st9" cx="279.4" cy="128.2" rx="40.3" ry="40.3"/>
<ellipse id="path3881" class="st10" cx="279.1" cy="128.2" rx="34.5" ry="34.1"/>
<path id="path96" d="M306.1,128.3l-26.4-26.8v7.7h-22.5v38.5h22.5v7.2L306.1,128.3L306.1,128.3z M265.2,136.1v-15.2h14.5v15.2
H265.2z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,84 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 996.25 690.92">
<defs>
<style>
.cls-1 {
stroke: #fff;
stroke-miterlimit: 10;
stroke-width: 2px;
}
.cls-1, .cls-2 {
fill: #444542;
}
.cls-3 {
fill: #3b3b3b;
}
.cls-3, .cls-4, .cls-2, .cls-5, .cls-6, .cls-7 {
stroke-width: 0px;
}
.cls-4 {
fill: #3b3c3a;
}
.cls-5 {
fill: #454644;
}
.cls-6 {
fill: #20221f;
}
.cls-7 {
fill: #121212;
}
</style>
</defs>
<g id="Front">
<path id="Right_Grip" data-name="Right Grip" class="cls-6" d="m739.17,492.09c34,28.2,27.6,35.9,68.5,108.5,36.7,74.7,64.4,104.4,125.1,84.1h0c95.3-57.9,59.3-145.3,43.6-275.2-10-60.6-35.6-190.3-35.6-190.3l-201.6,272.9Z"/>
<path id="Left_Grip" data-name="Left Grip" class="cls-6" d="m55.47,219.19s-25.6,129.7-35.6,190.3c-15.7,129.9-51.7,217.2,43.6,275.1h0c60.8,20.3,88.4-9.4,125.1-84.1,40.9-72.7,34.5-80.3,68.5-108.5L55.47,219.19Z"/>
<path id="Right_Bumper" data-name="Right Bumper" class="cls-3" d="m649.47,19.99c10.1-4.3,39.7-22.5,58.7-19.7,59.5.9,166.7,17.7,172.6,81.2"/>
<path id="Left_Bumper" data-name="Left Bumper" class="cls-3" d="m115.57,81.49C121.47,18.09,228.57,1.29,288.17.29c19-2.8,48.6,15.4,58.7,19.7"/>
<path id="Background" class="cls-7" d="m739.17,492.09c35.5-30.8,68.5-74.7,96-113.5,26.9-36.3,94.7-136.7,105.6-159.3,0-2.4-6.3-30.1-12.8-56.2C892.27,3.49,675.37,19.69,498.17,19.69S104.07,3.49,68.27,162.99c-6.5,26-12.8,53.8-12.8,56.2,10.9,22.6,78.8,123,105.6,159.3,27.5,38.8,60.5,82.8,96,113.5"/>
<g id="Directional_Pad" data-name="Directional Pad">
<path id="Background-2" data-name="Background" class="cls-2" d="m439.37,325.09h-40c-2.8,0-5-2.2-5-5v-40c0-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,5v40c0,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-30c0-2.7-2.2-5-5-5Z"/>
</g>
<g id="R_Thumbstick" data-name="R Thumbstick">
<circle id="Background-3" data-name="Background" class="cls-6" cx="623.77" cy="345.09" r="55"/>
<circle id="Stick" class="cls-1" cx="623.77" cy="345.09" r="45"/>
</g>
<g id="L_Thumbstick" data-name="L Thumbstick">
<circle id="Background-4" data-name="Background" class="cls-6" cx="213.37" cy="206.39" r="55"/>
<circle id="Stick-2" data-name="Stick" class="cls-1" cx="213.37" cy="206.39" r="45" transform="translate(-24.53 383.95) rotate(-80.78)"/>
</g>
<g id="Minus_Button" data-name="Minus Button">
<circle id="_Background" data-name=" Background" class="cls-5" cx="374.17" cy="130.89" r="22.5"/>
</g>
<g id="Plus_Button" data-name="Plus Button">
<circle id="_Background-2" data-name=" Background" class="cls-5" cx="623.57" cy="131.19" r="22.5"/>
</g>
<g id="Home_Button" data-name="Home Button">
<circle id="_Background-3" data-name=" Background" class="cls-5" cx="578.57" cy="206.39" r="22.5"/>
</g>
<g id="Capture_Button" data-name="Capture Button">
<path class="cls-5" d="m441.77,228.09h-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.5c0,2.7-2.2,5-5,5Z"/>
</g>
<g id="Buttons">
<g id="A_Button" data-name="A Button">
<circle id="Background-5" data-name="Background" class="cls-4" cx="837.07" cy="206.39" r="35"/>
</g>
<g id="X_Button" data-name="X Button">
<circle id="Background-6" data-name="Background" class="cls-4" cx="767.07" cy="136.39" r="35"/>
</g>
<g id="Y_Button" data-name="Y Button">
<circle id="Background-7" data-name="Background" class="cls-4" cx="697.07" cy="206.39" r="35"/>
</g>
<g id="B_Button" data-name="B Button">
<circle id="Background-8" data-name="Background" class="cls-4" cx="767.07" cy="276.39" r="35"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -54,6 +54,8 @@
"GameListContextMenuManageTitleUpdatesToolTip": "Opens the Title Update management window",
"GameListContextMenuManageDlc": "Manage DLC",
"GameListContextMenuManageDlcToolTip": "Opens the DLC management window",
"GameListContextMenuOpenModsDirectory": "Open Mods Directory",
"GameListContextMenuOpenModsDirectoryToolTip": "Opens the directory which contains Application's Mods",
"GameListContextMenuCacheManagement": "Cache Management",
"GameListContextMenuCacheManagementPurgePptc": "Queue PPTC Rebuild",
"GameListContextMenuCacheManagementPurgePptcToolTip": "Trigger PPTC to rebuild at boot time on the next game launch",
@@ -292,9 +294,13 @@
"GameListContextMenuRunApplication": "Run Application",
"GameListContextMenuToggleFavorite": "Toggle Favorite",
"GameListContextMenuToggleFavoriteToolTip": "Toggle Favorite status of Game",
"SettingsTabGeneralTheme": "Theme:",
"SettingsTabGeneralThemeDark": "Dark",
"SettingsTabGeneralThemeLight": "Light",
"SettingsTabGeneralTheme": "Theme",
"SettingsTabGeneralThemeCustomTheme": "Custom Theme Path",
"SettingsTabGeneralThemeBaseStyle": "Base Style",
"SettingsTabGeneralThemeBaseStyleDark": "Dark",
"SettingsTabGeneralThemeBaseStyleLight": "Light",
"SettingsTabGeneralThemeEnableCustomTheme": "Enable Custom Theme",
"ButtonBrowse": "Browse",
"ControllerSettingsConfigureGeneral": "Configure",
"ControllerSettingsRumble": "Rumble",
"ControllerSettingsRumbleStrongMultiplier": "Strong Rumble Multiplier",
@@ -381,10 +387,7 @@
"DialogUserProfileUnsavedChangesSubMessage": "Do you want to discard your changes?",
"DialogControllerSettingsModifiedConfirmMessage": "The current controller settings has been updated.",
"DialogControllerSettingsModifiedConfirmSubMessage": "Do you want to save?",
"DialogLoadFileErrorMessage": "{0}. Errored File: {1}",
"DialogModAlreadyExistsMessage": "Mod already exists",
"DialogModInvalidMessage": "The specified directory does not contain a mod!",
"DialogModDeleteNoParentMessage": "Failed to Delete: Could not find the parent directory for mod \"{0}\"!",
"DialogLoadNcaErrorMessage": "{0}. Errored File: {1}",
"DialogDlcNoDlcErrorMessage": "The specified file does not contain a DLC for the selected title!",
"DialogPerformanceCheckLoggingEnabledMessage": "You have trace logging enabled, which is designed to be used by developers only.",
"DialogPerformanceCheckLoggingEnabledConfirmMessage": "For optimal performance, it's recommended to disable trace logging. Would you like to disable trace logging now?",
@@ -395,8 +398,6 @@
"DialogUpdateAddUpdateErrorMessage": "The specified file does not contain an update for the selected title!",
"DialogSettingsBackendThreadingWarningTitle": "Warning - Backend Threading",
"DialogSettingsBackendThreadingWarningMessage": "Ryujinx must be restarted after changing this option for it to apply fully. Depending on your platform, you may need to manually disable your driver's own multithreading when using Ryujinx's.",
"DialogModManagerDeletionWarningMessage": "You are about to delete the mod: {0}\n\nAre you sure you want to proceed?",
"DialogModManagerDeletionAllWarningMessage": "You are about to delete all mods for this title.\n\nAre you sure you want to proceed?",
"SettingsTabGraphicsFeaturesOptions": "Features",
"SettingsTabGraphicsBackendMultithreading": "Graphics Backend Multithreading:",
"CommonAuto": "Auto",
@@ -431,7 +432,6 @@
"DlcManagerRemoveAllButton": "Remove All",
"DlcManagerEnableAllButton": "Enable All",
"DlcManagerDisableAllButton": "Disable All",
"ModManagerDeleteAllButton": "Delete All",
"MenuBarOptionsChangeLanguage": "Change Language",
"MenuBarShowFileTypes": "Show File Types",
"CommonSort": "Sort",
@@ -506,8 +506,6 @@
"EnableInternetAccessTooltip": "Allows the emulated application to connect to the Internet.\n\nGames with a LAN mode can connect to each other when this is enabled and the systems are connected to the same access point. This includes real consoles as well.\n\nDoes NOT allow connecting to Nintendo servers. May cause crashing in certain games that try to connect to the Internet.\n\nLeave OFF if unsure.",
"GameListContextMenuManageCheatToolTip": "Manage Cheats",
"GameListContextMenuManageCheat": "Manage Cheats",
"GameListContextMenuManageModToolTip": "Manage Mods",
"GameListContextMenuManageMod": "Manage Mods",
"ControllerSettingsStickRange": "Range:",
"DialogStopEmulationTitle": "Ryujinx - Stop Emulation",
"DialogStopEmulationMessage": "Are you sure you want to stop emulation?",
@@ -519,6 +517,8 @@
"SettingsTabCpuMemory": "CPU Mode",
"DialogUpdaterFlatpakNotSupportedMessage": "Please update Ryujinx via FlatHub.",
"UpdaterDisabledWarningTitle": "Updater Disabled!",
"GameListContextMenuOpenSdModsDirectory": "Open Atmosphere Mods Directory",
"GameListContextMenuOpenSdModsDirectoryToolTip": "Opens the alternative SD card Atmosphere directory which contains Application's Mods. Useful for mods that are packaged for real hardware.",
"ControllerSettingsRotate90": "Rotate 90° Clockwise",
"IconSize": "Icon Size",
"IconSizeTooltip": "Change the size of game icons",
@@ -549,10 +549,9 @@
"SoftwareKeyboardModeNumeric": "Must be 0-9 or '.' only",
"SoftwareKeyboardModeAlphabet": "Must be non CJK-characters only",
"SoftwareKeyboardModeASCII": "Must be ASCII text only",
"ControllerAppletControllers": "Supported Controllers:",
"ControllerAppletPlayers": "Players:",
"ControllerAppletDescription": "Your current configuration is invalid. Open settings and reconfigure your inputs.",
"ControllerAppletDocked": "Docked mode set. Handheld control should be disabled.",
"DialogControllerAppletMessagePlayerRange": "Application requests {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletMessage": "Application requests exactly {0} player(s) with:\n\nTYPES: {1}\n\nPLAYERS: {2}\n\n{3}Please open Settings and reconfigure Input now or press Close.",
"DialogControllerAppletDockModeSet": "Docked mode set. Handheld is also invalid.\n\n",
"UpdaterRenaming": "Renaming Old Files...",
"UpdaterRenameFailed": "Updater was unable to rename file: {0}",
"UpdaterAddingFiles": "Adding New Files...",
@@ -590,7 +589,6 @@
"Writable": "Writable",
"SelectDlcDialogTitle": "Select DLC files",
"SelectUpdateDialogTitle": "Select update files",
"SelectModDialogTitle": "Select mod directory",
"UserProfileWindowTitle": "User Profiles Manager",
"CheatWindowTitle": "Cheats Manager",
"DlcWindowTitle": "Manage Downloadable Content for {0} ({1})",
@@ -598,7 +596,6 @@
"CheatWindowHeading": "Cheats Available for {0} [{1}]",
"BuildId": "BuildId:",
"DlcWindowHeading": "{0} Downloadable Content(s)",
"ModWindowHeading": "{0} Mod(s)",
"UserProfilesEditProfile": "Edit Selected",
"Cancel": "Cancel",
"Save": "Save",

View File

@@ -16,10 +16,8 @@ namespace Ryujinx.Ava.Common.Locale
private readonly Dictionary<LocaleKeys, string> _localeStrings;
private Dictionary<LocaleKeys, string> _localeDefaultStrings;
private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues;
private string _localeLanguageCode;
public static LocaleManager Instance { get; } = new();
public event Action LocaleChanged;
public LocaleManager()
{
@@ -106,15 +104,6 @@ namespace Ryujinx.Ava.Common.Locale
}
}
public bool IsRTL()
{
return _localeLanguageCode switch
{
"he_IL" => true,
_ => false
};
}
public string UpdateAndGetDynamicValue(LocaleKeys key, params object[] values)
{
_dynamicValues[key] = values;
@@ -135,9 +124,6 @@ namespace Ryujinx.Ava.Common.Locale
{
this[item.Key] = item.Value;
}
_localeLanguageCode = languageCode;
LocaleChanged?.Invoke();
}
private static Dictionary<LocaleKeys, string> LoadJsonLanguage(string languageCode = DefaultLanguageCode)

View File

@@ -119,7 +119,6 @@
<None Remove="Assets\Locales\en_US.json" />
<None Remove="Assets\Locales\es_ES.json" />
<None Remove="Assets\Locales\fr_FR.json" />
<None Remove="Assets\Locales\he_IL.json" />
<None Remove="Assets\Locales\de_DE.json" />
<None Remove="Assets\Locales\it_IT.json" />
<None Remove="Assets\Locales\ja_JP.json" />
@@ -133,10 +132,6 @@
<None Remove="Assets\Locales\zh_TW.json" />
<None Remove="Assets\Styles\Styles.xaml" />
<None Remove="Assets\Styles\Themes.xaml" />
<None Remove="Assets\Icons\Controller_JoyConLeft.svg" />
<None Remove="Assets\Icons\Controller_JoyConPair.svg" />
<None Remove="Assets\Icons\Controller_JoyConRight.svg" />
<None Remove="Assets\Icons\Controller_ProCon.svg" />
</ItemGroup>
<ItemGroup>
@@ -144,7 +139,6 @@
<EmbeddedResource Include="Assets\Locales\en_US.json" />
<EmbeddedResource Include="Assets\Locales\es_ES.json" />
<EmbeddedResource Include="Assets\Locales\fr_FR.json" />
<EmbeddedResource Include="Assets\Locales\he_IL.json" />
<EmbeddedResource Include="Assets\Locales\de_DE.json" />
<EmbeddedResource Include="Assets\Locales\it_IT.json" />
<EmbeddedResource Include="Assets\Locales\ja_JP.json" />
@@ -157,10 +151,6 @@
<EmbeddedResource Include="Assets\Locales\zh_CN.json" />
<EmbeddedResource Include="Assets\Locales\zh_TW.json" />
<EmbeddedResource Include="Assets\Styles\Styles.xaml" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConLeft.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConPair.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_JoyConRight.svg" />
<EmbeddedResource Include="Assets\Icons\Controller_ProCon.svg" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Assets\Locales\en_US.json" />

View File

@@ -29,24 +29,14 @@ namespace Ryujinx.Ava.UI.Applet
public bool DisplayMessageDialog(ControllerAppletUiArgs args)
{
ManualResetEvent dialogCloseEvent = new(false);
string message = LocaleManager.Instance.UpdateAndGetDynamicValue(
args.PlayerCountMin == args.PlayerCountMax ? LocaleKeys.DialogControllerAppletMessage : LocaleKeys.DialogControllerAppletMessagePlayerRange,
args.PlayerCountMin == args.PlayerCountMax ? args.PlayerCountMin.ToString() : $"{args.PlayerCountMin}-{args.PlayerCountMax}",
args.SupportedStyles,
string.Join(", ", args.SupportedPlayers),
args.IsDocked ? LocaleManager.Instance[LocaleKeys.DialogControllerAppletDockModeSet] : "");
bool okPressed = false;
Dispatcher.UIThread.InvokeAsync(async () =>
{
var response = await ControllerAppletDialog.ShowControllerAppletDialog(_parent, args);
if (response == UserResult.Ok)
{
okPressed = true;
}
dialogCloseEvent.Set();
});
dialogCloseEvent.WaitOne();
return okPressed;
return DisplayMessageDialog(LocaleManager.Instance[LocaleKeys.DialogControllerAppletTitle], message);
}
public bool DisplayMessageDialog(string title, string message)
@@ -85,8 +75,6 @@ namespace Ryujinx.Ava.UI.Applet
await _parent.SettingsWindow.ShowDialog(window);
_parent.SettingsWindow = null;
opened = false;
});

View File

@@ -1,145 +0,0 @@
<UserControl
x:Class="Ryujinx.Ava.UI.Applet.ControllerAppletDialog"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:applet="using:Ryujinx.Ava.UI.Applet"
mc:Ignorable="d"
Width="400"
Focusable="True"
x:DataType="applet:ControllerAppletDialog">
<Grid
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
Grid.Row="0"
Grid.ColumnSpan="2"
Margin="0 0 0 10"
BorderBrush="{DynamicResource ThemeControlBorderColor}"
BorderThickness="1"
CornerRadius="5">
<StackPanel
Spacing="10"
Margin="10">
<TextBlock
Text="{locale:Locale ControllerAppletDescription}" />
<TextBlock
IsVisible="{Binding IsDocked}"
FontWeight="Bold"
Text="{locale:Locale ControllerAppletDocked}" />
</StackPanel>
</Border>
<Border
Grid.Column="0"
Grid.Row="1"
BorderBrush="{DynamicResource ThemeControlBorderColor}"
BorderThickness="1"
CornerRadius="5"
Margin="0 0 10 0">
<StackPanel
Margin="10"
Spacing="10"
Orientation="Vertical">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center"
FontWeight="Bold"
Text="{locale:Locale ControllerAppletControllers}" />
<StackPanel
Spacing="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Orientation="Horizontal">
<Image
Height="50"
Width="50"
Stretch="Uniform"
Source="{Binding ProControllerImage}"
IsVisible="{Binding SupportsProController}" />
<Image
Height="50"
Width="50"
Stretch="Uniform"
Source="{Binding JoyconPairImage}"
IsVisible="{Binding SupportsJoyconPair}" />
<Image
Height="50"
Width="50"
Stretch="Uniform"
Source="{Binding JoyconLeftImage}"
IsVisible="{Binding SupportsLeftJoycon}" />
<Image
Height="50"
Width="50"
Stretch="Uniform"
Source="{Binding JoyconRightImage}"
IsVisible="{Binding SupportsRightJoycon}" />
</StackPanel>
</StackPanel>
</Border>
<Border
Grid.Column="1"
Grid.Row="1"
BorderBrush="{DynamicResource ThemeControlBorderColor}"
BorderThickness="1"
CornerRadius="5">
<StackPanel
Margin="10"
Spacing="10"
Orientation="Vertical">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center"
FontWeight="Bold"
Text="{locale:Locale ControllerAppletPlayers}" />
<Border Height="50">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center"
FontSize="40"
FontWeight="Thin"
Text="{Binding PlayerCount}" />
</Border>
</StackPanel>
</Border>
<Panel
Margin="0 24 0 0"
Grid.Column="0"
Grid.Row="2"
Grid.ColumnSpan="2">
<StackPanel
Orientation="Horizontal"
Spacing="10"
HorizontalAlignment="Right">
<Button
Name="SaveButton"
MinWidth="90"
Command="{Binding OpenSettingsWindow}">
<TextBlock Text="{locale:Locale DialogOpenSettingsWindowLabel}" />
</Button>
<Button
Name="CancelButton"
MinWidth="90"
Command="{Binding Close}">
<TextBlock Text="{locale:Locale SettingsButtonClose}" />
</Button>
</StackPanel>
</Panel>
</Grid>
</UserControl>

View File

@@ -1,139 +0,0 @@
using Avalonia.Controls;
using Avalonia.Styling;
using Avalonia.Svg.Skia;
using Avalonia.Threading;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common;
using Ryujinx.HLE.HOS.Applets;
using Ryujinx.HLE.HOS.Services.Hid;
using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Applet
{
internal partial class ControllerAppletDialog : UserControl
{
private const string ProControllerResource = "Ryujinx.Ava/Assets/Icons/Controller_ProCon.svg";
private const string JoyConPairResource = "Ryujinx.Ava/Assets/Icons/Controller_JoyConPair.svg";
private const string JoyConLeftResource = "Ryujinx.Ava/Assets/Icons/Controller_JoyConLeft.svg";
private const string JoyConRightResource = "Ryujinx.Ava/Assets/Icons/Controller_JoyConRight.svg";
public static SvgImage ProControllerImage => GetResource(ProControllerResource);
public static SvgImage JoyconPairImage => GetResource(JoyConPairResource);
public static SvgImage JoyconLeftImage => GetResource(JoyConLeftResource);
public static SvgImage JoyconRightImage => GetResource(JoyConRightResource);
public string PlayerCount { get; set; } = "";
public bool SupportsProController { get; set; }
public bool SupportsLeftJoycon { get; set; }
public bool SupportsRightJoycon { get; set; }
public bool SupportsJoyconPair { get; set; }
public bool IsDocked { get; set; }
private readonly MainWindow _mainWindow;
public ControllerAppletDialog(MainWindow mainWindow, ControllerAppletUiArgs args)
{
if (args.PlayerCountMin == args.PlayerCountMax)
{
PlayerCount = args.PlayerCountMin.ToString();
}
else
{
PlayerCount = $"{args.PlayerCountMin} - {args.PlayerCountMax}";
}
SupportsProController = (args.SupportedStyles & ControllerType.ProController) != 0;
SupportsLeftJoycon = (args.SupportedStyles & ControllerType.JoyconLeft) != 0;
SupportsRightJoycon = (args.SupportedStyles & ControllerType.JoyconRight) != 0;
SupportsJoyconPair = (args.SupportedStyles & ControllerType.JoyconPair) != 0;
IsDocked = args.IsDocked;
_mainWindow = mainWindow;
DataContext = this;
InitializeComponent();
}
public ControllerAppletDialog(MainWindow mainWindow)
{
_mainWindow = mainWindow;
DataContext = this;
InitializeComponent();
}
public static async Task<UserResult> ShowControllerAppletDialog(MainWindow window, ControllerAppletUiArgs args)
{
ContentDialog contentDialog = new();
UserResult result = UserResult.Cancel;
ControllerAppletDialog content = new(window, args);
contentDialog.Title = LocaleManager.Instance[LocaleKeys.DialogControllerAppletTitle];
contentDialog.Content = content;
void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
{
if (eventArgs.Result == ContentDialogResult.Primary)
{
result = UserResult.Ok;
}
}
contentDialog.Closed += Handler;
Style bottomBorder = new(x => x.OfType<Grid>().Name("DialogSpace").Child().OfType<Border>());
bottomBorder.Setters.Add(new Setter(IsVisibleProperty, false));
contentDialog.Styles.Add(bottomBorder);
await ContentDialogHelper.ShowAsync(contentDialog);
return result;
}
private static SvgImage GetResource(string path)
{
SvgImage image = new();
if (!string.IsNullOrWhiteSpace(path))
{
SvgSource source = new();
source.Load(EmbeddedResources.GetStream(path));
image.Source = source;
}
return image;
}
public void OpenSettingsWindow()
{
if (_mainWindow.SettingsWindow == null)
{
Dispatcher.UIThread.InvokeAsync(async () =>
{
_mainWindow.SettingsWindow = new SettingsWindow(_mainWindow.VirtualFileSystem, _mainWindow.ContentManager);
_mainWindow.SettingsWindow.NavPanel.Content = _mainWindow.SettingsWindow.InputPage;
_mainWindow.SettingsWindow.NavPanel.SelectedItem = _mainWindow.SettingsWindow.NavPanel.MenuItems.ElementAt(1);
await ContentDialogHelper.ShowWindowAsync(_mainWindow.SettingsWindow, _mainWindow);
_mainWindow.SettingsWindow = null;
this.Close();
});
}
}
public void Close()
{
((ContentDialog)Parent)?.Hide();
}
}
}

View File

@@ -47,9 +47,13 @@
Header="{locale:Locale GameListContextMenuManageCheat}"
ToolTip.Tip="{locale:Locale GameListContextMenuManageCheatToolTip}" />
<MenuItem
Click="OpenModManager_Click"
Header="{locale:Locale GameListContextMenuManageMod}"
ToolTip.Tip="{locale:Locale GameListContextMenuManageModToolTip}" />
Click="OpenModsDirectory_Click"
Header="{locale:Locale GameListContextMenuOpenModsDirectory}"
ToolTip.Tip="{locale:Locale GameListContextMenuOpenModsDirectoryToolTip}" />
<MenuItem
Click="OpenSdModsDirectory_Click"
Header="{locale:Locale GameListContextMenuOpenSdModsDirectory}"
ToolTip.Tip="{locale:Locale GameListContextMenuOpenSdModsDirectoryToolTip}" />
<Separator />
<MenuItem Header="{locale:Locale GameListContextMenuCacheManagement}">
<MenuItem

View File

@@ -126,13 +126,29 @@ namespace Ryujinx.Ava.UI.Controls
}
}
public async void OpenModManager_Click(object sender, RoutedEventArgs args)
public void OpenModsDirectory_Click(object sender, RoutedEventArgs args)
{
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
if (viewModel?.SelectedApplication != null)
{
await ModManagerWindow.Show(ulong.Parse(viewModel.SelectedApplication.TitleId, NumberStyles.HexNumber), viewModel.SelectedApplication.TitleName);
string modsBasePath = ModLoader.GetModsBasePath();
string titleModsPath = ModLoader.GetTitleDir(modsBasePath, viewModel.SelectedApplication.TitleId);
OpenHelper.OpenFolder(titleModsPath);
}
}
public void OpenSdModsDirectory_Click(object sender, RoutedEventArgs args)
{
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
if (viewModel?.SelectedApplication != null)
{
string sdModsBasePath = ModLoader.GetSdModsBasePath();
string titleModsPath = ModLoader.GetTitleDir(sdModsBasePath, viewModel.SelectedApplication.TitleId);
OpenHelper.OpenFolder(titleModsPath);
}
}

View File

@@ -86,17 +86,17 @@
HorizontalAlignment="Stretch"
FontWeight="Bold"
Text="{Binding TitleName}"
TextAlignment="Start"
TextAlignment="Left"
TextWrapping="Wrap" />
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding Developer}"
TextAlignment="Start"
TextAlignment="Left"
TextWrapping="Wrap" />
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding Version}"
TextAlignment="Start"
TextAlignment="Left"
TextWrapping="Wrap" />
</StackPanel>
</Border>
@@ -110,12 +110,12 @@
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding TitleId}"
TextAlignment="Start"
TextAlignment="Left"
TextWrapping="Wrap" />
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding FileExtension}"
TextAlignment="Start"
TextAlignment="Left"
TextWrapping="Wrap" />
</StackPanel>
<StackPanel
@@ -127,17 +127,17 @@
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding TimePlayedString}"
TextAlignment="End"
TextAlignment="Right"
TextWrapping="Wrap" />
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding LastPlayedString, Converter={helpers:LocalizedNeverConverter}}"
TextAlignment="End"
TextAlignment="Right"
TextWrapping="Wrap" />
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding FileSizeString}"
TextAlignment="End"
TextAlignment="Right"
TextWrapping="Wrap" />
</StackPanel>
<ui:SymbolIcon

View File

@@ -18,7 +18,6 @@ namespace Ryujinx.Ava.UI.Helpers
public static class ContentDialogHelper
{
private static bool _isChoiceDialogOpen;
private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
private async static Task<UserResult> ShowContentDialog(
string title,
@@ -311,20 +310,16 @@ namespace Ryujinx.Ava.UI.Helpers
public static async Task<ContentDialogResult> ShowAsync(ContentDialog contentDialog)
{
ContentDialogResult result;
bool isTopDialog = true;
ContentDialogOverlayWindow contentDialogOverlayWindow = null;
Window parent = GetMainWindow();
if (_contentDialogOverlayWindow != null)
{
isTopDialog = false;
}
if (parent is MainWindow window)
{
parent.Activate();
_contentDialogOverlayWindow = new ContentDialogOverlayWindow
contentDialogOverlayWindow = new()
{
Height = parent.Bounds.Height,
Width = parent.Bounds.Width,
@@ -336,14 +331,14 @@ namespace Ryujinx.Ava.UI.Helpers
void OverlayOnPositionChanged(object sender, PixelPointEventArgs e)
{
_contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
}
_contentDialogOverlayWindow.ContentDialog = contentDialog;
contentDialogOverlayWindow.ContentDialog = contentDialog;
bool opened = false;
_contentDialogOverlayWindow.Opened += OverlayOnActivated;
contentDialogOverlayWindow.Opened += OverlayOnActivated;
async void OverlayOnActivated(object sender, EventArgs e)
{
@@ -354,12 +349,12 @@ namespace Ryujinx.Ava.UI.Helpers
opened = true;
_contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
contentDialogOverlayWindow.Position = parent.PointToScreen(new Point());
result = await ShowDialog();
}
result = await _contentDialogOverlayWindow.ShowDialog<ContentDialogResult>(parent);
result = await contentDialogOverlayWindow.ShowDialog<ContentDialogResult>(parent);
}
else
{
@@ -368,11 +363,11 @@ namespace Ryujinx.Ava.UI.Helpers
async Task<ContentDialogResult> ShowDialog()
{
if (_contentDialogOverlayWindow is not null)
if (contentDialogOverlayWindow is not null)
{
result = await contentDialog.ShowAsync(_contentDialogOverlayWindow);
result = await contentDialog.ShowAsync(contentDialogOverlayWindow);
_contentDialogOverlayWindow!.Close();
contentDialogOverlayWindow!.Close();
}
else
{
@@ -384,22 +379,15 @@ namespace Ryujinx.Ava.UI.Helpers
return result;
}
if (isTopDialog && _contentDialogOverlayWindow is not null)
if (contentDialogOverlayWindow is not null)
{
_contentDialogOverlayWindow.Content = null;
_contentDialogOverlayWindow.Close();
contentDialogOverlayWindow.Content = null;
contentDialogOverlayWindow.Close();
}
return result;
}
public static Task ShowWindowAsync(Window dialogWindow, Window mainWindow = null)
{
mainWindow ??= GetMainWindow();
return dialogWindow.ShowDialog(_contentDialogOverlayWindow ?? mainWindow);
}
private static Window GetMainWindow()
{
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al)

View File

@@ -0,0 +1,40 @@
using Ryujinx.Ava.UI.ViewModels;
using System;
namespace Ryujinx.Ava.UI.Models
{
public class CheatModel : BaseModel
{
private bool _isEnabled;
public event EventHandler<bool> EnableToggled;
public CheatModel(string name, string buildId, bool isEnabled)
{
Name = name;
BuildId = buildId;
IsEnabled = isEnabled;
}
public bool IsEnabled
{
get => _isEnabled;
set
{
_isEnabled = value;
EnableToggled?.Invoke(this, _isEnabled);
OnPropertyChanged();
}
}
public string BuildId { get; }
public string BuildIdKey => $"{BuildId}-{Name}";
public string Name { get; }
public string CleanName => Name[1..^7];
}
}

View File

@@ -1,57 +0,0 @@
using Ryujinx.Ava.UI.ViewModels;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
namespace Ryujinx.Ava.UI.Models
{
public class CheatNode : BaseModel
{
private bool _isEnabled = false;
public ObservableCollection<CheatNode> SubNodes { get; } = new();
public string CleanName => Name[1..^7];
public string BuildIdKey => $"{BuildId}-{Name}";
public bool IsRootNode { get; }
public string Name { get; }
public string BuildId { get; }
public string Path { get; }
public bool IsEnabled
{
get
{
if (SubNodes.Count > 0)
{
return SubNodes.ToList().TrueForAll(x => x.IsEnabled);
}
return _isEnabled;
}
set
{
foreach (var cheat in SubNodes)
{
cheat.IsEnabled = value;
cheat.OnPropertyChanged();
}
_isEnabled = value;
}
}
public CheatNode(string name, string buildId, string path, bool isRootNode, bool isEnabled = false)
{
Name = name;
BuildId = buildId;
Path = path;
IsEnabled = isEnabled;
IsRootNode = isRootNode;
SubNodes.CollectionChanged += CheatsList_CollectionChanged;
}
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(nameof(IsEnabled));
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
namespace Ryujinx.Ava.UI.Models
{
public class CheatsList : ObservableCollection<CheatModel>
{
public CheatsList(string buildId, string path)
{
BuildId = buildId;
Path = path;
CollectionChanged += CheatsList_CollectionChanged;
}
public string BuildId { get; }
public string Path { get; }
public bool IsEnabled
{
get
{
return this.ToList().TrueForAll(x => x.IsEnabled);
}
set
{
foreach (var cheat in this)
{
cheat.IsEnabled = value;
}
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
}
}
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
(e.NewItems[0] as CheatModel).EnableToggled += Item_EnableToggled;
}
}
private void Item_EnableToggled(object sender, bool e)
{
OnPropertyChanged(new PropertyChangedEventArgs(nameof(IsEnabled)));
}
}
}

View File

@@ -1,30 +0,0 @@
using Ryujinx.Ava.UI.ViewModels;
using System.IO;
namespace Ryujinx.Ava.UI.Models
{
public class ModModel : BaseModel
{
private bool _enabled;
public bool Enabled
{
get => _enabled;
set
{
_enabled = value;
OnPropertyChanged();
}
}
public string Path { get; }
public string Name { get; }
public ModModel(string path, string name, bool enabled)
{
Path = path;
Name = name;
Enabled = enabled;
}
}
}

View File

@@ -7,6 +7,5 @@
d:DesignWidth="800"
d:DesignHeight="450"
x:Class="Ryujinx.Ava.UI.Renderer.RendererHost"
FlowDirection="LeftToRight"
Focusable="True">
</UserControl>

View File

@@ -17,7 +17,6 @@ using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.ViewModels
@@ -189,83 +188,35 @@ namespace Ryujinx.Ava.UI.ViewModels
_httpClient.Dispose();
}
private static bool TryGetAmiiboJson(string json, out AmiiboJson amiiboJson)
{
if (string.IsNullOrEmpty(json))
{
amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson);
return false;
}
try
{
amiiboJson = JsonHelper.Deserialize(json, _serializerContext.AmiiboJson);
return true;
}
catch (JsonException exception)
{
Logger.Error?.Print(LogClass.Application, $"Unable to deserialize amiibo data: {exception}");
amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson);
return false;
}
}
private async Task<AmiiboJson> GetMostRecentAmiiboListOrDefaultJson()
{
bool localIsValid = false;
bool remoteIsValid = false;
AmiiboJson amiiboJson = new();
try
{
try
{
if (File.Exists(_amiiboJsonPath))
{
localIsValid = TryGetAmiiboJson(await File.ReadAllTextAsync(_amiiboJsonPath), out amiiboJson);
}
}
catch (Exception exception)
{
Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}");
}
if (!localIsValid || await NeedsUpdate(amiiboJson.LastUpdated))
{
remoteIsValid = TryGetAmiiboJson(await DownloadAmiiboJson(), out amiiboJson);
}
}
catch (Exception exception)
{
if (!(localIsValid || remoteIsValid))
{
Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}");
// Neither local or remote files are valid JSON, close window.
ShowInfoDialog();
Close();
}
else if (!remoteIsValid)
{
Logger.Warning?.Print(LogClass.Application, $"Couldn't update amiibo data: {exception}");
// Only the local file is valid, the local one should be used
// but the user should be warned.
ShowInfoDialog();
}
}
return amiiboJson;
}
private async Task LoadContentAsync()
{
AmiiboJson amiiboJson = await GetMostRecentAmiiboListOrDefaultJson();
string amiiboJsonString = DefaultJson;
_amiiboList = amiiboJson.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
if (File.Exists(_amiiboJsonPath))
{
amiiboJsonString = await File.ReadAllTextAsync(_amiiboJsonPath);
if (await NeedsUpdate(JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).LastUpdated))
{
amiiboJsonString = await DownloadAmiiboJson();
}
}
else
{
try
{
amiiboJsonString = await DownloadAmiiboJson();
}
catch (Exception ex)
{
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data: {ex}");
ShowInfoDialog();
}
}
_amiiboList = JsonHelper.Deserialize(amiiboJsonString, _serializerContext.AmiiboJson).Amiibo;
_amiiboList = _amiiboList.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
ParseAmiiboData();
}
@@ -413,24 +364,27 @@ namespace Ryujinx.Ava.UI.ViewModels
{
try
{
HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
HttpResponseMessage response =
await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
if (response.IsSuccessStatusCode)
{
return response.Content.Headers.LastModified != oldLastModified;
}
}
catch (HttpRequestException exception)
{
Logger.Error?.Print(LogClass.Application, $"Unable to check for amiibo data updates: {exception}");
return response.Content.Headers.LastModified != new DateTimeOffset(oldLastModified.Ticks - (oldLastModified.Ticks % TimeSpan.TicksPerSecond), TimeSpan.Zero);
}
return false;
}
catch (Exception ex)
{
Logger.Error?.Print(LogClass.Application, $"Failed to check for amiibo updates: {ex}");
ShowInfoDialog();
return false;
}
}
private async Task<string> DownloadAmiiboJson()
{
try
{
HttpResponseMessage response = await _httpClient.GetAsync("https://amiibo.ryujinx.org/");
@@ -438,25 +392,15 @@ namespace Ryujinx.Ava.UI.ViewModels
{
string amiiboJsonString = await response.Content.ReadAsStringAsync();
try
using (FileStream amiiboJsonStream = File.Create(_amiiboJsonPath, 4096, FileOptions.WriteThrough))
{
using FileStream dlcJsonStream = File.Create(_amiiboJsonPath, 4096, FileOptions.WriteThrough);
dlcJsonStream.Write(Encoding.UTF8.GetBytes(amiiboJsonString));
}
catch (Exception exception)
{
Logger.Warning?.Print(LogClass.Application, $"Couldn't write amiibo data to file '{_amiiboJsonPath}: {exception}'");
amiiboJsonStream.Write(Encoding.UTF8.GetBytes(amiiboJsonString));
}
return amiiboJsonString;
}
Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data. Response status code: {response.StatusCode}");
}
catch (HttpRequestException exception)
{
Logger.Error?.Print(LogClass.Application, $"Failed to request amiibo data: {exception}");
}
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle],
LocaleManager.Instance[LocaleKeys.DialogAmiiboApiFailFetchMessage],
@@ -464,7 +408,9 @@ namespace Ryujinx.Ava.UI.ViewModels
"",
LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
return null;
Close();
return DefaultJson;
}
private void Close()

View File

@@ -39,7 +39,6 @@ namespace Ryujinx.Ava.UI.ViewModels
private string _search;
private readonly ulong _titleId;
private readonly IStorageProvider _storageProvider;
private static readonly DownloadableContentJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
@@ -91,6 +90,8 @@ namespace Ryujinx.Ava.UI.ViewModels
get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count);
}
public IStorageProvider StorageProvider;
public DownloadableContentManagerViewModel(VirtualFileSystem virtualFileSystem, ulong titleId)
{
_virtualFileSystem = virtualFileSystem;
@@ -99,7 +100,7 @@ namespace Ryujinx.Ava.UI.ViewModels
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
_storageProvider = desktop.MainWindow.StorageProvider;
StorageProvider = desktop.MainWindow.StorageProvider;
}
_downloadableContentJsonPath = Path.Combine(AppDataManager.GamesDirPath, titleId.ToString("x16"), "dlc.json");
@@ -193,7 +194,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{
Dispatcher.UIThread.InvokeAsync(async () =>
{
await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogLoadFileErrorMessage], ex.Message, containerPath));
await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[LocaleKeys.DialogLoadNcaErrorMessage], ex.Message, containerPath));
});
}
@@ -202,7 +203,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public async void Add()
{
var result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.SelectDlcDialogTitle],
AllowMultiple = true,

View File

@@ -1,322 +0,0 @@
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage;
using Avalonia.Threading;
using DynamicData;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS;
using System;
using System.IO;
using System.Linq;
namespace Ryujinx.Ava.UI.ViewModels
{
public class ModManagerViewModel : BaseModel
{
private readonly string _modJsonPath;
private AvaloniaList<ModModel> _mods = new();
private AvaloniaList<ModModel> _views = new();
private AvaloniaList<ModModel> _selectedMods = new();
private string _search;
private readonly ulong _applicationId;
private readonly IStorageProvider _storageProvider;
private static readonly ModMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
public AvaloniaList<ModModel> Mods
{
get => _mods;
set
{
_mods = value;
OnPropertyChanged();
OnPropertyChanged(nameof(ModCount));
Sort();
}
}
public AvaloniaList<ModModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public AvaloniaList<ModModel> SelectedMods
{
get => _selectedMods;
set
{
_selectedMods = value;
OnPropertyChanged();
}
}
public string Search
{
get => _search;
set
{
_search = value;
OnPropertyChanged();
Sort();
}
}
public string ModCount
{
get => string.Format(LocaleManager.Instance[LocaleKeys.ModWindowHeading], Mods.Count);
}
public ModManagerViewModel(ulong applicationId)
{
_applicationId = applicationId;
_modJsonPath = Path.Combine(AppDataManager.GamesDirPath, applicationId.ToString("x16"), "mods.json");
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
_storageProvider = desktop.MainWindow.StorageProvider;
}
LoadMods(applicationId);
}
private void LoadMods(ulong applicationId)
{
Mods.Clear();
SelectedMods.Clear();
string[] modsBasePaths = [ModLoader.GetSdModsBasePath(), ModLoader.GetModsBasePath()];
foreach (var path in modsBasePaths)
{
var modCache = new ModLoader.ModCache();
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId);
foreach (var mod in modCache.RomfsDirs)
{
var modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled);
if (Mods.All(x => x.Path != mod.Path.Parent.FullName))
{
Mods.Add(modModel);
}
}
foreach (var mod in modCache.RomfsContainers)
{
Mods.Add(new ModModel(mod.Path.FullName, mod.Name, mod.Enabled));
}
foreach (var mod in modCache.ExefsDirs)
{
var modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled);
if (Mods.All(x => x.Path != mod.Path.Parent.FullName))
{
Mods.Add(modModel);
}
}
foreach (var mod in modCache.ExefsContainers)
{
Mods.Add(new ModModel(mod.Path.FullName, mod.Name, mod.Enabled));
}
}
Sort();
}
public void Sort()
{
Mods.AsObservableChangeSet()
.Filter(Filter)
.Bind(out var view).AsObservableList();
_views.Clear();
_views.AddRange(view);
SelectedMods = new(Views.Where(x => x.Enabled));
OnPropertyChanged(nameof(ModCount));
OnPropertyChanged(nameof(Views));
OnPropertyChanged(nameof(SelectedMods));
}
private bool Filter(object arg)
{
if (arg is ModModel content)
{
return string.IsNullOrWhiteSpace(_search) || content.Name.ToLower().Contains(_search.ToLower());
}
return false;
}
public void Save()
{
ModMetadata modData = new();
foreach (ModModel mod in Mods)
{
modData.Mods.Add(new Mod
{
Name = mod.Name,
Path = mod.Path,
Enabled = SelectedMods.Contains(mod),
});
}
JsonHelper.SerializeToFile(_modJsonPath, modData, _serializerContext.ModMetadata);
}
public void Delete(ModModel model)
{
var modsDir = ModLoader.GetApplicationDir(ModLoader.GetSdModsBasePath(), _applicationId.ToString("x16"));
var parentDir = String.Empty;
foreach (var dir in Directory.GetDirectories(modsDir, "*", SearchOption.TopDirectoryOnly))
{
if (Directory.GetDirectories(dir, "*", SearchOption.AllDirectories).Contains(model.Path))
{
parentDir = dir;
}
}
if (parentDir == String.Empty)
{
Dispatcher.UIThread.Post(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(
LocaleKeys.DialogModDeleteNoParentMessage,
parentDir));
});
return;
}
Logger.Info?.Print(LogClass.Application, $"Deleting mod at \"{model.Path}\"");
Directory.Delete(parentDir, true);
Mods.Remove(model);
OnPropertyChanged(nameof(ModCount));
Sort();
}
private void AddMod(DirectoryInfo directory)
{
string[] directories;
try
{
directories = Directory.GetDirectories(directory.ToString(), "*", SearchOption.AllDirectories);
}
catch (Exception exception)
{
Dispatcher.UIThread.Post(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(
LocaleKeys.DialogLoadFileErrorMessage,
exception.ToString(),
directory));
});
return;
}
var destinationDir = ModLoader.GetApplicationDir(ModLoader.GetSdModsBasePath(), _applicationId.ToString("x16"));
// TODO: More robust checking for valid mod folders
var isDirectoryValid = true;
if (directories.Length == 0)
{
isDirectoryValid = false;
}
if (!isDirectoryValid)
{
Dispatcher.UIThread.Post(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogModInvalidMessage]);
});
return;
}
foreach (var dir in directories)
{
string dirToCreate = dir.Replace(directory.Parent.ToString(), destinationDir);
// Mod already exists
if (Directory.Exists(dirToCreate))
{
Dispatcher.UIThread.Post(async () =>
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(
LocaleKeys.DialogLoadFileErrorMessage,
LocaleManager.Instance[LocaleKeys.DialogModAlreadyExistsMessage],
dirToCreate));
});
return;
}
Directory.CreateDirectory(dirToCreate);
}
var files = Directory.GetFiles(directory.ToString(), "*", SearchOption.AllDirectories);
foreach (var file in files)
{
File.Copy(file, file.Replace(directory.Parent.ToString(), destinationDir), true);
}
LoadMods(_applicationId);
}
public async void Add()
{
var result = await _storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.SelectModDialogTitle],
AllowMultiple = true,
});
foreach (var folder in result)
{
AddMod(new DirectoryInfo(folder.Path.LocalPath));
}
}
public void DeleteAll()
{
foreach (var mod in Mods)
{
Delete(mod);
}
Mods.Clear();
OnPropertyChanged(nameof(ModCount));
Sort();
}
public void EnableAll()
{
SelectedMods = new(Mods);
}
public void DisableAll()
{
SelectedMods.Clear();
}
}
}

View File

@@ -48,6 +48,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private readonly List<string> _gpuIds = new();
private KeyboardHotkeys _keyboardHotkeys;
private int _graphicsBackendIndex;
private string _customThemePath;
private int _scalingFilter;
private int _scalingFilterLevel;
@@ -159,6 +160,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsOpenAlEnabled { get; set; }
public bool IsSoundIoEnabled { get; set; }
public bool IsSDL2Enabled { get; set; }
public bool EnableCustomTheme { get; set; }
public bool IsCustomResolutionScaleActive => _resolutionScale == 4;
public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr;
@@ -168,6 +170,20 @@ namespace Ryujinx.Ava.UI.ViewModels
public string TimeZone { get; set; }
public string ShaderDumpPath { get; set; }
public string CustomThemePath
{
get
{
return _customThemePath;
}
set
{
_customThemePath = value;
OnPropertyChanged();
}
}
public int Language { get; set; }
public int Region { get; set; }
public int FsGlobalAccessLogMode { get; set; }
@@ -410,6 +426,8 @@ namespace Ryujinx.Ava.UI.ViewModels
GameDirectories.Clear();
GameDirectories.AddRange(config.Ui.GameDirs.Value);
EnableCustomTheme = config.Ui.EnableCustomTheme;
CustomThemePath = config.Ui.CustomThemePath;
BaseStyleIndex = config.Ui.BaseStyle == "Light" ? 0 : 1;
// Input
@@ -497,6 +515,8 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Ui.GameDirs.Value = gameDirs;
}
config.Ui.EnableCustomTheme.Value = EnableCustomTheme;
config.Ui.CustomThemePath.Value = CustomThemePath;
config.Ui.BaseStyle.Value = BaseStyleIndex == 0 ? "Light" : "Dark";
// Input

View File

@@ -192,7 +192,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}
catch (Exception ex)
{
Dispatcher.UIThread.InvokeAsync(() => ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadFileErrorMessage, ex.Message, path)));
Dispatcher.UIThread.InvokeAsync(() => ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, path)));
}
}
}

View File

@@ -218,7 +218,6 @@
<Grid
Name="SettingButtons"
MinHeight="450"
FlowDirection="LeftToRight"
IsVisible="{Binding ShowSettings}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />

View File

@@ -122,8 +122,6 @@ namespace Ryujinx.Ava.UI.Views.Main
await Window.SettingsWindow.ShowDialog(Window);
Window.SettingsWindow = null;
ViewModel.LoadConfigurableHotKeys();
}

View File

@@ -88,7 +88,7 @@
IsVisible="{Binding !ShowLoadProgress}"
PointerReleased="VsyncStatus_PointerReleased"
Text="VSync"
TextAlignment="Start" />
TextAlignment="Left" />
<Border
Width="2"
Height="12"
@@ -105,7 +105,7 @@
IsVisible="{Binding !ShowLoadProgress}"
PointerReleased="DockedStatus_PointerReleased"
Text="{Binding DockedStatusText}"
TextAlignment="Start" />
TextAlignment="Left" />
<Border
Width="2"
Height="12"
@@ -225,7 +225,7 @@
VerticalAlignment="Center"
IsVisible="{Binding !ShowLoadProgress}"
Text="{Binding GameStatusText}"
TextAlignment="Start" />
TextAlignment="Left" />
<Border
Width="2"
Height="12"
@@ -240,7 +240,7 @@
VerticalAlignment="Center"
IsVisible="{Binding !ShowLoadProgress}"
Text="{Binding FifoStatusText}"
TextAlignment="Start" />
TextAlignment="Left" />
<Border
Width="2"
Height="12"
@@ -255,7 +255,7 @@
VerticalAlignment="Center"
IsVisible="{Binding !ShowLoadProgress}"
Text="{Binding BackendText}"
TextAlignment="Start" />
TextAlignment="Left" />
<Border
Width="2"
Height="12"
@@ -270,7 +270,7 @@
VerticalAlignment="Center"
IsVisible="{Binding !ShowLoadProgress}"
Text="{Binding GpuNameText}"
TextAlignment="Start" />
TextAlignment="Left" />
</StackPanel>
<StackPanel
Grid.Column="3"

View File

@@ -36,7 +36,7 @@
<CheckBox IsChecked="{Binding ShowConfirmExit}">
<TextBlock Text="{locale:Locale SettingsTabGeneralShowConfirmExitDialog}" />
</CheckBox>
<StackPanel Margin="0, 15, 0, 0" Orientation="Horizontal">
<StackPanel Margin="0, 15, 0, 10" Orientation="Horizontal">
<TextBlock VerticalAlignment="Center"
Text="{locale:Locale SettingsTabGeneralHideCursor}"
Width="150" />
@@ -54,22 +54,6 @@
</ComboBoxItem>
</ComboBox>
</StackPanel>
<StackPanel Margin="0, 15, 0, 10" Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Text="{locale:Locale SettingsTabGeneralTheme}"
Width="150" />
<ComboBox SelectedIndex="{Binding BaseStyleIndex}"
HorizontalContentAlignment="Left"
MinWidth="100">
<ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabGeneralThemeLight}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabGeneralThemeDark}" />
</ComboBoxItem>
</ComboBox>
</StackPanel>
</StackPanel>
<Separator Height="1" />
<TextBlock Classes="h1" Text="{locale:Locale SettingsTabGeneralGameDirectories}" />
@@ -122,6 +106,64 @@
</Button>
</Grid>
</StackPanel>
<Separator Height="1" />
<TextBlock Classes="h1" Text="{locale:Locale SettingsTabGeneralTheme}" />
<Grid Margin="10,0,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<CheckBox
IsChecked="{Binding EnableCustomTheme}"
ToolTip.Tip="{locale:Locale CustomThemeCheckTooltip}">
<TextBlock Text="{locale:Locale SettingsTabGeneralThemeEnableCustomTheme}" />
</CheckBox>
<TextBlock
Grid.Column="0"
Grid.Row="1"
VerticalAlignment="Center"
Margin="0,10,0,0"
Text="{locale:Locale SettingsTabGeneralThemeCustomTheme}"
ToolTip.Tip="{locale:Locale CustomThemePathTooltip}" />
<TextBox
Grid.Row="1"
Grid.Column="1"
Margin="0,10,0,0"
Text="{Binding CustomThemePath}" />
<Button
Grid.Row="1"
Grid.Column="2"
Margin="10,10,0,0"
Click="BrowseTheme"
ToolTip.Tip="{locale:Locale CustomThemeBrowseTooltip}"
Content="{locale:Locale ButtonBrowse}" />
<TextBlock
Grid.Column="0"
Grid.Row="2"
VerticalAlignment="Center"
Margin="0,10,0,0"
Text="{locale:Locale SettingsTabGeneralThemeBaseStyle}" />
<ComboBox
Grid.Column="1"
Grid.Row="2"
VerticalAlignment="Center"
Margin="0,10,0,0"
MinWidth="100"
SelectedIndex="{Binding BaseStyleIndex}">
<ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabGeneralThemeBaseStyleLight}" />
</ComboBoxItem>
<ComboBoxItem>
<TextBlock Text="{locale:Locale SettingsTabGeneralThemeBaseStyleDark}" />
</ComboBoxItem>
</ComboBox>
</Grid>
</StackPanel>
</Border>
</ScrollViewer>

View File

@@ -61,5 +61,29 @@ namespace Ryujinx.Ava.UI.Views.Settings
GameList.SelectedIndex = oldIndex < GameList.ItemCount ? oldIndex : 0;
}
}
public async void BrowseTheme(object sender, RoutedEventArgs e)
{
var window = this.GetVisualRoot() as Window;
var result = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = LocaleManager.Instance[LocaleKeys.SettingsSelectThemeFileDialogTitle],
AllowMultiple = false,
FileTypeFilter = new List<FilePickerFileType>
{
new("xml")
{
Patterns = new[] { "*.xaml" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xaml" },
MimeTypes = new[] { "application/xaml+xml" },
},
},
});
if (result.Count > 0)
{
ViewModel.CustomThemePath = result[0].Path.LocalPath;
}
}
}
}

View File

@@ -27,7 +27,7 @@
Grid.Row="0"
TextWrapping="Wrap"
HorizontalAlignment="Left"
TextAlignment="Start"
TextAlignment="Left"
Text="{locale:Locale ProfileImageSelectionNote}" />
<StackPanel
Grid.Row="2"

View File

@@ -49,7 +49,7 @@
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding UserId}"
TextAlignment="Start"
TextAlignment="Left"
TextWrapping="Wrap" />
<Button Grid.Column="1"
HorizontalAlignment="Right"

View File

@@ -238,7 +238,7 @@
<TextBlock
FontSize="10"
Text="{locale:Locale AboutRyujinxContributorsButtonHeader}"
TextAlignment="End"
TextAlignment="Right"
ToolTip.Tip="{locale:Locale AboutRyujinxMaintainersContentTooltipMessage}" />
</Button>
</StackPanel>

View File

@@ -86,16 +86,28 @@
</Style>
</Styles>
</TreeView.Styles>
<TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding SubNodes}">
<TreeView.DataTemplates>
<TreeDataTemplate DataType="model:CheatsList" ItemsSource="{Binding}">
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
<CheckBox MinWidth="20" IsChecked="{Binding IsEnabled}" />
<TextBlock Width="150" Text="{Binding CleanName}" IsVisible="{Binding !IsRootNode}" />
<TextBlock Width="150" Text="{Binding BuildId}" IsVisible="{Binding IsRootNode}" />
<TextBlock Text="{Binding Path}" IsVisible="{Binding IsRootNode}" />
<TextBlock Width="150" Text="{Binding BuildId}" />
<TextBlock Text="{Binding Path}" />
</StackPanel>
</TreeDataTemplate>
</TreeView.ItemTemplate>
<DataTemplate x:DataType="model:CheatModel">
<StackPanel
Margin="0"
HorizontalAlignment="Left"
Orientation="Horizontal">
<CheckBox
MinWidth="20"
Margin="5,0"
Padding="0"
IsChecked="{Binding IsEnabled}" />
<TextBlock VerticalAlignment="Center" Text="{Binding CleanName}" />
</StackPanel>
</DataTemplate>
</TreeView.DataTemplates>
</TreeView>
</Border>
<DockPanel

View File

@@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Windows
private readonly string _enabledCheatsPath;
public bool NoCheatsFound { get; }
public AvaloniaList<CheatNode> LoadedCheats { get; }
public AvaloniaList<CheatsList> LoadedCheats { get; }
public string Heading { get; }
public string BuildId { get; }
@@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.Windows
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
{
LoadedCheats = new AvaloniaList<CheatNode>();
LoadedCheats = new AvaloniaList<CheatsList>();
Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper());
BuildId = ApplicationData.GetApplicationBuildId(virtualFileSystem, titlePath);
@@ -41,7 +41,7 @@ namespace Ryujinx.Ava.UI.Windows
InitializeComponent();
string modsBasePath = ModLoader.GetModsBasePath();
string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, titleId);
string titleModsPath = ModLoader.GetTitleDir(modsBasePath, titleId);
ulong titleIdValue = ulong.Parse(titleId, NumberStyles.HexNumber);
_enabledCheatsPath = Path.Combine(titleModsPath, "cheats", "enabled.txt");
@@ -62,7 +62,7 @@ namespace Ryujinx.Ava.UI.Windows
string currentCheatFile = string.Empty;
string buildId = string.Empty;
CheatNode currentGroup = null;
CheatsList currentGroup = null;
foreach (var cheat in mods.Cheats)
{
@@ -72,13 +72,13 @@ namespace Ryujinx.Ava.UI.Windows
string parentPath = currentCheatFile.Replace(titleModsPath, "");
buildId = Path.GetFileNameWithoutExtension(currentCheatFile).ToUpper();
currentGroup = new CheatNode("", buildId, parentPath, true);
currentGroup = new CheatsList(buildId, parentPath);
LoadedCheats.Add(currentGroup);
}
var model = new CheatNode(cheat.Name, buildId, "", false, enabled.Contains($"{buildId}-{cheat.Name}"));
currentGroup?.SubNodes.Add(model);
var model = new CheatModel(cheat.Name, buildId, enabled.Contains($"{buildId}-{cheat.Name}"));
currentGroup?.Add(model);
cheatAdded++;
}
@@ -104,7 +104,7 @@ namespace Ryujinx.Ava.UI.Windows
foreach (var cheats in LoadedCheats)
{
foreach (var cheat in cheats.SubNodes)
foreach (var cheat in cheats)
{
if (cheat.IsEnabled)
{

View File

@@ -158,7 +158,7 @@
FontWeight="Bold"
IsVisible="{Binding ShowLoadProgress}"
Text="{Binding LoadHeading}"
TextAlignment="Start"
TextAlignment="Left"
TextWrapping="Wrap"
MaxWidth="500" />
<Border
@@ -192,7 +192,7 @@
FontSize="18"
IsVisible="{Binding ShowLoadProgress}"
Text="{Binding CacheLoadStatus}"
TextAlignment="Start"
TextAlignment="Left"
MaxWidth="500" />
</Grid>
</Grid>

View File

@@ -1,179 +0,0 @@
<UserControl
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels"
xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
Width="500"
Height="380"
mc:Ignorable="d"
x:Class="Ryujinx.Ava.UI.Windows.ModManagerWindow"
x:CompileBindings="True"
x:DataType="viewModels:ModManagerViewModel"
Focusable="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Panel
Margin="0 0 0 10"
Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Column="0"
Text="{Binding ModCount}" />
<StackPanel
Margin="10 0"
Grid.Column="1"
Orientation="Horizontal">
<Button
Name="EnableAllButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding EnableAll}">
<TextBlock Text="{locale:Locale DlcManagerEnableAllButton}" />
</Button>
<Button
Name="DisableAllButton"
MinWidth="90"
Margin="5"
Command="{ReflectionBinding DisableAll}">
<TextBlock Text="{locale:Locale DlcManagerDisableAllButton}" />
</Button>
</StackPanel>
<TextBox
Grid.Column="2"
MinHeight="27"
MaxHeight="27"
HorizontalAlignment="Stretch"
Watermark="{locale:Locale Search}"
Text="{Binding Search}" />
</Grid>
</Panel>
<Border
Grid.Row="1"
Margin="0 0 0 24"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
BorderBrush="{DynamicResource AppListHoverBackgroundColor}"
BorderThickness="1"
CornerRadius="5"
Padding="2.5">
<ListBox
AutoScrollToSelectedItem="False"
SelectionMode="Multiple, Toggle"
Background="Transparent"
SelectionChanged="OnSelectionChanged"
SelectedItems="{Binding SelectedMods, Mode=TwoWay}"
ItemsSource="{Binding Views}">
<ListBox.DataTemplates>
<DataTemplate
DataType="models:ModModel">
<Panel Margin="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock
HorizontalAlignment="Left"
VerticalAlignment="Center"
MaxLines="2"
TextWrapping="Wrap"
TextTrimming="CharacterEllipsis"
Text="{Binding Name}" />
<StackPanel
Grid.Column="1"
Spacing="10"
Orientation="Horizontal"
HorizontalAlignment="Right">
<Button
VerticalAlignment="Center"
HorizontalAlignment="Right"
Padding="10"
MinWidth="0"
MinHeight="0"
Click="OpenLocation">
<ui:SymbolIcon
Symbol="OpenFolder"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Button>
<Button
VerticalAlignment="Center"
HorizontalAlignment="Right"
Padding="10"
MinWidth="0"
MinHeight="0"
Click="DeleteMod">
<ui:SymbolIcon
Symbol="Cancel"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Button>
</StackPanel>
</Grid>
</Panel>
</DataTemplate>
</ListBox.DataTemplates>
<ListBox.Styles>
<Style Selector="ListBoxItem">
<Setter Property="Background" Value="Transparent" />
</Style>
</ListBox.Styles>
</ListBox>
</Border>
<Panel
Grid.Row="2"
HorizontalAlignment="Stretch">
<StackPanel
Orientation="Horizontal"
Spacing="10"
HorizontalAlignment="Left">
<Button
Name="AddButton"
MinWidth="90"
Margin="5"
Command="{Binding Add}">
<TextBlock Text="{locale:Locale SettingsTabGeneralAdd}" />
</Button>
<Button
Name="RemoveAllButton"
MinWidth="90"
Margin="5"
Click="DeleteAll">
<TextBlock Text="{locale:Locale ModManagerDeleteAllButton}" />
</Button>
</StackPanel>
<StackPanel
Orientation="Horizontal"
Spacing="10"
HorizontalAlignment="Right">
<Button
Name="SaveButton"
MinWidth="90"
Margin="5"
Click="SaveAndClose">
<TextBlock Text="{locale:Locale SettingsButtonSave}" />
</Button>
<Button
Name="CancelButton"
MinWidth="90"
Margin="5"
Click="Close">
<TextBlock Text="{locale:Locale InputDialogCancel}" />
</Button>
</StackPanel>
</Panel>
</Grid>
</UserControl>

View File

@@ -1,139 +0,0 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ui.Common.Helper;
using System.Threading.Tasks;
using Button = Avalonia.Controls.Button;
namespace Ryujinx.Ava.UI.Windows
{
public partial class ModManagerWindow : UserControl
{
public ModManagerViewModel ViewModel;
public ModManagerWindow()
{
DataContext = this;
InitializeComponent();
}
public ModManagerWindow(ulong titleId)
{
DataContext = ViewModel = new ModManagerViewModel(titleId);
InitializeComponent();
}
public static async Task Show(ulong titleId, string titleName)
{
ContentDialog contentDialog = new()
{
PrimaryButtonText = "",
SecondaryButtonText = "",
CloseButtonText = "",
Content = new ModManagerWindow(titleId),
Title = string.Format(LocaleManager.Instance[LocaleKeys.ModWindowHeading], titleName, titleId.ToString("X16")),
};
Style bottomBorder = new(x => x.OfType<Grid>().Name("DialogSpace").Child().OfType<Border>());
bottomBorder.Setters.Add(new Setter(IsVisibleProperty, false));
contentDialog.Styles.Add(bottomBorder);
await contentDialog.ShowAsync();
}
private void SaveAndClose(object sender, RoutedEventArgs e)
{
ViewModel.Save();
((ContentDialog)Parent).Hide();
}
private void Close(object sender, RoutedEventArgs e)
{
((ContentDialog)Parent).Hide();
}
private async void DeleteMod(object sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if (button.DataContext is ModModel model)
{
var result = await ContentDialogHelper.CreateConfirmationDialog(
LocaleManager.Instance[LocaleKeys.DialogWarning],
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogModManagerDeletionWarningMessage, model.Name),
LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
if (result == UserResult.Yes)
{
ViewModel.Delete(model);
}
}
}
}
private async void DeleteAll(object sender, RoutedEventArgs e)
{
var result = await ContentDialogHelper.CreateConfirmationDialog(
LocaleManager.Instance[LocaleKeys.DialogWarning],
LocaleManager.Instance[LocaleKeys.DialogModManagerDeletionAllWarningMessage],
LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
if (result == UserResult.Yes)
{
ViewModel.DeleteAll();
}
}
private void OpenLocation(object sender, RoutedEventArgs e)
{
if (sender is Button button)
{
if (button.DataContext is ModModel model)
{
OpenHelper.OpenFolder(model.Path);
}
}
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (var content in e.AddedItems)
{
if (content is ModModel model)
{
var index = ViewModel.Mods.IndexOf(model);
if (index != -1)
{
ViewModel.Mods[index].Enabled = true;
}
}
}
foreach (var content in e.RemovedItems)
{
if (content is ModModel model)
{
var index = ViewModel.Mods.IndexOf(model);
if (index != -1)
{
ViewModel.Mods[index].Enabled = false;
}
}
}
}
}
}

View File

@@ -101,9 +101,6 @@
<Style Selector="Grid#PlaceholderGrid">
<Setter Property="Height" Value="40" />
</Style>
<Style Selector="ui|NavigationViewItem ui|SymbolIcon">
<Setter Property="FlowDirection" Value="LeftToRight" />
</Style>
</ui:NavigationView.Styles>
</ui:NavigationView>
<ReversibleStackPanel

View File

@@ -1,9 +1,7 @@
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ui.Common.Configuration;
using System.IO;
using System.Reflection;
@@ -24,14 +22,6 @@ namespace Ryujinx.Ava.UI.Windows
Icon = new WindowIcon(stream);
stream.Position = 0;
IconImage = new Bitmap(stream);
LocaleManager.Instance.LocaleChanged += LocaleChanged;
LocaleChanged();
}
private void LocaleChanged()
{
FlowDirection = LocaleManager.Instance.IsRTL() ? FlowDirection.RightToLeft : FlowDirection.LeftToRight;
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)

View File

@@ -63,17 +63,6 @@ namespace Ryujinx.Common.Configuration
string userProfilePath = Path.Combine(appDataPath, DefaultBaseDir);
string portablePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DefaultPortableDir);
// On macOS, check for a portable directory next to the app bundle as well.
if (OperatingSystem.IsMacOS() && !Directory.Exists(portablePath))
{
string bundlePath = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", ".."));
// Make sure we're actually running within an app bundle.
if (bundlePath.EndsWith(".app"))
{
portablePath = Path.GetFullPath(Path.Combine(bundlePath, "..", DefaultPortableDir));
}
}
if (Directory.Exists(portablePath))
{
BaseDirPath = portablePath;

View File

@@ -1,9 +0,0 @@
namespace Ryujinx.Common.Configuration
{
public class Mod
{
public string Name { get; set; }
public string Path { get; set; }
public bool Enabled { get; set; }
}
}

View File

@@ -1,14 +0,0 @@
using System.Collections.Generic;
namespace Ryujinx.Common.Configuration
{
public struct ModMetadata
{
public List<Mod> Mods { get; set; }
public ModMetadata()
{
Mods = new List<Mod>();
}
}
}

View File

@@ -1,10 +0,0 @@
using System.Text.Json.Serialization;
namespace Ryujinx.Common.Configuration
{
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ModMetadata))]
public partial class ModMetadataJsonSerializerContext : JsonSerializerContext
{
}
}

View File

@@ -744,17 +744,6 @@ namespace Ryujinx.Common.Memory
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
}
public struct Array65<T> : IArray<T> where T : unmanaged
{
T _e0;
Array64<T> _other;
public readonly int Length => 65;
public ref T this[int index] => ref AsSpan()[index];
[Pure]
public Span<T> AsSpan() => MemoryMarshal.CreateSpan(ref _e0, Length);
}
public struct Array73<T> : IArray<T> where T : unmanaged
{
T _e0;

View File

@@ -63,18 +63,6 @@ namespace Ryujinx.Common.Memory
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
}
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
public struct ByteArray3000 : IArray<byte>
{
private const int Size = 3000;
byte _element;
public readonly int Length => Size;
public ref byte this[int index] => ref AsSpan()[index];
public Span<byte> AsSpan() => MemoryMarshal.CreateSpan(ref _element, Size);
}
[StructLayout(LayoutKind.Sequential, Size = Size, Pack = 1)]
public struct ByteArray4096 : IArray<byte>
{

View File

@@ -0,0 +1,62 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
namespace Ryujinx.Cpu.AppleHv
{
static class HvCodePatcher
{
private const uint XMask = 0x3f808000u;
private const uint XValue = 0x8000000u;
private const uint ZrIndex = 31u;
public static void RewriteUnorderedExclusiveInstructions(Span<byte> code)
{
Span<uint> codeUint = MemoryMarshal.Cast<byte, uint>(code);
Span<Vector128<uint>> codeVector = MemoryMarshal.Cast<byte, Vector128<uint>>(code);
Vector128<uint> mask = Vector128.Create(XMask);
Vector128<uint> value = Vector128.Create(XValue);
for (int index = 0; index < codeVector.Length; index++)
{
Vector128<uint> v = codeVector[index];
if (Vector128.EqualsAny(Vector128.BitwiseAnd(v, mask), value))
{
int baseIndex = index * 4;
for (int instIndex = baseIndex; instIndex < baseIndex + 4; instIndex++)
{
ref uint inst = ref codeUint[instIndex];
if ((inst & XMask) != XValue)
{
continue;
}
bool isPair = (inst & (1u << 21)) != 0;
bool isLoad = (inst & (1u << 22)) != 0;
uint rt2 = (inst >> 10) & 0x1fu;
uint rs = (inst >> 16) & 0x1fu;
if (isLoad && rs != ZrIndex)
{
continue;
}
if (!isPair && rt2 != ZrIndex)
{
continue;
}
// Set the ordered flag.
inst |= 1u << 15;
}
}
}
}
}
}

View File

@@ -40,9 +40,5 @@ namespace Ryujinx.Cpu.AppleHv
public void PrepareCodeRange(ulong address, ulong size)
{
}
public void Dispose()
{
}
}
}

View File

@@ -724,6 +724,18 @@ namespace Ryujinx.Cpu.AppleHv
/// <inheritdoc/>
public void Reprotect(ulong va, ulong size, MemoryPermission protection)
{
if (protection.HasFlag(MemoryPermission.Execute))
{
// Some applications use unordered exclusive memory access instructions
// where it is not valid to do so, leading to memory re-ordering that
// makes the code behave incorrectly on some CPUs.
// To work around this, we force all such accesses to be ordered.
using WritableRegion writableRegion = GetWritableRegion(va, (int)size);
HvCodePatcher.RewriteUnorderedExclusiveInstructions(writableRegion.Memory.Span);
}
// TODO
}

View File

@@ -1,17 +0,0 @@
using System;
namespace Ryujinx.Cpu
{
public class DummyDiskCacheLoadState : IDiskCacheLoadState
{
#pragma warning disable CS0067 // The event is never used
/// <inheritdoc/>
public event Action<LoadState, int, int> StateChanged;
#pragma warning restore CS0067
/// <inheritdoc/>
public void Cancel()
{
}
}
}

View File

@@ -1,11 +1,9 @@
using System;
namespace Ryujinx.Cpu
{
/// <summary>
/// CPU context interface.
/// </summary>
public interface ICpuContext : IDisposable
public interface ICpuContext
{
/// <summary>
/// Creates a new execution context that will store thread CPU register state when executing guest code.

View File

@@ -1,7 +1,5 @@
using ARMeilleure.Memory;
using ARMeilleure.Translation;
using Ryujinx.Cpu.Signal;
using Ryujinx.Memory;
namespace Ryujinx.Cpu.Jit
{
@@ -13,13 +11,7 @@ namespace Ryujinx.Cpu.Jit
public JitCpuContext(ITickSource tickSource, IMemoryManager memory, bool for64Bit)
{
_tickSource = tickSource;
_translator = new Translator(new JitMemoryAllocator(forJit: true), memory, for64Bit);
if (memory.Type.IsHostMapped())
{
NativeSignalHandler.InitializeSignalHandler(MemoryBlock.GetPageSize());
}
_translator = new Translator(new JitMemoryAllocator(), memory, for64Bit);
memory.UnmapEvent += UnmapHandler;
}
@@ -57,9 +49,5 @@ namespace Ryujinx.Cpu.Jit
{
_translator.PrepareCodeRange(address, size);
}
public void Dispose()
{
}
}
}

View File

@@ -5,14 +5,9 @@ namespace Ryujinx.Cpu.Jit
{
public class JitMemoryAllocator : IJitMemoryAllocator
{
private readonly MemoryAllocationFlags _jitFlag;
public JitMemoryAllocator(bool forJit = false)
{
_jitFlag = forJit ? MemoryAllocationFlags.Jit : MemoryAllocationFlags.None;
}
public IJitMemoryBlock Allocate(ulong size) => new JitMemoryBlock(size, MemoryAllocationFlags.None);
public IJitMemoryBlock Reserve(ulong size) => new JitMemoryBlock(size, MemoryAllocationFlags.Reserve | _jitFlag);
public IJitMemoryBlock Reserve(ulong size) => new JitMemoryBlock(size, MemoryAllocationFlags.Reserve | MemoryAllocationFlags.Jit);
public ulong GetPageSize() => MemoryBlock.GetPageSize();
}
}

View File

@@ -16,7 +16,6 @@ namespace Ryujinx.Cpu.Jit
}
public void Commit(ulong offset, ulong size) => _impl.Commit(offset, size);
public void MapAsRw(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadAndWrite);
public void MapAsRx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadAndExecute);
public void MapAsRwx(ulong offset, ulong size) => _impl.Reprotect(offset, size, MemoryPermission.ReadWriteExecute);

View File

@@ -1,32 +0,0 @@
using ARMeilleure.Common;
using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.Arm32;
using Ryujinx.Cpu.LightningJit.Arm64;
using Ryujinx.Cpu.LightningJit.State;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Cpu.LightningJit
{
class AarchCompiler
{
public static CompiledFunction Compile(
CpuPreset cpuPreset,
IMemoryManager memoryManager,
ulong address,
AddressTable<ulong> funcTable,
IntPtr dispatchStubPtr,
ExecutionMode executionMode,
Architecture targetArch)
{
if (executionMode == ExecutionMode.Aarch64)
{
return A64Compiler.Compile(cpuPreset, memoryManager, address, funcTable, dispatchStubPtr, targetArch);
}
else
{
return A32Compiler.Compile(cpuPreset, memoryManager, address, funcTable, dispatchStubPtr, executionMode == ExecutionMode.Aarch32Thumb, targetArch);
}
}
}
}

View File

@@ -1,18 +0,0 @@
namespace Ryujinx.Cpu.LightningJit
{
enum AddressForm : byte
{
None,
OffsetReg,
PostIndexed,
PreIndexed,
SignedScaled,
UnsignedScaled,
BaseRegister,
BasePlusOffset,
Literal,
StructNoOffset,
StructPostIndexedReg,
}
}

View File

@@ -1,30 +0,0 @@
using ARMeilleure.Common;
using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
static class A32Compiler
{
public static CompiledFunction Compile(
CpuPreset cpuPreset,
IMemoryManager memoryManager,
ulong address,
AddressTable<ulong> funcTable,
IntPtr dispatchStubPtr,
bool isThumb,
Architecture targetArch)
{
if (targetArch == Architecture.Arm64)
{
return Compiler.Compile(cpuPreset, memoryManager, address, funcTable, dispatchStubPtr, isThumb);
}
else
{
throw new PlatformNotSupportedException();
}
}
}
}

View File

@@ -1,101 +0,0 @@
using System.Collections.Generic;
using System.Diagnostics;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
class Block
{
public readonly ulong Address;
public readonly ulong EndAddress;
public readonly List<InstInfo> Instructions;
public readonly bool EndsWithBranch;
public readonly bool HasHostCall;
public readonly bool IsTruncated;
public readonly bool IsLoopEnd;
public readonly bool IsThumb;
public Block(
ulong address,
ulong endAddress,
List<InstInfo> instructions,
bool endsWithBranch,
bool hasHostCall,
bool isTruncated,
bool isLoopEnd,
bool isThumb)
{
Debug.Assert(isThumb || (int)((endAddress - address) / 4) == instructions.Count);
Address = address;
EndAddress = endAddress;
Instructions = instructions;
EndsWithBranch = endsWithBranch;
HasHostCall = hasHostCall;
IsTruncated = isTruncated;
IsLoopEnd = isLoopEnd;
IsThumb = isThumb;
}
public (Block, Block) SplitAtAddress(ulong address)
{
int splitIndex = FindSplitIndex(address);
if (splitIndex < 0)
{
return (null, null);
}
int splitCount = Instructions.Count - splitIndex;
// Technically those are valid, but we don't want to create empty blocks.
Debug.Assert(splitIndex != 0);
Debug.Assert(splitCount != 0);
Block leftBlock = new(
Address,
address,
Instructions.GetRange(0, splitIndex),
false,
HasHostCall,
false,
false,
IsThumb);
Block rightBlock = new(
address,
EndAddress,
Instructions.GetRange(splitIndex, splitCount),
EndsWithBranch,
HasHostCall,
IsTruncated,
IsLoopEnd,
IsThumb);
return (leftBlock, rightBlock);
}
private int FindSplitIndex(ulong address)
{
if (IsThumb)
{
ulong pc = Address;
for (int index = 0; index < Instructions.Count; index++)
{
if (pc == address)
{
return index;
}
pc += Instructions[index].Flags.HasFlag(InstFlags.Thumb16) ? 2UL : 4UL;
}
return -1;
}
else
{
return (int)((address - Address) / 4);
}
}
}
}

View File

@@ -1,15 +0,0 @@
namespace Ryujinx.Cpu.LightningJit.Arm32
{
enum BranchType
{
Branch,
Call,
IndirectBranch,
TableBranchByte,
TableBranchHalfword,
IndirectCall,
SyncPoint,
SoftwareInterrupt,
ReadCntpct,
}
}

View File

@@ -1,198 +0,0 @@
using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System;
using System.Collections.Generic;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
class CodeGenContext
{
public CodeWriter CodeWriter { get; }
public Assembler Arm64Assembler { get; }
public RegisterAllocator RegisterAllocator { get; }
public MemoryManagerType MemoryManagerType { get; }
private uint _instructionAddress;
public bool IsThumb { get; }
public uint Pc { get; private set; }
public bool InITBlock { get; private set; }
private InstInfo _nextInstruction;
private bool _skipNextInstruction;
private readonly ArmCondition[] _itConditions;
private int _itCount;
private readonly List<PendingBranch> _pendingBranches;
private bool _nzcvModified;
public CodeGenContext(CodeWriter codeWriter, Assembler arm64Assembler, RegisterAllocator registerAllocator, MemoryManagerType mmType, bool isThumb)
{
CodeWriter = codeWriter;
Arm64Assembler = arm64Assembler;
RegisterAllocator = registerAllocator;
MemoryManagerType = mmType;
_itConditions = new ArmCondition[4];
_pendingBranches = new();
IsThumb = isThumb;
}
public void SetPc(uint address)
{
// Due to historical reasons, the PC value is always 2 instructions ahead on 32-bit Arm CPUs.
Pc = address + (IsThumb ? 4u : 8u);
_instructionAddress = address;
}
public void SetNextInstruction(InstInfo info)
{
_nextInstruction = info;
}
public InstInfo PeekNextInstruction()
{
return _nextInstruction;
}
public void SetSkipNextInstruction()
{
_skipNextInstruction = true;
}
public bool ConsumeSkipNextInstruction()
{
bool skip = _skipNextInstruction;
_skipNextInstruction = false;
return skip;
}
public void AddPendingBranch(InstName name, int offset)
{
_pendingBranches.Add(new(BranchType.Branch, Pc + (uint)offset, 0u, name, CodeWriter.InstructionPointer));
}
public void AddPendingCall(uint targetAddress, uint nextAddress)
{
_pendingBranches.Add(new(BranchType.Call, targetAddress, nextAddress, InstName.BlI, CodeWriter.InstructionPointer));
RegisterAllocator.EnsureTempGprRegisters(1);
RegisterAllocator.MarkGprAsUsed(RegisterUtils.LrRegister);
}
public void AddPendingIndirectBranch(InstName name, uint targetRegister)
{
_pendingBranches.Add(new(BranchType.IndirectBranch, targetRegister, 0u, name, CodeWriter.InstructionPointer));
RegisterAllocator.MarkGprAsUsed((int)targetRegister);
}
public void AddPendingTableBranch(uint rn, uint rm, bool halfword)
{
_pendingBranches.Add(new(halfword ? BranchType.TableBranchHalfword : BranchType.TableBranchByte, rn, rm, InstName.Tbb, CodeWriter.InstructionPointer));
RegisterAllocator.EnsureTempGprRegisters(2);
RegisterAllocator.MarkGprAsUsed((int)rn);
RegisterAllocator.MarkGprAsUsed((int)rm);
}
public void AddPendingIndirectCall(uint targetRegister, uint nextAddress)
{
_pendingBranches.Add(new(BranchType.IndirectCall, targetRegister, nextAddress, InstName.BlxR, CodeWriter.InstructionPointer));
RegisterAllocator.EnsureTempGprRegisters(targetRegister == RegisterUtils.LrRegister ? 1 : 0);
RegisterAllocator.MarkGprAsUsed((int)targetRegister);
RegisterAllocator.MarkGprAsUsed(RegisterUtils.LrRegister);
}
public void AddPendingSyncPoint()
{
_pendingBranches.Add(new(BranchType.SyncPoint, 0, 0, default, CodeWriter.InstructionPointer));
RegisterAllocator.EnsureTempGprRegisters(1);
}
public void AddPendingBkpt(uint imm)
{
_pendingBranches.Add(new(BranchType.SoftwareInterrupt, imm, _instructionAddress, InstName.Bkpt, CodeWriter.InstructionPointer));
RegisterAllocator.EnsureTempGprRegisters(1);
}
public void AddPendingSvc(uint imm)
{
_pendingBranches.Add(new(BranchType.SoftwareInterrupt, imm, _instructionAddress, InstName.Svc, CodeWriter.InstructionPointer));
RegisterAllocator.EnsureTempGprRegisters(1);
}
public void AddPendingUdf(uint imm)
{
_pendingBranches.Add(new(BranchType.SoftwareInterrupt, imm, _instructionAddress, InstName.Udf, CodeWriter.InstructionPointer));
RegisterAllocator.EnsureTempGprRegisters(1);
}
public void AddPendingReadCntpct(uint rt, uint rt2)
{
_pendingBranches.Add(new(BranchType.ReadCntpct, rt, rt2, InstName.Mrrc, CodeWriter.InstructionPointer));
RegisterAllocator.EnsureTempGprRegisters(1);
}
public IEnumerable<PendingBranch> GetPendingBranches()
{
return _pendingBranches;
}
public void SetItBlockStart(ReadOnlySpan<ArmCondition> conditions)
{
_itCount = conditions.Length;
for (int index = 0; index < conditions.Length; index++)
{
_itConditions[index] = conditions[index];
}
InITBlock = true;
}
public bool ConsumeItCondition(out ArmCondition condition)
{
if (_itCount != 0)
{
condition = _itConditions[--_itCount];
return true;
}
condition = ArmCondition.Al;
return false;
}
public void UpdateItState()
{
if (_itCount == 0)
{
InITBlock = false;
}
}
public void SetNzcvModified()
{
_nzcvModified = true;
}
public bool ConsumeNzcvModified()
{
bool modified = _nzcvModified;
_nzcvModified = false;
return modified;
}
}
}

View File

@@ -1,546 +0,0 @@
using ARMeilleure.Memory;
using Ryujinx.Cpu.LightningJit.Arm32.Target.Arm64;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System.Collections.Generic;
using System.Diagnostics;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
static class Decoder<T> where T : IInstEmit
{
public static MultiBlock DecodeMulti(CpuPreset cpuPreset, IMemoryManager memoryManager, ulong address, bool isThumb)
{
List<Block> blocks = new();
List<ulong> branchTargets = new();
while (true)
{
Block block = Decode(cpuPreset, memoryManager, address, isThumb);
if (!block.IsTruncated && TryGetBranchTarget(block, out ulong targetAddress))
{
branchTargets.Add(targetAddress);
}
blocks.Add(block);
if (block.IsTruncated || !HasNextBlock(block, block.EndAddress - 4UL, branchTargets))
{
break;
}
address = block.EndAddress;
}
branchTargets.Sort();
SplitBlocks(blocks, branchTargets);
return new(blocks);
}
private static bool TryGetBranchTarget(Block block, out ulong targetAddress)
{
// PC is 2 instructions ahead, since the end address is already one instruction after the last one, we just need to add
// another instruction.
ulong pc = block.EndAddress + (block.IsThumb ? 2UL : 4UL);
return TryGetBranchTarget(block.Instructions[^1].Name, block.Instructions[^1].Flags, pc, block.Instructions[^1].Encoding, block.IsThumb, out targetAddress);
}
private static bool TryGetBranchTarget(InstName name, InstFlags flags, ulong pc, uint encoding, bool isThumb, out ulong targetAddress)
{
int originalOffset;
switch (name)
{
case InstName.B:
if (isThumb)
{
if (flags.HasFlag(InstFlags.Thumb16))
{
if ((encoding & (1u << 29)) != 0)
{
InstImm11b16w11 inst = new(encoding);
originalOffset = ImmUtils.ExtractT16SImm11Times2(inst.Imm11);
}
else
{
InstCondb24w4Imm8b16w8 inst = new(encoding);
originalOffset = ImmUtils.ExtractT16SImm8Times2(inst.Imm8);
}
}
else
{
if ((encoding & (1u << 12)) != 0)
{
InstSb26w1Imm10b16w10J1b13w1J2b11w1Imm11b0w11 inst = new(encoding);
originalOffset = ImmUtils.CombineSImm24Times2(inst.Imm11, inst.Imm10, inst.J1, inst.J2, inst.S);
}
else
{
InstSb26w1Condb22w4Imm6b16w6J1b13w1J2b11w1Imm11b0w11 inst = new(encoding);
originalOffset = ImmUtils.CombineSImm20Times2(inst.Imm11, inst.Imm6, inst.J1, inst.J2, inst.S);
}
}
}
else
{
originalOffset = ImmUtils.ExtractSImm24Times4(encoding);
}
targetAddress = pc + (ulong)originalOffset;
Debug.Assert((targetAddress & 1) == 0);
return true;
case InstName.Cbnz:
originalOffset = ImmUtils.ExtractT16UImm5Times2(encoding);
targetAddress = pc + (ulong)originalOffset;
Debug.Assert((targetAddress & 1) == 0);
return true;
}
targetAddress = 0;
return false;
}
private static void SplitBlocks(List<Block> blocks, List<ulong> branchTargets)
{
int btIndex = 0;
while (btIndex < branchTargets.Count)
{
for (int blockIndex = 0; blockIndex < blocks.Count && btIndex < branchTargets.Count; blockIndex++)
{
Block block = blocks[blockIndex];
ulong currentBranchTarget = branchTargets[btIndex];
while (currentBranchTarget >= block.Address && currentBranchTarget < block.EndAddress)
{
if (block.Address != currentBranchTarget)
{
(Block leftBlock, Block rightBlock) = block.SplitAtAddress(currentBranchTarget);
if (leftBlock != null && rightBlock != null)
{
blocks.Insert(blockIndex, leftBlock);
blocks[blockIndex + 1] = rightBlock;
block = leftBlock;
}
else
{
// Split can only fail in thumb mode, where the instruction size is not fixed.
Debug.Assert(block.IsThumb);
}
}
btIndex++;
while (btIndex < branchTargets.Count && branchTargets[btIndex] == currentBranchTarget)
{
btIndex++;
}
if (btIndex >= branchTargets.Count)
{
break;
}
currentBranchTarget = branchTargets[btIndex];
}
}
Debug.Assert(btIndex < int.MaxValue);
btIndex++;
}
}
private static bool HasNextBlock(in Block block, ulong pc, List<ulong> branchTargets)
{
InstFlags lastInstFlags = block.Instructions[^1].Flags;
// Thumb has separate encodings for conditional and unconditional branch instructions.
if (lastInstFlags.HasFlag(InstFlags.Cond) && (block.IsThumb || (ArmCondition)(block.Instructions[^1].Encoding >> 28) < ArmCondition.Al))
{
return true;
}
switch (block.Instructions[^1].Name)
{
case InstName.B:
return branchTargets.Contains(pc + 4UL) ||
(TryGetBranchTarget(block, out ulong targetAddress) && targetAddress >= pc && targetAddress < pc + 0x1000);
case InstName.Bx:
case InstName.Bxj:
return branchTargets.Contains(pc + 4UL);
case InstName.Cbnz:
case InstName.BlI:
case InstName.BlxR:
return true;
}
if (WritesToPC(block.Instructions[^1].Encoding, block.Instructions[^1].Name, lastInstFlags, block.IsThumb))
{
return branchTargets.Contains(pc + 4UL);
}
return !block.EndsWithBranch;
}
private static Block Decode(CpuPreset cpuPreset, IMemoryManager memoryManager, ulong address, bool isThumb)
{
ulong startAddress = address;
List<InstInfo> insts = new();
uint encoding;
InstMeta meta;
InstFlags extraFlags = InstFlags.None;
bool hasHostCall = false;
bool isTruncated = false;
do
{
if (!memoryManager.IsMapped(address))
{
encoding = 0;
meta = default;
isTruncated = true;
break;
}
if (isThumb)
{
encoding = (uint)memoryManager.Read<ushort>(address) << 16;
address += 2UL;
extraFlags = InstFlags.Thumb16;
if (!InstTableT16<T>.TryGetMeta(encoding, cpuPreset.Version, cpuPreset.Features, out meta))
{
encoding |= memoryManager.Read<ushort>(address);
if (InstTableT32<T>.TryGetMeta(encoding, cpuPreset.Version, cpuPreset.Features, out meta))
{
address += 2UL;
extraFlags = InstFlags.None;
}
}
}
else
{
encoding = memoryManager.Read<uint>(address);
address += 4UL;
meta = InstTableA32<T>.GetMeta(encoding, cpuPreset.Version, cpuPreset.Features);
}
if (meta.Name.IsSystemOrCall() && !hasHostCall)
{
hasHostCall = meta.Name.IsCall() || InstEmitSystem.NeedsCall(meta.Name);
}
insts.Add(new(encoding, meta.Name, meta.EmitFunc, meta.Flags | extraFlags));
}
while (!IsControlFlow(encoding, meta.Name, meta.Flags | extraFlags, isThumb));
bool isLoopEnd = false;
if (!isTruncated && IsBackwardsBranch(meta.Name, encoding))
{
hasHostCall = true;
isLoopEnd = true;
}
return new(
startAddress,
address,
insts,
!isTruncated,
hasHostCall,
isTruncated,
isLoopEnd,
isThumb);
}
private static bool IsControlFlow(uint encoding, InstName name, InstFlags flags, bool isThumb)
{
switch (name)
{
case InstName.B:
case InstName.BlI:
case InstName.BlxR:
case InstName.Bx:
case InstName.Bxj:
case InstName.Cbnz:
case InstName.Tbb:
return true;
}
return WritesToPC(encoding, name, flags, isThumb);
}
public static bool WritesToPC(uint encoding, InstName name, InstFlags flags, bool isThumb)
{
return (GetRegisterWriteMask(encoding, name, flags, isThumb) & (1u << RegisterUtils.PcRegister)) != 0;
}
private static uint GetRegisterWriteMask(uint encoding, InstName name, InstFlags flags, bool isThumb)
{
uint mask = 0;
if (isThumb)
{
if (flags.HasFlag(InstFlags.Thumb16))
{
if (flags.HasFlag(InstFlags.Rdn))
{
mask |= 1u << RegisterUtils.ExtractRdn(flags, encoding);
}
if (flags.HasFlag(InstFlags.Rd))
{
mask |= 1u << RegisterUtils.ExtractRdT16(flags, encoding);
}
Debug.Assert(!flags.HasFlag(InstFlags.RdHi));
if (IsRegisterWrite(flags, InstFlags.Rt))
{
mask |= 1u << RegisterUtils.ExtractRtT16(flags, encoding);
}
Debug.Assert(!flags.HasFlag(InstFlags.Rt2));
if (IsRegisterWrite(flags, InstFlags.Rlist))
{
mask |= (byte)(encoding >> 16);
if (name == InstName.Push)
{
mask |= (encoding >> 10) & 0x4000; // LR
}
else if (name == InstName.Pop)
{
mask |= (encoding >> 9) & 0x8000; // PC
}
}
Debug.Assert(!flags.HasFlag(InstFlags.WBack));
}
else
{
if (flags.HasFlag(InstFlags.Rd))
{
mask |= 1u << RegisterUtils.ExtractRdT32(flags, encoding);
}
if (flags.HasFlag(InstFlags.RdLo))
{
mask |= 1u << RegisterUtils.ExtractRdLoT32(encoding);
}
if (flags.HasFlag(InstFlags.RdHi))
{
mask |= 1u << RegisterUtils.ExtractRdHiT32(encoding);
}
if (IsRegisterWrite(flags, InstFlags.Rt) && IsRtWrite(name, encoding) && !IsR15RtEncodingSpecial(name, encoding))
{
mask |= 1u << RegisterUtils.ExtractRtT32(encoding);
}
if (IsRegisterWrite(flags, InstFlags.Rt2) && IsRtWrite(name, encoding))
{
mask |= 1u << RegisterUtils.ExtractRt2T32(encoding);
}
if (IsRegisterWrite(flags, InstFlags.Rlist))
{
mask |= (ushort)encoding;
}
if (flags.HasFlag(InstFlags.WBack) && HasWriteBackT32(name, encoding))
{
mask |= 1u << RegisterUtils.ExtractRn(encoding); // This is at the same bit position as A32.
}
}
}
else
{
if (flags.HasFlag(InstFlags.Rd))
{
mask |= 1u << RegisterUtils.ExtractRd(flags, encoding);
}
if (flags.HasFlag(InstFlags.RdHi))
{
mask |= 1u << RegisterUtils.ExtractRdHi(encoding);
}
if (IsRegisterWrite(flags, InstFlags.Rt) && IsRtWrite(name, encoding) && !IsR15RtEncodingSpecial(name, encoding))
{
mask |= 1u << RegisterUtils.ExtractRt(encoding);
}
if (IsRegisterWrite(flags, InstFlags.Rt2) && IsRtWrite(name, encoding))
{
mask |= 1u << RegisterUtils.ExtractRt2(encoding);
}
if (IsRegisterWrite(flags, InstFlags.Rlist))
{
mask |= (ushort)encoding;
}
if (flags.HasFlag(InstFlags.WBack) && HasWriteBack(name, encoding))
{
mask |= 1u << RegisterUtils.ExtractRn(encoding);
}
}
return mask;
}
private static bool IsRtWrite(InstName name, uint encoding)
{
// Some instructions can move GPR to FP/SIMD or FP/SIMD to GPR depending on the encoding.
// Detect those cases so that we can tell if we're actually doing a register write.
switch (name)
{
case InstName.VmovD:
case InstName.VmovH:
case InstName.VmovS:
case InstName.VmovSs:
return (encoding & (1u << 20)) != 0;
}
return true;
}
private static bool HasWriteBack(InstName name, uint encoding)
{
if (IsLoadStoreMultiple(name))
{
return (encoding & (1u << 21)) != 0;
}
if (IsVLDnVSTn(name))
{
return (encoding & 0xf) != RegisterUtils.PcRegister;
}
bool w = (encoding & (1u << 21)) != 0;
bool p = (encoding & (1u << 24)) != 0;
return !p || w;
}
private static bool HasWriteBackT32(InstName name, uint encoding)
{
if (IsLoadStoreMultiple(name))
{
return (encoding & (1u << 21)) != 0;
}
if (IsVLDnVSTn(name))
{
return (encoding & 0xf) != RegisterUtils.PcRegister;
}
return (encoding & (1u << 8)) != 0;
}
private static bool IsLoadStoreMultiple(InstName name)
{
switch (name)
{
case InstName.Ldm:
case InstName.Ldmda:
case InstName.Ldmdb:
case InstName.LdmE:
case InstName.Ldmib:
case InstName.LdmU:
case InstName.Stm:
case InstName.Stmda:
case InstName.Stmdb:
case InstName.Stmib:
case InstName.StmU:
case InstName.Fldmx:
case InstName.Fstmx:
case InstName.Vldm:
case InstName.Vstm:
return true;
}
return false;
}
private static bool IsVLDnVSTn(InstName name)
{
switch (name)
{
case InstName.Vld11:
case InstName.Vld1A:
case InstName.Vld1M:
case InstName.Vld21:
case InstName.Vld2A:
case InstName.Vld2M:
case InstName.Vld31:
case InstName.Vld3A:
case InstName.Vld3M:
case InstName.Vld41:
case InstName.Vld4A:
case InstName.Vld4M:
case InstName.Vst11:
case InstName.Vst1M:
case InstName.Vst21:
case InstName.Vst2M:
case InstName.Vst31:
case InstName.Vst3M:
case InstName.Vst41:
case InstName.Vst4M:
return true;
}
return false;
}
private static bool IsR15RtEncodingSpecial(InstName name, uint encoding)
{
if (name == InstName.Vmrs)
{
return ((encoding >> 16) & 0xf) == 1;
}
return false;
}
private static bool IsRegisterWrite(InstFlags flags, InstFlags testFlag)
{
return flags.HasFlag(testFlag) && !flags.HasFlag(InstFlags.ReadRd);
}
private static bool IsBackwardsBranch(InstName name, uint encoding)
{
if (name == InstName.B)
{
return ImmUtils.ExtractSImm24Times4(encoding) < 0;
}
return false;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,137 +0,0 @@
using System.Numerics;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
static class ImmUtils
{
public static uint ExpandImm(uint imm)
{
return BitOperations.RotateRight((byte)imm, (int)(imm >> 8) * 2);
}
public static bool ExpandedImmRotated(uint imm)
{
return (imm >> 8) != 0;
}
public static uint ExpandImm(uint imm8, uint imm3, uint i)
{
uint imm = CombineImmU12(imm8, imm3, i);
if (imm >> 10 == 0)
{
return ((imm >> 8) & 3) switch
{
0 => (byte)imm,
1 => (byte)imm * 0x00010001u,
2 => (byte)imm * 0x01000100u,
3 => (byte)imm * 0x01010101u,
_ => 0,
};
}
else
{
return BitOperations.RotateRight(0x80u | (byte)imm, (int)(imm >> 7));
}
}
public static bool ExpandedImmRotated(uint imm8, uint imm3, uint i)
{
uint imm = CombineImmU12(imm8, imm3, i);
return (imm >> 7) != 0;
}
public static uint CombineImmU5(uint imm2, uint imm3)
{
return imm2 | (imm3 << 2);
}
public static uint CombineImmU5IImm4(uint i, uint imm4)
{
return i | (imm4 << 1);
}
public static uint CombineImmU8(uint imm4l, uint imm4h)
{
return imm4l | (imm4h << 4);
}
public static uint CombineImmU8(uint imm4, uint imm3, uint i)
{
return imm4 | (imm3 << 4) | (i << 7);
}
public static uint CombineImmU12(uint imm8, uint imm3, uint i)
{
return imm8 | (imm3 << 8) | (i << 11);
}
public static uint CombineImmU16(uint imm12, uint imm4)
{
return imm12 | (imm4 << 12);
}
public static uint CombineImmU16(uint imm8, uint imm3, uint i, uint imm4)
{
return imm8 | (imm3 << 8) | (i << 11) | (imm4 << 12);
}
public static int CombineSImm20Times2(uint imm11, uint imm6, uint j1, uint j2, uint s)
{
int imm32 = (int)(imm11 | (imm6 << 11) | (j1 << 17) | (j2 << 18) | (s << 19));
return (imm32 << 13) >> 12;
}
public static int CombineSImm24Times2(uint imm11, uint imm10, uint j1, uint j2, uint s)
{
uint i1 = j1 ^ s ^ 1;
uint i2 = j2 ^ s ^ 1;
int imm32 = (int)(imm11 | (imm10 << 11) | (i2 << 21) | (i1 << 22) | (s << 23));
return (imm32 << 8) >> 7;
}
public static int CombineSImm24Times4(uint imm10L, uint imm10H, uint j1, uint j2, uint s)
{
uint i1 = j1 ^ s ^ 1;
uint i2 = j2 ^ s ^ 1;
int imm32 = (int)(imm10L | (imm10H << 10) | (i2 << 20) | (i1 << 21) | (s << 22));
return (imm32 << 9) >> 7;
}
public static uint CombineRegisterList(uint registerList, uint m)
{
return registerList | (m << 14);
}
public static uint CombineRegisterList(uint registerList, uint m, uint p)
{
return registerList | (m << 14) | (p << 15);
}
public static int ExtractSImm24Times4(uint encoding)
{
return (int)(encoding << 8) >> 6;
}
public static int ExtractT16UImm5Times2(uint encoding)
{
return (int)(encoding >> 18) & 0x3e;
}
public static int ExtractT16SImm8Times2(uint encoding)
{
return (int)(encoding << 24) >> 23;
}
public static int ExtractT16SImm11Times2(uint encoding)
{
return (int)(encoding << 21) >> 20;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +0,0 @@
using System;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
[Flags]
enum InstFlags
{
None = 0,
Cond = 1 << 0,
Rd = 1 << 1,
RdLo = 1 << 2,
RdHi = 1 << 3,
Rdn = 1 << 4,
Dn = 1 << 5,
Rt = 1 << 6,
Rt2 = 1 << 7,
Rlist = 1 << 8,
Rd16 = 1 << 9,
ReadRd = 1 << 10,
WBack = 1 << 11,
Thumb16 = 1 << 12,
RdnDn = Rdn | Dn,
RdRd16 = Rd | Rd16,
RtRt2 = Rt | Rt2,
RdLoRdHi = RdLo | RdHi,
RdLoHi = Rd | RdHi,
RdRtRead = Rd | RtRead,
RdRtReadRd16 = Rd | RtRead | Rd16,
RdRt2Read = Rd | Rt2 | RtRead,
RdRt2ReadRd16 = Rd | Rt2 | RtRead | Rd16,
RtRd16 = Rt | Rd16,
RtWBack = Rt | WBack,
Rt2WBack = Rt2 | RtWBack,
RtRead = Rt | ReadRd,
RtReadRd16 = Rt | ReadRd | Rd16,
Rt2Read = Rt2 | RtRead,
RtReadWBack = RtRead | WBack,
Rt2ReadWBack = Rt2 | RtReadWBack,
RlistWBack = Rlist | WBack,
RlistRead = Rlist | ReadRd,
RlistReadWBack = Rlist | ReadRd | WBack,
CondRd = Cond | Rd,
CondRdLoHi = Cond | Rd | RdHi,
CondRt = Cond | Rt,
CondRt2 = Cond | Rt | Rt2,
CondRd16 = Cond | Rd | Rd16,
CondWBack = Cond | WBack,
CondRdRtRead = Cond | Rd | RtRead,
CondRdRt2Read = Cond | Rd | Rt2 | RtRead,
CondRtWBack = Cond | RtWBack,
CondRt2WBack = Cond | Rt2 | RtWBack,
CondRtRead = Cond | RtRead,
CondRt2Read = Cond | Rt2 | RtRead,
CondRtReadWBack = Cond | RtReadWBack,
CondRt2ReadWBack = Cond | Rt2 | RtReadWBack,
CondRlist = Cond | Rlist,
CondRlistWBack = Cond | Rlist | WBack,
CondRlistRead = Cond | Rlist | ReadRd,
CondRlistReadWBack = Cond | Rlist | ReadRd | WBack,
}
}

View File

@@ -1,20 +0,0 @@
using System;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
readonly struct InstInfo
{
public readonly uint Encoding;
public readonly InstName Name;
public readonly Action<CodeGenContext, uint> EmitFunc;
public readonly InstFlags Flags;
public InstInfo(uint encoding, InstName name, Action<CodeGenContext, uint> emitFunc, InstFlags flags)
{
Encoding = encoding;
Name = name;
EmitFunc = emitFunc;
Flags = flags;
}
}
}

View File

@@ -1,79 +0,0 @@
using Ryujinx.Cpu.LightningJit.Table;
using System;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
readonly struct InstInfoForTable : IInstInfo
{
public uint Encoding { get; }
public uint EncodingMask { get; }
public InstEncoding[] Constraints { get; }
public InstMeta Meta { get; }
public IsaVersion Version => Meta.Version;
public IsaFeature Feature => Meta.Feature;
public InstInfoForTable(
uint encoding,
uint encodingMask,
InstEncoding[] constraints,
InstName name,
Action<CodeGenContext, uint> emitFunc,
IsaVersion isaVersion,
IsaFeature isaFeature,
InstFlags flags)
{
Encoding = encoding;
EncodingMask = encodingMask;
Constraints = constraints;
Meta = new(name, emitFunc, isaVersion, isaFeature, flags);
}
public InstInfoForTable(
uint encoding,
uint encodingMask,
InstEncoding[] constraints,
InstName name,
Action<CodeGenContext, uint> emitFunc,
IsaVersion isaVersion,
InstFlags flags) : this(encoding, encodingMask, constraints, name, emitFunc, isaVersion, IsaFeature.None, flags)
{
}
public InstInfoForTable(
uint encoding,
uint encodingMask,
InstName name,
Action<CodeGenContext, uint> emitFunc,
IsaVersion isaVersion,
IsaFeature isaFeature,
InstFlags flags) : this(encoding, encodingMask, null, name, emitFunc, isaVersion, isaFeature, flags)
{
}
public InstInfoForTable(
uint encoding,
uint encodingMask,
InstName name,
Action<CodeGenContext, uint> emitFunc,
IsaVersion isaVersion,
InstFlags flags) : this(encoding, encodingMask, null, name, emitFunc, isaVersion, IsaFeature.None, flags)
{
}
public bool IsConstrained(uint encoding)
{
if (Constraints != null)
{
foreach (InstEncoding constraint in Constraints)
{
if ((encoding & constraint.EncodingMask) == constraint.Encoding)
{
return true;
}
}
}
return false;
}
}
}

View File

@@ -1,22 +0,0 @@
using System;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
readonly struct InstMeta
{
public readonly InstName Name;
public readonly Action<CodeGenContext, uint> EmitFunc;
public readonly IsaVersion Version;
public readonly IsaFeature Feature;
public readonly InstFlags Flags;
public InstMeta(InstName name, Action<CodeGenContext, uint> emitFunc, IsaVersion isaVersion, IsaFeature isaFeature, InstFlags flags)
{
Name = name;
EmitFunc = emitFunc;
Version = isaVersion;
Feature = isaFeature;
Flags = flags;
}
}
}

View File

@@ -1,562 +0,0 @@
namespace Ryujinx.Cpu.LightningJit.Arm32
{
enum InstName
{
AdcI,
AdcR,
AdcRr,
AddI,
AddR,
AddRr,
AddSpI,
AddSpR,
Adr,
Aesd,
Aese,
Aesimc,
Aesmc,
AndI,
AndR,
AndRr,
B,
Bfc,
Bfi,
BicI,
BicR,
BicRr,
Bkpt,
BlxR,
BlI,
Bx,
Bxj,
Cbnz,
Clrbhb,
Clrex,
Clz,
CmnI,
CmnR,
CmnRr,
CmpI,
CmpR,
CmpRr,
Cps,
Crc32,
Crc32c,
Csdb,
Dbg,
Dcps1,
Dcps2,
Dcps3,
Dmb,
Dsb,
EorI,
EorR,
EorRr,
Eret,
Esb,
Fldmx,
Fstmx,
Hlt,
Hvc,
Isb,
It,
Lda,
Ldab,
Ldaex,
Ldaexb,
Ldaexd,
Ldaexh,
Ldah,
LdcI,
LdcL,
Ldm,
Ldmda,
Ldmdb,
Ldmib,
LdmE,
LdmU,
Ldrbt,
LdrbI,
LdrbL,
LdrbR,
LdrdI,
LdrdL,
LdrdR,
Ldrex,
Ldrexb,
Ldrexd,
Ldrexh,
Ldrht,
LdrhI,
LdrhL,
LdrhR,
Ldrsbt,
LdrsbI,
LdrsbL,
LdrsbR,
Ldrsht,
LdrshI,
LdrshL,
LdrshR,
Ldrt,
LdrI,
LdrL,
LdrR,
Mcr,
Mcrr,
Mla,
Mls,
Movt,
MovI,
MovR,
MovRr,
Mrc,
Mrrc,
Mrs,
MrsBr,
MsrBr,
MsrI,
MsrR,
Mul,
MvnI,
MvnR,
MvnRr,
Nop,
OrnI,
OrnR,
OrrI,
OrrR,
OrrRr,
Pkh,
PldI,
PldL,
PldR,
PliI,
PliR,
Pop,
Pssbb,
Push,
Qadd,
Qadd16,
Qadd8,
Qasx,
Qdadd,
Qdsub,
Qsax,
Qsub,
Qsub16,
Qsub8,
Rbit,
Rev,
Rev16,
Revsh,
Rfe,
RsbI,
RsbR,
RsbRr,
RscI,
RscR,
RscRr,
Sadd16,
Sadd8,
Sasx,
Sb,
SbcI,
SbcR,
SbcRr,
Sbfx,
Sdiv,
Sel,
Setend,
Setpan,
Sev,
Sevl,
Sha1c,
Sha1h,
Sha1m,
Sha1p,
Sha1su0,
Sha1su1,
Sha256h,
Sha256h2,
Sha256su0,
Sha256su1,
Shadd16,
Shadd8,
Shasx,
Shsax,
Shsub16,
Shsub8,
Smc,
Smlabb,
Smlad,
Smlal,
Smlalbb,
Smlald,
Smlawb,
Smlsd,
Smlsld,
Smmla,
Smmls,
Smmul,
Smuad,
Smulbb,
Smull,
Smulwb,
Smusd,
Srs,
Ssat,
Ssat16,
Ssax,
Ssbb,
Ssub16,
Ssub8,
Stc,
Stl,
Stlb,
Stlex,
Stlexb,
Stlexd,
Stlexh,
Stlh,
Stm,
Stmda,
Stmdb,
Stmib,
StmU,
Strbt,
StrbI,
StrbR,
StrdI,
StrdR,
Strex,
Strexb,
Strexd,
Strexh,
Strht,
StrhI,
StrhR,
Strt,
StrI,
StrR,
SubI,
SubR,
SubRr,
SubSpI,
SubSpR,
Svc,
Sxtab,
Sxtab16,
Sxtah,
Sxtb,
Sxtb16,
Sxth,
Tbb,
TeqI,
TeqR,
TeqRr,
Tsb,
TstI,
TstR,
TstRr,
Uadd16,
Uadd8,
Uasx,
Ubfx,
Udf,
Udiv,
Uhadd16,
Uhadd8,
Uhasx,
Uhsax,
Uhsub16,
Uhsub8,
Umaal,
Umlal,
Umull,
Uqadd16,
Uqadd8,
Uqasx,
Uqsax,
Uqsub16,
Uqsub8,
Usad8,
Usada8,
Usat,
Usat16,
Usax,
Usub16,
Usub8,
Uxtab,
Uxtab16,
Uxtah,
Uxtb,
Uxtb16,
Uxth,
Vaba,
Vabal,
VabdlI,
VabdF,
VabdI,
Vabs,
Vacge,
Vacgt,
Vaddhn,
Vaddl,
Vaddw,
VaddF,
VaddI,
VandR,
VbicI,
VbicR,
Vbif,
Vbit,
Vbsl,
Vcadd,
VceqI,
VceqR,
VcgeI,
VcgeR,
VcgtI,
VcgtR,
VcleI,
Vcls,
VcltI,
Vclz,
Vcmla,
VcmlaS,
Vcmp,
Vcmpe,
Vcnt,
VcvtaAsimd,
VcvtaVfp,
Vcvtb,
VcvtbBfs,
VcvtmAsimd,
VcvtmVfp,
VcvtnAsimd,
VcvtnVfp,
VcvtpAsimd,
VcvtpVfp,
VcvtrIv,
Vcvtt,
VcvttBfs,
VcvtBfs,
VcvtDs,
VcvtHs,
VcvtIs,
VcvtIv,
VcvtVi,
VcvtXs,
VcvtXv,
Vdiv,
Vdot,
VdotS,
VdupR,
VdupS,
Veor,
Vext,
Vfma,
Vfmal,
VfmalS,
VfmaBf,
VfmaBfs,
Vfms,
Vfmsl,
VfmslS,
Vfnma,
Vfnms,
Vhadd,
Vhsub,
Vins,
Vjcvt,
Vld11,
Vld1A,
Vld1M,
Vld21,
Vld2A,
Vld2M,
Vld31,
Vld3A,
Vld3M,
Vld41,
Vld4A,
Vld4M,
Vldm,
VldrI,
VldrL,
Vmaxnm,
VmaxF,
VmaxI,
Vminnm,
VminF,
VminI,
VmlalI,
VmlalS,
VmlaF,
VmlaI,
VmlaS,
VmlslI,
VmlslS,
VmlsF,
VmlsI,
VmlsS,
Vmmla,
Vmovl,
Vmovn,
Vmovx,
VmovD,
VmovH,
VmovI,
VmovR,
VmovRs,
VmovS,
VmovSr,
VmovSs,
Vmrs,
Vmsr,
VmullI,
VmullS,
VmulF,
VmulI,
VmulS,
VmvnI,
VmvnR,
Vneg,
Vnmla,
Vnmls,
Vnmul,
VornR,
VorrI,
VorrR,
Vpadal,
Vpaddl,
VpaddF,
VpaddI,
VpmaxF,
VpmaxI,
VpminF,
VpminI,
Vqabs,
Vqadd,
Vqdmlal,
Vqdmlsl,
Vqdmulh,
Vqdmull,
Vqmovn,
Vqneg,
Vqrdmlah,
Vqrdmlsh,
Vqrdmulh,
Vqrshl,
Vqrshrn,
VqshlI,
VqshlR,
Vqshrn,
Vqsub,
Vraddhn,
Vrecpe,
Vrecps,
Vrev16,
Vrev32,
Vrev64,
Vrhadd,
VrintaAsimd,
VrintaVfp,
VrintmAsimd,
VrintmVfp,
VrintnAsimd,
VrintnVfp,
VrintpAsimd,
VrintpVfp,
VrintrVfp,
VrintxAsimd,
VrintxVfp,
VrintzAsimd,
VrintzVfp,
Vrshl,
Vrshr,
Vrshrn,
Vrsqrte,
Vrsqrts,
Vrsra,
Vrsubhn,
Vsdot,
VsdotS,
Vsel,
Vshll,
VshlI,
VshlR,
Vshr,
Vshrn,
Vsli,
Vsmmla,
Vsqrt,
Vsra,
Vsri,
Vst11,
Vst1M,
Vst21,
Vst2M,
Vst31,
Vst3M,
Vst41,
Vst4M,
Vstm,
Vstr,
Vsubhn,
Vsubl,
Vsubw,
VsubF,
VsubI,
VsudotS,
Vswp,
Vtbl,
Vtrn,
Vtst,
Vudot,
VudotS,
Vummla,
Vusdot,
VusdotS,
Vusmmla,
Vuzp,
Vzip,
Wfe,
Wfi,
Yield,
}
static class InstNameExtensions
{
public static bool IsCall(this InstName name)
{
return name == InstName.BlI || name == InstName.BlxR;
}
public static bool IsSystem(this InstName name)
{
switch (name)
{
case InstName.Mcr:
case InstName.Mcrr:
case InstName.Mrc:
case InstName.Mrs:
case InstName.MrsBr:
case InstName.MsrBr:
case InstName.MsrI:
case InstName.MsrR:
case InstName.Mrrc:
case InstName.Svc:
return true;
}
return false;
}
public static bool IsSystemOrCall(this InstName name)
{
return name.IsSystem() || name.IsCall();
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,146 +0,0 @@
using Ryujinx.Cpu.LightningJit.Table;
using System.Collections.Generic;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
static class InstTableT16<T> where T : IInstEmit
{
private static readonly InstTableLevel<InstInfoForTable> _table;
static InstTableT16()
{
InstEncoding[] rmRdndnConstraints = new InstEncoding[]
{
new(0x00680000, 0x00780000),
new(0x00850000, 0x00870000),
};
InstEncoding[] rmConstraints = new InstEncoding[]
{
new(0x00680000, 0x00780000),
};
InstEncoding[] condCondConstraints = new InstEncoding[]
{
new(0x0E000000, 0x0F000000),
new(0x0F000000, 0x0F000000),
};
InstEncoding[] maskConstraints = new InstEncoding[]
{
new(0x00000000, 0x000F0000),
};
InstEncoding[] opConstraints = new InstEncoding[]
{
new(0x18000000, 0x18000000),
};
InstEncoding[] opOpOpOpConstraints = new InstEncoding[]
{
new(0x00000000, 0x03C00000),
new(0x00400000, 0x03C00000),
new(0x01400000, 0x03C00000),
new(0x01800000, 0x03C00000),
};
List<InstInfoForTable> insts = new()
{
new(0x41400000, 0xFFC00000, InstName.AdcR, T.AdcRT1, IsaVersion.v80, InstFlags.Rdn),
new(0x1C000000, 0xFE000000, InstName.AddI, T.AddIT1, IsaVersion.v80, InstFlags.Rd),
new(0x30000000, 0xF8000000, InstName.AddI, T.AddIT2, IsaVersion.v80, InstFlags.Rdn),
new(0x18000000, 0xFE000000, InstName.AddR, T.AddRT1, IsaVersion.v80, InstFlags.Rd),
new(0x44000000, 0xFF000000, rmRdndnConstraints, InstName.AddR, T.AddRT2, IsaVersion.v80, InstFlags.RdnDn),
new(0xA8000000, 0xF8000000, InstName.AddSpI, T.AddSpIT1, IsaVersion.v80, InstFlags.RdRd16),
new(0xB0000000, 0xFF800000, InstName.AddSpI, T.AddSpIT2, IsaVersion.v80, InstFlags.None),
new(0x44680000, 0xFF780000, InstName.AddSpR, T.AddSpRT1, IsaVersion.v80, InstFlags.None),
new(0x44850000, 0xFF870000, rmConstraints, InstName.AddSpR, T.AddSpRT2, IsaVersion.v80, InstFlags.None),
new(0xA0000000, 0xF8000000, InstName.Adr, T.AdrT1, IsaVersion.v80, InstFlags.RdRd16),
new(0x40000000, 0xFFC00000, InstName.AndR, T.AndRT1, IsaVersion.v80, InstFlags.Rdn),
new(0xD0000000, 0xF0000000, condCondConstraints, InstName.B, T.BT1, IsaVersion.v80, InstFlags.Cond),
new(0xE0000000, 0xF8000000, InstName.B, T.BT2, IsaVersion.v80, InstFlags.None),
new(0x43800000, 0xFFC00000, InstName.BicR, T.BicRT1, IsaVersion.v80, InstFlags.Rdn),
new(0xBE000000, 0xFF000000, InstName.Bkpt, T.BkptT1, IsaVersion.v80, InstFlags.None),
new(0x47800000, 0xFF870000, InstName.BlxR, T.BlxRT1, IsaVersion.v80, InstFlags.None),
new(0x47000000, 0xFF870000, InstName.Bx, T.BxT1, IsaVersion.v80, InstFlags.None),
new(0xB1000000, 0xF5000000, InstName.Cbnz, T.CbnzT1, IsaVersion.v80, InstFlags.None),
new(0x42C00000, 0xFFC00000, InstName.CmnR, T.CmnRT1, IsaVersion.v80, InstFlags.None),
new(0x28000000, 0xF8000000, InstName.CmpI, T.CmpIT1, IsaVersion.v80, InstFlags.None),
new(0x42800000, 0xFFC00000, InstName.CmpR, T.CmpRT1, IsaVersion.v80, InstFlags.None),
new(0x45000000, 0xFF000000, InstName.CmpR, T.CmpRT2, IsaVersion.v80, InstFlags.None),
new(0xB6600000, 0xFFE80000, InstName.Cps, T.CpsT1, IsaVersion.v80, InstFlags.None),
new(0x40400000, 0xFFC00000, InstName.EorR, T.EorRT1, IsaVersion.v80, InstFlags.Rdn),
new(0xBA800000, 0xFFC00000, InstName.Hlt, T.HltT1, IsaVersion.v80, InstFlags.None),
new(0xBF000000, 0xFF000000, maskConstraints, InstName.It, T.ItT1, IsaVersion.v80, InstFlags.None),
new(0xC8000000, 0xF8000000, InstName.Ldm, T.LdmT1, IsaVersion.v80, InstFlags.Rlist),
new(0x78000000, 0xF8000000, InstName.LdrbI, T.LdrbIT1, IsaVersion.v80, InstFlags.Rt),
new(0x5C000000, 0xFE000000, InstName.LdrbR, T.LdrbRT1, IsaVersion.v80, InstFlags.Rt),
new(0x88000000, 0xF8000000, InstName.LdrhI, T.LdrhIT1, IsaVersion.v80, InstFlags.Rt),
new(0x5A000000, 0xFE000000, InstName.LdrhR, T.LdrhRT1, IsaVersion.v80, InstFlags.Rt),
new(0x56000000, 0xFE000000, InstName.LdrsbR, T.LdrsbRT1, IsaVersion.v80, InstFlags.Rt),
new(0x5E000000, 0xFE000000, InstName.LdrshR, T.LdrshRT1, IsaVersion.v80, InstFlags.Rt),
new(0x68000000, 0xF8000000, InstName.LdrI, T.LdrIT1, IsaVersion.v80, InstFlags.Rt),
new(0x98000000, 0xF8000000, InstName.LdrI, T.LdrIT2, IsaVersion.v80, InstFlags.RtRd16),
new(0x48000000, 0xF8000000, InstName.LdrL, T.LdrLT1, IsaVersion.v80, InstFlags.RtRd16),
new(0x58000000, 0xFE000000, InstName.LdrR, T.LdrRT1, IsaVersion.v80, InstFlags.Rt),
new(0x20000000, 0xF8000000, InstName.MovI, T.MovIT1, IsaVersion.v80, InstFlags.RdRd16),
new(0x46000000, 0xFF000000, InstName.MovR, T.MovRT1, IsaVersion.v80, InstFlags.Rd),
new(0x00000000, 0xE0000000, opConstraints, InstName.MovR, T.MovRT2, IsaVersion.v80, InstFlags.Rd),
new(0x40000000, 0xFE000000, opOpOpOpConstraints, InstName.MovRr, T.MovRrT1, IsaVersion.v80, InstFlags.None),
new(0x43400000, 0xFFC00000, InstName.Mul, T.MulT1, IsaVersion.v80, InstFlags.None),
new(0x43C00000, 0xFFC00000, InstName.MvnR, T.MvnRT1, IsaVersion.v80, InstFlags.Rd),
new(0xBF000000, 0xFFFF0000, InstName.Nop, T.NopT1, IsaVersion.v80, InstFlags.None),
new(0x43000000, 0xFFC00000, InstName.OrrR, T.OrrRT1, IsaVersion.v80, InstFlags.Rdn),
new(0xBC000000, 0xFE000000, InstName.Pop, T.PopT1, IsaVersion.v80, InstFlags.Rlist),
new(0xB4000000, 0xFE000000, InstName.Push, T.PushT1, IsaVersion.v80, InstFlags.RlistRead),
new(0xBA000000, 0xFFC00000, InstName.Rev, T.RevT1, IsaVersion.v80, InstFlags.Rd),
new(0xBA400000, 0xFFC00000, InstName.Rev16, T.Rev16T1, IsaVersion.v80, InstFlags.Rd),
new(0xBAC00000, 0xFFC00000, InstName.Revsh, T.RevshT1, IsaVersion.v80, InstFlags.Rd),
new(0x42400000, 0xFFC00000, InstName.RsbI, T.RsbIT1, IsaVersion.v80, InstFlags.Rd),
new(0x41800000, 0xFFC00000, InstName.SbcR, T.SbcRT1, IsaVersion.v80, InstFlags.Rdn),
new(0xB6500000, 0xFFF70000, InstName.Setend, T.SetendT1, IsaVersion.v80, InstFlags.None),
new(0xB6100000, 0xFFF70000, InstName.Setpan, T.SetpanT1, IsaVersion.v81, IsaFeature.FeatPan, InstFlags.None),
new(0xBF400000, 0xFFFF0000, InstName.Sev, T.SevT1, IsaVersion.v80, InstFlags.None),
new(0xBF500000, 0xFFFF0000, InstName.Sevl, T.SevlT1, IsaVersion.v80, InstFlags.None),
new(0xC0000000, 0xF8000000, InstName.Stm, T.StmT1, IsaVersion.v80, InstFlags.RlistRead),
new(0x70000000, 0xF8000000, InstName.StrbI, T.StrbIT1, IsaVersion.v80, InstFlags.RtRead),
new(0x54000000, 0xFE000000, InstName.StrbR, T.StrbRT1, IsaVersion.v80, InstFlags.RtRead),
new(0x80000000, 0xF8000000, InstName.StrhI, T.StrhIT1, IsaVersion.v80, InstFlags.RtRead),
new(0x52000000, 0xFE000000, InstName.StrhR, T.StrhRT1, IsaVersion.v80, InstFlags.RtRead),
new(0x60000000, 0xF8000000, InstName.StrI, T.StrIT1, IsaVersion.v80, InstFlags.RtRead),
new(0x90000000, 0xF8000000, InstName.StrI, T.StrIT2, IsaVersion.v80, InstFlags.RtReadRd16),
new(0x50000000, 0xFE000000, InstName.StrR, T.StrRT1, IsaVersion.v80, InstFlags.RtRead),
new(0x1E000000, 0xFE000000, InstName.SubI, T.SubIT1, IsaVersion.v80, InstFlags.Rd),
new(0x38000000, 0xF8000000, InstName.SubI, T.SubIT2, IsaVersion.v80, InstFlags.Rdn),
new(0x1A000000, 0xFE000000, InstName.SubR, T.SubRT1, IsaVersion.v80, InstFlags.Rd),
new(0xB0800000, 0xFF800000, InstName.SubSpI, T.SubSpIT1, IsaVersion.v80, InstFlags.None),
new(0xDF000000, 0xFF000000, InstName.Svc, T.SvcT1, IsaVersion.v80, InstFlags.None),
new(0xB2400000, 0xFFC00000, InstName.Sxtb, T.SxtbT1, IsaVersion.v80, InstFlags.Rd),
new(0xB2000000, 0xFFC00000, InstName.Sxth, T.SxthT1, IsaVersion.v80, InstFlags.Rd),
new(0x42000000, 0xFFC00000, InstName.TstR, T.TstRT1, IsaVersion.v80, InstFlags.None),
new(0xDE000000, 0xFF000000, InstName.Udf, T.UdfT1, IsaVersion.v80, InstFlags.None),
new(0xB2C00000, 0xFFC00000, InstName.Uxtb, T.UxtbT1, IsaVersion.v80, InstFlags.Rd),
new(0xB2800000, 0xFFC00000, InstName.Uxth, T.UxthT1, IsaVersion.v80, InstFlags.Rd),
new(0xBF200000, 0xFFFF0000, InstName.Wfe, T.WfeT1, IsaVersion.v80, InstFlags.None),
new(0xBF300000, 0xFFFF0000, InstName.Wfi, T.WfiT1, IsaVersion.v80, InstFlags.None),
new(0xBF100000, 0xFFFF0000, InstName.Yield, T.YieldT1, IsaVersion.v80, InstFlags.None),
};
_table = new(insts);
}
public static bool TryGetMeta(uint encoding, IsaVersion version, IsaFeature features, out InstMeta meta)
{
if (_table.TryFind(encoding, version, features, out InstInfoForTable info))
{
meta = info.Meta;
return true;
}
meta = new(InstName.Udf, T.UdfA1, IsaVersion.v80, IsaFeature.None, InstFlags.None);
return false;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +0,0 @@
using System.Collections.Generic;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
class MultiBlock
{
public readonly List<Block> Blocks;
public readonly bool HasHostCall;
public readonly bool IsTruncated;
public MultiBlock(List<Block> blocks)
{
Blocks = blocks;
Block block = blocks[0];
HasHostCall = block.HasHostCall;
for (int index = 1; index < blocks.Count; index++)
{
block = blocks[index];
HasHostCall |= block.HasHostCall;
}
block = blocks[^1];
IsTruncated = block.IsTruncated;
}
}
}

View File

@@ -1,20 +0,0 @@
namespace Ryujinx.Cpu.LightningJit.Arm32
{
readonly struct PendingBranch
{
public readonly BranchType BranchType;
public readonly uint TargetAddress;
public readonly uint NextAddress;
public readonly InstName Name;
public readonly int WriterPointer;
public PendingBranch(BranchType branchType, uint targetAddress, uint nextAddress, InstName name, int writerPointer)
{
BranchType = branchType;
TargetAddress = targetAddress;
NextAddress = nextAddress;
Name = name;
WriterPointer = writerPointer;
}
}
}

View File

@@ -1,169 +0,0 @@
using Ryujinx.Cpu.LightningJit.CodeGen;
using Ryujinx.Cpu.LightningJit.CodeGen.Arm64;
using System;
using System.Numerics;
namespace Ryujinx.Cpu.LightningJit.Arm32
{
class RegisterAllocator
{
public const int MaxTemps = 1;
private uint _gprMask;
private uint _fpSimdMask;
public int FixedContextRegister { get; }
public int FixedPageTableRegister { get; }
public uint UsedGprsMask { get; private set; }
public uint UsedFpSimdMask { get; private set; }
public RegisterAllocator()
{
_gprMask = ushort.MaxValue;
_fpSimdMask = ushort.MaxValue;
FixedContextRegister = AllocateTempRegisterWithPreferencing();
FixedPageTableRegister = AllocateTempRegisterWithPreferencing();
}
public void MarkGprAsUsed(int index)
{
UsedGprsMask |= 1u << index;
}
public void MarkFpSimdAsUsed(int index)
{
UsedFpSimdMask |= 1u << index;
}
public void MarkFpSimdRangeAsUsed(int index, int count)
{
UsedFpSimdMask |= (uint.MaxValue >> (32 - count)) << index;
}
public Operand RemapGprRegister(int index)
{
MarkGprAsUsed(index);
return new Operand(OperandKind.Register, OperandType.I32, (ulong)index);
}
public Operand RemapFpRegister(int index, bool isFP32)
{
MarkFpSimdAsUsed(index);
return new Operand(OperandKind.Register, isFP32 ? OperandType.FP32 : OperandType.FP64, (ulong)index);
}
public Operand RemapSimdRegister(int index)
{
MarkFpSimdAsUsed(index);
return new Operand(OperandKind.Register, OperandType.V128, (ulong)index);
}
public Operand RemapSimdRegister(int index, int count)
{
MarkFpSimdRangeAsUsed(index, count);
return new Operand(OperandKind.Register, OperandType.V128, (ulong)index);
}
public void EnsureTempGprRegisters(int count)
{
if (count != 0)
{
Span<int> registers = stackalloc int[count];
for (int index = 0; index < count; index++)
{
registers[index] = AllocateTempGprRegister();
}
for (int index = 0; index < count; index++)
{
FreeTempGprRegister(registers[index]);
}
}
}
public int AllocateTempGprRegister()
{
int index = AllocateTempRegister(ref _gprMask, AbiConstants.ReservedRegsMask);
MarkGprAsUsed(index);
return index;
}
private int AllocateTempRegisterWithPreferencing()
{
int firstCalleeSaved = BitOperations.TrailingZeroCount(~_gprMask & AbiConstants.GprCalleeSavedRegsMask);
if (firstCalleeSaved < 32)
{
uint regMask = 1u << firstCalleeSaved;
if ((regMask & AbiConstants.ReservedRegsMask) == 0)
{
_gprMask |= regMask;
return firstCalleeSaved;
}
}
return AllocateTempRegister(ref _gprMask, AbiConstants.ReservedRegsMask);
}
public int AllocateTempFpSimdRegister()
{
int index = AllocateTempRegister(ref _fpSimdMask, 0);
MarkFpSimdAsUsed(index);
return index;
}
public ScopedRegister AllocateTempGprRegisterScoped()
{
return new(this, new(OperandKind.Register, OperandType.I32, (ulong)AllocateTempGprRegister()));
}
public ScopedRegister AllocateTempFpRegisterScoped(bool isFP32)
{
return new(this, new(OperandKind.Register, isFP32 ? OperandType.FP32 : OperandType.FP64, (ulong)AllocateTempFpSimdRegister()));
}
public ScopedRegister AllocateTempSimdRegisterScoped()
{
return new(this, new(OperandKind.Register, OperandType.V128, (ulong)AllocateTempFpSimdRegister()));
}
public void FreeTempGprRegister(int index)
{
FreeTempRegister(ref _gprMask, index);
}
public void FreeTempFpSimdRegister(int index)
{
FreeTempRegister(ref _fpSimdMask, index);
}
private static int AllocateTempRegister(ref uint mask, uint reservedMask)
{
int index = BitOperations.TrailingZeroCount(~(mask | reservedMask));
if (index == sizeof(uint) * 8)
{
throw new InvalidOperationException("No free registers.");
}
mask |= 1u << index;
return index;
}
private static void FreeTempRegister(ref uint mask, int index)
{
mask &= ~(1u << index);
}
}
}

Some files were not shown because too many files have changed in this diff Show More