Merge branch 'master' into pptc_and_pool_enhancements

This commit is contained in:
LDj3SNuD 2021-01-27 06:25:40 +01:00
commit b767d1a6b0
82 changed files with 3890 additions and 793 deletions

View file

@ -33,6 +33,8 @@ jobs:
- uses: actions/setup-dotnet@v1 - uses: actions/setup-dotnet@v1
with: with:
dotnet-version: 5.0.x dotnet-version: 5.0.x
- name: Clear
run: dotnet clean && dotnet nuget locals all --clear
- name: Build - name: Build
run: dotnet build -c "${{ matrix.configuration }}" run: dotnet build -c "${{ matrix.configuration }}"
- name: Test - name: Test

View file

@ -119,6 +119,7 @@ namespace ARMeilleure.CodeGen.X86
Add(Intrinsic.X86Popcnt, new IntrinsicInfo(X86Instruction.Popcnt, IntrinsicType.PopCount)); Add(Intrinsic.X86Popcnt, new IntrinsicInfo(X86Instruction.Popcnt, IntrinsicType.PopCount));
Add(Intrinsic.X86Por, new IntrinsicInfo(X86Instruction.Por, IntrinsicType.Binary)); Add(Intrinsic.X86Por, new IntrinsicInfo(X86Instruction.Por, IntrinsicType.Binary));
Add(Intrinsic.X86Pshufb, new IntrinsicInfo(X86Instruction.Pshufb, IntrinsicType.Binary)); Add(Intrinsic.X86Pshufb, new IntrinsicInfo(X86Instruction.Pshufb, IntrinsicType.Binary));
Add(Intrinsic.X86Pshufd, new IntrinsicInfo(X86Instruction.Pshufd, IntrinsicType.BinaryImm));
Add(Intrinsic.X86Pslld, new IntrinsicInfo(X86Instruction.Pslld, IntrinsicType.Binary)); Add(Intrinsic.X86Pslld, new IntrinsicInfo(X86Instruction.Pslld, IntrinsicType.Binary));
Add(Intrinsic.X86Pslldq, new IntrinsicInfo(X86Instruction.Pslldq, IntrinsicType.Binary)); Add(Intrinsic.X86Pslldq, new IntrinsicInfo(X86Instruction.Pslldq, IntrinsicType.Binary));
Add(Intrinsic.X86Psllq, new IntrinsicInfo(X86Instruction.Psllq, IntrinsicType.Binary)); Add(Intrinsic.X86Psllq, new IntrinsicInfo(X86Instruction.Psllq, IntrinsicType.Binary));

View file

@ -144,9 +144,10 @@ namespace ARMeilleure.Decoders
SetA64("101100100xxxxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, OpCodeAluImm.Create); SetA64("101100100xxxxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, OpCodeAluImm.Create);
SetA64("00101010xx0xxxxx0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, OpCodeAluRs.Create); SetA64("00101010xx0xxxxx0xxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, OpCodeAluRs.Create);
SetA64("10101010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, OpCodeAluRs.Create); SetA64("10101010xx0xxxxxxxxxxxxxxxxxxxxx", InstName.Orr, InstEmit.Orr, OpCodeAluRs.Create);
SetA64("1111100110xxxxxxxxxxxxxxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, OpCodeMemImm.Create); SetA64("1111100110xxxxxxxxxxxxxxxxxxxxxx", InstName.Prfm, InstEmit.Prfm, OpCodeMemImm.Create); // immediate
SetA64("11111000100xxxxxxxxx00xxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, OpCodeMemImm.Create); SetA64("11111000100xxxxxxxxx00xxxxxxxxxx", InstName.Prfm, InstEmit.Prfm, OpCodeMemImm.Create); // prfum (unscaled offset)
SetA64("11011000xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Pfrm, InstEmit.Pfrm, OpCodeMemLit.Create); SetA64("11011000xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Prfm, InstEmit.Prfm, OpCodeMemLit.Create); // literal
SetA64("11111000101xxxxxxxxx10xxxxxxxxxx", InstName.Prfm, InstEmit.Prfm, OpCodeMemReg.Create); // register
SetA64("x101101011000000000000xxxxxxxxxx", InstName.Rbit, InstEmit.Rbit, OpCodeAlu.Create); SetA64("x101101011000000000000xxxxxxxxxx", InstName.Rbit, InstEmit.Rbit, OpCodeAlu.Create);
SetA64("1101011001011111000000xxxxx00000", InstName.Ret, InstEmit.Ret, OpCodeBReg.Create); SetA64("1101011001011111000000xxxxx00000", InstName.Ret, InstEmit.Ret, OpCodeBReg.Create);
SetA64("x101101011000000000001xxxxxxxxxx", InstName.Rev16, InstEmit.Rev16, OpCodeAlu.Create); SetA64("x101101011000000000001xxxxxxxxxx", InstName.Rev16, InstEmit.Rev16, OpCodeAlu.Create);
@ -311,6 +312,7 @@ namespace ARMeilleure.Decoders
SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, InstEmit.Fmax_V, OpCodeSimdReg.Create); SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, InstEmit.Fmax_V, OpCodeSimdReg.Create);
SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, InstEmit.Fmaxnm_S, OpCodeSimdReg.Create); SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, InstEmit.Fmaxnm_S, OpCodeSimdReg.Create);
SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, InstEmit.Fmaxnm_V, OpCodeSimdReg.Create); SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, InstEmit.Fmaxnm_V, OpCodeSimdReg.Create);
SetA64("011111100x110000110010xxxxxxxxxx", InstName.Fmaxnmp_S, InstEmit.Fmaxnmp_S, OpCodeSimd.Create);
SetA64("0>1011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnmp_V, InstEmit.Fmaxnmp_V, OpCodeSimdReg.Create); SetA64("0>1011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnmp_V, InstEmit.Fmaxnmp_V, OpCodeSimdReg.Create);
SetA64("0110111000110000110010xxxxxxxxxx", InstName.Fmaxnmv_V, InstEmit.Fmaxnmv_V, OpCodeSimd.Create); SetA64("0110111000110000110010xxxxxxxxxx", InstName.Fmaxnmv_V, InstEmit.Fmaxnmv_V, OpCodeSimd.Create);
SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, InstEmit.Fmaxp_V, OpCodeSimdReg.Create); SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, InstEmit.Fmaxp_V, OpCodeSimdReg.Create);
@ -319,6 +321,7 @@ namespace ARMeilleure.Decoders
SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, InstEmit.Fmin_V, OpCodeSimdReg.Create); SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, InstEmit.Fmin_V, OpCodeSimdReg.Create);
SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, InstEmit.Fminnm_S, OpCodeSimdReg.Create); SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, InstEmit.Fminnm_S, OpCodeSimdReg.Create);
SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, InstEmit.Fminnm_V, OpCodeSimdReg.Create); SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, InstEmit.Fminnm_V, OpCodeSimdReg.Create);
SetA64("011111101x110000110010xxxxxxxxxx", InstName.Fminnmp_S, InstEmit.Fminnmp_S, OpCodeSimd.Create);
SetA64("0>1011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnmp_V, InstEmit.Fminnmp_V, OpCodeSimdReg.Create); SetA64("0>1011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnmp_V, InstEmit.Fminnmp_V, OpCodeSimdReg.Create);
SetA64("0110111010110000110010xxxxxxxxxx", InstName.Fminnmv_V, InstEmit.Fminnmv_V, OpCodeSimd.Create); SetA64("0110111010110000110010xxxxxxxxxx", InstName.Fminnmv_V, InstEmit.Fminnmv_V, OpCodeSimd.Create);
SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, InstEmit.Fminp_V, OpCodeSimdReg.Create); SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, InstEmit.Fminp_V, OpCodeSimdReg.Create);

View file

@ -102,7 +102,7 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Pfrm(ArmEmitterContext context) public static void Prfm(ArmEmitterContext context)
{ {
// Memory Prefetch, execute as no-op. // Memory Prefetch, execute as no-op.
} }

View file

@ -120,24 +120,155 @@ namespace ARMeilleure.Instructions
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand res = context.VectorZero();
int elems = op.GetBytesCount() >> op.Size;
int eSize = 8 << op.Size; int eSize = 8 << op.Size;
for (int index = 0; index < elems; index++) Operand res = eSize switch {
8 => Clz_V_I8 (context, GetVec(op.Rn)),
16 => Clz_V_I16(context, GetVec(op.Rn)),
32 => Clz_V_I32(context, GetVec(op.Rn)),
_ => null
};
if (res != null)
{ {
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size); if (op.RegisterSize == RegisterSize.Simd64)
{
res = context.VectorZeroUpper64(res);
}
}
else
{
int elems = op.GetBytesCount() >> op.Size;
Operand de = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)), ne, Const(eSize)); res = context.VectorZero();
res = EmitVectorInsert(context, res, de, index, op.Size); for (int index = 0; index < elems; index++)
{
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
Operand de = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)), ne, Const(eSize));
res = EmitVectorInsert(context, res, de, index, op.Size);
}
} }
context.Copy(GetVec(op.Rd), res); context.Copy(GetVec(op.Rd), res);
} }
private static Operand Clz_V_I8(ArmEmitterContext context, Operand arg)
{
if (!Optimizations.UseSsse3)
{
return null;
}
// CLZ nibble table.
Operand clzTable = X86GetScalar(context, 0x01_01_01_01_02_02_03_04);
Operand maskLow = X86GetAllElements(context, 0x0f_0f_0f_0f);
Operand c04 = X86GetAllElements(context, 0x04_04_04_04);
// CLZ of low 4 bits of elements in arg.
Operand loClz = context.AddIntrinsic(Intrinsic.X86Pshufb, clzTable, arg);
// Get the high 4 bits of elements in arg.
Operand hiArg = context.AddIntrinsic(Intrinsic.X86Psrlw, arg, Const(4));
hiArg = context.AddIntrinsic(Intrinsic.X86Pand, hiArg, maskLow);
// CLZ of high 4 bits of elements in arg.
Operand hiClz = context.AddIntrinsic(Intrinsic.X86Pshufb, clzTable, hiArg);
// If high 4 bits are not all zero, we discard the CLZ of the low 4 bits.
Operand mask = context.AddIntrinsic(Intrinsic.X86Pcmpeqb, hiClz, c04);
loClz = context.AddIntrinsic(Intrinsic.X86Pand, loClz, mask);
return context.AddIntrinsic(Intrinsic.X86Paddb, loClz, hiClz);
}
private static Operand Clz_V_I16(ArmEmitterContext context, Operand arg)
{
if (!Optimizations.UseSsse3)
{
return null;
}
Operand maskSwap = X86GetElements(context, 0x80_0f_80_0d_80_0b_80_09, 0x80_07_80_05_80_03_80_01);
Operand maskLow = X86GetAllElements(context, 0x00ff_00ff);
Operand c0008 = X86GetAllElements(context, 0x0008_0008);
// CLZ pair of high 8 and low 8 bits of elements in arg.
Operand hiloClz = Clz_V_I8(context, arg);
// Get CLZ of low 8 bits in each pair.
Operand loClz = context.AddIntrinsic(Intrinsic.X86Pand, hiloClz, maskLow);
// Get CLZ of high 8 bits in each pair.
Operand hiClz = context.AddIntrinsic(Intrinsic.X86Pshufb, hiloClz, maskSwap);
// If high 8 bits are not all zero, we discard the CLZ of the low 8 bits.
Operand mask = context.AddIntrinsic(Intrinsic.X86Pcmpeqw, hiClz, c0008);
loClz = context.AddIntrinsic(Intrinsic.X86Pand, loClz, mask);
return context.AddIntrinsic(Intrinsic.X86Paddw, loClz, hiClz);
}
private static Operand Clz_V_I32(ArmEmitterContext context, Operand arg)
{
// TODO: Use vplzcntd when AVX-512 is supported.
if (!Optimizations.UseSse2)
{
return null;
}
Operand AddVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Paddd, op0, op1);
Operand SubVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Psubd, op0, op1);
Operand ShiftRightVectorUI32(Operand op0, int imm8) => context.AddIntrinsic(Intrinsic.X86Psrld, op0, Const(imm8));
Operand OrVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Por, op0, op1);
Operand AndVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Pand, op0, op1);
Operand NotVector(Operand op0) => context.AddIntrinsic(Intrinsic.X86Pandn, op0, context.VectorOne());
Operand c55555555 = X86GetAllElements(context, 0x55555555);
Operand c33333333 = X86GetAllElements(context, 0x33333333);
Operand c0f0f0f0f = X86GetAllElements(context, 0x0f0f0f0f);
Operand c0000003f = X86GetAllElements(context, 0x0000003f);
Operand tmp0;
Operand tmp1;
Operand res;
// Set all bits after highest set bit to 1.
res = OrVector(ShiftRightVectorUI32(arg, 1), arg);
res = OrVector(ShiftRightVectorUI32(res, 2), res);
res = OrVector(ShiftRightVectorUI32(res, 4), res);
res = OrVector(ShiftRightVectorUI32(res, 8), res);
res = OrVector(ShiftRightVectorUI32(res, 16), res);
// Make leading 0s into leading 1s.
res = NotVector(res);
// Count leading 1s, which is the population count.
tmp0 = ShiftRightVectorUI32(res, 1);
tmp0 = AndVector(tmp0, c55555555);
res = SubVectorI32(res, tmp0);
tmp0 = ShiftRightVectorUI32(res, 2);
tmp0 = AndVector(tmp0, c33333333);
tmp1 = AndVector(res, c33333333);
res = AddVectorI32(tmp0, tmp1);
tmp0 = ShiftRightVectorUI32(res, 4);
tmp0 = AddVectorI32(tmp0, res);
res = AndVector(tmp0, c0f0f0f0f);
tmp0 = ShiftRightVectorUI32(res, 8);
res = AddVectorI32(tmp0, res);
tmp0 = ShiftRightVectorUI32(res, 16);
res = AddVectorI32(tmp0, res);
res = AndVector(res, c0000003f);
return res;
}
public static void Cnt_V(ArmEmitterContext context) public static void Cnt_V(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp; OpCodeSimd op = (OpCodeSimd)context.CurrOp;
@ -347,19 +478,17 @@ namespace ARMeilleure.Instructions
public static void Faddp_S(ArmEmitterContext context) public static void Faddp_S(ArmEmitterContext context)
{ {
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
int sizeF = op.Size & 1;
if (Optimizations.FastFP && Optimizations.UseSse3) if (Optimizations.FastFP && Optimizations.UseSse3)
{ {
if (sizeF == 0) OpCodeSimd op = (OpCodeSimd)context.CurrOp;
if ((op.Size & 1) == 0)
{ {
Operand res = context.AddIntrinsic(Intrinsic.X86Haddps, GetVec(op.Rn), GetVec(op.Rn)); Operand res = context.AddIntrinsic(Intrinsic.X86Haddps, GetVec(op.Rn), GetVec(op.Rn));
context.Copy(GetVec(op.Rd), context.VectorZeroUpper96(res)); context.Copy(GetVec(op.Rd), context.VectorZeroUpper96(res));
} }
else /* if (sizeF == 1) */ else /* if ((op.Size & 1) == 1) */
{ {
Operand res = context.AddIntrinsic(Intrinsic.X86Haddpd, GetVec(op.Rn), GetVec(op.Rn)); Operand res = context.AddIntrinsic(Intrinsic.X86Haddpd, GetVec(op.Rn), GetVec(op.Rn));
@ -368,14 +497,10 @@ namespace ARMeilleure.Instructions
} }
else else
{ {
OperandType type = sizeF != 0 ? OperandType.FP64 : OperandType.FP32; EmitScalarPairwiseOpF(context, (op1, op2) =>
{
Operand ne0 = context.VectorExtract(type, GetVec(op.Rn), 0); return EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd), op1, op2);
Operand ne1 = context.VectorExtract(type, GetVec(op.Rn), 1); });
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd), ne0, ne1);
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
} }
} }
@ -552,6 +677,24 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fmaxnmp_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse41)
{
EmitSse2ScalarPairwiseOpF(context, (op1, op2) =>
{
return EmitSse41MaxMinNumOpF(context, isMaxNum: true, scalar: true, op1, op2);
});
}
else
{
EmitScalarPairwiseOpF(context, (op1, op2) =>
{
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum), op1, op2);
});
}
}
public static void Fmaxnmp_V(ArmEmitterContext context) public static void Fmaxnmp_V(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse41) if (Optimizations.FastFP && Optimizations.UseSse41)
@ -708,6 +851,24 @@ namespace ARMeilleure.Instructions
} }
} }
public static void Fminnmp_S(ArmEmitterContext context)
{
if (Optimizations.FastFP && Optimizations.UseSse41)
{
EmitSse2ScalarPairwiseOpF(context, (op1, op2) =>
{
return EmitSse41MaxMinNumOpF(context, isMaxNum: false, scalar: true, op1, op2);
});
}
else
{
EmitScalarPairwiseOpF(context, (op1, op2) =>
{
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum), op1, op2);
});
}
}
public static void Fminnmp_V(ArmEmitterContext context) public static void Fminnmp_V(ArmEmitterContext context)
{ {
if (Optimizations.FastFP && Optimizations.UseSse41) if (Optimizations.FastFP && Optimizations.UseSse41)

View file

@ -209,6 +209,11 @@ namespace ARMeilleure.Instructions
} }
public static Operand X86GetElements(ArmEmitterContext context, long e1, long e0) public static Operand X86GetElements(ArmEmitterContext context, long e1, long e0)
{
return X86GetElements(context, (ulong)e1, (ulong)e0);
}
public static Operand X86GetElements(ArmEmitterContext context, ulong e1, ulong e0)
{ {
Operand vector0 = context.VectorCreateScalar(Const(e0)); Operand vector0 = context.VectorCreateScalar(Const(e0));
Operand vector1 = context.VectorCreateScalar(Const(e1)); Operand vector1 = context.VectorCreateScalar(Const(e1));
@ -1118,6 +1123,49 @@ namespace ARMeilleure.Instructions
context.Copy(GetVec(op.Rd), context.VectorZeroUpper96(res)); context.Copy(GetVec(op.Rd), context.VectorZeroUpper96(res));
} }
public static void EmitScalarPairwiseOpF(ArmEmitterContext context, Func2I emit)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
OperandType type = (op.Size & 1) != 0 ? OperandType.FP64 : OperandType.FP32;
Operand ne0 = context.VectorExtract(type, GetVec(op.Rn), 0);
Operand ne1 = context.VectorExtract(type, GetVec(op.Rn), 1);
Operand res = context.VectorInsert(context.VectorZero(), emit(ne0, ne1), 0);
context.Copy(GetVec(op.Rd), res);
}
public static void EmitSse2ScalarPairwiseOpF(ArmEmitterContext context, Func2I emit)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
Operand op0, op1;
if ((op.Size & 1) == 0)
{
const int sm0 = 2 << 6 | 2 << 4 | 2 << 2 | 0 << 0;
const int sm1 = 2 << 6 | 2 << 4 | 2 << 2 | 1 << 0;
Operand zeroN = context.VectorZeroUpper64(n);
op0 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(sm0));
op1 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(sm1));
}
else /* if ((op.Size & 1) == 1) */
{
Operand zero = context.VectorZero();
op0 = context.AddIntrinsic(Intrinsic.X86Movlhps, n, zero);
op1 = context.AddIntrinsic(Intrinsic.X86Movhlps, zero, n);
}
context.Copy(GetVec(op.Rd), emit(op0, op1));
}
public static void EmitVectorPairwiseOpF(ArmEmitterContext context, Func2I emit) public static void EmitVectorPairwiseOpF(ArmEmitterContext context, Func2I emit)
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;

View file

@ -68,7 +68,7 @@ namespace ARMeilleure.Instructions
Nop, Nop,
Orn, Orn,
Orr, Orr,
Pfrm, Prfm,
Rbit, Rbit,
Ret, Ret,
Rev16, Rev16,
@ -212,6 +212,7 @@ namespace ARMeilleure.Instructions
Fmax_V, Fmax_V,
Fmaxnm_S, Fmaxnm_S,
Fmaxnm_V, Fmaxnm_V,
Fmaxnmp_S,
Fmaxnmp_V, Fmaxnmp_V,
Fmaxnmv_V, Fmaxnmv_V,
Fmaxp_V, Fmaxp_V,
@ -220,6 +221,7 @@ namespace ARMeilleure.Instructions
Fmin_V, Fmin_V,
Fminnm_S, Fminnm_S,
Fminnm_V, Fminnm_V,
Fminnmp_S,
Fminnmp_V, Fminnmp_V,
Fminnmv_V, Fminnmv_V,
Fminp_V, Fminp_V,

View file

@ -108,6 +108,7 @@ namespace ARMeilleure.IntermediateRepresentation
X86Popcnt, X86Popcnt,
X86Por, X86Por,
X86Pshufb, X86Pshufb,
X86Pshufd,
X86Pslld, X86Pslld,
X86Pslldq, X86Pslldq,
X86Psllq, X86Psllq,

View file

@ -23,7 +23,7 @@ namespace ARMeilleure.Translation.PTC
{ {
private const string HeaderMagicString = "PTChd\0\0\0"; private const string HeaderMagicString = "PTChd\0\0\0";
private const uint InternalVersion = 1817; //! To be incremented manually for each change to the ARMeilleure project. private const uint InternalVersion = 1968; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0"; private const string ActualDir = "0";
private const string BackupDir = "1"; private const string BackupDir = "1";

View file

@ -0,0 +1,35 @@
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Common.System
{
public class DisplaySleep
{
[Flags]
enum EXECUTION_STATE : uint
{
ES_CONTINUOUS = 0x80000000,
ES_DISPLAY_REQUIRED = 0x00000002,
ES_SYSTEM_REQUIRED = 0x00000001
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
static public void Prevent()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED);
}
}
static public void Restore()
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);
}
}
}
}

View file

@ -131,7 +131,7 @@ namespace Ryujinx.Cpu
/// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception> /// <exception cref="InvalidMemoryRegionException">Throw for unhandled invalid or unmapped memory accesses</exception>
public T Read<T>(ulong va) where T : unmanaged public T Read<T>(ulong va) where T : unmanaged
{ {
return MemoryMarshal.Cast<byte, T>(GetSpan(va, Unsafe.SizeOf<T>()))[0]; return MemoryMarshal.Cast<byte, T>(GetSpan(va, Unsafe.SizeOf<T>(), true))[0];
} }
/// <summary> /// <summary>

View file

@ -18,6 +18,7 @@ namespace Ryujinx.Cpu.Tracking
public void QueryModified(Action<ulong, ulong> modifiedAction) => _impl.QueryModified(modifiedAction); public void QueryModified(Action<ulong, ulong> modifiedAction) => _impl.QueryModified(modifiedAction);
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction) => _impl.QueryModified(address, size, modifiedAction); public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction) => _impl.QueryModified(address, size, modifiedAction);
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction, int sequenceNumber) => _impl.QueryModified(address, size, modifiedAction, sequenceNumber); public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction, int sequenceNumber) => _impl.QueryModified(address, size, modifiedAction, sequenceNumber);
public void RegisterAction(ulong address, ulong size, RegionSignal action) => _impl.RegisterAction(address, size, action);
public void SignalWrite() => _impl.SignalWrite(); public void SignalWrite() => _impl.SignalWrite();
} }
} }

View file

@ -15,6 +15,7 @@ namespace Ryujinx.Cpu.Tracking
} }
public void Dispose() => _impl.Dispose(); public void Dispose() => _impl.Dispose();
public void RegisterAction(RegionSignal action) => _impl.RegisterAction(action);
public void QueryModified(Action<ulong, ulong> modifiedAction) => _impl.QueryModified(modifiedAction); public void QueryModified(Action<ulong, ulong> modifiedAction) => _impl.QueryModified(modifiedAction);
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction) => _impl.QueryModified(address, size, modifiedAction); public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction) => _impl.QueryModified(address, size, modifiedAction);
public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction, int sequenceNumber) => _impl.QueryModified(address, size, modifiedAction, sequenceNumber); public void QueryModified(ulong address, ulong size, Action<ulong, ulong> modifiedAction, int sequenceNumber) => _impl.QueryModified(address, size, modifiedAction, sequenceNumber);

View file

@ -68,8 +68,7 @@ namespace Ryujinx.Graphics.GAL
void SetSampler(int binding, ISampler sampler); void SetSampler(int binding, ISampler sampler);
void SetScissorEnable(int index, bool enable); void SetScissor(int index, bool enable, int x, int y, int width, int height);
void SetScissor(int index, int x, int y, int width, int height);
void SetStencilTest(StencilTestDescriptor stencilTest); void SetStencilTest(StencilTestDescriptor stencilTest);

View file

@ -21,6 +21,8 @@ namespace Ryujinx.Graphics.GAL
ISampler CreateSampler(SamplerCreateInfo info); ISampler CreateSampler(SamplerCreateInfo info);
ITexture CreateTexture(TextureCreateInfo info, float scale); ITexture CreateTexture(TextureCreateInfo info, float scale);
void CreateSync(ulong id);
void DeleteBuffer(BufferHandle buffer); void DeleteBuffer(BufferHandle buffer);
byte[] GetBufferData(BufferHandle buffer, int offset, int size); byte[] GetBufferData(BufferHandle buffer, int offset, int size);
@ -39,6 +41,8 @@ namespace Ryujinx.Graphics.GAL
void ResetCounter(CounterType type); void ResetCounter(CounterType type);
void WaitSync(ulong id);
void Initialize(GraphicsDebugLevel logLevel); void Initialize(GraphicsDebugLevel logLevel);
} }
} }

View file

@ -1,6 +1,8 @@
using System;
namespace Ryujinx.Graphics.GAL namespace Ryujinx.Graphics.GAL
{ {
public struct VertexAttribDescriptor public struct VertexAttribDescriptor : IEquatable<VertexAttribDescriptor>
{ {
public int BufferIndex { get; } public int BufferIndex { get; }
public int Offset { get; } public int Offset { get; }
@ -16,5 +18,23 @@ namespace Ryujinx.Graphics.GAL
IsZero = isZero; IsZero = isZero;
Format = format; Format = format;
} }
public override bool Equals(object obj)
{
return obj is VertexAttribDescriptor other && Equals(other);
}
public bool Equals(VertexAttribDescriptor other)
{
return BufferIndex == other.BufferIndex &&
Offset == other.Offset &&
IsZero == other.IsZero &&
Format == other.Format;
}
public override int GetHashCode()
{
return HashCode.Combine(BufferIndex, Offset, IsZero, Format);
}
} }
} }

View file

@ -97,7 +97,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
SbDescriptor sbDescriptor = _context.PhysicalMemory.Read<SbDescriptor>(sbDescAddress); SbDescriptor sbDescriptor = _context.PhysicalMemory.Read<SbDescriptor>(sbDescAddress);
BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size); BufferManager.SetComputeStorageBuffer(sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
} }
BufferManager.SetComputeStorageBufferBindings(info.SBuffers); BufferManager.SetComputeStorageBufferBindings(info.SBuffers);

View file

@ -39,6 +39,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
{ nameof(GPFifoClassState.Semaphored), new RwCallback(Semaphored, null) }, { nameof(GPFifoClassState.Semaphored), new RwCallback(Semaphored, null) },
{ nameof(GPFifoClassState.Syncpointb), new RwCallback(Syncpointb, null) }, { nameof(GPFifoClassState.Syncpointb), new RwCallback(Syncpointb, null) },
{ nameof(GPFifoClassState.WaitForIdle), new RwCallback(WaitForIdle, null) }, { nameof(GPFifoClassState.WaitForIdle), new RwCallback(WaitForIdle, null) },
{ nameof(GPFifoClassState.SetReference), new RwCallback(SetReference, null) },
{ nameof(GPFifoClassState.LoadMmeInstructionRam), new RwCallback(LoadMmeInstructionRam, null) }, { nameof(GPFifoClassState.LoadMmeInstructionRam), new RwCallback(LoadMmeInstructionRam, null) },
{ nameof(GPFifoClassState.LoadMmeStartAddressRam), new RwCallback(LoadMmeStartAddressRam, null) }, { nameof(GPFifoClassState.LoadMmeStartAddressRam), new RwCallback(LoadMmeStartAddressRam, null) },
{ nameof(GPFifoClassState.SetMmeShadowRamControl), new RwCallback(SetMmeShadowRamControl, null) } { nameof(GPFifoClassState.SetMmeShadowRamControl), new RwCallback(SetMmeShadowRamControl, null) }
@ -136,6 +137,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
} }
else if (operation == SyncpointbOperation.Incr) else if (operation == SyncpointbOperation.Incr)
{ {
_context.CreateHostSyncIfNeeded();
_context.Synchronization.IncrementSyncpoint(syncpointId); _context.Synchronization.IncrementSyncpoint(syncpointId);
} }
@ -150,6 +152,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
{ {
_context.Methods.PerformDeferredDraws(); _context.Methods.PerformDeferredDraws();
_context.Renderer.Pipeline.Barrier(); _context.Renderer.Pipeline.Barrier();
_context.CreateHostSyncIfNeeded();
}
/// <summary>
/// Used as an indirect data barrier on NVN. When used, access to previously written data must be coherent.
/// </summary>
/// <param name="argument">Method call argument</param>
public void SetReference(int argument)
{
_context.CreateHostSyncIfNeeded();
} }
/// <summary> /// <summary>

View file

@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
{ {
if (Words == null) if (Words == null)
{ {
Words = MemoryMarshal.Cast<byte, int>(context.MemoryManager.GetSpan(EntryAddress, (int)EntryCount * 4)).ToArray(); Words = MemoryMarshal.Cast<byte, int>(context.MemoryManager.GetSpan(EntryAddress, (int)EntryCount * 4, true)).ToArray();
} }
} }
} }

View file

@ -71,11 +71,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
ICounterEvent evt = FindEvent(gpuVa); ICounterEvent evt = FindEvent(gpuVa);
ICounterEvent evt2 = FindEvent(gpuVa + 16); ICounterEvent evt2 = FindEvent(gpuVa + 16);
if (evt == null && evt2 == null)
{
return ConditionalRenderEnabled.False;
}
bool useHost; bool useHost;
if (evt != null && evt2 == null) if (evt != null && evt2 == null)
@ -86,10 +81,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
useHost = _context.Renderer.Pipeline.TryHostConditionalRendering(evt2, _context.MemoryManager.Read<ulong>(gpuVa), isEqual); useHost = _context.Renderer.Pipeline.TryHostConditionalRendering(evt2, _context.MemoryManager.Read<ulong>(gpuVa), isEqual);
} }
else else if (evt != null && evt2 != null)
{ {
useHost = _context.Renderer.Pipeline.TryHostConditionalRendering(evt, evt2, isEqual); useHost = _context.Renderer.Pipeline.TryHostConditionalRendering(evt, evt2, isEqual);
} }
else
{
useHost = false;
}
if (useHost) if (useHost)
{ {

View file

@ -13,6 +13,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
uint syncpointId = (uint)(argument) & 0xFFFF; uint syncpointId = (uint)(argument) & 0xFFFF;
_context.CreateHostSyncIfNeeded();
_context.Renderer.UpdateCounters(); // Poll the query counters, the game may want an updated result. _context.Renderer.UpdateCounters(); // Poll the query counters, the game may want an updated result.
_context.Synchronization.IncrementSyncpoint(syncpointId); _context.Synchronization.IncrementSyncpoint(syncpointId);
} }

View file

@ -61,6 +61,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
context.MemoryManager.MemoryUnmapped += _counterCache.MemoryUnmappedHandler; context.MemoryManager.MemoryUnmapped += _counterCache.MemoryUnmappedHandler;
context.MemoryManager.MemoryUnmapped += TextureManager.MemoryUnmappedHandler; context.MemoryManager.MemoryUnmapped += TextureManager.MemoryUnmappedHandler;
context.MemoryManager.MemoryUnmapped += BufferManager.MemoryUnmappedHandler;
} }
/// <summary> /// <summary>
@ -333,7 +334,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
SbDescriptor sbDescriptor = _context.PhysicalMemory.Read<SbDescriptor>(sbDescAddress); SbDescriptor sbDescriptor = _context.PhysicalMemory.Read<SbDescriptor>(sbDescAddress);
BufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size); BufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
} }
} }
} }
@ -435,8 +436,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
bool enable = scissor.Enable && (scissor.X1 != 0 || scissor.Y1 != 0 || scissor.X2 != 0xffff || scissor.Y2 != 0xffff); bool enable = scissor.Enable && (scissor.X1 != 0 || scissor.Y1 != 0 || scissor.X2 != 0xffff || scissor.Y2 != 0xffff);
_context.Renderer.Pipeline.SetScissorEnable(index, enable);
if (enable) if (enable)
{ {
int x = scissor.X1; int x = scissor.X1;
@ -453,7 +452,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
height = (int)Math.Ceiling(height * scale); height = (int)Math.Ceiling(height * scale);
} }
_context.Renderer.Pipeline.SetScissor(index, x, y, width, height); _context.Renderer.Pipeline.SetScissor(index, true, x, y, width, height);
}
else
{
_context.Renderer.Pipeline.SetScissor(index, false, 0, 0, 0, 0);
} }
} }
} }

View file

@ -4,6 +4,7 @@ using Ryujinx.Graphics.Gpu.Engine.GPFifo;
using Ryujinx.Graphics.Gpu.Memory; using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Gpu.Synchronization; using Ryujinx.Graphics.Gpu.Synchronization;
using System; using System;
using System.Collections.Generic;
using System.Threading; using System.Threading;
namespace Ryujinx.Graphics.Gpu namespace Ryujinx.Graphics.Gpu
@ -59,6 +60,18 @@ namespace Ryujinx.Graphics.Gpu
/// </summary> /// </summary>
internal int SequenceNumber { get; private set; } internal int SequenceNumber { get; private set; }
/// <summary>
/// Internal sync number, used to denote points at which host synchronization can be requested.
/// </summary>
internal ulong SyncNumber { get; private set; }
/// <summary>
/// Actions to be performed when a CPU waiting sync point is triggered.
/// If there are more than 0 items when this happens, a host sync object will be generated for the given <see cref="SyncNumber"/>,
/// and the SyncNumber will be incremented.
/// </summary>
internal List<Action> SyncActions { get; }
private readonly Lazy<Capabilities> _caps; private readonly Lazy<Capabilities> _caps;
/// <summary> /// <summary>
@ -87,6 +100,8 @@ namespace Ryujinx.Graphics.Gpu
_caps = new Lazy<Capabilities>(Renderer.GetCapabilities); _caps = new Lazy<Capabilities>(Renderer.GetCapabilities);
HostInitalized = new ManualResetEvent(false); HostInitalized = new ManualResetEvent(false);
SyncActions = new List<Action>();
} }
/// <summary> /// <summary>
@ -118,6 +133,37 @@ namespace Ryujinx.Graphics.Gpu
PhysicalMemory = new PhysicalMemory(cpuMemory); PhysicalMemory = new PhysicalMemory(cpuMemory);
} }
/// <summary>
/// Registers an action to be performed the next time a syncpoint is incremented.
/// This will also ensure a host sync object is created, and <see cref="SyncNumber"/> is incremented.
/// </summary>
/// <param name="action">The action to be performed on sync object creation</param>
public void RegisterSyncAction(Action action)
{
SyncActions.Add(action);
}
/// <summary>
/// Creates a host sync object if there are any pending sync actions. The actions will then be called.
/// If no actions are present, a host sync object is not created.
/// </summary>
public void CreateHostSyncIfNeeded()
{
if (SyncActions.Count > 0)
{
Renderer.CreateSync(SyncNumber);
SyncNumber++;
foreach (Action action in SyncActions)
{
action();
}
SyncActions.Clear();
}
}
/// <summary> /// <summary>
/// Disposes all GPU resources currently cached. /// Disposes all GPU resources currently cached.
/// It's an error to push any GPU commands after disposal. /// It's an error to push any GPU commands after disposal.

View file

@ -646,7 +646,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// - BC4/BC5 is not supported on 3D textures. // - BC4/BC5 is not supported on 3D textures.
if (!_context.Capabilities.SupportsAstcCompression && Info.FormatInfo.Format.IsAstc()) if (!_context.Capabilities.SupportsAstcCompression && Info.FormatInfo.Format.IsAstc())
{ {
if (!AstcDecoder.TryDecodeToRgba8( if (!AstcDecoder.TryDecodeToRgba8P(
data.ToArray(), data.ToArray(),
Info.FormatInfo.BlockWidth, Info.FormatInfo.BlockWidth,
Info.FormatInfo.BlockHeight, Info.FormatInfo.BlockHeight,

View file

@ -685,14 +685,28 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
Texture overlap = _textureOverlaps[index]; Texture overlap = _textureOverlaps[index];
bool rangeMatches = range != null ? overlap.Range.Equals(range.Value) : overlap.Info.GpuAddress == info.GpuAddress;
if (!rangeMatches)
{
continue;
}
TextureMatchQuality matchQuality = overlap.IsExactMatch(info, flags); TextureMatchQuality matchQuality = overlap.IsExactMatch(info, flags);
if (matchQuality != TextureMatchQuality.NoMatch)
{
// If the parameters match, we need to make sure the texture is mapped to the same memory regions.
// If a range of memory was supplied, just check if the ranges match.
if (range != null && !overlap.Range.Equals(range.Value))
{
continue;
}
// If no range was supplied, we can check if the GPU virtual address match. If they do,
// we know the textures are located at the same memory region.
// If they don't, it may still be mapped to the same physical region, so we
// do a more expensive check to tell if they are mapped into the same physical regions.
if (overlap.Info.GpuAddress != info.GpuAddress && !_context.MemoryManager.CompareRange(overlap.Range, info.GpuAddress))
{
continue;
}
}
if (matchQuality == TextureMatchQuality.Perfect) if (matchQuality == TextureMatchQuality.Perfect)
{ {
texture = overlap; texture = overlap;

View file

@ -223,7 +223,7 @@ namespace Ryujinx.Graphics.Gpu.Image
layerSize = sizeInfo.LayerSize; layerSize = sizeInfo.LayerSize;
if (minLod != 0) if (minLod != 0 && minLod < levels)
{ {
// If the base level is not zero, we additionally add the mip level offset // If the base level is not zero, we additionally add the mip level offset
// to the address, this allows the texture manager to find the base level from the // to the address, this allows the texture manager to find the base level from the

View file

@ -1,6 +1,7 @@
using Ryujinx.Cpu.Tracking; using Ryujinx.Cpu.Tracking;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Memory.Range; using Ryujinx.Memory.Range;
using Ryujinx.Memory.Tracking;
using System; using System;
namespace Ryujinx.Graphics.Gpu.Memory namespace Ryujinx.Graphics.Gpu.Memory
@ -34,12 +35,28 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary> /// </summary>
public ulong EndAddress => Address + Size; public ulong EndAddress => Address + Size;
/// <summary>
/// Ranges of the buffer that have been modified on the GPU.
/// Ranges defined here cannot be updated from CPU until a CPU waiting sync point is reached.
/// Then, write tracking will signal, wait for GPU sync (generated at the syncpoint) and flush these regions.
/// </summary>
/// <remarks>
/// This is null until at least one modification occurs.
/// </remarks>
private BufferModifiedRangeList _modifiedRanges = null;
private CpuMultiRegionHandle _memoryTrackingGranular; private CpuMultiRegionHandle _memoryTrackingGranular;
private CpuRegionHandle _memoryTracking; private CpuRegionHandle _memoryTracking;
private readonly RegionSignal _externalFlushDelegate;
private readonly Action<ulong, ulong> _loadDelegate;
private readonly Action<ulong, ulong> _modifiedDelegate; private readonly Action<ulong, ulong> _modifiedDelegate;
private int _sequenceNumber; private int _sequenceNumber;
private bool _useGranular; private bool _useGranular;
private bool _syncActionRegistered;
/// <summary> /// <summary>
/// Creates a new instance of the buffer. /// Creates a new instance of the buffer.
@ -66,9 +83,26 @@ namespace Ryujinx.Graphics.Gpu.Memory
_memoryTracking = context.PhysicalMemory.BeginTracking(address, size); _memoryTracking = context.PhysicalMemory.BeginTracking(address, size);
} }
_externalFlushDelegate = new RegionSignal(ExternalFlush);
_loadDelegate = new Action<ulong, ulong>(LoadRegion);
_modifiedDelegate = new Action<ulong, ulong>(RegionModified); _modifiedDelegate = new Action<ulong, ulong>(RegionModified);
} }
/// <summary>
/// Gets a sub-range from the buffer, from a start address till the end of the buffer.
/// </summary>
/// <remarks>
/// This can be used to bind and use sub-ranges of the buffer on the host API.
/// </remarks>
/// <param name="address">Start address of the sub-range, must be greater than or equal to the buffer address</param>
/// <returns>The buffer sub-range</returns>
public BufferRange GetRange(ulong address)
{
ulong offset = address - Address;
return new BufferRange(Handle, (int)offset, (int)(Size - offset));
}
/// <summary> /// <summary>
/// Gets a sub-range from the buffer. /// Gets a sub-range from the buffer.
/// </summary> /// </summary>
@ -116,12 +150,131 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (_memoryTracking.Dirty && _context.SequenceNumber != _sequenceNumber) if (_memoryTracking.Dirty && _context.SequenceNumber != _sequenceNumber)
{ {
_memoryTracking.Reprotect(); _memoryTracking.Reprotect();
_context.Renderer.SetBufferData(Handle, 0, _context.PhysicalMemory.GetSpan(Address, (int)Size));
if (_modifiedRanges != null)
{
_modifiedRanges.ExcludeModifiedRegions(Address, Size, _loadDelegate);
}
else
{
_context.Renderer.SetBufferData(Handle, 0, _context.PhysicalMemory.GetSpan(Address, (int)Size));
}
_sequenceNumber = _context.SequenceNumber; _sequenceNumber = _context.SequenceNumber;
} }
} }
} }
/// <summary>
/// Ensure that the modified range list exists.
/// </summary>
private void EnsureRangeList()
{
if (_modifiedRanges == null)
{
_modifiedRanges = new BufferModifiedRangeList(_context);
}
}
/// <summary>
/// Signal that the given region of the buffer has been modified.
/// </summary>
/// <param name="address">The start address of the modified region</param>
/// <param name="size">The size of the modified region</param>
public void SignalModified(ulong address, ulong size)
{
EnsureRangeList();
_modifiedRanges.SignalModified(address, size);
if (!_syncActionRegistered)
{
_context.RegisterSyncAction(SyncAction);
_syncActionRegistered = true;
}
}
/// <summary>
/// Indicate that mofifications in a given region of this buffer have been overwritten.
/// </summary>
/// <param name="address">The start address of the region</param>
/// <param name="size">The size of the region</param>
public void ClearModified(ulong address, ulong size)
{
if (_modifiedRanges != null)
{
_modifiedRanges.Clear(address, size);
}
}
/// <summary>
/// Action to be performed when a syncpoint is reached after modification.
/// This will register read/write tracking to flush the buffer from GPU when its memory is used.
/// </summary>
private void SyncAction()
{
_syncActionRegistered = false;
if (_useGranular)
{
_modifiedRanges.GetRanges(Address, Size, (address, size) =>
{
_memoryTrackingGranular.RegisterAction(address, size, _externalFlushDelegate);
SynchronizeMemory(address, size);
});
}
else
{
_memoryTracking.RegisterAction(_externalFlushDelegate);
SynchronizeMemory(Address, Size);
}
}
/// <summary>
/// Inherit modified ranges from another buffer.
/// </summary>
/// <param name="from">The buffer to inherit from</param>
public void InheritModifiedRanges(Buffer from)
{
if (from._modifiedRanges != null)
{
if (from._syncActionRegistered && !_syncActionRegistered)
{
_context.RegisterSyncAction(SyncAction);
_syncActionRegistered = true;
}
EnsureRangeList();
_modifiedRanges.InheritRanges(from._modifiedRanges, (ulong address, ulong size) =>
{
if (_useGranular)
{
_memoryTrackingGranular.RegisterAction(address, size, _externalFlushDelegate);
}
else
{
_memoryTracking.RegisterAction(_externalFlushDelegate);
}
});
}
}
/// <summary>
/// Determine if a given region of the buffer has been modified, and must be flushed.
/// </summary>
/// <param name="address">The start address of the region</param>
/// <param name="size">The size of the region</param>
/// <returns></returns>
public bool IsModified(ulong address, ulong size)
{
if (_modifiedRanges != null)
{
return _modifiedRanges.HasRange(address, size);
}
return false;
}
/// <summary> /// <summary>
/// Indicate that a region of the buffer was modified, and must be loaded from memory. /// Indicate that a region of the buffer was modified, and must be loaded from memory.
/// </summary> /// </summary>
@ -141,6 +294,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
mSize = maxSize; mSize = maxSize;
} }
if (_modifiedRanges != null)
{
_modifiedRanges.ExcludeModifiedRegions(mAddress, mSize, _loadDelegate);
}
else
{
LoadRegion(mAddress, mSize);
}
}
/// <summary>
/// Load a region of the buffer from memory.
/// </summary>
/// <param name="mAddress">Start address of the modified region</param>
/// <param name="mSize">Size of the modified region</param>
private void LoadRegion(ulong mAddress, ulong mSize)
{
int offset = (int)(mAddress - Address); int offset = (int)(mAddress - Address);
_context.Renderer.SetBufferData(Handle, offset, _context.PhysicalMemory.GetSpan(mAddress, (int)mSize)); _context.Renderer.SetBufferData(Handle, offset, _context.PhysicalMemory.GetSpan(mAddress, (int)mSize));
@ -172,15 +342,62 @@ namespace Ryujinx.Graphics.Gpu.Memory
_context.PhysicalMemory.WriteUntracked(address, data); _context.PhysicalMemory.WriteUntracked(address, data);
} }
/// <summary>
/// Align a given address and size region to page boundaries.
/// </summary>
/// <param name="address">The start address of the region</param>
/// <param name="size">The size of the region</param>
/// <returns>The page aligned address and size</returns>
private static (ulong address, ulong size) PageAlign(ulong address, ulong size)
{
ulong pageMask = MemoryManager.PageMask;
ulong rA = address & ~pageMask;
ulong rS = ((address + size + pageMask) & ~pageMask) - rA;
return (rA, rS);
}
/// <summary>
/// Flush modified ranges of the buffer from another thread.
/// This will flush all modifications made before the active SyncNumber was set, and may block to wait for GPU sync.
/// </summary>
/// <param name="address">Address of the memory action</param>
/// <param name="size">Size in bytes</param>
public void ExternalFlush(ulong address, ulong size)
{
_context.Renderer.BackgroundContextAction(() =>
{
var ranges = _modifiedRanges;
if (ranges != null)
{
(address, size) = PageAlign(address, size);
ranges.WaitForAndGetRanges(address, size, Flush);
}
});
}
/// <summary>
/// Called when part of the memory for this buffer has been unmapped.
/// Calls are from non-GPU threads.
/// </summary>
/// <param name="address">Start address of the unmapped region</param>
/// <param name="size">Size of the unmapped region</param>
public void Unmapped(ulong address, ulong size)
{
_modifiedRanges?.Clear(address, size);
}
/// <summary> /// <summary>
/// Disposes the host buffer. /// Disposes the host buffer.
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
_context.Renderer.DeleteBuffer(Handle); _modifiedRanges?.Clear();
_memoryTrackingGranular?.Dispose(); _memoryTrackingGranular?.Dispose();
_memoryTracking?.Dispose(); _memoryTracking?.Dispose();
_context.Renderer.DeleteBuffer(Handle);
} }
} }
} }

View file

@ -1,3 +1,5 @@
using Ryujinx.Graphics.Shader;
namespace Ryujinx.Graphics.Gpu.Memory namespace Ryujinx.Graphics.Gpu.Memory
{ {
/// <summary> /// <summary>
@ -15,15 +17,22 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary> /// </summary>
public ulong Size { get; } public ulong Size { get; }
/// <summary>
/// Buffer usage flags.
/// </summary>
public BufferUsageFlags Flags { get; }
/// <summary> /// <summary>
/// Creates a new buffer region. /// Creates a new buffer region.
/// </summary> /// </summary>
/// <param name="address">Region address</param> /// <param name="address">Region address</param>
/// <param name="size">Region size</param> /// <param name="size">Region size</param>
public BufferBounds(ulong address, ulong size) /// <param name="flags">Buffer usage flags</param>
public BufferBounds(ulong address, ulong size, BufferUsageFlags flags = BufferUsageFlags.None)
{ {
Address = address; Address = address;
Size = size; Size = size;
Flags = flags;
} }
} }
} }

View file

@ -68,9 +68,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="index">Buffer slot</param> /// <param name="index">Buffer slot</param>
/// <param name="address">Region virtual address</param> /// <param name="address">Region virtual address</param>
/// <param name="size">Region size in bytes</param> /// <param name="size">Region size in bytes</param>
public void SetBounds(int index, ulong address, ulong size) /// <param name="flags">Buffer usage flags</param>
public void SetBounds(int index, ulong address, ulong size, BufferUsageFlags flags = BufferUsageFlags.None)
{ {
Buffers[index] = new BufferBounds(address, size); Buffers[index] = new BufferBounds(address, size, flags);
} }
/// <summary> /// <summary>
@ -219,7 +220,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="index">Index of the storage buffer</param> /// <param name="index">Index of the storage buffer</param>
/// <param name="gpuVa">Start GPU virtual address of the buffer</param> /// <param name="gpuVa">Start GPU virtual address of the buffer</param>
/// <param name="size">Size in bytes of the storage buffer</param> /// <param name="size">Size in bytes of the storage buffer</param>
public void SetComputeStorageBuffer(int index, ulong gpuVa, ulong size) /// <param name="flags">Buffer usage flags</param>
public void SetComputeStorageBuffer(int index, ulong gpuVa, ulong size, BufferUsageFlags flags)
{ {
size += gpuVa & ((ulong)_context.Capabilities.StorageBufferOffsetAlignment - 1); size += gpuVa & ((ulong)_context.Capabilities.StorageBufferOffsetAlignment - 1);
@ -227,7 +229,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
ulong address = TranslateAndCreateBuffer(gpuVa, size); ulong address = TranslateAndCreateBuffer(gpuVa, size);
_cpStorageBuffers.SetBounds(index, address, size); _cpStorageBuffers.SetBounds(index, address, size, flags);
} }
/// <summary> /// <summary>
@ -238,7 +240,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="index">Index of the storage buffer</param> /// <param name="index">Index of the storage buffer</param>
/// <param name="gpuVa">Start GPU virtual address of the buffer</param> /// <param name="gpuVa">Start GPU virtual address of the buffer</param>
/// <param name="size">Size in bytes of the storage buffer</param> /// <param name="size">Size in bytes of the storage buffer</param>
public void SetGraphicsStorageBuffer(int stage, int index, ulong gpuVa, ulong size) /// <param name="flags">Buffer usage flags</param>
public void SetGraphicsStorageBuffer(int stage, int index, ulong gpuVa, ulong size, BufferUsageFlags flags)
{ {
size += gpuVa & ((ulong)_context.Capabilities.StorageBufferOffsetAlignment - 1); size += gpuVa & ((ulong)_context.Capabilities.StorageBufferOffsetAlignment - 1);
@ -252,7 +255,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
_gpStorageBuffersDirty = true; _gpStorageBuffersDirty = true;
} }
_gpStorageBuffers[stage].SetBounds(index, address, size); _gpStorageBuffers[stage].SetBounds(index, address, size, flags);
} }
/// <summary> /// <summary>
@ -385,6 +388,30 @@ namespace Ryujinx.Graphics.Gpu.Memory
return mask; return mask;
} }
/// <summary>
/// Handles removal of buffers written to a memory region being unmapped.
/// </summary>
/// <param name="sender">Sender object</param>
/// <param name="e">Event arguments</param>
public void MemoryUnmappedHandler(object sender, UnmapEventArgs e)
{
Buffer[] overlaps = new Buffer[10];
int overlapCount;
ulong address = _context.MemoryManager.Translate(e.Address);
ulong size = e.Size;
lock (_buffers)
{
overlapCount = _buffers.FindOverlaps(address, size, ref overlaps);
}
for (int i = 0; i < overlapCount; i++)
{
overlaps[i].Unmapped(address, size);
}
}
/// <summary> /// <summary>
/// Performs address translation of the GPU virtual address, and creates a /// Performs address translation of the GPU virtual address, and creates a
/// new buffer, if needed, for the specified range. /// new buffer, if needed, for the specified range.
@ -443,7 +470,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// <param name="size">Size in bytes of the buffer</param> /// <param name="size">Size in bytes of the buffer</param>
private void CreateBufferAligned(ulong address, ulong size) private void CreateBufferAligned(ulong address, ulong size)
{ {
int overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref _bufferOverlaps); int overlapsCount;
lock (_buffers)
{
overlapsCount = _buffers.FindOverlapsNonOverlapping(address, size, ref _bufferOverlaps);
}
if (overlapsCount != 0) if (overlapsCount != 0)
{ {
@ -463,15 +495,19 @@ namespace Ryujinx.Graphics.Gpu.Memory
address = Math.Min(address, buffer.Address); address = Math.Min(address, buffer.Address);
endAddress = Math.Max(endAddress, buffer.EndAddress); endAddress = Math.Max(endAddress, buffer.EndAddress);
buffer.SynchronizeMemory(buffer.Address, buffer.Size); lock (_buffers)
{
_buffers.Remove(buffer); _buffers.Remove(buffer);
}
} }
Buffer newBuffer = new Buffer(_context, address, endAddress - address); Buffer newBuffer = new Buffer(_context, address, endAddress - address);
newBuffer.SynchronizeMemory(address, endAddress - address); newBuffer.SynchronizeMemory(address, endAddress - address);
_buffers.Add(newBuffer); lock (_buffers)
{
_buffers.Add(newBuffer);
}
for (int index = 0; index < overlapsCount; index++) for (int index = 0; index < overlapsCount; index++)
{ {
@ -479,7 +515,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
int dstOffset = (int)(buffer.Address - newBuffer.Address); int dstOffset = (int)(buffer.Address - newBuffer.Address);
buffer.SynchronizeMemory(buffer.Address, buffer.Size);
buffer.CopyTo(newBuffer, dstOffset); buffer.CopyTo(newBuffer, dstOffset);
newBuffer.InheritModifiedRanges(buffer);
buffer.Dispose(); buffer.Dispose();
} }
@ -493,7 +532,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
// No overlap, just create a new buffer. // No overlap, just create a new buffer.
Buffer buffer = new Buffer(_context, address, size); Buffer buffer = new Buffer(_context, address, size);
_buffers.Add(buffer); lock (_buffers)
{
_buffers.Add(buffer);
}
} }
ShrinkOverlapsBufferIfNeeded(); ShrinkOverlapsBufferIfNeeded();
@ -549,7 +591,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (bounds.Address != 0) if (bounds.Address != 0)
{ {
sRanges[bindingInfo.Binding] = GetBufferRange(bounds.Address, bounds.Size); // The storage buffer size is not reliable (it might be lower than the actual size),
// so we bind the entire buffer to allow otherwise out of range accesses to work.
sRanges[bindingInfo.Binding] = GetBufferRangeTillEnd(
bounds.Address,
bounds.Size,
bounds.Flags.HasFlag(BufferUsageFlags.Write));
} }
} }
@ -722,7 +769,9 @@ namespace Ryujinx.Graphics.Gpu.Memory
if (bounds.Address != 0) if (bounds.Address != 0)
{ {
ranges[bindingInfo.Binding] = GetBufferRange(bounds.Address, bounds.Size); ranges[bindingInfo.Binding] = isStorage
? GetBufferRangeTillEnd(bounds.Address, bounds.Size, bounds.Flags.HasFlag(BufferUsageFlags.Write))
: GetBufferRange(bounds.Address, bounds.Size, bounds.Flags.HasFlag(BufferUsageFlags.Write));
} }
} }
} }
@ -818,7 +867,17 @@ namespace Ryujinx.Graphics.Gpu.Memory
dstOffset, dstOffset,
(int)size); (int)size);
dstBuffer.Flush(dstAddress, size); if (srcBuffer.IsModified(srcAddress, size))
{
dstBuffer.SignalModified(dstAddress, size);
}
else
{
// Optimization: If the data being copied is already in memory, then copy it directly instead of flushing from GPU.
dstBuffer.ClearModified(dstAddress, size);
_context.PhysicalMemory.WriteUntracked(dstAddress, _context.PhysicalMemory.GetSpan(srcAddress, (int)size));
}
} }
/// <summary> /// <summary>
@ -840,7 +899,19 @@ namespace Ryujinx.Graphics.Gpu.Memory
_context.Renderer.Pipeline.ClearBuffer(buffer.Handle, offset, (int)size, value); _context.Renderer.Pipeline.ClearBuffer(buffer.Handle, offset, (int)size, value);
buffer.Flush(address, size); buffer.SignalModified(address, size);
}
/// <summary>
/// Gets a buffer sub-range starting at a given memory address.
/// </summary>
/// <param name="address">Start address of the memory range</param>
/// <param name="size">Size in bytes of the memory range</param>
/// <param name="write">Whether the buffer will be written to by this use</param>
/// <returns>The buffer sub-range starting at the given memory address</returns>
private BufferRange GetBufferRangeTillEnd(ulong address, ulong size, bool write = false)
{
return GetBuffer(address, size, write).GetRange(address);
} }
/// <summary> /// <summary>
@ -848,10 +919,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary> /// </summary>
/// <param name="address">Start address of the memory range</param> /// <param name="address">Start address of the memory range</param>
/// <param name="size">Size in bytes of the memory range</param> /// <param name="size">Size in bytes of the memory range</param>
/// <param name="write">Whether the buffer will be written to by this use</param>
/// <returns>The buffer sub-range for the given range</returns> /// <returns>The buffer sub-range for the given range</returns>
private BufferRange GetBufferRange(ulong address, ulong size) private BufferRange GetBufferRange(ulong address, ulong size, bool write = false)
{ {
return GetBuffer(address, size).GetRange(address, size); return GetBuffer(address, size, write).GetRange(address, size);
} }
/// <summary> /// <summary>
@ -860,20 +932,32 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary> /// </summary>
/// <param name="address">Start address of the memory range</param> /// <param name="address">Start address of the memory range</param>
/// <param name="size">Size in bytes of the memory range</param> /// <param name="size">Size in bytes of the memory range</param>
/// <param name="write">Whether the buffer will be written to by this use</param>
/// <returns>The buffer where the range is fully contained</returns> /// <returns>The buffer where the range is fully contained</returns>
private Buffer GetBuffer(ulong address, ulong size) private Buffer GetBuffer(ulong address, ulong size, bool write = false)
{ {
Buffer buffer; Buffer buffer;
if (size != 0) if (size != 0)
{ {
buffer = _buffers.FindFirstOverlap(address, size); lock (_buffers)
{
buffer = _buffers.FindFirstOverlap(address, size);
}
buffer.SynchronizeMemory(address, size); buffer.SynchronizeMemory(address, size);
if (write)
{
buffer.SignalModified(address, size);
}
} }
else else
{ {
buffer = _buffers.FindFirstOverlap(address, 1); lock (_buffers)
{
buffer = _buffers.FindFirstOverlap(address, 1);
}
} }
return buffer; return buffer;
@ -888,7 +972,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
{ {
if (size != 0) if (size != 0)
{ {
Buffer buffer = _buffers.FindFirstOverlap(address, size); Buffer buffer;
lock (_buffers)
{
buffer = _buffers.FindFirstOverlap(address, size);
}
buffer.SynchronizeMemory(address, size); buffer.SynchronizeMemory(address, size);
} }
@ -900,9 +989,12 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
foreach (Buffer buffer in _buffers) lock (_buffers)
{ {
buffer.Dispose(); foreach (Buffer buffer in _buffers)
{
buffer.Dispose();
}
} }
} }
} }

View file

@ -0,0 +1,367 @@
using Ryujinx.Memory.Range;
using System;
using System.Linq;
namespace Ryujinx.Graphics.Gpu.Memory
{
/// <summary>
/// A range within a buffer that has been modified by the GPU.
/// </summary>
class BufferModifiedRange : IRange
{
/// <summary>
/// Start address of the range in guest memory.
/// </summary>
public ulong Address { get; }
/// <summary>
/// Size of the range in bytes.
/// </summary>
public ulong Size { get; }
/// <summary>
/// End address of the range in guest memory.
/// </summary>
public ulong EndAddress => Address + Size;
/// <summary>
/// The GPU sync number at the time of the last modification.
/// </summary>
public ulong SyncNumber { get; internal set; }
/// <summary>
/// Creates a new instance of a modified range.
/// </summary>
/// <param name="address">Start address of the range</param>
/// <param name="size">Size of the range in bytes</param>
/// <param name="syncNumber">The GPU sync number at the time of creation</param>
public BufferModifiedRange(ulong address, ulong size, ulong syncNumber)
{
Address = address;
Size = size;
SyncNumber = syncNumber;
}
/// <summary>
/// Checks if a given range overlaps with the modified range.
/// </summary>
/// <param name="address">Start address of the range</param>
/// <param name="size">Size in bytes of the range</param>
/// <returns>True if the range overlaps, false otherwise</returns>
public bool OverlapsWith(ulong address, ulong size)
{
return Address < address + size && address < EndAddress;
}
}
/// <summary>
/// A structure used to track GPU modified ranges within a buffer.
/// </summary>
class BufferModifiedRangeList : RangeList<BufferModifiedRange>
{
private GpuContext _context;
private object _lock = new object();
// The list can be accessed from both the GPU thread, and a background thread.
private BufferModifiedRange[] _foregroundOverlaps = new BufferModifiedRange[1];
private BufferModifiedRange[] _backgroundOverlaps = new BufferModifiedRange[1];
/// <summary>
/// Creates a new instance of a modified range list.
/// </summary>
/// <param name="context">GPU context that the buffer range list belongs to</param>
public BufferModifiedRangeList(GpuContext context)
{
_context = context;
}
/// <summary>
/// Given an input range, calls the given action with sub-ranges which exclude any of the modified regions.
/// </summary>
/// <param name="address">Start address of the query range</param>
/// <param name="size">Size of the query range in bytes</param>
/// <param name="action">Action to perform for each remaining sub-range of the input range</param>
public void ExcludeModifiedRegions(ulong address, ulong size, Action<ulong, ulong> action)
{
lock (_lock)
{
// Slices a given region using the modified regions in the list. Calls the action for the new slices.
int count = FindOverlapsNonOverlapping(address, size, ref _foregroundOverlaps);
for (int i = 0; i < count; i++)
{
BufferModifiedRange overlap = _foregroundOverlaps[i];
if (overlap.Address > address)
{
// The start of the remaining region is uncovered by this overlap. Call the action for it.
action(address, overlap.Address - address);
}
// Remaining region is after this overlap.
size -= overlap.EndAddress - address;
address = overlap.EndAddress;
}
if ((long)size > 0)
{
// If there is any region left after removing the overlaps, signal it.
action(address, size);
}
}
}
/// <summary>
/// Signal that a region of the buffer has been modified, and add the new region to the range list.
/// Any overlapping ranges will be (partially) removed.
/// </summary>
/// <param name="address">Start address of the modified region</param>
/// <param name="size">Size of the modified region in bytes</param>
public void SignalModified(ulong address, ulong size)
{
// Must lock, as this can affect flushes from the background thread.
lock (_lock)
{
// We may overlap with some existing modified regions. They must be cut into by the new entry.
int count = FindOverlapsNonOverlapping(address, size, ref _foregroundOverlaps);
ulong endAddress = address + size;
ulong syncNumber = _context.SyncNumber;
for (int i = 0; i < count; i++)
{
// The overlaps must be removed or split.
BufferModifiedRange overlap = _foregroundOverlaps[i];
if (overlap.Address == address && overlap.Size == size)
{
// Region already exists. Just update the existing sync number.
overlap.SyncNumber = syncNumber;
return;
}
Remove(overlap);
if (overlap.Address < address && overlap.EndAddress > address)
{
// A split item must be created behind this overlap.
Add(new BufferModifiedRange(overlap.Address, address - overlap.Address, overlap.SyncNumber));
}
if (overlap.Address < endAddress && overlap.EndAddress > endAddress)
{
// A split item must be created after this overlap.
Add(new BufferModifiedRange(endAddress, overlap.EndAddress - endAddress, overlap.SyncNumber));
}
}
Add(new BufferModifiedRange(address, size, syncNumber));
}
}
/// <summary>
/// Gets modified ranges within the specified region, and then fires the given action for each range individually.
/// </summary>
/// <param name="address">Start address to query</param>
/// <param name="size">Size to query</param>
/// <param name="rangeAction">The action to call for each modified range</param>
public void GetRanges(ulong address, ulong size, Action<ulong, ulong> rangeAction)
{
int count = 0;
// Range list must be consistent for this operation.
lock (_lock)
{
count = FindOverlapsNonOverlapping(address, size, ref _foregroundOverlaps);
}
for (int i = 0; i < count; i++)
{
BufferModifiedRange overlap = _foregroundOverlaps[i];
rangeAction(overlap.Address, overlap.Size);
}
}
/// <summary>
/// Queries if a range exists within the specified region.
/// </summary>
/// <param name="address">Start address to query</param>
/// <param name="size">Size to query</param>
/// <returns>True if a range exists in the specified region, false otherwise</returns>
public bool HasRange(ulong address, ulong size)
{
// Range list must be consistent for this operation.
lock (_lock)
{
return FindOverlapsNonOverlapping(address, size, ref _foregroundOverlaps) > 0;
}
}
/// <summary>
/// Gets modified ranges within the specified region, waits on ones from a previous sync number,
/// and then fires the given action for each range individually.
/// </summary>
/// <remarks>
/// This function assumes it is called from the background thread.
/// Modifications from the current sync number are ignored because the guest should not expect them to be available yet.
/// They will remain reserved, so that any data sync prioritizes the data in the GPU.
/// </remarks>
/// <param name="address">Start address to query</param>
/// <param name="size">Size to query</param>
/// <param name="rangeAction">The action to call for each modified range</param>
public void WaitForAndGetRanges(ulong address, ulong size, Action<ulong, ulong> rangeAction)
{
ulong endAddress = address + size;
ulong currentSync = _context.SyncNumber;
int rangeCount = 0;
// Range list must be consistent for this operation
lock (_lock)
{
rangeCount = FindOverlapsNonOverlapping(address, size, ref _backgroundOverlaps);
}
if (rangeCount == 0)
{
return;
}
// First, determine which syncpoint to wait on.
// This is the latest syncpoint that is not equal to the current sync.
long highestDiff = long.MinValue;
for (int i = 0; i < rangeCount; i++)
{
BufferModifiedRange overlap = _backgroundOverlaps[i];
long diff = (long)(overlap.SyncNumber - currentSync);
if (diff < 0 && diff > highestDiff)
{
highestDiff = diff;
}
}
if (highestDiff == long.MinValue)
{
return;
}
// Wait for the syncpoint.
_context.Renderer.WaitSync(currentSync + (ulong)highestDiff);
// Flush and remove all regions with the older syncpoint.
lock (_lock)
{
for (int i = 0; i < rangeCount; i++)
{
BufferModifiedRange overlap = _backgroundOverlaps[i];
long diff = (long)(overlap.SyncNumber - currentSync);
if (diff <= highestDiff)
{
ulong clampAddress = Math.Max(address, overlap.Address);
ulong clampEnd = Math.Min(endAddress, overlap.EndAddress);
ClearPart(overlap, clampAddress, clampEnd);
rangeAction(clampAddress, clampEnd - clampAddress);
}
}
}
}
/// <summary>
/// Inherit ranges from another modified range list.
/// </summary>
/// <param name="ranges">The range list to inherit from</param>
/// <param name="rangeAction">The action to call for each modified range</param>
public void InheritRanges(BufferModifiedRangeList ranges, Action<ulong, ulong> rangeAction)
{
BufferModifiedRange[] inheritRanges;
lock (ranges._lock)
{
inheritRanges = ranges.ToArray();
}
lock (_lock)
{
foreach (BufferModifiedRange range in inheritRanges)
{
Add(range);
}
}
ulong currentSync = _context.SyncNumber;
foreach (BufferModifiedRange range in inheritRanges)
{
if (range.SyncNumber != currentSync)
{
rangeAction(range.Address, range.Size);
}
}
}
private void ClearPart(BufferModifiedRange overlap, ulong address, ulong endAddress)
{
Remove(overlap);
// If the overlap extends outside of the clear range, make sure those parts still exist.
if (overlap.Address < address)
{
Add(new BufferModifiedRange(overlap.Address, address - overlap.Address, overlap.SyncNumber));
}
if (overlap.EndAddress > endAddress)
{
Add(new BufferModifiedRange(endAddress, overlap.EndAddress - endAddress, overlap.SyncNumber));
}
}
/// <summary>
/// Clear modified ranges within the specified area.
/// </summary>
/// <param name="address">Start address to clear</param>
/// <param name="size">Size to clear</param>
public void Clear(ulong address, ulong size)
{
lock (_lock)
{
// This function can be called from any thread, so it cannot use the arrays for background or foreground.
BufferModifiedRange[] toClear = new BufferModifiedRange[1];
int rangeCount = FindOverlapsNonOverlapping(address, size, ref toClear);
ulong endAddress = address + size;
for (int i = 0; i < rangeCount; i++)
{
BufferModifiedRange overlap = toClear[i];
ClearPart(overlap, address, endAddress);
}
}
}
/// <summary>
/// Clear all modified ranges.
/// </summary>
public void Clear()
{
lock (_lock)
{
Items.Clear();
}
}
}
}

View file

@ -61,6 +61,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
/// </summary> /// </summary>
/// <param name="va">GPU virtual address where the data is located</param> /// <param name="va">GPU virtual address where the data is located</param>
/// <param name="size">Size of the data</param> /// <param name="size">Size of the data</param>
/// <param name="tracked">True if read tracking is triggered on the span</param>
/// <returns>The span of the data at the specified memory location</returns> /// <returns>The span of the data at the specified memory location</returns>
public ReadOnlySpan<byte> GetSpan(ulong va, int size, bool tracked = false) public ReadOnlySpan<byte> GetSpan(ulong va, int size, bool tracked = false)
{ {
@ -342,6 +343,39 @@ namespace Ryujinx.Graphics.Gpu.Memory
return new MultiRange(regions.ToArray()); return new MultiRange(regions.ToArray());
} }
/// <summary>
/// Checks if a given GPU virtual memory range is mapped to the same physical regions
/// as the specified physical memory multi-range.
/// </summary>
/// <param name="range">Physical memory multi-range</param>
/// <param name="va">GPU virtual memory address</param>
/// <returns>True if the virtual memory region is mapped into the specified physical one, false otherwise</returns>
public bool CompareRange(MultiRange range, ulong va)
{
va &= ~PageMask;
for (int i = 0; i < range.Count; i++)
{
MemoryRange currentRange = range.GetSubRange(i);
ulong address = currentRange.Address & ~PageMask;
ulong endAddress = (currentRange.EndAddress + PageMask) & ~PageMask;
while (address < endAddress)
{
if (Translate(va) != address)
{
return false;
}
va += PageSize;
address += PageSize;
}
}
return true;
}
/// <summary> /// <summary>
/// Validates a GPU virtual address. /// Validates a GPU virtual address.
/// </summary> /// </summary>

View file

@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// <summary> /// <summary>
/// Version of the codegen (to be changed when codegen or guest format change). /// Version of the codegen (to be changed when codegen or guest format change).
/// </summary> /// </summary>
private const ulong ShaderCodeGenVersion = 1910; private const ulong ShaderCodeGenVersion = 1790;
/// <summary> /// <summary>
/// Creates a new instance of the shader cache. /// Creates a new instance of the shader cache.
@ -759,7 +759,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
{ {
byte[] code = _context.MemoryManager.GetSpan(translatorContext.Address, translatorContext.Size).ToArray(); byte[] code = _context.MemoryManager.GetSpan(translatorContext.Address, translatorContext.Size).ToArray();
_dumper.Dump(code, compute: false, out string fullPath, out string codePath); _dumper.Dump(code, translatorContext.Stage == ShaderStage.Compute, out string fullPath, out string codePath);
ShaderProgram program = translatorContext.Translate(out ShaderProgramInfo shaderProgramInfo); ShaderProgram program = translatorContext.Translate(out ShaderProgramInfo shaderProgramInfo);

View file

@ -2,6 +2,7 @@ using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.OpenGL.Image; using Ryujinx.Graphics.OpenGL.Image;
using System; using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Graphics.OpenGL namespace Ryujinx.Graphics.OpenGL
{ {
@ -29,21 +30,27 @@ namespace Ryujinx.Graphics.OpenGL
return Handle; return Handle;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AttachColor(int index, TextureView color) public void AttachColor(int index, TextureView color)
{ {
if (_colors[index] == color)
{
return;
}
FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index; FramebufferAttachment attachment = FramebufferAttachment.ColorAttachment0 + index;
if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd || if (HwCapabilities.Vendor == HwCapabilities.GpuVendor.Amd ||
HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel) HwCapabilities.Vendor == HwCapabilities.GpuVendor.Intel)
{ {
GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.GetIncompatibleFormatViewHandle() ?? 0, 0); GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.GetIncompatibleFormatViewHandle() ?? 0, 0);
_colors[index] = color;
} }
else else
{ {
GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0); GL.FramebufferTexture(FramebufferTarget.Framebuffer, attachment, color?.Handle ?? 0, 0);
} }
_colors[index] = color;
} }
public void AttachDepthStencil(TextureView depthStencil) public void AttachDepthStencil(TextureView depthStencil)

View file

@ -43,7 +43,7 @@ namespace Ryujinx.Graphics.OpenGL
private readonly uint[] _componentMasks; private readonly uint[] _componentMasks;
private bool _scissor0Enable = false; private uint _scissorEnables;
private bool _tfEnabled; private bool _tfEnabled;
private TransformFeedbackPrimitiveType _tfTopology; private TransformFeedbackPrimitiveType _tfTopology;
@ -883,25 +883,27 @@ namespace Ryujinx.Graphics.OpenGL
((Sampler)sampler).Bind(binding); ((Sampler)sampler).Bind(binding);
} }
public void SetScissorEnable(int index, bool enable) public void SetScissor(int index, bool enable, int x, int y, int width, int height)
{ {
if (enable) uint mask = 1u << index;
if (!enable)
{ {
if ((_scissorEnables & mask) != 0)
{
_scissorEnables &= ~mask;
GL.Disable(IndexedEnableCap.ScissorTest, index);
}
return;
}
if ((_scissorEnables & mask) == 0)
{
_scissorEnables |= mask;
GL.Enable(IndexedEnableCap.ScissorTest, index); GL.Enable(IndexedEnableCap.ScissorTest, index);
} }
else
{
GL.Disable(IndexedEnableCap.ScissorTest, index);
}
if (index == 0)
{
_scissor0Enable = enable;
}
}
public void SetScissor(int index, int x, int y, int width, int height)
{
GL.ScissorIndexed(index, x, y, width, height); GL.ScissorIndexed(index, x, y, width, height);
} }
@ -1241,7 +1243,7 @@ namespace Ryujinx.Graphics.OpenGL
public void RestoreScissor0Enable() public void RestoreScissor0Enable()
{ {
if (_scissor0Enable) if ((_scissorEnables & 1u) != 0)
{ {
GL.Enable(IndexedEnableCap.ScissorTest, 0); GL.Enable(IndexedEnableCap.ScissorTest, 0);
} }

View file

@ -26,6 +26,8 @@ namespace Ryujinx.Graphics.OpenGL
private TextureCopy _backgroundTextureCopy; private TextureCopy _backgroundTextureCopy;
internal TextureCopy TextureCopy => BackgroundContextWorker.InBackground ? _backgroundTextureCopy : _textureCopy; internal TextureCopy TextureCopy => BackgroundContextWorker.InBackground ? _backgroundTextureCopy : _textureCopy;
private Sync _sync;
internal ResourcePool ResourcePool { get; } internal ResourcePool ResourcePool { get; }
public string GpuVendor { get; private set; } public string GpuVendor { get; private set; }
@ -39,6 +41,7 @@ namespace Ryujinx.Graphics.OpenGL
_window = new Window(this); _window = new Window(this);
_textureCopy = new TextureCopy(this); _textureCopy = new TextureCopy(this);
_backgroundTextureCopy = new TextureCopy(this); _backgroundTextureCopy = new TextureCopy(this);
_sync = new Sync();
ResourcePool = new ResourcePool(); ResourcePool = new ResourcePool();
} }
@ -108,6 +111,7 @@ namespace Ryujinx.Graphics.OpenGL
public void PreFrame() public void PreFrame()
{ {
_sync.Cleanup();
ResourcePool.Tick(); ResourcePool.Tick();
} }
@ -164,6 +168,7 @@ namespace Ryujinx.Graphics.OpenGL
_pipeline.Dispose(); _pipeline.Dispose();
_window.Dispose(); _window.Dispose();
_counters.Dispose(); _counters.Dispose();
_sync.Dispose();
} }
public IProgram LoadProgramBinary(byte[] programBinary) public IProgram LoadProgramBinary(byte[] programBinary)
@ -179,5 +184,15 @@ namespace Ryujinx.Graphics.OpenGL
return null; return null;
} }
public void CreateSync(ulong id)
{
_sync.Create(id);
}
public void WaitSync(ulong id)
{
_sync.Wait(id);
}
} }
} }

View file

@ -0,0 +1,129 @@
using OpenTK.Graphics.OpenGL;
using Ryujinx.Common.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Ryujinx.Graphics.OpenGL
{
class Sync : IDisposable
{
private class SyncHandle
{
public ulong ID;
public IntPtr Handle;
}
private ulong _firstHandle = 0;
private List<SyncHandle> Handles = new List<SyncHandle>();
public void Create(ulong id)
{
SyncHandle handle = new SyncHandle
{
ID = id,
Handle = GL.FenceSync(SyncCondition.SyncGpuCommandsComplete, WaitSyncFlags.None)
};
lock (Handles)
{
Handles.Add(handle);
}
}
public void Wait(ulong id)
{
SyncHandle result = null;
lock (Handles)
{
if ((long)(_firstHandle - id) > 0)
{
return; // The handle has already been signalled or deleted.
}
foreach (SyncHandle handle in Handles)
{
if (handle.ID == id)
{
result = handle;
break;
}
}
}
if (result != null)
{
lock (result)
{
if (result.Handle == IntPtr.Zero)
{
return;
}
WaitSyncStatus syncResult = GL.ClientWaitSync(result.Handle, ClientWaitSyncFlags.SyncFlushCommandsBit, 1000000000);
if (syncResult == WaitSyncStatus.TimeoutExpired)
{
Logger.Error?.PrintMsg(LogClass.Gpu, $"GL Sync Object {result.ID} failed to signal within 1000ms. Continuing...");
}
}
}
}
public void Cleanup()
{
// Iterate through handles and remove any that have already been signalled.
while (true)
{
SyncHandle first = null;
lock (Handles)
{
first = Handles.FirstOrDefault();
}
if (first == null) break;
WaitSyncStatus syncResult = GL.ClientWaitSync(first.Handle, ClientWaitSyncFlags.SyncFlushCommandsBit, 0);
if (syncResult == WaitSyncStatus.AlreadySignaled)
{
// Delete the sync object.
lock (Handles)
{
lock (first)
{
_firstHandle = first.ID + 1;
Handles.RemoveAt(0);
GL.DeleteSync(first.Handle);
first.Handle = IntPtr.Zero;
}
}
} else
{
// This sync handle and any following have not been reached yet.
break;
}
}
}
public void Dispose()
{
lock (Handles)
{
foreach (SyncHandle handle in Handles)
{
lock (handle)
{
GL.DeleteSync(handle.Handle);
handle.Handle = IntPtr.Zero;
}
}
Handles.Clear();
}
}
}
}

View file

@ -1,6 +1,7 @@
using OpenTK.Graphics.OpenGL; using OpenTK.Graphics.OpenGL;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using System; using System;
using System.Runtime.CompilerServices;
namespace Ryujinx.Graphics.OpenGL namespace Ryujinx.Graphics.OpenGL
{ {
@ -16,6 +17,9 @@ namespace Ryujinx.Graphics.OpenGL
private int _vertexAttribsCount; private int _vertexAttribsCount;
private int _vertexBuffersCount; private int _vertexBuffersCount;
private uint _vertexAttribsInUse;
private uint _vertexBuffersInUse;
public VertexArray() public VertexArray()
{ {
Handle = GL.GenVertexArray(); Handle = GL.GenVertexArray();
@ -31,30 +35,30 @@ namespace Ryujinx.Graphics.OpenGL
public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers) public void SetVertexBuffers(ReadOnlySpan<VertexBufferDescriptor> vertexBuffers)
{ {
int bindingIndex = 0; int bindingIndex;
for (bindingIndex = 0; bindingIndex < vertexBuffers.Length; bindingIndex++)
for (int index = 0; index < vertexBuffers.Length; index++)
{ {
VertexBufferDescriptor vb = vertexBuffers[index]; VertexBufferDescriptor vb = vertexBuffers[bindingIndex];
if (vb.Buffer.Handle != BufferHandle.Null) if (vb.Buffer.Handle != BufferHandle.Null)
{ {
GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride); GL.BindVertexBuffer(bindingIndex, vb.Buffer.Handle.ToInt32(), (IntPtr)vb.Buffer.Offset, vb.Stride);
GL.VertexBindingDivisor(bindingIndex, vb.Divisor); GL.VertexBindingDivisor(bindingIndex, vb.Divisor);
_vertexBuffersInUse |= 1u << bindingIndex;
} }
else else
{ {
GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0); if ((_vertexBuffersInUse & (1u << bindingIndex)) != 0)
{
GL.BindVertexBuffer(bindingIndex, 0, IntPtr.Zero, 0);
_vertexBuffersInUse &= ~(1u << bindingIndex);
}
} }
_vertexBuffers[index] = vb; _vertexBuffers[bindingIndex] = vb;
bindingIndex++;
} }
_vertexBuffersCount = bindingIndex; _vertexBuffersCount = bindingIndex;
_needsAttribsUpdate = true; _needsAttribsUpdate = true;
} }
@ -66,17 +70,22 @@ namespace Ryujinx.Graphics.OpenGL
{ {
VertexAttribDescriptor attrib = vertexAttribs[index]; VertexAttribDescriptor attrib = vertexAttribs[index];
if (attrib.Equals(_vertexAttribs[index]))
{
continue;
}
FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format); FormatInfo fmtInfo = FormatTable.GetFormatInfo(attrib.Format);
if (attrib.IsZero) if (attrib.IsZero)
{ {
// Disabling the attribute causes the shader to read a constant value. // Disabling the attribute causes the shader to read a constant value.
// The value is configurable, but by default is a vector of (0, 0, 0, 1). // The value is configurable, but by default is a vector of (0, 0, 0, 1).
GL.DisableVertexAttribArray(index); DisableVertexAttrib(index);
} }
else else
{ {
GL.EnableVertexAttribArray(index); EnableVertexAttrib(index);
} }
int offset = attrib.Offset; int offset = attrib.Offset;
@ -107,7 +116,7 @@ namespace Ryujinx.Graphics.OpenGL
for (; index < Constants.MaxVertexAttribs; index++) for (; index < Constants.MaxVertexAttribs; index++)
{ {
GL.DisableVertexAttribArray(index); DisableVertexAttrib(index);
} }
} }
@ -122,29 +131,54 @@ namespace Ryujinx.Graphics.OpenGL
{ {
VertexAttribDescriptor attrib = _vertexAttribs[attribIndex]; VertexAttribDescriptor attrib = _vertexAttribs[attribIndex];
if ((uint)attrib.BufferIndex >= _vertexBuffersCount) if (!attrib.IsZero)
{ {
GL.DisableVertexAttribArray(attribIndex); if ((uint)attrib.BufferIndex >= _vertexBuffersCount)
{
DisableVertexAttrib(attribIndex);
continue;
}
continue; if (_vertexBuffers[attrib.BufferIndex].Buffer.Handle == BufferHandle.Null)
} {
DisableVertexAttrib(attribIndex);
continue;
}
if (_vertexBuffers[attrib.BufferIndex].Buffer.Handle == BufferHandle.Null) if (_needsAttribsUpdate)
{ {
GL.DisableVertexAttribArray(attribIndex); EnableVertexAttrib(attribIndex);
}
continue;
}
if (_needsAttribsUpdate && !attrib.IsZero)
{
GL.EnableVertexAttribArray(attribIndex);
} }
} }
_needsAttribsUpdate = false; _needsAttribsUpdate = false;
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void EnableVertexAttrib(int index)
{
uint mask = 1u << index;
if ((_vertexAttribsInUse & mask) == 0)
{
_vertexAttribsInUse |= mask;
GL.EnableVertexAttribArray(index);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DisableVertexAttrib(int index)
{
uint mask = 1u << index;
if ((_vertexAttribsInUse & mask) != 0)
{
_vertexAttribsInUse &= ~mask;
GL.DisableVertexAttribArray(index);
}
}
public void Dispose() public void Dispose()
{ {
if (Handle != 0) if (Handle != 0)

View file

@ -4,11 +4,21 @@ namespace Ryujinx.Graphics.Shader
{ {
public readonly int Binding; public readonly int Binding;
public readonly int Slot; public readonly int Slot;
public BufferUsageFlags Flags;
public BufferDescriptor(int binding, int slot) public BufferDescriptor(int binding, int slot)
{ {
Binding = binding; Binding = binding;
Slot = slot; Slot = slot;
Flags = BufferUsageFlags.None;
}
public BufferDescriptor SetFlag(BufferUsageFlags flag)
{
Flags |= flag;
return this;
} }
} }
} }

View file

@ -0,0 +1,18 @@
using System;
namespace Ryujinx.Graphics.Shader
{
/// <summary>
/// Flags that indicate how a buffer will be used in a shader.
/// </summary>
[Flags]
public enum BufferUsageFlags
{
None = 0,
/// <summary>
/// Buffer is written to.
/// </summary>
Write = 1 << 0
}
}

View file

@ -157,6 +157,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
} }
} }
if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Shared) != 0)
{
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Shared.glsl");
}
if ((info.HelperFunctionsMask & HelperFunctionsMask.AtomicMinMaxS32Storage) != 0)
{
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/AtomicMinMaxS32Storage.glsl");
}
if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0) if ((info.HelperFunctionsMask & HelperFunctionsMask.MultiplyHighS32) != 0)
{ {
AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl"); AppendHelperFunction(context, "Ryujinx.Graphics.Shader/CodeGen/Glsl/HelperFunctions/MultiplyHighS32.glsl");
@ -523,7 +533,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
string code = EmbeddedResources.ReadAllText(filename); string code = EmbeddedResources.ReadAllText(filename);
context.AppendLine(code.Replace("\t", CodeGenContext.Tab)); code = code.Replace("\t", CodeGenContext.Tab);
code = code.Replace("$SHARED_MEM$", DefaultNames.SharedMemoryName);
code = code.Replace("$STORAGE_MEM$", OperandManager.GetShaderStagePrefix(context.Config.Stage) + "_" + DefaultNames.StorageNamePrefix);
context.AppendLine(code);
context.AppendLine(); context.AppendLine();
} }
} }

View file

@ -0,0 +1,21 @@
int Helper_AtomicMaxS32(int offset, int value)
{
uint oldValue, newValue;
do
{
oldValue = $SHARED_MEM$[offset];
newValue = uint(max(int(oldValue), value));
} while (atomicCompSwap($SHARED_MEM$[offset], newValue, oldValue) != oldValue);
return int(oldValue);
}
int Helper_AtomicMinS32(int offset, int value)
{
uint oldValue, newValue;
do
{
oldValue = $SHARED_MEM$[offset];
newValue = uint(min(int(oldValue), value));
} while (atomicCompSwap($SHARED_MEM$[offset], newValue, oldValue) != oldValue);
return int(oldValue);
}

View file

@ -0,0 +1,21 @@
int Helper_AtomicMaxS32(int index, int offset, int value)
{
uint oldValue, newValue;
do
{
oldValue = $STORAGE_MEM$[index].data[offset];
newValue = uint(max(int(oldValue), value));
} while (atomicCompSwap($STORAGE_MEM$[index].data[offset], newValue, oldValue) != oldValue);
return int(oldValue);
}
int Helper_AtomicMinS32(int index, int offset, int value)
{
uint oldValue, newValue;
do
{
oldValue = $STORAGE_MEM$[index].data[offset];
newValue = uint(min(int(oldValue), value));
} while (atomicCompSwap($STORAGE_MEM$[index].data[offset], newValue, oldValue) != oldValue);
return int(oldValue);
}

View file

@ -2,6 +2,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
{ {
static class HelperFunctionNames static class HelperFunctionNames
{ {
public static string AtomicMaxS32 = "Helper_AtomicMaxS32";
public static string AtomicMinS32 = "Helper_AtomicMinS32";
public static string MultiplyHighS32 = "Helper_MultiplyHighS32"; public static string MultiplyHighS32 = "Helper_MultiplyHighS32";
public static string MultiplyHighU32 = "Helper_MultiplyHighU32"; public static string MultiplyHighU32 = "Helper_MultiplyHighU32";

View file

@ -1,6 +1,8 @@
ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex) { ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex)
{
float scale = cp_renderScale[samplerIndex]; float scale = cp_renderScale[samplerIndex];
if (scale == 1.0) { if (scale == 1.0)
{
return inputVec; return inputVec;
} }
return ivec2(vec2(inputVec) * scale); return ivec2(vec2(inputVec) * scale);

View file

@ -1,11 +1,16 @@
ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex) { ivec2 Helper_TexelFetchScale(ivec2 inputVec, int samplerIndex)
{
float scale = fp_renderScale[1 + samplerIndex]; float scale = fp_renderScale[1 + samplerIndex];
if (scale == 1.0) { if (scale == 1.0)
{
return inputVec; return inputVec;
} }
if (scale < 0.0) { // If less than 0, try interpolate between texels by using the screen position. if (scale < 0.0) // If less than 0, try interpolate between texels by using the screen position.
{
return ivec2(vec2(inputVec) * (-scale) + mod(gl_FragCoord.xy, -scale)); return ivec2(vec2(inputVec) * (-scale) + mod(gl_FragCoord.xy, -scale));
} else { }
else
{
return ivec2(vec2(inputVec) * scale); return ivec2(vec2(inputVec) * scale);
} }
} }

View file

@ -42,13 +42,19 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
for (int argIndex = 0; argIndex < arity; argIndex++) for (int argIndex = 0; argIndex < arity; argIndex++)
{ {
// For shared memory access, the second argument is unused and should be ignored.
// It is there to make both storage and shared access have the same number of arguments.
// For storage, both inputs are consumed when the argument index is 0, so we should skip it here.
if (argIndex == 1 && (atomic || (inst & Instruction.MrMask) == Instruction.MrShared))
{
continue;
}
if (argIndex != 0) if (argIndex != 0)
{ {
args += ", "; args += ", ";
} }
VariableType dstType = GetSrcVarType(inst, argIndex);
if (argIndex == 0 && atomic) if (argIndex == 0 && atomic)
{ {
Instruction memRegion = inst & Instruction.MrMask; Instruction memRegion = inst & Instruction.MrMask;
@ -60,12 +66,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
default: throw new InvalidOperationException($"Invalid memory region \"{memRegion}\"."); default: throw new InvalidOperationException($"Invalid memory region \"{memRegion}\".");
} }
// We use the first 2 operands above.
argIndex++;
} }
else else
{ {
VariableType dstType = GetSrcVarType(inst, argIndex);
args += GetSoureExpr(context, operation.GetSource(argIndex), dstType); args += GetSoureExpr(context, operation.GetSource(argIndex), dstType);
} }
} }

View file

@ -16,9 +16,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd"); Add(Instruction.AtomicAdd, InstType.AtomicBinary, "atomicAdd");
Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd"); Add(Instruction.AtomicAnd, InstType.AtomicBinary, "atomicAnd");
Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap"); Add(Instruction.AtomicCompareAndSwap, InstType.AtomicTernary, "atomicCompSwap");
Add(Instruction.AtomicMaxS32, InstType.AtomicBinary, "atomicMax"); Add(Instruction.AtomicMaxS32, InstType.CallTernary, HelperFunctionNames.AtomicMaxS32);
Add(Instruction.AtomicMaxU32, InstType.AtomicBinary, "atomicMax"); Add(Instruction.AtomicMaxU32, InstType.AtomicBinary, "atomicMax");
Add(Instruction.AtomicMinS32, InstType.AtomicBinary, "atomicMin"); Add(Instruction.AtomicMinS32, InstType.CallTernary, HelperFunctionNames.AtomicMinS32);
Add(Instruction.AtomicMinU32, InstType.AtomicBinary, "atomicMin"); Add(Instruction.AtomicMinU32, InstType.AtomicBinary, "atomicMin");
Add(Instruction.AtomicOr, InstType.AtomicBinary, "atomicOr"); Add(Instruction.AtomicOr, InstType.AtomicBinary, "atomicOr");
Add(Instruction.AtomicSwap, InstType.AtomicBinary, "atomicExchange"); Add(Instruction.AtomicSwap, InstType.AtomicBinary, "atomicExchange");

View file

@ -298,6 +298,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
string src = TypeConversion.ReinterpretCast(context, src3, srcType, VariableType.U32); string src = TypeConversion.ReinterpretCast(context, src3, srcType, VariableType.U32);
SetStorageWriteFlag(context, src1, context.Config.Stage);
string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage); string sb = GetStorageBufferAccessor(indexExpr, offsetExpr, context.Config.Stage);
return $"{sb} = {src}"; return $"{sb} = {src}";
@ -629,6 +630,32 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
} }
} }
private static void SetStorageWriteFlag(CodeGenContext context, IAstNode indexExpr, ShaderStage stage)
{
// Attempt to find a BufferDescriptor with the given index.
// If it cannot be resolved or is not constant, assume that the slot expression could potentially index any of them,
// and set the flag on all storage buffers.
int index = -1;
if (indexExpr is AstOperand operand && operand.Type == OperandType.Constant)
{
index = context.SBufferDescriptors.FindIndex(buffer => buffer.Slot == operand.Value);
}
if (index != -1)
{
context.SBufferDescriptors[index] = context.SBufferDescriptors[index].SetFlag(BufferUsageFlags.Write);
}
else
{
for (int i = 0; i < context.SBufferDescriptors.Count; i++)
{
context.SBufferDescriptors[i] = context.SBufferDescriptors[i].SetFlag(BufferUsageFlags.Write);
}
}
}
private static string GetStorageBufferAccessor(string slotExpr, string offsetExpr, ShaderStage stage) private static string GetStorageBufferAccessor(string slotExpr, string offsetExpr, ShaderStage stage)
{ {
string sbName = OperandManager.GetShaderStagePrefix(stage); string sbName = OperandManager.GetShaderStagePrefix(stage);

View file

@ -9,6 +9,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\AtomicMinMaxS32Shared.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\AtomicMinMaxS32Storage.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\MultiplyHighS32.glsl" /> <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\MultiplyHighS32.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\MultiplyHighU32.glsl" /> <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\MultiplyHighU32.glsl" />
<EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\Shuffle.glsl" /> <EmbeddedResource Include="CodeGen\Glsl\HelperFunctions\Shuffle.glsl" />

View file

@ -5,12 +5,14 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
[Flags] [Flags]
enum HelperFunctionsMask enum HelperFunctionsMask
{ {
MultiplyHighS32 = 1 << 0, AtomicMinMaxS32Shared = 1 << 0,
MultiplyHighU32 = 1 << 1, AtomicMinMaxS32Storage = 1 << 1,
Shuffle = 1 << 2, MultiplyHighS32 = 1 << 2,
ShuffleDown = 1 << 3, MultiplyHighU32 = 1 << 3,
ShuffleUp = 1 << 4, Shuffle = 1 << 4,
ShuffleXor = 1 << 5, ShuffleDown = 1 << 5,
SwizzleAdd = 1 << 6 ShuffleUp = 1 << 6,
ShuffleXor = 1 << 7,
SwizzleAdd = 1 << 8
} }
} }

View file

@ -244,6 +244,14 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
// decide which helper functions are needed on the final generated code. // decide which helper functions are needed on the final generated code.
switch (operation.Inst) switch (operation.Inst)
{ {
case Instruction.AtomicMaxS32 | Instruction.MrShared:
case Instruction.AtomicMinS32 | Instruction.MrShared:
context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Shared;
break;
case Instruction.AtomicMaxS32 | Instruction.MrStorage:
case Instruction.AtomicMinS32 | Instruction.MrStorage:
context.Info.HelperFunctionsMask |= HelperFunctionsMask.AtomicMinMaxS32Storage;
break;
case Instruction.MultiplyHighS32: case Instruction.MultiplyHighS32:
context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32; context.Info.HelperFunctionsMask |= HelperFunctionsMask.MultiplyHighS32;
break; break;

View file

@ -653,6 +653,15 @@ namespace Ryujinx.HLE.FileSystem.Content
public SystemVersion VerifyFirmwarePackage(string firmwarePackage) public SystemVersion VerifyFirmwarePackage(string firmwarePackage)
{ {
_virtualFileSystem.Reload();
// LibHac.NcaHeader's DecryptHeader doesn't check if HeaderKey is empty and throws InvalidDataException instead
// So, we check it early for a better user experience.
if (_virtualFileSystem.KeySet.HeaderKey.IsEmpty())
{
throw new MissingKeyException("HeaderKey is empty. Cannot decrypt NCA headers.");
}
Dictionary<ulong, List<(NcaContentType type, string path)>> updateNcas = new Dictionary<ulong, List<(NcaContentType, string)>>(); Dictionary<ulong, List<(NcaContentType type, string path)>> updateNcas = new Dictionary<ulong, List<(NcaContentType, string)>>();
if (Directory.Exists(firmwarePackage)) if (Directory.Exists(firmwarePackage))

View file

@ -26,8 +26,15 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
{ {
long size = context.RequestData.ReadInt64(); long size = context.RequestData.ReadInt64();
if (size <= 0)
{
return ResultCode.ObjectInvalid;
}
MakeObject(context, new IStorage(new byte[size])); MakeObject(context, new IStorage(new byte[size]));
// NOTE: Returns ResultCode.MemoryAllocationFailed if IStorage is null, it doesn't occur in our case.
return ResultCode.Success; return ResultCode.Success;
} }
@ -35,20 +42,44 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys
// CreateTransferMemoryStorage(b8, u64, handle<copy>) -> object<nn::am::service::IStorage> // CreateTransferMemoryStorage(b8, u64, handle<copy>) -> object<nn::am::service::IStorage>
public ResultCode CreateTransferMemoryStorage(ServiceCtx context) public ResultCode CreateTransferMemoryStorage(ServiceCtx context)
{ {
bool unknown = context.RequestData.ReadBoolean(); bool isReadOnly = (context.RequestData.ReadInt64() & 1) == 0;
long size = context.RequestData.ReadInt64(); long size = context.RequestData.ReadInt64();
int handle = context.Request.HandleDesc.ToCopy[0]; int handle = context.Request.HandleDesc.ToCopy[0];
KTransferMemory transferMem = context.Process.HandleTable.GetObject<KTransferMemory>(handle); KTransferMemory transferMem = context.Process.HandleTable.GetObject<KTransferMemory>(handle);
if (transferMem == null) if (size <= 0)
{ {
Logger.Warning?.Print(LogClass.ServiceAm, $"Invalid TransferMemory Handle: {handle:X}"); return ResultCode.ObjectInvalid;
return ResultCode.Success; // TODO: Find correct error code
} }
var data = new byte[transferMem.Size]; byte[] data = new byte[transferMem.Size];
transferMem.Creator.CpuMemory.Read(transferMem.Address, data);
context.Device.System.KernelContext.Syscall.CloseHandle(handle);
MakeObject(context, new IStorage(data, isReadOnly));
return ResultCode.Success;
}
[Command(12)] // 2.0.0+
// CreateHandleStorage(u64, handle<copy>) -> object<nn::am::service::IStorage>
public ResultCode CreateHandleStorage(ServiceCtx context)
{
long size = context.RequestData.ReadInt64();
int handle = context.Request.HandleDesc.ToCopy[0];
KTransferMemory transferMem = context.Process.HandleTable.GetObject<KTransferMemory>(handle);
if (size <= 0)
{
return ResultCode.ObjectInvalid;
}
byte[] data = new byte[transferMem.Size];
transferMem.Creator.CpuMemory.Read(transferMem.Address, data); transferMem.Creator.CpuMemory.Read(transferMem.Address, data);
context.Device.System.KernelContext.Syscall.CloseHandle(handle); context.Device.System.KernelContext.Syscall.CloseHandle(handle);

View file

@ -2,11 +2,13 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
{ {
class IStorage : IpcService class IStorage : IpcService
{ {
public byte[] Data { get; private set; } public bool IsReadOnly { get; private set; }
public byte[] Data { get; private set; }
public IStorage(byte[] data) public IStorage(byte[] data, bool isReadOnly = false)
{ {
Data = data; IsReadOnly = isReadOnly;
Data = data;
} }
[Command(0)] [Command(0)]

View file

@ -24,6 +24,11 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE
// Write(u64, buffer<bytes, 0x21>) // Write(u64, buffer<bytes, 0x21>)
public ResultCode Write(ServiceCtx context) public ResultCode Write(ServiceCtx context)
{ {
if (_storage.IsReadOnly)
{
return ResultCode.ObjectInvalid;
}
long writePosition = context.RequestData.ReadInt64(); long writePosition = context.RequestData.ReadInt64();
if (writePosition > _storage.Data.Length) if (writePosition > _storage.Data.Length)

View file

@ -183,11 +183,10 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
{ {
int i = namePosition; int i = namePosition;
char c = name[i]; char c;
while (c != '\0' && !char.IsDigit(c) && c != ',' && c != '-' && c != '+') while ((c = name[i]) != '\0' && !char.IsDigit(c) && c != ',' && c != '-' && c != '+')
{ {
c = name[i];
i++; i++;
} }

View file

@ -6,6 +6,8 @@ namespace Ryujinx.Memory.Tests
{ {
public bool NoMappings; public bool NoMappings;
public event Action<ulong, ulong, MemoryPermission> OnProtect;
public MockVirtualMemoryManager(ulong size, int pageSize) public MockVirtualMemoryManager(ulong size, int pageSize)
{ {
} }
@ -82,6 +84,7 @@ namespace Ryujinx.Memory.Tests
public void TrackingReprotect(ulong va, ulong size, MemoryPermission protection) public void TrackingReprotect(ulong va, ulong size, MemoryPermission protection)
{ {
OnProtect?.Invoke(va, size, protection);
} }
} }
} }

View file

@ -421,5 +421,68 @@ namespace Ryujinx.Memory.Tests
Assert.AreEqual((0, 0), _tracking.GetRegionCounts()); Assert.AreEqual((0, 0), _tracking.GetRegionCounts());
} }
[Test]
public void ReadAndWriteProtection()
{
MemoryPermission protection = MemoryPermission.ReadAndWrite;
_memoryManager.OnProtect += (va, size, newProtection) =>
{
Assert.AreEqual((0, PageSize), (va, size)); // Should protect the exact region all the operations use.
protection = newProtection;
};
RegionHandle handle = _tracking.BeginTracking(0, PageSize);
// After creating the handle, there is no protection yet.
Assert.AreEqual(MemoryPermission.ReadAndWrite, protection);
bool dirtyInitial = handle.Dirty;
Assert.True(dirtyInitial); // Handle starts dirty.
handle.Reprotect();
// After a reprotect, there is write protection, which will set a dirty flag when any write happens.
Assert.AreEqual(MemoryPermission.Read, protection);
(ulong address, ulong size)? readTrackingTriggered = null;
handle.RegisterAction((address, size) =>
{
readTrackingTriggered = (address, size);
});
// Registering an action adds read/write protection.
Assert.AreEqual(MemoryPermission.None, protection);
bool dirtyAfterReprotect = handle.Dirty;
Assert.False(dirtyAfterReprotect); // Handle is no longer dirty.
// First we should read, which will trigger the action. This _should not_ remove write protection on the memory.
_tracking.VirtualMemoryEvent(0, 4, false);
bool dirtyAfterRead = handle.Dirty;
Assert.False(dirtyAfterRead); // Not dirtied, as this was a read.
Assert.AreEqual(readTrackingTriggered, (0UL, 4UL)); // Read action was triggered.
Assert.AreEqual(MemoryPermission.Read, protection); // Write protection is still present.
readTrackingTriggered = null;
// Now, perform a write.
_tracking.VirtualMemoryEvent(0, 4, true);
bool dirtyAfterWriteAfterRead = handle.Dirty;
Assert.True(dirtyAfterWriteAfterRead); // Should be dirty.
Assert.AreEqual(MemoryPermission.ReadAndWrite, protection); // All protection is now be removed from the memory.
Assert.IsNull(readTrackingTriggered); // Read tracking was removed when the action fired, as it can only fire once.
handle.Dispose();
}
} }
} }

View file

@ -15,7 +15,7 @@ namespace Ryujinx.Memory
void Fill(ulong va, ulong size, byte value) void Fill(ulong va, ulong size, byte value)
{ {
const int MaxChunkSize = 1 << 30; const int MaxChunkSize = 1 << 24;
for (ulong subOffset = 0; subOffset < size; subOffset += MaxChunkSize) for (ulong subOffset = 0; subOffset < size; subOffset += MaxChunkSize)
{ {

View file

@ -134,7 +134,7 @@ namespace Ryujinx.Memory
/// <exception cref="InvalidMemoryRegionException">Throw when <paramref name="srcOffset"/>, <paramref name="dstOffset"/> or <paramref name="size"/> is out of range</exception> /// <exception cref="InvalidMemoryRegionException">Throw when <paramref name="srcOffset"/>, <paramref name="dstOffset"/> or <paramref name="size"/> is out of range</exception>
public void Copy(ulong dstOffset, ulong srcOffset, ulong size) public void Copy(ulong dstOffset, ulong srcOffset, ulong size)
{ {
const int MaxChunkSize = 1 << 30; const int MaxChunkSize = 1 << 24;
for (ulong offset = 0; offset < size; offset += MaxChunkSize) for (ulong offset = 0; offset < size; offset += MaxChunkSize)
{ {
@ -153,7 +153,7 @@ namespace Ryujinx.Memory
/// <exception cref="InvalidMemoryRegionException">Throw when either <paramref name="offset"/> or <paramref name="size"/> are out of range</exception> /// <exception cref="InvalidMemoryRegionException">Throw when either <paramref name="offset"/> or <paramref name="size"/> are out of range</exception>
public void ZeroFill(ulong offset, ulong size) public void ZeroFill(ulong offset, ulong size)
{ {
const int MaxChunkSize = 1 << 30; const int MaxChunkSize = 1 << 24;
for (ulong subOffset = 0; subOffset < size; subOffset += MaxChunkSize) for (ulong subOffset = 0; subOffset < size; subOffset += MaxChunkSize)
{ {

View file

@ -12,16 +12,16 @@ namespace Ryujinx.Memory.Range
{ {
private const int ArrayGrowthSize = 32; private const int ArrayGrowthSize = 32;
private readonly List<T> _items; protected readonly List<T> Items;
public int Count => _items.Count; public int Count => Items.Count;
/// <summary> /// <summary>
/// Creates a new range list. /// Creates a new range list.
/// </summary> /// </summary>
public RangeList() public RangeList()
{ {
_items = new List<T>(); Items = new List<T>();
} }
/// <summary> /// <summary>
@ -37,7 +37,7 @@ namespace Ryujinx.Memory.Range
index = ~index; index = ~index;
} }
_items.Insert(index, item); Items.Insert(index, item);
} }
/// <summary> /// <summary>
@ -51,21 +51,21 @@ namespace Ryujinx.Memory.Range
if (index >= 0) if (index >= 0)
{ {
while (index > 0 && _items[index - 1].Address == item.Address) while (index > 0 && Items[index - 1].Address == item.Address)
{ {
index--; index--;
} }
while (index < _items.Count) while (index < Items.Count)
{ {
if (_items[index].Equals(item)) if (Items[index].Equals(item))
{ {
_items.RemoveAt(index); Items.RemoveAt(index);
return true; return true;
} }
if (_items[index].Address > item.Address) if (Items[index].Address > item.Address)
{ {
break; break;
} }
@ -110,7 +110,7 @@ namespace Ryujinx.Memory.Range
return default(T); return default(T);
} }
return _items[index]; return Items[index];
} }
/// <summary> /// <summary>
@ -137,7 +137,7 @@ namespace Ryujinx.Memory.Range
ulong endAddress = address + size; ulong endAddress = address + size;
foreach (T item in _items) foreach (T item in Items)
{ {
if (item.Address >= endAddress) if (item.Address >= endAddress)
{ {
@ -196,7 +196,7 @@ namespace Ryujinx.Memory.Range
if (index >= 0) if (index >= 0)
{ {
while (index > 0 && _items[index - 1].OverlapsWith(address, size)) while (index > 0 && Items[index - 1].OverlapsWith(address, size))
{ {
index--; index--;
} }
@ -208,9 +208,9 @@ namespace Ryujinx.Memory.Range
Array.Resize(ref output, outputIndex + ArrayGrowthSize); Array.Resize(ref output, outputIndex + ArrayGrowthSize);
} }
output[outputIndex++] = _items[index++]; output[outputIndex++] = Items[index++];
} }
while (index < _items.Count && _items[index].OverlapsWith(address, size)); while (index < Items.Count && Items[index].OverlapsWith(address, size));
} }
return outputIndex; return outputIndex;
@ -230,14 +230,14 @@ namespace Ryujinx.Memory.Range
if (index >= 0) if (index >= 0)
{ {
while (index > 0 && _items[index - 1].Address == address) while (index > 0 && Items[index - 1].Address == address)
{ {
index--; index--;
} }
while (index < _items.Count) while (index < Items.Count)
{ {
T overlap = _items[index++]; T overlap = Items[index++];
if (overlap.Address != address) if (overlap.Address != address)
{ {
@ -264,7 +264,7 @@ namespace Ryujinx.Memory.Range
private int BinarySearch(ulong address) private int BinarySearch(ulong address)
{ {
int left = 0; int left = 0;
int right = _items.Count - 1; int right = Items.Count - 1;
while (left <= right) while (left <= right)
{ {
@ -272,7 +272,7 @@ namespace Ryujinx.Memory.Range
int middle = left + (range >> 1); int middle = left + (range >> 1);
T item = _items[middle]; T item = Items[middle];
if (item.Address == address) if (item.Address == address)
{ {
@ -301,7 +301,7 @@ namespace Ryujinx.Memory.Range
private int BinarySearch(ulong address, ulong size) private int BinarySearch(ulong address, ulong size)
{ {
int left = 0; int left = 0;
int right = _items.Count - 1; int right = Items.Count - 1;
while (left <= right) while (left <= right)
{ {
@ -309,7 +309,7 @@ namespace Ryujinx.Memory.Range
int middle = left + (range >> 1); int middle = left + (range >> 1);
T item = _items[middle]; T item = Items[middle];
if (item.OverlapsWith(address, size)) if (item.OverlapsWith(address, size))
{ {
@ -331,12 +331,12 @@ namespace Ryujinx.Memory.Range
public IEnumerator<T> GetEnumerator() public IEnumerator<T> GetEnumerator()
{ {
return _items.GetEnumerator(); return Items.GetEnumerator();
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return _items.GetEnumerator(); return Items.GetEnumerator();
} }
} }
} }

View file

@ -123,6 +123,17 @@ namespace Ryujinx.Memory.Tracking
} }
} }
public void RegisterAction(ulong address, ulong size, RegionSignal action)
{
int startHandle = (int)((address - Address) / Granularity);
int lastHandle = (int)((address + (size - 1) - Address) / Granularity);
for (int i = startHandle; i <= lastHandle; i++)
{
_handles[i].RegisterAction(action);
}
}
public void Dispose() public void Dispose()
{ {
foreach (var handle in _handles) foreach (var handle in _handles)

View file

@ -24,6 +24,7 @@ namespace Ryujinx.Memory.Tracking
private readonly MemoryTracking _tracking; private readonly MemoryTracking _tracking;
internal MemoryPermission RequiredPermission => _preAction != null ? MemoryPermission.None : (Dirty ? MemoryPermission.ReadAndWrite : MemoryPermission.Read); internal MemoryPermission RequiredPermission => _preAction != null ? MemoryPermission.None : (Dirty ? MemoryPermission.ReadAndWrite : MemoryPermission.Read);
internal RegionSignal PreAction => _preAction;
/// <summary> /// <summary>
/// Create a new region handle. The handle is registered with the given tracking object, /// Create a new region handle. The handle is registered with the given tracking object,

View file

@ -41,6 +41,17 @@ namespace Ryujinx.Memory.Tracking
Dirty = true; Dirty = true;
} }
public void RegisterAction(RegionSignal action)
{
foreach (var handle in _handles)
{
if (handle != null)
{
handle?.RegisterAction((address, size) => action(handle.Address, handle.Size));
}
}
}
public void QueryModified(Action<ulong, ulong> modifiedAction) public void QueryModified(Action<ulong, ulong> modifiedAction)
{ {
if (!Dirty) if (!Dirty)
@ -66,14 +77,23 @@ namespace Ryujinx.Memory.Tracking
ulong size = HandlesToBytes(splitIndex - handleIndex); ulong size = HandlesToBytes(splitIndex - handleIndex);
// First, the target handle must be removed. Its data can still be used to determine the new handles. // First, the target handle must be removed. Its data can still be used to determine the new handles.
RegionSignal signal = handle.PreAction;
handle.Dispose(); handle.Dispose();
RegionHandle splitLow = _tracking.BeginTracking(address, size); RegionHandle splitLow = _tracking.BeginTracking(address, size);
splitLow.Parent = this; splitLow.Parent = this;
if (signal != null)
{
splitLow.RegisterAction(signal);
}
_handles[handleIndex] = splitLow; _handles[handleIndex] = splitLow;
RegionHandle splitHigh = _tracking.BeginTracking(address + size, handle.Size - size); RegionHandle splitHigh = _tracking.BeginTracking(address + size, handle.Size - size);
splitHigh.Parent = this; splitHigh.Parent = this;
if (signal != null)
{
splitHigh.RegisterAction(signal);
}
_handles[splitIndex] = splitHigh; _handles[splitIndex] = splitHigh;
} }

View file

@ -22,12 +22,12 @@ namespace Ryujinx.Memory.Tracking
public override void Signal(ulong address, ulong size, bool write) public override void Signal(ulong address, ulong size, bool write)
{ {
_tracking.ProtectVirtualRegion(this, MemoryPermission.ReadAndWrite); // Remove our protection immedately.
foreach (var handle in Handles) foreach (var handle in Handles)
{ {
handle.Signal(address, size, write); handle.Signal(address, size, write);
} }
UpdateProtection();
} }
/// <summary> /// <summary>

View file

@ -715,19 +715,23 @@ namespace Ryujinx.Tests.Cpu
}; };
} }
private static uint[] _F_Add_P_S_2SS_() private static uint[] _F_Add_Max_Min_Nm_P_S_2SS_()
{ {
return new uint[] return new uint[]
{ {
0x7E30D820u // FADDP S0, V1.2S 0x7E30D820u, // FADDP S0, V1.2S
0x7E30C820u, // FMAXNMP S0, V1.2S
0x7EB0C820u // FMINNMP S0, V1.2S
}; };
} }
private static uint[] _F_Add_P_S_2DD_() private static uint[] _F_Add_Max_Min_Nm_P_S_2DD_()
{ {
return new uint[] return new uint[]
{ {
0x7E70D820u // FADDP D0, V1.2D 0x7E70D820u, // FADDP D0, V1.2D
0x7E70C820u, // FMAXNMP D0, V1.2D
0x7EF0C820u // FMINNMP D0, V1.2D
}; };
} }
@ -1802,12 +1806,13 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise] [Explicit] [Test, Pairwise] [Explicit]
public void F_Add_P_S_2SS([ValueSource("_F_Add_P_S_2SS_")] uint opcodes, public void F_Add_Max_Min_Nm_P_S_2SS([ValueSource("_F_Add_Max_Min_Nm_P_S_2SS_")] uint opcodes,
[ValueSource("_2S_F_")] ulong a) [ValueSource("_2S_F_")] ulong a)
{ {
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE0E1(z, z); V128 v0 = MakeVectorE0E1(z, z);
V128 v1 = MakeVectorE0(a); V128 v1 = MakeVectorE0E1(a, z);
int rnd = (int)TestContext.CurrentContext.Random.NextUInt(); int rnd = (int)TestContext.CurrentContext.Random.NextUInt();
@ -1820,12 +1825,14 @@ namespace Ryujinx.Tests.Cpu
} }
[Test, Pairwise] [Explicit] [Test, Pairwise] [Explicit]
public void F_Add_P_S_2DD([ValueSource("_F_Add_P_S_2DD_")] uint opcodes, public void F_Add_Max_Min_Nm_P_S_2DD([ValueSource("_F_Add_Max_Min_Nm_P_S_2DD_")] uint opcodes,
[ValueSource("_1D_F_")] ulong a) [ValueSource("_1D_F_")] ulong a0,
[ValueSource("_1D_F_")] ulong a1)
{ {
ulong z = TestContext.CurrentContext.Random.NextULong(); ulong z = TestContext.CurrentContext.Random.NextULong();
V128 v0 = MakeVectorE1(z);
V128 v1 = MakeVectorE0E1(a, a); V128 v0 = MakeVectorE0E1(z, z);
V128 v1 = MakeVectorE0E1(a0, a1);
int rnd = (int)TestContext.CurrentContext.Random.NextUInt(); int rnd = (int)TestContext.CurrentContext.Random.NextUInt();

View file

@ -298,8 +298,7 @@ namespace Ryujinx.Ui.App
} }
catch (Exception exception) catch (Exception exception)
{ {
Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. Errored File: {applicationPath}"); Logger.Warning?.Print(LogClass.Application, $"The file encountered was not of a valid type. File: '{applicationPath}' Error: {exception}");
Logger.Debug?.Print(LogClass.Application, exception.ToString());
numApplicationsFound--; numApplicationsFound--;
_loadingError = true; _loadingError = true;

View file

@ -1,4 +1,5 @@
using Gtk; using Gtk;
using System.Reflection;
namespace Ryujinx.Ui.Applet namespace Ryujinx.Ui.Applet
{ {
@ -6,6 +7,8 @@ namespace Ryujinx.Ui.Applet
{ {
public ErrorAppletDialog(Window parentWindow, DialogFlags dialogFlags, MessageType messageType, string[] buttons) : base(parentWindow, dialogFlags, messageType, ButtonsType.None, null) public ErrorAppletDialog(Window parentWindow, DialogFlags dialogFlags, MessageType messageType, string[] buttons) : base(parentWindow, dialogFlags, messageType, ButtonsType.None, null)
{ {
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png");
int responseId = 0; int responseId = 0;
if (buttons != null) if (buttons != null)

View file

@ -1,4 +1,5 @@
using System; using System;
using OpenTK;
using OpenTK.Input; using OpenTK.Input;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Configuration; using Ryujinx.Configuration;
@ -46,7 +47,7 @@ namespace Ryujinx.Ui
if (keyboard[(Key)_config.LeftJoycon.ButtonL]) buttons |= ControllerKeys.L; if (keyboard[(Key)_config.LeftJoycon.ButtonL]) buttons |= ControllerKeys.L;
if (keyboard[(Key)_config.LeftJoycon.ButtonZl]) buttons |= ControllerKeys.Zl; if (keyboard[(Key)_config.LeftJoycon.ButtonZl]) buttons |= ControllerKeys.Zl;
if (keyboard[(Key)_config.LeftJoycon.ButtonSl]) buttons |= ControllerKeys.SlLeft; if (keyboard[(Key)_config.LeftJoycon.ButtonSl]) buttons |= ControllerKeys.SlLeft;
if (keyboard[(Key)_config.LeftJoycon.ButtonSr]) buttons |= ControllerKeys.SlRight; if (keyboard[(Key)_config.LeftJoycon.ButtonSr]) buttons |= ControllerKeys.SrLeft;
if (keyboard[(Key)_config.RightJoycon.StickButton]) buttons |= ControllerKeys.RStick; if (keyboard[(Key)_config.RightJoycon.StickButton]) buttons |= ControllerKeys.RStick;
if (keyboard[(Key)_config.RightJoycon.ButtonA]) buttons |= ControllerKeys.A; if (keyboard[(Key)_config.RightJoycon.ButtonA]) buttons |= ControllerKeys.A;
@ -56,7 +57,7 @@ namespace Ryujinx.Ui
if (keyboard[(Key)_config.RightJoycon.ButtonPlus]) buttons |= ControllerKeys.Plus; if (keyboard[(Key)_config.RightJoycon.ButtonPlus]) buttons |= ControllerKeys.Plus;
if (keyboard[(Key)_config.RightJoycon.ButtonR]) buttons |= ControllerKeys.R; if (keyboard[(Key)_config.RightJoycon.ButtonR]) buttons |= ControllerKeys.R;
if (keyboard[(Key)_config.RightJoycon.ButtonZr]) buttons |= ControllerKeys.Zr; if (keyboard[(Key)_config.RightJoycon.ButtonZr]) buttons |= ControllerKeys.Zr;
if (keyboard[(Key)_config.RightJoycon.ButtonSl]) buttons |= ControllerKeys.SrLeft; if (keyboard[(Key)_config.RightJoycon.ButtonSl]) buttons |= ControllerKeys.SlRight;
if (keyboard[(Key)_config.RightJoycon.ButtonSr]) buttons |= ControllerKeys.SrRight; if (keyboard[(Key)_config.RightJoycon.ButtonSr]) buttons |= ControllerKeys.SrRight;
return buttons; return buttons;
@ -68,13 +69,16 @@ namespace Ryujinx.Ui
short dx = 0; short dx = 0;
short dy = 0; short dy = 0;
if (keyboard[(Key)_config.LeftJoycon.StickUp]) dy = short.MaxValue;
if (keyboard[(Key)_config.LeftJoycon.StickDown]) dy = -short.MaxValue;
if (keyboard[(Key)_config.LeftJoycon.StickLeft]) dx = -short.MaxValue;
if (keyboard[(Key)_config.LeftJoycon.StickRight]) dx = short.MaxValue;
return (dx, dy); if (keyboard[(Key)_config.LeftJoycon.StickUp]) dy += 1;
if (keyboard[(Key)_config.LeftJoycon.StickDown]) dy += -1;
if (keyboard[(Key)_config.LeftJoycon.StickLeft]) dx += -1;
if (keyboard[(Key)_config.LeftJoycon.StickRight]) dx += 1;
Vector2 stick = new Vector2(dx, dy);
stick.NormalizeFast();
return ((short)(stick.X * short.MaxValue), (short)(stick.Y * short.MaxValue));
} }
public (short, short) GetRightStick() public (short, short) GetRightStick()
@ -84,12 +88,15 @@ namespace Ryujinx.Ui
short dx = 0; short dx = 0;
short dy = 0; short dy = 0;
if (keyboard[(Key)_config.RightJoycon.StickUp]) dy = short.MaxValue; if (keyboard[(Key)_config.RightJoycon.StickUp]) dy += 1;
if (keyboard[(Key)_config.RightJoycon.StickDown]) dy = -short.MaxValue; if (keyboard[(Key)_config.RightJoycon.StickDown]) dy += -1;
if (keyboard[(Key)_config.RightJoycon.StickLeft]) dx = -short.MaxValue; if (keyboard[(Key)_config.RightJoycon.StickLeft]) dx += -1;
if (keyboard[(Key)_config.RightJoycon.StickRight]) dx = short.MaxValue; if (keyboard[(Key)_config.RightJoycon.StickRight]) dx += 1;
return (dx, dy); Vector2 stick = new Vector2(dx, dy);
stick.NormalizeFast();
return ((short)(stick.X * short.MaxValue), (short)(stick.Y * short.MaxValue));
} }
public static HotkeyButtons GetHotkeyButtons(KeyboardState keyboard) public static HotkeyButtons GetHotkeyButtons(KeyboardState keyboard)

View file

@ -22,6 +22,7 @@ using Ryujinx.Ui.Windows;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -110,6 +111,7 @@ namespace Ryujinx.Ui
DefaultWidth = monitorWidth < 1280 ? monitorWidth : 1280; DefaultWidth = monitorWidth < 1280 ? monitorWidth : 1280;
DefaultHeight = monitorHeight < 760 ? monitorHeight : 760; DefaultHeight = monitorHeight < 760 ? monitorHeight : 760;
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png");
Title = $"Ryujinx {Program.Version}"; Title = $"Ryujinx {Program.Version}";
// Hide emulation context status bar. // Hide emulation context status bar.
@ -552,6 +554,8 @@ namespace Ryujinx.Ui
_windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1); _windowsMultimediaTimerResolution = new WindowsMultimediaTimerResolution(1);
} }
DisplaySleep.Prevent();
GlRendererWidget = new GlRenderer(_emulationContext, ConfigurationState.Instance.Logger.GraphicsDebugLevel); GlRendererWidget = new GlRenderer(_emulationContext, ConfigurationState.Instance.Logger.GraphicsDebugLevel);
Application.Invoke(delegate Application.Invoke(delegate
@ -591,7 +595,6 @@ namespace Ryujinx.Ui
ToggleExtraWidgets(true); ToggleExtraWidgets(true);
} }
_viewBox.Remove(GlRendererWidget);
GlRendererWidget.Exit(); GlRendererWidget.Exit();
if(GlRendererWidget.Window != Window && GlRendererWidget.Window != null) if(GlRendererWidget.Window != Window && GlRendererWidget.Window != null)
@ -603,7 +606,9 @@ namespace Ryujinx.Ui
_windowsMultimediaTimerResolution?.Dispose(); _windowsMultimediaTimerResolution?.Dispose();
_windowsMultimediaTimerResolution = null; _windowsMultimediaTimerResolution = null;
DisplaySleep.Restore();
_viewBox.Remove(GlRendererWidget);
_viewBox.Add(_gameTableWindow); _viewBox.Add(_gameTableWindow);
_gameTableWindow.Expand = true; _gameTableWindow.Expand = true;
@ -711,6 +716,7 @@ namespace Ryujinx.Ui
// Wait for the other thread to dispose the HLE context before exiting. // Wait for the other thread to dispose the HLE context before exiting.
_deviceExitStatus.WaitOne(); _deviceExitStatus.WaitOne();
GlRendererWidget.Dispose();
} }
} }
@ -1029,6 +1035,11 @@ namespace Ryujinx.Ui
thread.Start(); thread.Start();
} }
} }
catch (LibHac.MissingKeyException ex)
{
Logger.Error?.Print(LogClass.Application, ex.ToString());
UserErrorDialog.CreateUserErrorDialog(UserError.NoKeys);
}
catch (Exception ex) catch (Exception ex)
{ {
GtkDialog.CreateErrorDialog(ex.Message); GtkDialog.CreateErrorDialog(ex.Message);
@ -1200,4 +1211,4 @@ namespace Ryujinx.Ui
UpdateGameTable(); UpdateGameTable();
} }
} }
} }

View file

@ -1,105 +1,232 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg
<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" xmlns:dc="http://purl.org/dc/elements/1.1/"
viewBox="0 0 1000.8 1000" style="enable-background:new 0 0 1000.8 1000;" xml:space="preserve"> xmlns:cc="http://creativecommons.org/ns#"
<style type="text/css"> xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 1000.8 1000"
style="enable-background:new 0 0 1000.8 1000;"
xml:space="preserve"
sodipodi:docname="JoyConLeft.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"><metadata
id="metadata85"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs83" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1003"
id="namedview81"
showgrid="false"
inkscape:zoom="0.66711859"
inkscape:cx="290.89733"
inkscape:cy="479.45052"
inkscape:window-x="1400"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<style
type="text/css"
id="style2">
.st0{opacity:0.1;} .st0{opacity:0.1;}
.st1{fill:#02C5E5;} .st1{fill:#02C5E5;}
.st2{fill:#FFFFFF;} .st2{fill:#FFFFFF;}
</style> </style>
<g class="st0">
<path class="st1" d="M419.1,642.6v67.6c0,3.3-2.7,6-6,6h-4.2v-79.5h4.2C416.4,636.6,419.1,639.3,419.1,642.6z"/>
<path class="st1" d="M419.1,239.8v67.6c0,3.3-2.7,6-6,6h-4.2v-79.5h4.2C416.4,233.9,419.1,236.5,419.1,239.8z"/>
<path class="st1" d="M330.1,7v2.6h-54.2c-84.8,0-161.4,50.7-194.6,128.7l-3.4-3.4c-1.8-1.7-2.3-4.4-1.3-6.6
C111.2,50.8,188.1,1,272.9,1h51.2C327.4,1,330.1,3.7,330.1,7z"/>
<path class="st1" d="M359.6,115.1h-46.9c-1.6,0-3-1.3-3-3v-11.7c0-1.6,1.3-3,3-3h46.9c1.6,0,3,1.3,3,3v11.7
C362.6,113.8,361.3,115.1,359.6,115.1z"/>
<circle class="st1" cx="237.9" cy="464.4" r="37.5"/>
<circle class="st1" cx="237.9" cy="611.3" r="37.5"/>
<circle class="st1" cx="311.4" cy="537.9" r="37.5"/>
<ellipse class="st1" cx="164.5" cy="537.9" rx="37.5" ry="37.5"/>
<path class="st1" d="M269.1,689.9h45c4.9,0,8.9,4,8.9,8.9v45c0,4.9-4,8.9-8.9,8.9h-45c-4.9,0-8.9-4-8.9-8.9v-45
C260.2,693.9,264.2,689.9,269.1,689.9z"/>
<circle class="st1" cx="291.6" cy="721.3" r="19.4"/>
<path class="st1" d="M234.6,187.1v12.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.2h-12.3
C164.3,220.1,195.5,188.9,234.6,187.1z"/>
<path class="st1" d="M234.6,325.6v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7
C232.4,320.1,234.6,322.6,234.6,325.6z"/>
<path class="st1" d="M313.3,265.9c-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.2L313.3,265.9z"/>
<path class="st1" d="M313.3,259.2H301c-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.9v-12.3
C280.3,188.9,311.6,220.1,313.3,259.2z"/>
<path class="st1" d="M313.4,262.5c0,1.1,0,2.2-0.1,3.3H301c-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 <style
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 type="text/css"
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 id="style2-6">
c0.4,2.9,2.9,5.1,5.9,5.2h12.3C313.4,260.3,313.4,261.4,313.4,262.5z"/> .st0{opacity:0.1;}
</g> .st1{fill:#02C5E5;}
<path class="st2" d="M413.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 .st2{fill:#FF5F55;}
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 .st3{fill:#FFFFFF;}
c2.2,4.3,3.4,9.1,3.4,13.9v157.2C419.6,903.7,416.7,906.6,413.1,906.6z M405.2,65.7c-3,0-5.5,2.4-5.5,5.5v828.9c0,3,2.4,5.5,5.5,5.5 </style><g
h7.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.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1 id="g344"><path
c2.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.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1 class="st3"
c2.2-4.2,3.3-8.8,3.3-13.5V71.2c0-3-2.4-5.5-5.5-5.5H405.2z"/> d="m 413.1,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 V 207 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 v 79.2 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 269.7 c 0,4.9 -1.2,9.6 -3.4,14 l -6.7,13 V 716 l 6.7,13 c 2.2,4.3 3.4,9.1 3.4,13.9 v 157.2 c 0,3.6 -2.9,6.5 -6.5,6.5 z M 405.2,65.7 c -3,0 -5.5,2.4 -5.5,5.5 v 828.9 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 742.9 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 340.1 c 0,-4.7 -1.1,-9.3 -3.3,-13.5 l -6.8,-13.1 c 0,-0.1 -0.1,-0.2 -0.1,-0.2 v -79.5 c 0,-0.1 0,-0.2 0.1,-0.2 l 6.8,-13.1 c 2.2,-4.2 3.3,-8.8 3.3,-13.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z"
<path class="st2" d="M399.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 id="path66-7"
C399.8,858.7,399.6,858.9,399.3,858.9z M388.6,857.9h10.2V72.5h-10.2V857.9z"/> style="fill:#000000" /><path
<path class="st2" d="M382.1,1000H275.9C158.9,1000,64,905.2,64,788.1l0,0V220.9C64,104.1,159.1,9.1,275.9,9.1h106.2 class="st3"
c3.6,0,6.5,2.9,6.5,6.5v978C388.6,997.1,385.7,1000,382.1,1000z M275.9,10.1C159.6,10.1,65,104.7,65,220.9v567.2 d="m 399.3,858.9 h -11.2 c -0.3,0 -0.5,-0.2 -0.5,-0.5 V 72 c 0,-0.3 0.2,-0.5 0.5,-0.5 h 11.2 c 0.3,0 0.5,0.2 0.5,0.5 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 z m -10.7,-1 h 10.2 V 72.5 h -10.2 z"
C65,904.4,159.6,999,275.9,999h106.2c3,0,5.5-2.4,5.5-5.5v-978c0-3-2.4-5.5-5.5-5.5H275.9V10.1z"/> id="path68-5"
<polygon class="st1" points="237.9,448.9 225.8,469.9 250,469.9 "/> style="fill:#000000" /><path
<polygon class="st1" points="237.9,626.9 225.8,605.9 250,605.9 "/> class="st3"
<polygon class="st1" points="148.9,537.9 169.9,550 169.9,525.8 "/> d="M 382.1,1000 H 275.9 C 158.9,1000 64,905.2 64,788.1 c 0,0 0,0 0,0 V 220.9 C 64,104.1 159.1,9.1 275.9,9.1 h 106.2 c 3.6,0 6.5,2.9 6.5,6.5 v 978 c 0,3.5 -2.9,6.4 -6.5,6.4 z M 275.9,10.1 C 159.6,10.1 65,104.7 65,220.9 V 788.1 C 65,904.4 159.6,999 275.9,999 h 106.2 c 3,0 5.5,-2.4 5.5,-5.5 v -978 c 0,-3 -2.4,-5.5 -5.5,-5.5 H 275.9 Z"
<polygon class="st1" points="326.9,537.9 305.9,550 305.9,525.8 "/> id="path70-3"
<path class="st1" d="M413.1,717.1h-4.2c-0.6,0-1-0.4-1-1l0,0v-79.5c0-0.6,0.4-1,1-1l0,0h4.2c3.8,0,6.9,3.1,7,7v67.6 style="fill:#000000" /><path
C420.1,714,417,717.1,413.1,717.1z M409.9,715.1h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V715.1z"/> class="st1"
<path class="st1" d="M413.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 d="m 413.1,717.1 h -4.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -79.5 c 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z"
C420.1,311.2,417,314.3,413.1,314.3z M409.9,312.3h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V312.3z"/> id="path98"
<path class="st1" d="M81.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.8C110.5,50.1,187.7,0.1,272.9,0h51.2 style="fill:#000000" /><path
c3.8,0,6.9,3.1,7,7v2.6c0,0.6-0.4,1-1,1h-54.2C191.4,10.5,115.1,61,82.2,138.7c-0.1,0.3-0.4,0.5-0.7,0.6 class="st1"
C81.4,139.3,81.3,139.3,81.3,139.3z M272.9,2C188.5,2.1,112,51.7,77.5,128.7c-0.8,1.9-0.4,4.1,1.1,5.5l2.4,2.4 d="m 413.1,314.3 h -4.2 c -0.6,0 -1,-0.4 -1,-1 v -79.5 c 0,-0.6 0.4,-1 1,-1 h 4.2 c 3.8,0 6.9,3.1 7,7 v 67.6 c 0,3.8 -3.1,6.9 -7,6.9 z m -3.2,-2 h 3.2 c 2.7,0 5,-2.2 5,-5 v -67.6 c 0,-2.7 -2.2,-5 -5,-5 h -3.2 z"
C114.6,58.8,191.3,8.5,276,8.6h53.2V7c0-2.7-2.2-5-5-5H272.9z"/> id="path100"
<path class="st1" d="M359.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 style="fill:#000000" /><path
C363.6,114.3,361.8,116.1,359.6,116.1z M312.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 style="fill:#01c6e6;fill-opacity:0.992157;stroke:#4d4d4d;stroke-width:1"
c0-1.1-0.9-2-2-2H312.7z"/> d="m 257.47599,997.49473 c -26.30234,-2.3493 -49.90186,-9.17738 -75.04426,-21.71262 C 117.17154,943.24531 74.755874,881.82088 66.727355,808.2243 64.943441,791.87136 64.94041,218.41588 66.724145,200.93415 69.379611,174.90893 75.914592,151.99608 87.247373,128.97592 118.63505,65.218492 179.0982,21.796519 249.3051,12.593199 c 18.18131,-2.383363 133.61873,-2.6919419 135.94726,-0.363405 1.12672,1.12671 1.45478,112.251076 1.45478,492.764216 0,484.50248 -0.0325,491.32681 -2.34493,492.5644 -2.80172,1.49943 -109.98822,1.44564 -126.88622,-0.0636 z"
<path class="st1" d="M237.9,502.9c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 id="path1144" /><polygon
C276.4,485.7,259.2,502.9,237.9,502.9z M237.9,428c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 class="st1"
c20.1,0,36.5-16.3,36.5-36.5S258.1,428,237.9,428z"/> points="237.9,448.9 225.8,469.9 250,469.9 "
<path class="st1" d="M237.9,649.8c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 id="polygon80"
S259.2,649.8,237.9,649.8z M237.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 style="fill:#333333;stroke:#4d4d4d;stroke-width:0.927894"
C274.4,591.2,258.1,574.9,237.9,574.9z"/> transform="matrix(1.1037134,0,0,1.0523169,-24.636066,-24.267048)" /><polygon
<path class="st1" d="M311.4,576.3c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0 class="st1"
C349.8,559.1,332.6,576.3,311.4,576.3z M311.4,501.4c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5c20.1,0,36.5-16.3,36.5-36.5 points="250,605.9 237.9,626.9 225.8,605.9 "
l0,0C347.8,517.7,331.5,501.4,311.4,501.4L311.4,501.4z"/> id="polygon82"
<path class="st1" d="M164.5,576.3c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0 style="fill:#333333;stroke:#4d4d4d;stroke-width:0.957418"
C202.9,559.1,185.7,576.3,164.5,576.3z M164.5,501.4c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 transform="matrix(1.0574383,0,0,1.0316716,-13.259456,-19.457378)" /><polygon
c20.1,0,36.5-16.3,36.5-36.5l0,0C200.9,517.7,184.6,501.4,164.5,501.4L164.5,501.4z"/> class="st1"
<path class="st1" d="M314.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 points="169.9,525.8 148.9,537.9 169.9,550 "
C324,749.3,319.5,753.7,314.1,753.7z M269.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 id="polygon84"
c0-4.4-3.6-7.9-7.9-7.9H269.1z"/> style="fill:#333333;stroke:#4d4d4d;stroke-width:0.931439"
<path class="st1" d="M291.6,741.7c-11.3,0-20.4-9.2-20.4-20.4c0-11.3,9.2-20.4,20.4-20.4c11.3,0,20.4,9.2,20.4,20.4l0,0 transform="matrix(1.0443863,0,0,1.1036462,-7.5389156,-55.555947)" /><polygon
C312,732.6,302.9,741.7,291.6,741.7z M291.6,702.8c-10.2,0-18.4,8.3-18.4,18.4s8.3,18.4,18.4,18.4c10.2,0,18.4-8.3,18.4-18.4 class="st1"
S301.8,702.9,291.6,702.8z"/> points="326.9,537.9 305.9,550 305.9,525.8 "
<path class="st1" d="M174.8,260.2h-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.3s0.3,0.4,0.3,0.7v12.3 id="polygon86"
c0,3.5-2.6,6.4-6,6.9c-24.7,3.7-44.2,23.1-47.9,47.9C181.2,257.6,178.3,260.2,174.8,260.2z M163.6,258.2h11.2c2.5,0,4.6-1.8,4.9-4.3 style="fill:#333333;stroke:#4d4d4d;stroke-width:0.849928"
c3.9-25.6,24-45.7,49.6-49.6c2.5-0.3,4.3-2.4,4.3-4.9v-11.2C196.2,190.3,165.7,220.8,163.6,258.2L163.6,258.2z"/> transform="matrix(1.2181479,0,0,1.1364095,-67.797686,-73.39984)" /><path
<path class="st1" d="M234.6,338.9L234.6,338.9c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1l0,0h12.3c3.5,0,6.4,2.6,6.9,6 class="st1"
c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9V338C235.6,338.5,235.1,338.9,234.6,338.9L234.6,338.9z M163.6,266.9 d="m 81.300444,139.3 c -0.3,0 -0.5,-0.1 -0.7,-0.3 l -3.4,-3.4 c -2,-2 -2.6,-5.1 -1.5,-7.8 C 110.50044,50.1 187.70044,0.1 272.90044,0 h 51.2 c 3.8,0 6.9,3.1 7,7 v 2.6 c 0,0.6 -0.4,1 -1,1 h -54.2 c -84.5,-0.1 -160.8,50.4 -193.699996,128.1 -0.1,0.3 -0.4,0.5 -0.7,0.6 -0.1,0 -0.2,0 -0.2,0 z M 272.90044,2 c -84.4,0.1 -160.9,49.7 -195.399996,126.7 -0.8,1.9 -0.4,4.1 1.1,5.5 l 2.4,2.4 C 114.60044,58.8 191.30044,8.5 276.00044,8.6 h 53.2 V 7 c 0,-2.7 -2.2,-5 -5,-5 z"
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.3H163.6z"/> id="path102"
<path class="st1" d="M241.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 style="fill:#000000" /><path
h12.3c0.6,0,1,0.4,1,1l0,0C312.6,305.5,280.9,337.2,241.3,338.9L241.3,338.9z M301,266.9c-2.5,0-4.6,1.8-4.9,4.3 class="st1"
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-70H301z"/> d="m 359.60044,116.1 h -46.9 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 46.9 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 z m -46.9,-17.6 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 46.9 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 z"
<path class="st1" d="M313.3,260.2H301c-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 id="path104"
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,73C314.3,259.7,313.9,260.2,313.3,260.2L313.3,260.2L313.3,260.2z style="fill:#000000" /><path
M242.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 class="st1"
C310.1,220.8,279.6,190.3,242.3,188.2L242.3,188.2z"/> d="m 237.90044,502.9 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.2 -16.3,-36.5 -36.5,-36.5 z"
<path class="st1" d="M237.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 id="path106"
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 style="fill:#000000" /><path
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 class="st1"
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 d="m 237.90044,649.8 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.3 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.2,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 0,-20.2 -16.3,-36.5 -36.5,-36.5 z"
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.9H301c-2.5,0-4.6,1.8-4.9,4.3 id="path108"
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,1C240.2,339,239.1,339,237.9,339z M235.6,337 style="fill:#000000" /><path
c1.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.3c0-0.8,0-1.5,0-2.3 class="st1"
s0-1.6,0-2.3H301c-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 d="m 311.40044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z"
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.3c0,0.8,0,1.5,0,2.3s0,1.6,0,2.3h11.3 id="path110"
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.9L235.6,337z"/> style="fill:#000000" /><path
</svg> class="st1"
d="m 164.50044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z"
id="path112"
style="fill:#000000" /><path
class="st1"
d="m 314.10044,753.7 h -45 c -5.5,0 -9.9,-4.4 -9.9,-9.9 v -45 c 0,-5.5 4.4,-9.9 9.9,-9.9 h 45 c 5.5,0 9.9,4.4 9.9,9.9 v 45 c 0,5.5 -4.5,9.9 -9.9,9.9 z m -45,-62.8 c -4.4,0 -7.9,3.6 -7.9,7.9 v 45 c 0,4.4 3.6,7.9 7.9,7.9 h 45 c 4.4,0 7.9,-3.6 7.9,-7.9 v -45 c 0,-4.4 -3.6,-7.9 -7.9,-7.9 z"
id="path114"
style="fill:#000000" /><path
class="st1"
d="m 291.60044,741.7 c -11.3,0 -20.4,-9.2 -20.4,-20.4 0,-11.3 9.2,-20.4 20.4,-20.4 11.3,0 20.4,9.2 20.4,20.4 0,0 0,0 0,0 0,11.3 -9.1,20.4 -20.4,20.4 z m 0,-38.9 c -10.2,0 -18.4,8.3 -18.4,18.4 0,10.1 8.3,18.4 18.4,18.4 10.2,0 18.4,-8.3 18.4,-18.4 0,-10.1 -8.2,-18.3 -18.4,-18.4 z"
id="path116"
style="fill:#000000" /><path
class="st1"
d="m 174.80044,260.2 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z"
id="path118"
style="fill:#000000" /><path
class="st1"
d="m 234.60044,338.9 v 0 c -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 V 338 c -0.1,0.5 -0.6,0.9 -1.1,0.9 z m -71,-72 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z"
id="path120"
style="fill:#000000" /><path
class="st1"
d="m 241.30044,338.9 c -0.6,0 -1,-0.4 -1,-1 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.5,71.4 -73.1,73.1 z m 59.7,-72 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 11.2 c 37.4,-2.2 67.8,-32.6 70,-70 z"
id="path122"
style="fill:#000000" /><path
class="st1"
d="m 313.30044,260.2 h -12.3 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1.1 -0.9,1.1 0,0 0,0 0,0 z m -71,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.2,-37.4 -32.7,-67.9 -70,-70 z"
id="path124"
style="fill:#000000" /><path
class="st1"
d="m 237.90044,339 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 h -12.3 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0.1 -2.2,0.1 -3.4,0.1 z m -2.3,-2 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 h -11.4 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 z"
id="path126"
style="fill:#000000" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999997"
d="m 158.02789,574.27925 c -14.73064,-3.25266 -24.85554,-12.70578 -29.04419,-27.11717 -0.98592,-3.39218 -1.21679,-6.26957 -0.93511,-11.65556 0.33774,-6.4583 0.67944,-7.76803 3.52546,-13.51272 11.35216,-22.91431 40.68588,-27.928 58.61532,-10.01846 19.42229,19.40073 11.99924,51.86436 -13.89781,60.78009 -5.19354,1.788 -13.81105,2.50701 -18.26367,1.52382 z m 12.59864,-36.29462 c 0,-7.35074 -0.18108,-13.36496 -0.40241,-13.36496 -0.89601,0 -23.32454,13.1809 -22.99291,13.51259 0.66445,0.66458 22.24473,13.11359 22.82266,13.1657 0.31497,0.0284 0.57266,-5.96261 0.57266,-13.31333 z"
id="path179" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999997"
d="m 232.50517,500.57091 c -6.91699,-0.86484 -15.04235,-4.99807 -20.4853,-10.42051 -14.58513,-14.53016 -14.55979,-36.85709 0.0584,-51.42015 23.0282,-22.94142 62.26853,-6.95317 62.26853,25.37095 0,10.34881 -3.46897,18.75364 -10.723,25.98031 -8.34032,8.30891 -19.22192,11.97685 -31.1186,10.4894 z m 18.58209,-30.69278 c -0.91811,-2.38357 -12.79282,-22.35099 -13.28879,-22.34521 -0.45143,0.005 -5.88471,9.05299 -11.95805,19.91302 l -2.0157,3.60439 h 13.85703 c 12.18288,0 13.80248,-0.14161 13.40551,-1.1722 z"
id="path181" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999997"
d="m 229.21434,646.98161 c -12.9232,-3.46654 -23.15418,-13.73508 -26.52403,-26.62142 -5.92248,-22.64757 11.58541,-45.21876 35.15949,-45.32763 7.44717,-0.0344 11.29183,0.91312 18.09999,4.46071 16.90217,8.80735 23.84898,30.39169 15.40753,47.87245 -7.54225,15.61868 -25.6403,24.04261 -42.14298,19.61589 z M 245.434,616.92014 c 3.65424,-6.30197 6.48622,-11.61534 6.29329,-11.8075 -0.19293,-0.19216 -6.40658,-0.25572 -13.80812,-0.14123 l -13.45735,0.20814 6.66623,11.58776 c 3.66642,6.37327 6.89025,11.59297 7.16405,11.59935 0.27381,0.006 3.48766,-5.14457 7.1419,-11.44652 z"
id="path185" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 307.85537,574.24407 c -0.34478,-0.0389 -1.62711,-0.27075 -2.84962,-0.51537 -11.23844,-2.24892 -20.9226,-9.70179 -26.17378,-20.1432 -2.82839,-5.62398 -4.20289,-12.18393 -3.75883,-17.93953 1.14218,-14.80435 11.33006,-27.74217 25.61809,-32.53303 8.75405,-2.93529 18.04495,-2.18507 26.72988,2.15843 8.69225,4.34715 15.48783,12.11097 18.64346,21.29973 5.25881,15.31297 -0.71552,32.17026 -14.73029,41.56334 -5.99457,4.01773 -13.35804,6.28235 -20.18834,6.20884 -1.46502,-0.0157 -2.94577,-0.0604 -3.29057,-0.0993 z m -0.66719,-23.08553 c 0.71175,-0.35815 3.02697,-1.62049 5.14496,-2.80516 8.66766,-4.84825 15.63944,-9.1681 16.21592,-10.0477 0.27948,-0.42642 0.28078,-0.49758 0.0166,-0.90068 -0.86957,-1.32678 -21.50733,-13.52937 -22.8817,-13.52937 -0.25925,0 -0.5656,0.11351 -0.68079,0.25225 -0.41371,0.49837 -0.59707,4.78502 -0.59431,13.89388 0.003,9.06159 0.17803,13.03427 0.59744,13.53951 0.32082,0.38645 0.78324,0.3011 2.18189,-0.40273 z"
id="path187" /><path
style="fill:#333333;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 287.96017,739.09726 c -1.01606,-0.21912 -2.9756,-0.9477 -4.35453,-1.61905 -2.09414,-1.01956 -2.88115,-1.59464 -4.77748,-3.49097 -1.89792,-1.89791 -2.4703,-2.68159 -3.48941,-4.77748 -2.66648,-5.48389 -2.66607,-10.55714 10e-4,-16.08572 1.0133,-2.10022 1.56326,-2.85257 3.48092,-4.76199 3.62968,-3.61405 7.72755,-5.3398 12.70198,-5.34921 8.35146,-0.0158 15.68299,5.71579 17.81213,13.92506 0.52326,2.01754 0.54009,6.16569 0.0339,8.34799 -1.47072,6.34008 -6.30854,11.44929 -12.69973,13.41212 -2.44922,0.7522 -6.26202,0.92699 -8.70906,0.39925 z"
id="path189" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 267.23012,751.2862 c -1.59942,-0.43597 -2.94763,-1.29847 -4.05871,-2.59652 -1.81264,-2.11766 -1.73429,-0.87988 -1.73429,-27.39725 0,-26.73402 -0.0972,-25.30688 1.87658,-27.54923 0.58306,-0.66239 1.71204,-1.51487 2.55332,-1.92799 l 1.5081,-0.74058 h 24.1534 24.15339 l 1.77672,0.87468 c 1.25727,0.61895 2.04823,1.23027 2.70544,2.091 1.78729,2.34073 1.72742,1.33094 1.64816,27.80036 -0.0712,23.78487 -0.0733,23.86757 -0.63865,25.09049 -0.72339,1.56486 -2.26169,3.10316 -3.93043,3.93043 l -1.30842,0.64864 -23.75199,0.0516 c -18.21394,0.0396 -24.03192,-0.0247 -24.95262,-0.27565 z m 27.28995,-9.68076 c 10.60326,-1.53286 18.09097,-10.66806 17.50501,-21.35655 -0.18432,-3.36213 -0.66908,-5.27077 -2.04745,-8.06138 -4.59235,-9.29756 -15.46557,-13.67756 -25.3079,-10.19463 -2.76161,0.97725 -4.68871,2.16763 -7.02836,4.34145 -3.05146,2.83517 -5.11688,6.34636 -6.04249,10.27217 -0.50715,2.151 -0.50715,7.22087 0,9.37186 0.92171,3.90925 2.95421,7.3745 6.0133,10.25221 2.20884,2.07787 4.16469,3.31668 6.72144,4.2573 3.40627,1.25315 6.72782,1.61756 10.18645,1.11757 z"
id="path191" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 235.77295,330.34531 c 0,-6.0203 -0.0462,-6.51813 -0.73076,-7.87124 -1.06164,-2.09851 -2.95253,-3.39477 -5.65313,-3.87537 -15.06064,-2.68022 -27.49575,-10.15006 -36.51861,-21.93692 -4.96934,-6.49162 -8.83069,-15.11098 -10.3887,-23.18981 -0.83474,-4.3284 -1.3998,-5.65891 -2.97647,-7.00848 -1.7724,-1.51711 -3.30405,-1.79252 -9.96885,-1.79252 h -5.86461 v -2.11107 -2.11107 h 6.26944 c 6.12912,0 6.30805,-0.0192 7.9945,-0.85963 2.44443,-1.21811 3.32179,-2.74063 4.22338,-7.32906 4.56927,-23.25403 22.39532,-40.97679 45.63214,-45.36773 4.16129,-0.78634 5.57438,-1.57205 6.90818,-3.84114 0.9048,-1.53927 0.91186,-1.5954 1.02116,-8.12677 l 0.11006,-6.57679 h 2.0822 2.0822 v 6.27497 c 0,6.20191 0.0104,6.29547 0.89315,8.03629 1.32629,2.61551 2.65075,3.37644 7.56606,4.34684 19.37922,3.82593 35.08856,16.98397 42.28514,35.41774 1.04383,2.67375 1.9437,5.93165 3.31831,12.01372 0.58905,2.60627 1.67368,4.16462 3.60307,5.17675 1.1513,0.60396 1.95144,0.68258 7.85861,0.77219 l 6.57679,0.0998 v 2.0925 2.09249 h -6.26944 c -6.12912,0 -6.30805,0.0192 -7.9945,0.85963 -2.20181,1.09721 -3.39863,2.90223 -3.90849,5.89474 -4.06097,23.83452 -22.22419,42.32715 -45.97159,46.8053 -4.2535,0.8021 -5.71797,1.66037 -6.96502,4.08193 -0.79329,1.54043 -0.83455,1.89301 -0.94026,8.03533 l -0.11057,6.42419 h -2.08169 -2.0817 z"
id="path1082" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 163.78864,257.28223 c 0.0926,-0.49123 0.26012,-1.9162 0.37218,-3.1666 0.34565,-3.85681 1.73866,-10.12043 3.27937,-14.74553 8.02141,-24.0797 28.10082,-42.70464 52.74332,-48.92282 3.12397,-0.78829 7.58171,-1.54879 11.2861,-1.92544 l 2.02988,-0.20639 v 5.8726 c 0,8.54266 -0.3854,9.15422 -6.53853,10.37563 -18.42711,3.65779 -33.66767,15.25204 -41.92018,31.89074 -2.55007,5.14144 -4.14587,10.08856 -5.47376,16.9691 -0.45828,2.3746 -1.81844,3.9985 -3.71595,4.43649 -0.71452,0.16493 -3.75876,0.30335 -6.76499,0.30761 l -5.46587,0.008 z"
id="path1084" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 229.76452,336.39384 c -26.99792,-3.04756 -50.79328,-21.35759 -60.92173,-46.87799 -2.38214,-6.00221 -4.22117,-13.35788 -4.67827,-18.71196 -0.11259,-1.31887 -0.27512,-2.73804 -0.36117,-3.1537 l -0.15645,-0.75574 6.32279,0.10618 c 5.78597,0.0972 6.39885,0.16304 7.21874,0.77582 1.58067,1.18137 2.03872,2.1715 2.89278,6.25312 1.21968,5.82894 2.45374,9.35857 5.18759,14.8375 2.85902,5.72977 5.67403,9.77885 9.85937,14.18161 8.62003,9.0678 19.6967,15.16512 31.73111,17.46684 3.63419,0.69508 4.63135,1.16546 5.80819,2.73983 0.6132,0.82034 0.6781,1.4276 0.77012,7.20628 0.0943,5.92221 0.0643,6.30785 -0.48717,6.26798 -0.32321,-0.0233 -1.75687,-0.17446 -3.1859,-0.33577 z"
id="path1086" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 299.6703,257.71116 c -2.39043,-0.853 -2.81858,-1.58503 -3.81252,-6.51855 -3.66786,-18.20579 -15.40436,-33.45997 -31.99138,-41.57986 -4.81668,-2.35792 -8.58209,-3.67044 -13.47836,-4.69819 -4.72195,-0.99115 -6.17077,-1.58672 -7.05619,-2.9006 -0.70499,-1.04613 -0.73853,-1.38133 -0.73853,-7.38107 0,-3.45685 0.11517,-6.28518 0.25593,-6.28518 0.14076,0 1.93111,0.20926 3.97855,0.46502 11.96867,1.4951 22.85594,5.62979 32.79042,12.45291 4.36974,3.00118 7.416,5.6069 11.57682,9.90259 9.30395,9.60553 15.50823,20.66713 18.77966,33.48224 0.93232,3.65217 2.12151,10.886 2.12151,12.90514 0,0.58643 -0.30132,0.619 -5.60245,0.60551 -3.82949,-0.01 -5.98886,-0.15214 -6.82346,-0.44996 z"
id="path1088" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 242.3249,330.46177 c 0.097,-5.7735 0.163,-6.38655 0.77566,-7.20629 1.18269,-1.58243 2.17182,-2.02925 6.33209,-2.86041 23.48707,-4.69236 41.89612,-23.31363 46.43689,-46.97223 0.66775,-3.47916 1.14738,-4.47847 2.71006,-5.64639 0.81991,-0.6128 1.43277,-0.67865 7.22079,-0.77584 l 6.32483,-0.10621 -0.19591,1.73011 c -1.19107,10.51857 -3.29919,17.9842 -7.45853,26.41337 -11.17834,22.65366 -32.93361,38.14197 -57.96776,41.26919 -2.04744,0.25577 -3.84896,0.46502 -4.00338,0.46502 -0.15442,0 -0.23305,-2.83964 -0.17474,-6.31032 z"
id="path1090" /><path
style="fill:#000000;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999998"
d="m 311.60253,113.45766 c -0.55307,-0.55307 -0.67321,-1.83753 -0.67321,-7.19731 0,-4.50308 0.15925,-6.68335 0.51409,-7.03819 0.38766,-0.38766 6.43841,-0.5141 24.60307,-0.5141 21.32785,0 24.16614,0.0772 24.76219,0.67322 0.55166,0.55166 0.67322,1.82364 0.67322,7.0445 0,6.09825 -0.0408,6.39986 -0.95215,7.03819 -0.83385,0.58406 -3.89051,0.66691 -24.60307,0.66691 -20.92962,0 -23.72838,-0.0775 -24.32414,-0.67322 z"
id="path1092" /><path
style="fill:#000000;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999998"
d="m 78.977784,134.18912 c -2.35328,-2.74929 -2.18932,-3.66269 2.26682,-12.62797 C 92.012734,99.89682 104.871,81.96966 121.771,65.058734 153.11752,33.69194 193.3541,12.833792 237.03838,5.305545 252.10894,2.708387 253.57756,2.630423 291.07604,2.43687 l 34.76922,-0.179466 1.35092,1.207149 c 0.9677,0.864713 1.41875,1.712966 1.59003,2.990242 l 0.23911,1.783092 -33.78877,0.194148 c -36.2509,0.208295 -38.76527,0.335101 -53.2555,2.685802 -38.392,6.2282 -72.8916,22.039868 -103.29303,47.340693 -6.79226,5.652686 -19.46547,18.33117 -25.22484,25.23531 -8.3636,10.02603 -16.479016,21.67655 -22.544486,32.36489 -3.07683,5.42188 -9.61802,18.64996 -9.61802,19.45027 0,0.91062 -0.80534,0.45303 -2.32289,-1.31988 z"
id="path1094" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 398.20583,464.93186 c 0,-216.02489 0.12146,-304.39871 0.26991,-196.38626 0.14845,108.01244 0.14845,284.76008 0,392.77252 -0.14845,108.01245 -0.26991,19.63863 -0.26991,-196.38626 z"
id="path1150" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 401.44318,902.40274 c -1.48283,-2.11702 -1.64585,-43.40647 -1.64585,-416.85429 0,-373.44781 0.16302,-414.737261 1.64585,-416.854286 1.37591,-1.964385 2.64173,-2.349769 7.718,-2.349769 3.33969,0 6.64309,0.570921 7.34088,1.268713 0.96181,0.961813 1.26871,18.598983 1.26871,72.911362 0,69.01305 -0.0775,71.84973 -2.1109,77.28456 -1.161,3.10304 -3.53984,7.89508 -5.28631,10.64899 l -3.1754,5.00708 v 40.24031 c 0,37.61687 0.12902,40.42327 1.97893,43.04667 1.08842,1.5435 3.34831,5.42309 5.02199,8.6213 l 3.04306,5.81494 0.27946,141.61892 c 0.30957,156.88126 0.80443,145.17745 -6.6628,157.57802 l -3.66064,6.0791 v 40.51406 c 0,26.52506 0.37415,40.74531 1.08359,41.18376 0.59597,0.36833 2.85586,4.08361 5.02199,8.25617 l 3.9384,7.58648 0.28906,83.91411 c 0.21318,61.88506 -0.029,84.29733 -0.9224,85.37384 -0.77641,0.93553 -3.42147,1.45973 -7.36562,1.45973 -5.161,0 -6.41977,-0.37921 -7.8,-2.34977 z"
id="path1152" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="M 389.22472,464.93186 V 72.687962 h 4.22905 4.22904 v 392.243898 392.2439 h -4.22904 -4.22905 z"
id="path1154" /><path
style="fill:#00c7e7;fill-opacity:0.992157;stroke:#4d4d4d;stroke-width:1"
d="m 409.89998,273.33293 v -38.63294 h 3.04188 c 1.74435,0 3.58682,0.88543 4.31941,2.07573 1.73761,2.82321 1.73761,70.29119 0,73.11439 -0.73259,1.19032 -2.57506,2.07573 -4.31941,2.07573 h -3.04188 z"
id="path1156" /><path
style="fill:#00c7e7;fill-opacity:0.992157;stroke:#4d4d4d;stroke-width:1"
d="m 409.89998,676.164 v -38.66403 h 3.04381 c 1.74545,0 3.58909,0.88613 4.32215,2.07741 1.7387,2.82547 1.7387,70.34777 0,73.17325 -0.73306,1.19129 -2.5767,2.0774 -4.32215,2.0774 h -3.04381 z"
id="path1158" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d=""
id="path1502" /></g></svg>

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View file

@ -1,218 +1,476 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg
<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" xmlns:dc="http://purl.org/dc/elements/1.1/"
viewBox="0 0 1000.8 1000" style="enable-background:new 0 0 1000.8 1000;" xml:space="preserve"> xmlns:cc="http://creativecommons.org/ns#"
<style type="text/css"> xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 1000.8 1000"
style="enable-background:new 0 0 1000.8 1000;"
xml:space="preserve"
sodipodi:docname="JoyConPair.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"><metadata
id="metadata161"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs159" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1003"
id="namedview157"
showgrid="false"
inkscape:zoom="0.70910507"
inkscape:cx="438.34351"
inkscape:cy="472.42785"
inkscape:window-x="1400"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<style
type="text/css"
id="style2">
.st0{opacity:0.1;} .st0{opacity:0.1;}
.st1{fill:#02C5E5;} .st1{fill:#02C5E5;}
.st2{fill:#FF5F55;} .st2{fill:#FF5F55;}
.st3{fill:#FFFFFF;} .st3{fill:#FFFFFF;}
</style> </style>
<g class="st0">
<path class="st1" d="M419.1,642.6v67.6c0,3.3-2.7,6-6,6h-4.2v-79.5h4.2C416.4,636.6,419.1,639.3,419.1,642.6z"/> <g
<path class="st1" d="M419.1,239.8v67.6c0,3.3-2.7,6-6,6h-4.2v-79.5h4.2C416.4,233.9,419.1,236.5,419.1,239.8z"/> class="st0"
<path class="st1" d="M330.1,7v2.6h-54.2c-84.8,0-161.4,50.7-194.6,128.7l-3.4-3.4c-1.8-1.7-2.3-4.4-1.3-6.6 id="g64">
C111.2,50.8,188.1,1,272.9,1h51.2C327.4,1,330.1,3.7,330.1,7z"/> <path
<path class="st1" d="M359.6,115.1h-46.9c-1.6,0-3-1.3-3-3v-11.7c0-1.6,1.3-3,3-3h46.9c1.6,0,3,1.3,3,3v11.7 class="st2"
C362.6,113.8,361.3,115.1,359.6,115.1z"/> d="M597.9,233.9v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6H597.9z"
<circle class="st1" cx="237.9" cy="464.4" r="37.5"/> id="path36" />
<circle class="st1" cx="237.9" cy="611.3" r="37.5"/> <path
<circle class="st1" cx="311.4" cy="537.9" r="37.5"/> class="st2"
d="M597.9,636.6v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6H597.9z"
<ellipse transform="matrix(0.9951 -9.853756e-02 9.853756e-02 0.9951 -52.201 18.8252)" class="st1" cx="164.5" cy="537.9" rx="37.5" ry="37.5"/> id="path38" />
<path class="st1" d="M269.1,689.9h45c4.9,0,8.9,4,8.9,8.9v45c0,4.9-4,8.9-8.9,8.9h-45c-4.9,0-8.9-4-8.9-8.9v-45 <path
C260.2,693.9,264.2,689.9,269.1,689.9z"/> class="st2"
<circle class="st1" cx="291.6" cy="721.3" r="19.4"/> d="M929,134.9l-3.4,3.4C892.4,60.3,815.8,9.6,730.9,9.6h-54.2V7c0-3.3,2.7-6,6-6c0,0,0,0,0,0h51.2 c84.8,0,161.7,49.8,196.4,127.2C931.3,130.5,930.8,133.1,929,134.9z"
<path class="st1" d="M234.6,187.1v12.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.2h-12.3 id="path40" />
C164.3,220.1,195.5,188.9,234.6,187.1z"/> <path
<path class="st1" d="M234.6,325.6v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7 class="st2"
C232.4,320.1,234.6,322.6,234.6,325.6z"/> d="M679.5,94.5V82.8c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3,1.3-3,3c0,0,0,0,0,0v11.7c0,1.6-1.3,3-3,3l0,0h-11.7 c-1.6,0-3,1.3-3,3c0,0,0,0,0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3,1.3,3,3c0,0,0,0,0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7 c1.6,0,3-1.3,3-3v0v-11.7c0-1.6,1.3-3,3-3l0,0h11.7c1.6,0,3-1.3,3-3c0,0,0,0,0,0v-11.7c0-1.6-1.3-3-3-3l0,0h-11.7 C680.8,97.5,679.5,96.1,679.5,94.5C679.5,94.5,679.5,94.5,679.5,94.5z"
<path class="st1" d="M313.3,265.9c-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 id="path42" />
c0.4-2.9,2.9-5.1,5.9-5.2L313.3,265.9z"/> <circle
<path class="st1" d="M313.3,259.2H301c-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.9v-12.3 class="st2"
C280.3,188.9,311.6,220.1,313.3,259.2z"/> cx="768.9"
<path class="st1" d="M313.4,262.5c0,1.1,0,2.2-0.1,3.3H301c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7 cy="333.9"
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 r="37.5"
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 id="circle44" />
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 <circle
c0.4,2.9,2.9,5.1,5.9,5.2h12.3C313.4,260.3,313.4,261.4,313.4,262.5z"/> class="st2"
cx="768.9"
cy="187.1"
r="37.5"
id="circle46" />
<circle
class="st2"
cx="842.3"
cy="260.5"
r="37.5"
id="circle48" />
<circle
class="st2"
cx="695.5"
cy="260.5"
r="37.5"
id="circle50" />
<circle
class="st2"
cx="715"
cy="721.3"
r="27.9"
id="circle52" />
<path
class="st2"
d="M765.6,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.2h-12.3 C695.2,493.3,726.5,462,765.6,460.3z"
id="path54" />
<path
class="st2"
d="M765.6,598.8v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7 C763.4,593.3,765.6,595.8,765.6,598.8z"
id="path56" />
<path
class="st2"
d="M844.3,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.2L844.3,539z"
id="path58" />
<path
class="st2"
d="M844.3,532.4H832c-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.9v-12.3 C811.3,462,842.6,493.3,844.3,532.4z"
id="path60" />
<path
class="st2"
d="M844.4,535.7c0,1.1,0,2.2-0.1,3.3H832c-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.2h12.3C844.3,533.5,844.4,534.6,844.4,535.7z"
id="path62" />
</g> </g>
<g class="st0"> <path
<path class="st2" d="M597.9,233.9v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6H597.9z"/> class="st3"
<path class="st2" d="M597.9,636.6v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6H597.9z"/> d="M413.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.2C419.6,903.7,416.7,906.6,413.1,906.6z M405.2,65.7c-3,0-5.5,2.4-5.5,5.5v828.9c0,3,2.4,5.5,5.5,5.5 h7.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.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1 c2.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.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1 c2.2-4.2,3.3-8.8,3.3-13.5V71.2c0-3-2.4-5.5-5.5-5.5L405.2,65.7z"
<path class="st2" d="M929,134.9l-3.4,3.4C892.4,60.3,815.8,9.6,730.9,9.6h-54.2V7c0-3.3,2.7-6,6-6c0,0,0,0,0,0h51.2 id="path66"
c84.8,0,161.7,49.8,196.4,127.2C931.3,130.5,930.8,133.1,929,134.9z"/> style="fill:#000000" />
<path class="st2" d="M679.5,94.5V82.8c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3,1.3-3,3c0,0,0,0,0,0v11.7c0,1.6-1.3,3-3,3l0,0h-11.7 <path
c-1.6,0-3,1.3-3,3c0,0,0,0,0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3,1.3,3,3c0,0,0,0,0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7 class="st3"
c1.6,0,3-1.3,3-3v0v-11.7c0-1.6,1.3-3,3-3l0,0h11.7c1.6,0,3-1.3,3-3c0,0,0,0,0,0v-11.7c0-1.6-1.3-3-3-3l0,0h-11.7 d="M399.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 C399.8,858.7,399.6,858.9,399.3,858.9z M388.6,857.9h10.2V72.5h-10.2V857.9z"
C680.8,97.5,679.5,96.1,679.5,94.5C679.5,94.5,679.5,94.5,679.5,94.5z"/> id="path68"
<circle class="st2" cx="768.9" cy="333.9" r="37.5"/> style="fill:#000000" />
<circle class="st2" cx="768.9" cy="187.1" r="37.5"/> <path
<circle class="st2" cx="842.3" cy="260.5" r="37.5"/> class="st3"
<circle class="st2" cx="695.5" cy="260.5" r="37.5"/> d="M382.1,1000H275.9C158.9,1000,64,905.2,64,788.1c0,0,0,0,0,0V220.9C64,104.1,159.1,9.1,275.9,9.1h106.2 c3.6,0,6.5,2.9,6.5,6.5v978C388.6,997.1,385.7,1000,382.1,1000z M275.9,10.1C159.6,10.1,65,104.7,65,220.9v567.2 C65,904.4,159.6,999,275.9,999h106.2c3,0,5.5-2.4,5.5-5.5v-978c0-3-2.4-5.5-5.5-5.5H275.9z"
<circle class="st2" cx="715" cy="721.3" r="27.9"/> id="path70"
<path class="st2" d="M765.6,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.2h-12.3 style="fill:#000000" />
C695.2,493.3,726.5,462,765.6,460.3z"/> <path
<path class="st2" d="M765.6,598.8v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7 class="st3"
C763.4,593.3,765.6,595.8,765.6,598.8z"/> d="M601.6,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.5h7.9 c3.6,0,6.4,2.9,6.5,6.5v828.9C608,903.7,605.1,906.6,601.6,906.6z M593.7,65.7c-3,0-5.5,2.4-5.5,5.5V207c0,4.7,1.1,9.3,3.3,13.5 l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-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.5 l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-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.9 c3,0,5.5-2.4,5.5-5.5V71.2c0-3-2.4-5.5-5.5-5.5L593.7,65.7z"
<path class="st2" d="M844.3,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 id="path72"
c0.4-2.9,2.9-5.1,5.9-5.2L844.3,539z"/> style="fill:#000000" />
<path class="st2" d="M844.3,532.4H832c-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.9v-12.3 <path
C811.3,462,842.6,493.3,844.3,532.4z"/> class="st3"
<path class="st2" d="M844.4,535.7c0,1.1,0,2.2-0.1,3.3H832c-3,0-5.5,2.2-5.9,5.2c-3.7,25.2-23.5,45-48.7,48.7 d="M618.8,858.9h-11.3c-0.3,0-0.5-0.2-0.5-0.5c0,0,0,0,0,0V72c0-0.3,0.2-0.5,0.5-0.5h11.3c0.3,0,0.5,0.2,0.5,0.5 v786.4C619.3,858.7,619.1,858.9,618.8,858.9C618.8,858.9,618.8,858.9,618.8,858.9z M608,857.9h10.3V72.5H608V857.9z"
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 id="path74"
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 style="fill:#000000" />
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 <path
c0.4,2.9,2.9,5.1,5.9,5.2h12.3C844.3,533.5,844.4,534.6,844.4,535.7z"/> class="st3"
</g> d="M730.9,1000H624.7c-3.6,0-6.5-2.9-6.5-6.5v-978c0-3.6,2.9-6.5,6.5-6.5h106.2c116.8,0,211.9,95.1,211.9,211.9 v567.2C942.8,905.1,848,1000,730.9,1000C730.9,1000,730.9,1000,730.9,1000z M624.7,10.1c-3,0-5.5,2.4-5.5,5.5v978 c0,3,2.4,5.5,5.5,5.5h106.2c116.3,0,210.9-94.6,210.9-210.9V220.9c0-116.3-94.6-210.9-210.9-210.9L624.7,10.1z"
<path class="st3" d="M413.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 id="path76"
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 style="fill:#000000" />
c2.2,4.3,3.4,9.1,3.4,13.9v157.2C419.6,903.7,416.7,906.6,413.1,906.6z M405.2,65.7c-3,0-5.5,2.4-5.5,5.5v828.9c0,3,2.4,5.5,5.5,5.5
h7.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.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1
c2.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.5c0-0.1,0-0.2,0.1-0.2l6.8-13.1
c2.2-4.2,3.3-8.8,3.3-13.5V71.2c0-3-2.4-5.5-5.5-5.5L405.2,65.7z"/>
<path class="st3" d="M399.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
C399.8,858.7,399.6,858.9,399.3,858.9z M388.6,857.9h10.2V72.5h-10.2V857.9z"/>
<path class="st3" d="M382.1,1000H275.9C158.9,1000,64,905.2,64,788.1c0,0,0,0,0,0V220.9C64,104.1,159.1,9.1,275.9,9.1h106.2
c3.6,0,6.5,2.9,6.5,6.5v978C388.6,997.1,385.7,1000,382.1,1000z M275.9,10.1C159.6,10.1,65,104.7,65,220.9v567.2
C65,904.4,159.6,999,275.9,999h106.2c3,0,5.5-2.4,5.5-5.5v-978c0-3-2.4-5.5-5.5-5.5H275.9z"/>
<path class="st3" d="M601.6,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.5h7.9 <path
c3.6,0,6.4,2.9,6.5,6.5v828.9C608,903.7,605.1,906.6,601.6,906.6z M593.7,65.7c-3,0-5.5,2.4-5.5,5.5V207c0,4.7,1.1,9.3,3.3,13.5 class="st1"
l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-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.5 d="M413.1,717.1h-4.2c-0.6,0-1-0.4-1-1c0,0,0,0,0,0v-79.5c0-0.6,0.4-1,1-1c0,0,0,0,0,0h4.2c3.8,0,6.9,3.1,7,7v67.6 C420.1,714,417,717.1,413.1,717.1z M409.9,715.1h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V715.1z"
l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-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.9 id="path98"
c3,0,5.5-2.4,5.5-5.5V71.2c0-3-2.4-5.5-5.5-5.5L593.7,65.7z"/> style="fill:#000000" />
<path class="st3" d="M618.8,858.9h-11.3c-0.3,0-0.5-0.2-0.5-0.5c0,0,0,0,0,0V72c0-0.3,0.2-0.5,0.5-0.5h11.3c0.3,0,0.5,0.2,0.5,0.5 <path
v786.4C619.3,858.7,619.1,858.9,618.8,858.9C618.8,858.9,618.8,858.9,618.8,858.9z M608,857.9h10.3V72.5H608V857.9z"/> class="st1"
<path class="st3" d="M730.9,1000H624.7c-3.6,0-6.5-2.9-6.5-6.5v-978c0-3.6,2.9-6.5,6.5-6.5h106.2c116.8,0,211.9,95.1,211.9,211.9 d="M413.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 C420.1,311.2,417,314.3,413.1,314.3z M409.9,312.3h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V312.3z"
v567.2C942.8,905.1,848,1000,730.9,1000C730.9,1000,730.9,1000,730.9,1000z M624.7,10.1c-3,0-5.5,2.4-5.5,5.5v978 id="path100"
c0,3,2.4,5.5,5.5,5.5h106.2c116.3,0,210.9-94.6,210.9-210.9V220.9c0-116.3-94.6-210.9-210.9-210.9L624.7,10.1z"/> style="fill:#000000" />
<path class="st3" d="M715,763.2c-23.1,0-41.9-18.7-41.9-41.9s18.7-41.9,41.9-41.9s41.9,18.7,41.9,41.9l0,0
C756.8,744.4,738.1,763.1,715,763.2z M715,680.4c-22.6,0-40.9,18.3-40.9,40.9c0,22.6,18.3,40.9,40.9,40.9
c22.6,0,40.9-18.3,40.9-40.9v0C755.8,698.7,737.6,680.4,715,680.4z"/>
<polygon class="st1" points="237.9,448.9 225.8,469.9 250,469.9 "/>
<polygon class="st1" points="237.9,626.9 225.8,605.9 250,605.9 "/>
<polygon class="st1" points="148.9,537.9 169.9,550 169.9,525.8 "/>
<polygon class="st1" points="326.9,537.9 305.9,550 305.9,525.8 "/>
<path class="st2" d="M782.2,203.2h-5.5l-7.8-12.9l-7.8,12.9h-5.4l10.6-16.3l-9.8-15.6h5.2l7.3,12l7.4-12h5l-9.8,15.4L782.2,203.2z"
/>
<path class="st2" d="M709.2,244.5l-11.6,20.6v11.4h-4.4V265l-11.6-20.5h5.3l6.4,11.7l2.3,4.7l2.2-4.3l6.4-12.1L709.2,244.5z"/>
<path class="st2" d="M855.9,276.5h-4.7l-2.2-7h-13.3l-2.3,7h-4.5l10.6-32h6L855.9,276.5z M847.7,265.6l-5.4-17.1l-5.4,17.1
L847.7,265.6z"/>
<path class="st2" d="M779.4,340.4c0,1.4-0.3,2.8-0.9,4.1c-0.6,1.2-1.5,2.2-2.5,3c-1.2,0.9-2.6,1.5-4,1.9c-1.7,0.4-3.4,0.7-5.2,0.6
h-8.4v-32h9.2c7.1,0,10.7,2.6,10.7,7.8c0,1.6-0.4,3.1-1.2,4.5c-1,1.4-2.4,2.3-4,2.8c0.9,0.2,1.7,0.4,2.5,0.8c0.8,0.4,1.5,0.9,2,1.5 <path
c0.6,0.6,1.1,1.4,1.4,2.2C779.2,338.4,779.4,339.4,779.4,340.4z M773.7,326.3c0-0.6-0.1-1.3-0.3-1.8c-0.2-0.6-0.6-1.1-1-1.5 class="st2"
c-0.6-0.5-1.3-0.8-2-1c-1-0.3-2.1-0.4-3.2-0.4h-4.5v10h4.4c0.9,0,1.8-0.1,2.7-0.3c0.8-0.2,1.5-0.5,2.1-1c0.6-0.4,1-1,1.3-1.7 d="M597.9,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,1c0,0,0,0,0,0v79.5 C598.9,313.9,598.4,314.3,597.9,314.3C597.9,314.3,597.9,314.3,597.9,314.3z M593.7,234.8c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5 h3.2v-77.5H593.7z"
C773.6,327.9,773.7,327.1,773.7,326.3L773.7,326.3z M774.8,340.5c0-0.8-0.2-1.5-0.5-2.2c-0.4-0.7-0.9-1.2-1.5-1.7 id="path128"
c-0.7-0.5-1.5-0.8-2.4-1c-1-0.3-2.1-0.4-3.2-0.4h-4.5v11h4.6c2.5,0,4.4-0.5,5.6-1.4C774.2,343.8,774.9,342.2,774.8,340.5 style="fill:#000000" />
L774.8,340.5z"/> <path
<path class="st2" d="M715,701.3L695.4,721h5.6v16.8h28.2V721h5.3L715,701.3z M720.7,731.8h-11.1V721h11.1V731.8z"/> class="st2"
<path class="st1" d="M413.1,717.1h-4.2c-0.6,0-1-0.4-1-1c0,0,0,0,0,0v-79.5c0-0.6,0.4-1,1-1c0,0,0,0,0,0h4.2c3.8,0,6.9,3.1,7,7v67.6 d="M597.9,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,1c0,0,0,0,0,0v79.5 C598.9,716.6,598.4,717.1,597.9,717.1C597.9,717.1,597.9,717.1,597.9,717.1z M593.7,637.6c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5 h3.2v-77.5H593.7z"
C420.1,714,417,717.1,413.1,717.1z M409.9,715.1h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V715.1z"/> id="path130"
<path class="st1" d="M413.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 style="fill:#000000" />
C420.1,311.2,417,314.3,413.1,314.3z M409.9,312.3h3.2c2.7,0,5-2.2,5-5v-67.6c0-2.7-2.2-5-5-5h-3.2V312.3z"/>
<path class="st1" d="M81.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.8C110.5,50.1,187.7,0.1,272.9,0h51.2
c3.8,0,6.9,3.1,7,7v2.6c0,0.6-0.4,1-1,1h-54.2C191.4,10.5,115.1,61,82.2,138.7c-0.1,0.3-0.4,0.5-0.7,0.6
C81.4,139.3,81.3,139.3,81.3,139.3z M272.9,2C188.5,2.1,112,51.7,77.5,128.7c-0.8,1.9-0.4,4.1,1.1,5.5l2.4,2.4
c33.6-77.8,110.3-128.1,195-128h53.2V7c0-2.7-2.2-5-5-5L272.9,2z"/>
<path class="st1" d="M359.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
C363.6,114.3,361.8,116.1,359.6,116.1z M312.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-2H312.7z"/>
<path class="st1" d="M237.9,502.9c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5
C276.4,485.7,259.2,502.9,237.9,502.9z M237.9,428c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5
c20.1,0,36.5-16.3,36.5-36.5C274.4,444.3,258.1,428,237.9,428z"/>
<path class="st1" d="M237.9,649.8c-21.2,0-38.5-17.2-38.5-38.5s17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5
C276.4,632.6,259.2,649.8,237.9,649.8z M237.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.5 <path
c0,0,0,0,0,0C274.4,591.2,258.1,574.9,237.9,574.9z"/> style="fill:#01c6e6;fill-opacity:0.992157;stroke:#4d4d4d;stroke-width:1"
<path class="st1" d="M311.4,576.3c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0 d="m 257.47599,997.49473 c -26.30234,-2.3493 -49.90186,-9.17738 -75.04426,-21.71262 C 117.17154,943.24531 74.755874,881.82088 66.727355,808.2243 64.943441,791.87136 64.94041,218.41588 66.724145,200.93415 69.379611,174.90893 75.914592,151.99608 87.247373,128.97592 118.63505,65.218492 179.0982,21.796519 249.3051,12.593199 c 18.18131,-2.383363 133.61873,-2.6919419 135.94726,-0.363405 1.12672,1.12671 1.45478,112.251076 1.45478,492.764216 0,484.50248 -0.0325,491.32681 -2.34493,492.5644 -2.80172,1.49943 -109.98822,1.44564 -126.88622,-0.0636 z"
C349.8,559.1,332.6,576.3,311.4,576.3z M311.4,501.4c-20.1,0-36.5,16.3-36.5,36.5s16.3,36.5,36.5,36.5c20.1,0,36.5-16.3,36.5-36.5 id="path1144" /><polygon
c0,0,0,0,0,0C347.8,517.7,331.5,501.4,311.4,501.4L311.4,501.4z"/> class="st1"
<path class="st1" d="M164.5,576.3c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5s38.5,17.2,38.5,38.5l0,0 points="225.8,469.9 250,469.9 237.9,448.9 "
C202.9,559.1,185.7,576.3,164.5,576.3z M164.5,501.4c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 id="polygon80"
c20.1,0,36.5-16.3,36.5-36.5c0,0,0,0,0,0C200.9,517.7,184.6,501.4,164.5,501.4L164.5,501.4z"/> style="fill:#333333;stroke:#4d4d4d;stroke-width:0.927894"
<path class="st1" d="M314.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 transform="matrix(1.1037134,0,0,1.0523169,-24.636066,-24.267048)" /><polygon
C324,749.3,319.5,753.7,314.1,753.7z M269.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 class="st1"
c0-4.4-3.6-7.9-7.9-7.9H269.1z"/> points="237.9,626.9 225.8,605.9 250,605.9 "
<path class="st1" d="M291.6,741.7c-11.3,0-20.4-9.2-20.4-20.4c0-11.3,9.2-20.4,20.4-20.4c11.3,0,20.4,9.2,20.4,20.4c0,0,0,0,0,0 id="polygon82"
C312,732.6,302.9,741.7,291.6,741.7z M291.6,702.8c-10.2,0-18.4,8.3-18.4,18.4s8.3,18.4,18.4,18.4c10.2,0,18.4-8.3,18.4-18.4 style="fill:#333333;stroke:#4d4d4d;stroke-width:0.957418"
C310,711.1,301.8,702.9,291.6,702.8z"/> transform="matrix(1.0574383,0,0,1.0316716,-13.259456,-19.457378)" /><polygon
<path class="st1" d="M174.8,260.2h-12.3c-0.6,0-1-0.4-1-1c0,0,0,0,0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3 class="st1"
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.9C181.2,257.6,178.3,260.2,174.8,260.2z points="148.9,537.9 169.9,550 169.9,525.8 "
M163.6,258.2h11.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 id="polygon84"
C196.2,190.3,165.7,220.8,163.6,258.2L163.6,258.2z"/> style="fill:#333333;stroke:#4d4d4d;stroke-width:0.931439"
<path class="st1" d="M234.6,338.9L234.6,338.9c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1c0,0,0,0,0,0h12.3c3.5,0,6.4,2.6,6.9,6 transform="matrix(1.0443863,0,0,1.1036462,-7.5389156,-55.555947)" /><polygon
c3.7,24.7,23.1,44.2,47.9,47.9c3.4,0.5,6,3.4,6,6.9v12.3C235.6,338.5,235.1,338.9,234.6,338.9L234.6,338.9z M163.6,266.9 class="st1"
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.3L163.6,266.9z"/> points="305.9,550 305.9,525.8 326.9,537.9 "
<path class="st1" d="M241.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 id="polygon86"
h12.3c0.6,0,1,0.4,1,1c0,0,0,0,0,0C312.6,305.5,280.9,337.2,241.3,338.9L241.3,338.9z M301,266.9c-2.5,0-4.6,1.8-4.9,4.3 style="fill:#333333;stroke:#4d4d4d;stroke-width:0.849928"
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-70L301,266.9z"/> transform="matrix(1.2181479,0,0,1.1364095,-67.797686,-73.39984)" /><path
<path class="st1" d="M313.3,260.2H301c-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 class="st1"
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,73C314.3,259.7,313.9,260.2,313.3,260.2 d="m 81.300444,139.3 c -0.3,0 -0.5,-0.1 -0.7,-0.3 l -3.4,-3.4 c -2,-2 -2.6,-5.1 -1.5,-7.8 C 110.50044,50.1 187.70044,0.1 272.90044,0 h 51.2 c 3.8,0 6.9,3.1 7,7 v 2.6 c 0,0.6 -0.4,1 -1,1 h -54.2 c -84.5,-0.1 -160.8,50.4 -193.699996,128.1 -0.1,0.3 -0.4,0.5 -0.7,0.6 -0.1,0 -0.2,0 -0.2,0 z M 272.90044,2 c -84.4,0.1 -160.9,49.7 -195.399996,126.7 -0.8,1.9 -0.4,4.1 1.1,5.5 l 2.4,2.4 C 114.60044,58.8 191.30044,8.5 276.00044,8.6 h 53.2 V 7 c 0,-2.7 -2.2,-5 -5,-5 z"
C313.3,260.2,313.3,260.2,313.3,260.2L313.3,260.2z M242.3,188.2v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6 id="path102"
c0.3,2.5,2.4,4.3,4.9,4.3h11.2C310.1,220.8,279.6,190.3,242.3,188.2L242.3,188.2z"/> style="fill:#000000" /><path
<path class="st1" d="M237.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 class="st1"
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 d="m 359.60044,116.1 h -46.9 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 46.9 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 z m -46.9,-17.6 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 46.9 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 z"
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 id="path104"
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 style="fill:#000000" /><path
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.9H301c-2.5,0-4.6,1.8-4.9,4.3 class="st1"
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,1C240.2,339,239.1,339,237.9,339z M235.6,337 d="m 237.90044,502.9 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.2 -16.3,-36.5 -36.5,-36.5 z"
c1.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.3c0-0.8,0-1.5,0-2.3 id="path106"
s0-1.6,0-2.3H301c-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 style="fill:#000000" /><path
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.3c0,0.8,0,1.5,0,2.3s0,1.6,0,2.3h11.3 class="st1"
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.9L235.6,337z"/> d="m 237.90044,649.8 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.3 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.3 -17.2,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.2,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 0,-20.2 -16.3,-36.5 -36.5,-36.5 z"
<path class="st2" d="M597.9,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,1c0,0,0,0,0,0v79.5 id="path108"
C598.9,313.9,598.4,314.3,597.9,314.3C597.9,314.3,597.9,314.3,597.9,314.3z M593.7,234.8c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5 style="fill:#000000" /><path
h3.2v-77.5H593.7z"/> class="st1"
<path class="st2" d="M597.9,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,1c0,0,0,0,0,0v79.5 d="m 311.40044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.2 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z"
C598.9,716.6,598.4,717.1,597.9,717.1C597.9,717.1,597.9,717.1,597.9,717.1z M593.7,637.6c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5 id="path110"
h3.2v-77.5H593.7z"/> style="fill:#000000" /><path
<path class="st2" d="M925.6,139.3c-0.1,0-0.1,0-0.2,0c-0.3-0.1-0.6-0.3-0.7-0.6C891.7,61,815.4,10.5,730.9,10.6h-54.2 class="st1"
c-0.6,0-1-0.4-1-1c0,0,0,0,0,0V7c0-3.8,3.1-6.9,7-7h51.2c85.2,0.1,162.4,50.1,197.3,127.8c1.2,2.6,0.6,5.7-1.5,7.8l-3.4,3.4 d="m 164.50044,576.3 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.3,0 38.5,17.2 38.5,38.5 v 0 c -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,0 0,0 0,0 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z"
C926.1,139.2,925.8,139.3,925.6,139.3z M677.7,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.5 id="path112"
C894.8,51.7,818.3,2.1,733.9,2h-51.2c-2.7,0-5,2.2-5,5V8.6z"/> style="fill:#000000" /><path
<path class="st2" d="M676.5,133.7h-11.7c-2.2,0-4-1.8-4-4v-11.7c0-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-4h11.7 class="st1"
c1.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.7c0,2.2-1.8,4-4,4h-11.7 d="m 314.10044,753.7 h -45 c -5.5,0 -9.9,-4.4 -9.9,-9.9 v -45 c 0,-5.5 4.4,-9.9 9.9,-9.9 h 45 c 5.5,0 9.9,4.4 9.9,9.9 v 45 c 0,5.5 -4.5,9.9 -9.9,9.9 z m -45,-62.8 c -4.4,0 -7.9,3.6 -7.9,7.9 v 45 c 0,4.4 3.6,7.9 7.9,7.9 h 45 c 4.4,0 7.9,-3.6 7.9,-7.9 v -45 c 0,-4.4 -3.6,-7.9 -7.9,-7.9 z"
c-1.1,0-2,0.9-2,2v11.7C680.5,131.9,678.7,133.7,676.5,133.7z M647.2,98.5c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h11.7 id="path114"
c2.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-4h11.7c1.1,0,2-0.9,2-2v-11.7c0-1.1-0.9-2-2-2 style="fill:#000000" /><path
h-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,4L647.2,98.5z"/> class="st1"
<path class="st2" d="M768.9,372.4c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 d="m 291.60044,741.7 c -11.3,0 -20.4,-9.2 -20.4,-20.4 0,-11.3 9.2,-20.4 20.4,-20.4 11.3,0 20.4,9.2 20.4,20.4 0,0 0,0 0,0 0,11.3 -9.1,20.4 -20.4,20.4 z m 0,-38.9 c -10.2,0 -18.4,8.3 -18.4,18.4 0,10.1 8.3,18.4 18.4,18.4 10.2,0 18.4,-8.3 18.4,-18.4 0,-10.1 -8.2,-18.3 -18.4,-18.4 z"
C807.3,355.2,790.1,372.4,768.9,372.4z M768.9,297.5c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 id="path116"
c20.1,0,36.5-16.3,36.5-36.5C805.3,313.8,789,297.5,768.9,297.5L768.9,297.5z"/> style="fill:#000000" /><path
<path class="st2" d="M768.9,225.5c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 class="st1"
C807.3,208.3,790.1,225.5,768.9,225.5z M768.9,150.6c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 d="m 174.80044,260.2 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z"
c20.1,0,36.5-16.3,36.5-36.5C805.3,166.9,789,150.6,768.9,150.6L768.9,150.6z"/> id="path118"
<path class="st2" d="M842.3,299c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 style="fill:#000000" /><path
C880.8,281.7,863.6,298.9,842.3,299z M842.3,224c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 class="st1"
c20.1,0,36.5-16.3,36.5-36.5C878.8,240.4,862.5,224,842.3,224L842.3,224z"/> d="m 234.60044,338.9 v 0 c -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 V 338 c -0.1,0.5 -0.6,0.9 -1.1,0.9 z m -71,-72 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z"
<path class="st2" d="M695.5,299c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 id="path120"
C733.9,281.7,716.7,298.9,695.5,299z M695.5,224c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 style="fill:#000000" /><path
c20.1,0,36.5-16.3,36.5-36.5C731.9,240.4,715.6,224,695.5,224L695.5,224z"/> class="st1"
<path class="st2" d="M715,750.2c-16,0-28.9-13-28.9-28.9s13-28.9,28.9-28.9c16,0,28.9,13,28.9,28.9c0,0,0,0,0,0 d="m 241.30044,338.9 c -0.6,0 -1,-0.4 -1,-1 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.5,71.4 -73.1,73.1 z m 59.7,-72 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 11.2 c 37.4,-2.2 67.8,-32.6 70,-70 z"
C743.9,737.3,731,750.2,715,750.2z M715,694.3c-14.9,0-26.9,12.1-26.9,26.9s12.1,26.9,26.9,26.9c14.9,0,26.9-12.1,26.9-26.9 id="path122"
C741.9,706.4,729.9,694.4,715,694.3z"/> style="fill:#000000" /><path
<path class="st2" d="M705.8,533.4h-12.3c-0.6,0-1-0.4-1-1c0,0,0,0,0,0c1.7-39.6,33.4-71.3,73-73c0.3,0,0.5,0.1,0.7,0.3 class="st1"
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.9C712.2,530.8,709.3,533.4,705.8,533.4z d="m 313.30044,260.2 h -12.3 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1.1 -0.9,1.1 0,0 0,0 0,0 z m -71,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.2,-37.4 -32.7,-67.9 -70,-70 z"
M694.6,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 id="path124"
C727.2,463.5,696.7,494,694.6,531.4z"/> style="fill:#000000" /><path
<path class="st2" d="M765.6,612.1C765.6,612.1,765.5,612.1,765.6,612.1c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1c0,0,0,0,0,0h12.3 class="st1"
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.3C766.6,611.6,766.1,612.1,765.6,612.1 d="m 237.90044,339 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 h -12.3 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0.1 -2.2,0.1 -3.4,0.1 z m -2.3,-2 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 h -11.4 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 z"
C765.6,612.1,765.6,612.1,765.6,612.1L765.6,612.1z M694.6,540c2.2,37.4,32.6,67.8,70,70v-11.2c0-2.5-1.8-4.6-4.3-4.9 id="path126"
c-25.6-3.9-45.7-24-49.6-49.6c-0.3-2.5-2.4-4.3-4.9-4.3H694.6z"/> style="fill:#000000" /><path
<path class="st2" d="M772.2,612.1c-0.6,0-1-0.4-1-1c0,0,0,0,0,0v-12.3c0-3.5,2.6-6.4,6-6.9c24.7-3.7,44.2-23.1,47.9-47.9 style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999997"
c0.5-3.4,3.4-6,6.9-6h12.3c0.6,0,1,0.4,1,1c0,0,0,0,0,0C843.5,578.7,811.9,610.3,772.2,612.1C772.3,612.1,772.3,612.1,772.2,612.1z d="m 158.02789,574.27925 c -14.73064,-3.25266 -24.85554,-12.70578 -29.04419,-27.11717 -0.98592,-3.39218 -1.21679,-6.26957 -0.93511,-11.65556 0.33774,-6.4583 0.67944,-7.76803 3.52546,-13.51272 11.35216,-22.91431 40.68588,-27.928 58.61532,-10.01846 19.42229,19.40073 11.99924,51.86436 -13.89781,60.78009 -5.19354,1.788 -13.81105,2.50701 -18.26367,1.52382 z m 12.59864,-36.29462 c 0,-7.35074 -0.18108,-13.36496 -0.40241,-13.36496 -0.89601,0 -23.32454,13.1809 -22.99291,13.51259 0.66445,0.66458 22.24473,13.11359 22.82266,13.1657 0.31497,0.0284 0.57266,-5.96261 0.57266,-13.31333 z"
M832,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.9V610c37.4-2.2,67.8-32.6,70-70H832z"/> id="path179" /><path
<path class="st2" d="M844.3,533.4H832c-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 style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999997"
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,73C845.3,532.9,844.9,533.3,844.3,533.4 d="m 232.50517,500.57091 c -6.91699,-0.86484 -15.04235,-4.99807 -20.4853,-10.42051 -14.58513,-14.53016 -14.55979,-36.85709 0.0584,-51.42015 23.0282,-22.94142 62.26853,-6.95317 62.26853,25.37095 0,10.34881 -3.46897,18.75364 -10.723,25.98031 -8.34032,8.30891 -19.22192,11.97685 -31.1186,10.4894 z m 18.58209,-30.69278 c -0.91811,-2.38357 -12.79282,-22.35099 -13.28879,-22.34521 -0.45143,0.005 -5.88471,9.05299 -11.95805,19.91302 l -2.0157,3.60439 h 13.85703 c 12.18288,0 13.80248,-0.14161 13.40551,-1.1722 z"
C844.3,533.4,844.3,533.4,844.3,533.4L844.3,533.4z M773.2,461.4v11.2c0,2.5,1.8,4.6,4.3,4.9c25.6,3.9,45.7,24,49.6,49.6 id="path181" /><path
c0.3,2.5,2.4,4.3,4.9,4.3h11.2C841.1,494,810.6,463.5,773.2,461.4z"/> style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999997"
<path class="st2" d="M768.9,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 d="m 229.21434,646.98161 c -12.9232,-3.46654 -23.15418,-13.73508 -26.52403,-26.62142 -5.92248,-22.64757 11.58541,-45.21876 35.15949,-45.32763 7.44717,-0.0344 11.29183,0.91312 18.09999,4.46071 16.90217,8.80735 23.84898,30.39169 15.40753,47.87245 -7.54225,15.61868 -25.6403,24.04261 -42.14298,19.61589 z M 245.434,616.92014 c 3.65424,-6.30197 6.48622,-11.61534 6.29329,-11.8075 -0.19293,-0.19216 -6.40658,-0.25572 -13.80812,-0.14123 l -13.45735,0.20814 6.66623,11.58776 c 3.66642,6.37327 6.89025,11.59297 7.16405,11.59935 0.27381,0.006 3.48766,-5.14457 7.1419,-11.44652 z"
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 id="path185" /><path
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 style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width: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 d="m 307.85537,574.24407 c -0.34478,-0.0389 -1.62711,-0.27075 -2.84962,-0.51537 -11.23844,-2.24892 -20.9226,-9.70179 -26.17378,-20.1432 -2.82839,-5.62398 -4.20289,-12.18393 -3.75883,-17.93953 1.14218,-14.80435 11.33006,-27.74217 25.61809,-32.53303 8.75405,-2.93529 18.04495,-2.18507 26.72988,2.15843 8.69225,4.34715 15.48783,12.11097 18.64346,21.29973 5.25881,15.31297 -0.71552,32.17026 -14.73029,41.56334 -5.99457,4.01773 -13.35804,6.28235 -20.18834,6.20884 -1.46502,-0.0157 -2.94577,-0.0604 -3.29057,-0.0993 z m -0.66719,-23.08553 c 0.71175,-0.35815 3.02697,-1.62049 5.14496,-2.80516 8.66766,-4.84825 15.63944,-9.1681 16.21592,-10.0477 0.27948,-0.42642 0.28078,-0.49758 0.0166,-0.90068 -0.86957,-1.32678 -21.50733,-13.52937 -22.8817,-13.52937 -0.25925,0 -0.5656,0.11351 -0.68079,0.25225 -0.41371,0.49837 -0.59707,4.78502 -0.59431,13.89388 0.003,9.06159 0.17803,13.03427 0.59744,13.53951 0.32082,0.38645 0.78324,0.3011 2.18189,-0.40273 z"
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.9H832c-2.5,0-4.6,1.8-4.9,4.3 id="path187" /><path
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,1C771.2,612.1,770.1,612.2,768.9,612.2z M766.6,610.1 style="fill:#333333;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
c1.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.3c0-0.8,0-1.5,0-2.3 d="m 287.96017,739.09726 c -1.01606,-0.21912 -2.9756,-0.9477 -4.35453,-1.61905 -2.09414,-1.01956 -2.88115,-1.59464 -4.77748,-3.49097 -1.89792,-1.89791 -2.4703,-2.68159 -3.48941,-4.77748 -2.66648,-5.48389 -2.66607,-10.55714 10e-4,-16.08572 1.0133,-2.10022 1.56326,-2.85257 3.48092,-4.76199 3.62968,-3.61405 7.72755,-5.3398 12.70198,-5.34921 8.35146,-0.0158 15.68299,5.71579 17.81213,13.92506 0.52326,2.01754 0.54009,6.16569 0.0339,8.34799 -1.47072,6.34008 -6.30854,11.44929 -12.69973,13.41212 -2.44922,0.7522 -6.26202,0.92699 -8.70906,0.39925 z"
s0-1.6,0-2.3H832c-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 id="path189" /><path
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.3c0,0.8,0,1.5,0,2.3s0,1.6,0,2.3h11.3 style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
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.9V610.1z"/> d="m 267.23012,751.2862 c -1.59942,-0.43597 -2.94763,-1.29847 -4.05871,-2.59652 -1.81264,-2.11766 -1.73429,-0.87988 -1.73429,-27.39725 0,-26.73402 -0.0972,-25.30688 1.87658,-27.54923 0.58306,-0.66239 1.71204,-1.51487 2.55332,-1.92799 l 1.5081,-0.74058 h 24.1534 24.15339 l 1.77672,0.87468 c 1.25727,0.61895 2.04823,1.23027 2.70544,2.091 1.78729,2.34073 1.72742,1.33094 1.64816,27.80036 -0.0712,23.78487 -0.0733,23.86757 -0.63865,25.09049 -0.72339,1.56486 -2.26169,3.10316 -3.93043,3.93043 l -1.30842,0.64864 -23.75199,0.0516 c -18.21394,0.0396 -24.03192,-0.0247 -24.95262,-0.27565 z m 27.28995,-9.68076 c 10.60326,-1.53286 18.09097,-10.66806 17.50501,-21.35655 -0.18432,-3.36213 -0.66908,-5.27077 -2.04745,-8.06138 -4.59235,-9.29756 -15.46557,-13.67756 -25.3079,-10.19463 -2.76161,0.97725 -4.68871,2.16763 -7.02836,4.34145 -3.05146,2.83517 -5.11688,6.34636 -6.04249,10.27217 -0.50715,2.151 -0.50715,7.22087 0,9.37186 0.92171,3.90925 2.95421,7.3745 6.0133,10.25221 2.20884,2.07787 4.16469,3.31668 6.72144,4.2573 3.40627,1.25315 6.72782,1.61756 10.18645,1.11757 z"
</svg> id="path191" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 235.77295,330.34531 c 0,-6.0203 -0.0462,-6.51813 -0.73076,-7.87124 -1.06164,-2.09851 -2.95253,-3.39477 -5.65313,-3.87537 -15.06064,-2.68022 -27.49575,-10.15006 -36.51861,-21.93692 -4.96934,-6.49162 -8.83069,-15.11098 -10.3887,-23.18981 -0.83474,-4.3284 -1.3998,-5.65891 -2.97647,-7.00848 -1.7724,-1.51711 -3.30405,-1.79252 -9.96885,-1.79252 h -5.86461 v -2.11107 -2.11107 h 6.26944 c 6.12912,0 6.30805,-0.0192 7.9945,-0.85963 2.44443,-1.21811 3.32179,-2.74063 4.22338,-7.32906 4.56927,-23.25403 22.39532,-40.97679 45.63214,-45.36773 4.16129,-0.78634 5.57438,-1.57205 6.90818,-3.84114 0.9048,-1.53927 0.91186,-1.5954 1.02116,-8.12677 l 0.11006,-6.57679 h 2.0822 2.0822 v 6.27497 c 0,6.20191 0.0104,6.29547 0.89315,8.03629 1.32629,2.61551 2.65075,3.37644 7.56606,4.34684 19.37922,3.82593 35.08856,16.98397 42.28514,35.41774 1.04383,2.67375 1.9437,5.93165 3.31831,12.01372 0.58905,2.60627 1.67368,4.16462 3.60307,5.17675 1.1513,0.60396 1.95144,0.68258 7.85861,0.77219 l 6.57679,0.0998 v 2.0925 2.09249 h -6.26944 c -6.12912,0 -6.30805,0.0192 -7.9945,0.85963 -2.20181,1.09721 -3.39863,2.90223 -3.90849,5.89474 -4.06097,23.83452 -22.22419,42.32715 -45.97159,46.8053 -4.2535,0.8021 -5.71797,1.66037 -6.96502,4.08193 -0.79329,1.54043 -0.83455,1.89301 -0.94026,8.03533 l -0.11057,6.42419 h -2.08169 -2.0817 z"
id="path1082" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 163.78864,257.28223 c 0.0926,-0.49123 0.26012,-1.9162 0.37218,-3.1666 0.34565,-3.85681 1.73866,-10.12043 3.27937,-14.74553 8.02141,-24.0797 28.10082,-42.70464 52.74332,-48.92282 3.12397,-0.78829 7.58171,-1.54879 11.2861,-1.92544 l 2.02988,-0.20639 v 5.8726 c 0,8.54266 -0.3854,9.15422 -6.53853,10.37563 -18.42711,3.65779 -33.66767,15.25204 -41.92018,31.89074 -2.55007,5.14144 -4.14587,10.08856 -5.47376,16.9691 -0.45828,2.3746 -1.81844,3.9985 -3.71595,4.43649 -0.71452,0.16493 -3.75876,0.30335 -6.76499,0.30761 l -5.46587,0.008 z"
id="path1084" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 229.76452,336.39384 c -26.99792,-3.04756 -50.79328,-21.35759 -60.92173,-46.87799 -2.38214,-6.00221 -4.22117,-13.35788 -4.67827,-18.71196 -0.11259,-1.31887 -0.27512,-2.73804 -0.36117,-3.1537 l -0.15645,-0.75574 6.32279,0.10618 c 5.78597,0.0972 6.39885,0.16304 7.21874,0.77582 1.58067,1.18137 2.03872,2.1715 2.89278,6.25312 1.21968,5.82894 2.45374,9.35857 5.18759,14.8375 2.85902,5.72977 5.67403,9.77885 9.85937,14.18161 8.62003,9.0678 19.6967,15.16512 31.73111,17.46684 3.63419,0.69508 4.63135,1.16546 5.80819,2.73983 0.6132,0.82034 0.6781,1.4276 0.77012,7.20628 0.0943,5.92221 0.0643,6.30785 -0.48717,6.26798 -0.32321,-0.0233 -1.75687,-0.17446 -3.1859,-0.33577 z"
id="path1086" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 299.6703,257.71116 c -2.39043,-0.853 -2.81858,-1.58503 -3.81252,-6.51855 -3.66786,-18.20579 -15.40436,-33.45997 -31.99138,-41.57986 -4.81668,-2.35792 -8.58209,-3.67044 -13.47836,-4.69819 -4.72195,-0.99115 -6.17077,-1.58672 -7.05619,-2.9006 -0.70499,-1.04613 -0.73853,-1.38133 -0.73853,-7.38107 0,-3.45685 0.11517,-6.28518 0.25593,-6.28518 0.14076,0 1.93111,0.20926 3.97855,0.46502 11.96867,1.4951 22.85594,5.62979 32.79042,12.45291 4.36974,3.00118 7.416,5.6069 11.57682,9.90259 9.30395,9.60553 15.50823,20.66713 18.77966,33.48224 0.93232,3.65217 2.12151,10.886 2.12151,12.90514 0,0.58643 -0.30132,0.619 -5.60245,0.60551 -3.82949,-0.01 -5.98886,-0.15214 -6.82346,-0.44996 z"
id="path1088" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 242.3249,330.46177 c 0.097,-5.7735 0.163,-6.38655 0.77566,-7.20629 1.18269,-1.58243 2.17182,-2.02925 6.33209,-2.86041 23.48707,-4.69236 41.89612,-23.31363 46.43689,-46.97223 0.66775,-3.47916 1.14738,-4.47847 2.71006,-5.64639 0.81991,-0.6128 1.43277,-0.67865 7.22079,-0.77584 l 6.32483,-0.10621 -0.19591,1.73011 c -1.19107,10.51857 -3.29919,17.9842 -7.45853,26.41337 -11.17834,22.65366 -32.93361,38.14197 -57.96776,41.26919 -2.04744,0.25577 -3.84896,0.46502 -4.00338,0.46502 -0.15442,0 -0.23305,-2.83964 -0.17474,-6.31032 z"
id="path1090" /><path
style="fill:#000000;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999998"
d="m 311.60253,113.45766 c -0.55307,-0.55307 -0.67321,-1.83753 -0.67321,-7.19731 0,-4.50308 0.15925,-6.68335 0.51409,-7.03819 0.38766,-0.38766 6.43841,-0.5141 24.60307,-0.5141 21.32785,0 24.16614,0.0772 24.76219,0.67322 0.55166,0.55166 0.67322,1.82364 0.67322,7.0445 0,6.09825 -0.0408,6.39986 -0.95215,7.03819 -0.83385,0.58406 -3.89051,0.66691 -24.60307,0.66691 -20.92962,0 -23.72838,-0.0775 -24.32414,-0.67322 z"
id="path1092" /><path
style="fill:#000000;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999998"
d="m 78.977784,134.18912 c -2.35328,-2.74929 -2.18932,-3.66269 2.26682,-12.62797 C 92.012734,99.89682 104.871,81.96966 121.771,65.058734 153.11752,33.69194 193.3541,12.833792 237.03838,5.305545 252.10894,2.708387 253.57756,2.630423 291.07604,2.43687 l 34.76922,-0.179466 1.35092,1.207149 c 0.9677,0.864713 1.41875,1.712966 1.59003,2.990242 l 0.23911,1.783092 -33.78877,0.194148 c -36.2509,0.208295 -38.76527,0.335101 -53.2555,2.685802 -38.392,6.2282 -72.8916,22.039868 -103.29303,47.340693 -6.79226,5.652686 -19.46547,18.33117 -25.22484,25.23531 -8.3636,10.02603 -16.479016,21.67655 -22.544486,32.36489 -3.07683,5.42188 -9.61802,18.64996 -9.61802,19.45027 0,0.91062 -0.80534,0.45303 -2.32289,-1.31988 z"
id="path1094" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 398.20583,464.93186 c 0,-216.02489 0.12146,-304.39871 0.26991,-196.38626 0.14845,108.01244 0.14845,284.76008 0,392.77252 -0.14845,108.01245 -0.26991,19.63863 -0.26991,-196.38626 z"
id="path1150" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 401.44318,902.40274 c -1.48283,-2.11702 -1.64585,-43.40647 -1.64585,-416.85429 0,-373.44781 0.16302,-414.737261 1.64585,-416.854286 1.37591,-1.964385 2.64173,-2.349769 7.718,-2.349769 3.33969,0 6.64309,0.570921 7.34088,1.268713 0.96181,0.961813 1.26871,18.598983 1.26871,72.911362 0,69.01305 -0.0775,71.84973 -2.1109,77.28456 -1.161,3.10304 -3.53984,7.89508 -5.28631,10.64899 l -3.1754,5.00708 v 40.24031 c 0,37.61687 0.12902,40.42327 1.97893,43.04667 1.08842,1.5435 3.34831,5.42309 5.02199,8.6213 l 3.04306,5.81494 0.27946,141.61892 c 0.30957,156.88126 0.80443,145.17745 -6.6628,157.57802 l -3.66064,6.0791 v 40.51406 c 0,26.52506 0.37415,40.74531 1.08359,41.18376 0.59597,0.36833 2.85586,4.08361 5.02199,8.25617 l 3.9384,7.58648 0.28906,83.91411 c 0.21318,61.88506 -0.029,84.29733 -0.9224,85.37384 -0.77641,0.93553 -3.42147,1.45973 -7.36562,1.45973 -5.161,0 -6.41977,-0.37921 -7.8,-2.34977 z"
id="path1152" /><path
style="fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="M 389.22472,464.93186 V 72.687962 h 4.22905 4.22904 v 392.243898 392.2439 h -4.22904 -4.22905 z"
id="path1154" /><path
style="fill:#00c7e7;fill-opacity:0.992157;stroke:#4d4d4d;stroke-width:1"
d="m 409.89998,273.33293 v -38.63294 h 3.04188 c 1.74435,0 3.58682,0.88543 4.31941,2.07573 1.73761,2.82321 1.73761,70.29119 0,73.11439 -0.73259,1.19032 -2.57506,2.07573 -4.31941,2.07573 h -3.04188 z"
id="path1156" /><path
style="fill:#00c7e7;fill-opacity:0.992157;stroke:#4d4d4d;stroke-width:1"
d="m 409.89998,676.164 v -38.66403 h 3.04381 c 1.74545,0 3.58909,0.88613 4.32215,2.07741 1.7387,2.82547 1.7387,70.34777 0,73.17325 -0.73306,1.19129 -2.5767,2.0774 -4.32215,2.0774 h -3.04381 z"
id="path1158" /><path
style="fill:#ff5f55;fill-opacity:0.95686275;stroke:#4d4d4d;stroke-width:1"
d="m 748.93436,998.67954 c 26.59545,-2.35471 50.45796,-9.1985 75.88056,-21.7626 65.98743,-32.61168 108.87577,-94.17749 116.99375,-167.94346 1.80381,-16.39057 1.80686,-591.16592 0.003,-608.68789 -2.68506,-26.08512 -9.29287,-49.0507 -20.75194,-72.12385 C 889.32253,64.257568 828.18558,20.735655 757.19631,11.511152 738.81239,9.1223039 622.08856,8.8130147 619.73408,11.146911 c -1.13928,1.129303 -1.47099,112.509439 -1.47099,493.898369 0,485.61761 0.0328,492.45765 2.37105,493.69808 2.83295,1.50294 111.21392,1.44894 128.30022,-0.0637 z"
id="path1240" /><path
class="st3"
d="m 715,763.2 c -23.1,0 -41.9,-18.7 -41.9,-41.9 0,-23.2 18.7,-41.9 41.9,-41.9 23.2,0 41.9,18.7 41.9,41.9 v 0 c -0.1,23.1 -18.8,41.8 -41.9,41.9 z m 0,-82.8 c -22.6,0 -40.9,18.3 -40.9,40.9 0,22.6 18.3,40.9 40.9,40.9 22.6,0 40.9,-18.3 40.9,-40.9 v 0 C 755.8,698.7 737.6,680.4 715,680.4 Z"
id="path78"
style="fill:#000000" /><path
class="st2"
d="m 782.2,203.2 h -5.5 l -7.8,-12.9 -7.8,12.9 h -5.4 l 10.6,-16.3 -9.8,-15.6 h 5.2 l 7.3,12 7.4,-12 h 5 l -9.8,15.4 z"
id="path88"
style="fill:#b3b3b3;fill-opacity:1" /><path
class="st2"
d="m 709.2,244.5 -11.6,20.6 v 11.4 h -4.4 V 265 l -11.6,-20.5 h 5.3 l 6.4,11.7 2.3,4.7 2.2,-4.3 6.4,-12.1 z"
id="path90"
style="fill:#b3b3b3" /><path
class="st2"
d="m 855.9,276.5 h -4.7 l -2.2,-7 h -13.3 l -2.3,7 h -4.5 l 10.6,-32 h 6 z m -8.2,-10.9 -5.4,-17.1 -5.4,17.1 z"
id="path92"
style="fill:#b3b3b3" /><path
class="st2"
d="m 779.4,340.4 c 0,1.4 -0.3,2.8 -0.9,4.1 -0.6,1.2 -1.5,2.2 -2.5,3 -1.2,0.9 -2.6,1.5 -4,1.9 -1.7,0.4 -3.4,0.7 -5.2,0.6 h -8.4 v -32 h 9.2 c 7.1,0 10.7,2.6 10.7,7.8 0,1.6 -0.4,3.1 -1.2,4.5 -1,1.4 -2.4,2.3 -4,2.8 0.9,0.2 1.7,0.4 2.5,0.8 0.8,0.4 1.5,0.9 2,1.5 0.6,0.6 1.1,1.4 1.4,2.2 0.2,0.8 0.4,1.8 0.4,2.8 z m -5.7,-14.1 c 0,-0.6 -0.1,-1.3 -0.3,-1.8 -0.2,-0.6 -0.6,-1.1 -1,-1.5 -0.6,-0.5 -1.3,-0.8 -2,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 10 h 4.4 c 0.9,0 1.8,-0.1 2.7,-0.3 0.8,-0.2 1.5,-0.5 2.1,-1 0.6,-0.4 1,-1 1.3,-1.7 0.4,-0.7 0.5,-1.5 0.5,-2.3 z m 1.1,14.2 c 0,-0.8 -0.2,-1.5 -0.5,-2.2 -0.4,-0.7 -0.9,-1.2 -1.5,-1.7 -0.7,-0.5 -1.5,-0.8 -2.4,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 11 h 4.6 c 2.5,0 4.4,-0.5 5.6,-1.4 1.3,-1 2,-2.6 1.9,-4.3 z"
id="path94"
style="fill:#b3b3b3" /><path
class="st2"
d="M 715,701.3 695.4,721 h 5.6 v 16.8 h 28.2 V 721 h 5.3 z m 5.7,30.5 H 709.6 V 721 h 11.1 z"
id="path96"
style="fill:#333333" /><path
class="st2"
d="m 925.6,139.3 c -0.1,0 -0.1,0 -0.2,0 -0.3,-0.1 -0.6,-0.3 -0.7,-0.6 C 891.7,61 815.4,10.5 730.9,10.6 h -54.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 V 7 c 0,-3.8 3.1,-6.9 7,-7 h 51.2 c 85.2,0.1 162.4,50.1 197.3,127.8 1.2,2.6 0.6,5.7 -1.5,7.8 l -3.4,3.4 c -0.2,0.2 -0.5,0.3 -0.7,0.3 z M 677.7,8.6 h 53.2 c 84.7,-0.1 161.3,50.2 195,128 l 2.4,-2.4 v 0 c 1.5,-1.4 1.9,-3.6 1.1,-5.5 C 894.8,51.7 818.3,2.1 733.9,2 h -51.2 c -2.7,0 -5,2.2 -5,5 z"
id="path132"
style="fill:#000000" /><path
class="st2"
d="m 676.5,133.7 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 118 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 V 82.8 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2 -1.8,3.8 -4,3.8 z M 647.2,98.5 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 82.8 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2.2 -1.8,4 -4,4 z"
id="path134"
style="fill:#000000" /><path
class="st2"
d="m 768.9,372.4 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z"
id="path136"
style="fill:#000000" /><path
class="st2"
d="m 768.9,225.5 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z"
id="path138"
style="fill:#000000" /><path
class="st2"
d="m 842.3,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.2 -17.2,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.1 -16.3,-36.5 -36.5,-36.5 z"
id="path140"
style="fill:#000000" /><path
class="st2"
d="m 695.5,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.2 -17.3,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 C 731.9,240.4 715.6,224 695.5,224 Z"
id="path142"
style="fill:#000000" /><path
class="st2"
d="m 715,750.2 c -16,0 -28.9,-13 -28.9,-28.9 0,-15.9 13,-28.9 28.9,-28.9 16,0 28.9,13 28.9,28.9 0,0 0,0 0,0 0,16 -12.9,28.9 -28.9,28.9 z m 0,-55.9 c -14.9,0 -26.9,12.1 -26.9,26.9 0,14.8 12.1,26.9 26.9,26.9 14.9,0 26.9,-12.1 26.9,-26.9 0,-14.8 -12,-26.8 -26.9,-26.9 z"
id="path144"
style="fill:#000000" /><path
class="st2"
d="m 705.8,533.4 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z"
id="path146"
style="fill:#000000" /><path
class="st2"
d="m 765.6,612.1 c 0,0 -0.1,0 0,0 -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 12.3 c -0.1,0.4 -0.6,0.9 -1.1,0.9 0,0 0,0 0,0 z m -71,-72.1 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z"
id="path148"
style="fill:#000000" /><path
class="st2"
d="m 772.2,612.1 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.4,71.3 -73.1,73.1 0.1,0 0.1,0 0,0 z M 832,540 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 V 610 c 37.4,-2.2 67.8,-32.6 70,-70 z"
id="path150"
style="fill:#000000" /><path
class="st2"
d="M 844.3,533.4 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1 -0.9,1.1 0,0 0,0 0,0 z m -71.1,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.1,-37.4 -32.6,-67.9 -70,-70 z"
id="path152"
style="fill:#000000" /><path
class="st2"
d="m 768.9,612.2 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 H 832 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0 -2.2,0.1 -3.4,0.1 z m -2.3,-2.1 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 11.3 z"
id="path154"
style="fill:#000000" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 686.27756,295.45757 c -6.3268,-1.65761 -11.02024,-4.44224 -16.19729,-9.60987 -7.7249,-7.71084 -11.00252,-16.02709 -10.55426,-26.7792 0.56274,-13.49806 7.94054,-24.90282 19.94518,-30.83167 10.51307,-5.1922 21.47279,-5.27638 31.58153,-0.24258 7.93543,3.95157 13.41304,9.50319 17.2109,17.44344 5.18792,10.84649 4.24806,24.40322 -2.39714,34.5766 -4.99743,7.65076 -13.48676,13.69608 -22.04004,15.69491 -4.81862,1.12607 -12.72306,1.01273 -17.54888,-0.25163 z m 11.6608,-24.5355 v -5.81067 l 5.62044,-9.96942 c 3.09124,-5.48319 5.62044,-10.21511 5.62044,-10.51538 0,-0.30027 -1.15454,-0.54595 -2.56564,-0.54595 h -2.56564 l -4.20029,8.09641 c -2.67942,5.1648 -4.33588,7.8298 -4.57474,7.3601 -0.20594,-0.40496 -2.13104,-4.04835 -4.27799,-8.0964 l -3.90356,-7.36011 h -2.87335 c -1.58035,0 -2.87336,0.12781 -2.87336,0.28402 0,0.1562 2.64964,4.96636 5.88808,10.68923 l 5.88809,10.40522 v 5.63681 5.63682 h 2.40876 2.40876 z"
id="path1462" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 762.70726,222.86949 c -4.07666,-0.78537 -10.17009,-3.29429 -13.6441,-5.61785 -6.91015,-4.6218 -11.71459,-10.88088 -14.5402,-18.94258 -1.34575,-3.83954 -1.49911,-4.98899 -1.49911,-11.23574 0,-6.24676 0.15336,-7.39621 1.49911,-11.23575 3.87774,-11.0635 11.80142,-19.0577 22.76847,-22.97107 4.25097,-1.51687 5.15889,-1.64602 11.57155,-1.64602 6.41266,0 7.32058,0.12915 11.57155,1.64602 14.51853,5.18065 23.77179,17.63258 24.42528,32.86862 0.45428,10.5913 -2.84072,19.07821 -10.28709,26.49636 -7.55957,7.53093 -14.1652,10.43737 -24.37154,10.72334 -3.38565,0.0949 -6.75791,0.0565 -7.49392,-0.0853 z m 2.38607,-25.68467 c 4.25443,-7.14961 3.37755,-7.25493 8.20926,0.98595 l 3.05431,5.20938 3.12152,0.01 3.12152,0.01 -1.22963,-2.0073 c -0.6763,-1.10401 -3.07664,-4.86619 -5.3341,-8.36039 l -4.10446,-6.35309 4.75516,-7.43514 c 2.61533,-4.08932 4.75516,-7.56602 4.75516,-7.72599 0,-0.15996 -1.24936,-0.21804 -2.77636,-0.12905 l -2.77635,0.16179 -3.10726,5.05393 c -1.70899,2.77966 -3.29562,5.24229 -3.52585,5.47251 -0.23022,0.23022 -1.93136,-2.10426 -3.78031,-5.18775 l -3.36174,-5.60633 h -2.95881 -2.95881 l 1.22685,2.0073 c 0.67476,1.10402 2.8714,4.62127 4.88142,7.81612 l 3.65457,5.80881 -4.85255,7.43415 c -2.66891,4.08878 -4.99211,7.79781 -5.16268,8.24229 -0.25287,0.65897 0.2216,0.80814 2.57051,0.80814 h 2.88063 z"
id="path1464" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 833.85476,295.72323 c -6.83119,-1.65863 -13.77734,-5.88165 -18.67395,-11.35311 -3.40208,-3.80148 -7.27107,-11.46438 -8.31543,-16.4695 -2.76322,-13.24277 2.63571,-27.85526 13.26894,-35.91309 19.99373,-15.15118 48.09433,-6.6877 56.44101,16.99918 1.86188,5.28381 2.27747,13.55775 0.97503,19.41195 -1.50813,6.77877 -4.55198,12.15816 -9.87968,17.46031 -5.26572,5.24048 -9.89475,7.95133 -16.43315,9.62357 -4.85615,1.24199 -12.80551,1.35206 -17.38277,0.24069 z m 0.90791,-22.33599 1.06927,-3.3455 6.50377,-0.1501 6.50377,-0.1501 0.98735,3.36178 0.98735,3.36179 2.51591,0.16314 c 1.8243,0.1183 2.51592,-0.0335 2.51592,-0.55237 0,-0.39353 -2.29576,-7.75345 -5.10169,-16.35537 l -5.10169,-15.63986 h -3.1506 -3.1506 l -5.20854,15.65695 c -2.86469,8.61132 -5.31927,15.95804 -5.45462,16.32605 -0.17576,0.47789 0.50564,0.6691 2.38452,0.6691 h 2.6306 z"
id="path1466" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 763.70798,369.86416 c -8.12397,-1.27622 -14.00129,-4.35733 -20.33165,-10.65861 -3.76197,-3.74468 -5.02094,-5.43974 -6.83916,-9.20812 -7.60051,-15.75262 -3.54817,-33.43875 10.18745,-44.46231 6.3567,-5.10159 13.61954,-7.5924 22.13836,-7.5924 29.9337,0 46.67981,33.83863 28.70945,58.01278 -7.44586,10.01634 -21.60997,15.83377 -33.86445,13.90866 z m 11.20335,-21.38348 c 3.07353,-1.75995 4.52918,-4.20847 4.57675,-7.69846 0.0443,-3.24643 -1.27165,-5.85301 -3.49954,-6.93201 l -1.49389,-0.72351 1.60877,-1.54129 c 1.87307,-1.79453 2.80455,-4.70189 2.3305,-7.27407 -0.92747,-5.03237 -3.68485,-6.33408 -13.45172,-6.35026 l -7.09246,-0.0118 v 16.10974 16.10973 l 7.3601,-0.18515 c 6.6513,-0.16732 7.58173,-0.31206 9.66149,-1.50296 z"
id="path1468" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 762.70726,326.44188 v -4.88945 l 3.72999,0.26688 c 4.16057,0.29769 6.24901,1.33706 6.7575,3.36306 0.94714,3.77369 -1.80659,6.14376 -7.14199,6.14695 l -3.3455,0.002 z"
id="path1470" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999998"
d="m 837.54718,264.82028 c 0,-0.76372 4.25204,-14.10124 4.62716,-14.51418 0.17889,-0.19692 1.32644,2.82483 2.55012,6.715 1.22368,3.89017 2.33144,7.35074 2.46168,7.69016 0.18748,0.48856 -0.7918,0.61711 -4.70107,0.61711 -3.25732,0 -4.93789,-0.17292 -4.93789,-0.50809 z"
id="path1496" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999998"
d="m 763.06218,340.74443 v -5.12084 h 3.61513 c 4.59667,0 6.58099,0.93645 7.49973,3.5393 0.55274,1.56594 0.54465,2.04231 -0.0591,3.47983 -0.97646,2.32493 -3.07062,3.22256 -7.51823,3.22256 h -3.53752 z"
id="path1498" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 766.92321,602.64753 c -0.29048,-8.92659 -0.85756,-9.59054 -10.1321,-11.86299 -21.45382,-5.25664 -37.29198,-20.85776 -42.70074,-42.06165 -0.55002,-2.15622 -1.00003,-4.47981 -1.00003,-5.16353 0,-0.68371 -1.0064,-2.24952 -2.23643,-3.47956 l -2.23643,-2.23643 h -6.9724 -6.97241 v -1.97332 -1.97332 h 5.94109 c 6.60342,0 9.93688,-1.00153 11.20212,-3.36564 0.44261,-0.82703 1.34271,-3.96544 2.00022,-6.97425 3.49259,-15.98235 14.91214,-30.68661 29.48362,-37.96428 4.71573,-2.35525 11.36654,-4.65443 15.50589,-5.36038 6.61875,-1.12879 8.22218,-3.61509 8.22218,-12.74947 v -5.94109 h 1.97332 1.97332 v 6.89625 c 0,6.61611 0.0735,6.97475 1.80888,8.82901 1.46262,1.5628 3.13096,2.25493 8.7155,3.61572 20.40883,4.97306 36.06052,19.9102 41.49254,39.59826 0.78813,2.85653 1.76467,6.36883 2.17007,7.80511 1.22789,4.35011 3.85392,5.61076 11.68766,5.61076 h 6.48046 v 1.97332 1.97332 h -6.6104 c -6.95598,0 -9.89025,0.84134 -10.81193,3.1001 -0.2638,0.64649 -1.18554,3.97814 -2.0483,7.40367 -5.38972,21.39923 -21.36363,37.35004 -42.22246,42.16138 -9.94989,2.29507 -10.66202,3.14671 -10.66202,12.75068 v 6.28151 h -1.91345 -1.91345 z"
id="path1500" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d=""
id="path1502" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 695.45795,526.49678 c 1.75282,-15.26781 9.42349,-30.89435 20.92126,-42.62035 11.95352,-12.1908 27.0212,-19.51188 45.22194,-21.97243 l 2.79554,-0.37793 v 6.18375 c 0,7.93282 -0.51936,8.65269 -7.23551,10.02904 -22.30129,4.57023 -40.70977,22.45408 -45.7072,44.40457 -2.01248,8.8395 -2.35691,9.12221 -11.11415,9.12221 h -5.42936 z"
id="path1504" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="M 754.53008,608.24817 C 722.31091,601.3332 698.78801,575.33696 695.1389,542.61223 l -0.23838,-2.13776 h 6.36187 c 5.30645,0 6.54081,0.19773 7.44049,1.19187 0.59325,0.65553 1.8242,4.13099 2.73545,7.72325 5.73315,22.60074 22.81787,39.26947 45.21411,44.1132 6.89875,1.49203 7.74425,2.60069 7.74425,10.15464 v 5.88328 l -2.13776,-0.0463 c -1.17577,-0.0255 -4.65375,-0.58628 -7.72885,-1.24626 z"
id="path1506" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 773.60552,603.37682 c 0,-7.26315 0.7124,-8.57514 5.06106,-9.32073 4.85038,-0.83162 11.1113,-2.92244 16.31659,-5.44891 15.80304,-7.67023 27.12455,-21.98721 31.55746,-39.907 0.97744,-3.95125 2.07685,-6.90365 2.75558,-7.39995 0.71733,-0.52453 3.39605,-0.82576 7.34299,-0.82576 h 6.21369 l -0.43161,3.7822 c -3.78834,33.19719 -31.7798,61.26383 -64.82878,65.00289 l -3.98698,0.45108 z"
id="path1508" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 829.28285,529.78565 c -1.17591,-1.07273 -1.92806,-2.90835 -2.7333,-6.67061 -4.37909,-20.45999 -18.95972,-36.61709 -39.28934,-43.53733 -2.43875,-0.83016 -5.8241,-1.71782 -7.52299,-1.97259 -1.88233,-0.28227 -3.68318,-1.05749 -4.6103,-1.9846 -1.37609,-1.3761 -1.5214,-2.11712 -1.5214,-7.7588 v -6.23739 l 2.46665,0.33127 c 18.99503,2.55107 32.67768,9.21103 45.44487,22.12006 10.43139,10.54728 17.44069,23.80984 20.16018,38.14583 0.547,2.88355 0.99455,6.09813 0.99455,7.14349 v 1.90066 h -5.88329 c -5.18197,0 -6.07667,-0.17643 -7.50563,-1.47999 z"
id="path1510" /><path
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999999"
d="m 663.62068,131.03319 c -0.53326,-0.58925 -0.625,-1.69704 -0.625,-7.54707 v -6.85645 l -1.10115,-1.23333 -1.10115,-1.23332 -7.11278,-0.10646 c -9.08871,-0.13604 -8.43455,0.46843 -8.43455,-7.79389 0,-4.68262 0.12554,-6.289149 0.5353,-6.850301 0.49015,-0.671243 1.10329,-0.741434 7.26979,-0.832236 3.70397,-0.05454 7.12214,-0.18656 7.59593,-0.293374 0.47378,-0.106815 1.19541,-0.741963 1.60361,-1.411441 0.66219,-1.086052 0.74232,-1.921972 0.74358,-7.756551 8.2e-4,-3.782617 0.16622,-6.847257 0.39235,-7.269795 0.3648,-0.681634 0.8563,-0.730476 7.35092,-0.730476 6.49462,0 6.98613,0.04884 7.35092,0.730476 0.22614,0.422538 0.39154,3.487178 0.39236,7.269795 10e-4,5.834579 0.0814,6.670499 0.74358,7.756551 0.4082,0.669478 1.12983,1.304626 1.60361,1.411441 0.47379,0.106814 3.89196,0.238833 7.59593,0.293374 6.1665,0.0908 6.77964,0.160993 7.26979,0.832236 0.40976,0.561152 0.5353,2.167681 0.5353,6.850301 0,8.26232 0.65416,7.65785 -8.43455,7.79389 l -7.11278,0.10646 -1.10115,1.23332 -1.10115,1.23333 v 6.92207 c 0,6.22636 -0.0694,6.98488 -0.69062,7.54707 -0.58568,0.53003 -1.66715,0.62501 -7.11685,0.62501 -5.74601,0 -6.49238,-0.0731 -7.05124,-0.69063 z"
id="path1512" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 709.89826,726.4428 v -5.25775 h 5.25776 5.25775 v 5.25775 5.25776 h -5.25775 -5.25776 z"
id="path1514" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 708.88715,747.11324 c -7.7953,-1.94254 -14.19265,-7.02605 -17.61469,-13.99713 -2.11167,-4.3017 -2.80967,-7.2657 -2.80967,-11.93106 0,-4.6603 0.69677,-7.62382 2.80517,-11.93107 2.98868,-6.10556 8.92756,-11.23718 15.51022,-13.40195 4.61637,-1.51813 11.17625,-1.60821 15.65781,-0.215 15.04474,4.67704 23.00917,20.70184 17.43246,35.07495 -4.8049,12.38391 -18.34269,19.55071 -30.9813,16.40126 z m 20.42437,-17.43489 v -8.4933 h 2.62887 c 1.44589,0 2.62888,-0.13514 2.62888,-0.3003 0,-0.16516 -4.4121,-4.71516 -9.80467,-10.1111 l -9.80467,-9.8108 -9.81081,9.80467 c -5.39594,5.39257 -9.8108,9.94257 -9.8108,10.1111 0,0.16854 1.27399,0.30643 2.8311,0.30643 h 2.8311 v 8.4933 8.4933 h 14.1555 14.1555 z"
id="path1516" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 709.32587,761.61376 c -14.84534,-2.33618 -27.22151,-12.34303 -32.43644,-26.22673 -7.52289,-20.0282 2.33277,-43.0312 22.02756,-51.41208 6.07171,-2.58375 8.49788,-3.03235 16.23903,-3.00264 6.50926,0.025 7.37011,0.11595 10.71773,1.13248 14.44352,4.38591 24.64194,14.87492 28.58676,29.40132 0.78714,2.89856 0.92468,4.38074 0.9169,9.88116 -0.008,5.44704 -0.15534,7.01511 -0.93296,9.90885 -4.75273,17.68623 -20.04274,29.95104 -38.0751,30.54176 -2.55811,0.0838 -5.72767,-0.0171 -7.04348,-0.22412 z m 12.01917,-11.94961 c 11.93985,-2.6283 21.26602,-13.04595 22.49006,-25.12213 2.18282,-21.53536 -18.13115,-37.7028 -38.52104,-30.65805 -4.17709,1.44319 -6.99053,3.28712 -10.81791,7.09005 -2.821,2.80297 -3.81838,4.14269 -5.32568,7.15366 -2.55937,5.1126 -3.29841,8.68914 -3.02322,14.63061 0.31524,6.80606 2.15585,11.73401 6.30752,16.88741 6.75846,8.38917 18.22621,12.36591 28.89027,10.01845 z"
id="path1518" /><path
style="opacity:1;fill:#ff5f55;fill-opacity:0.956863;stroke:#4d4d4d;stroke-width:1"
d="m 591.47251,714.31134 c -2.59326,-1.58129 -2.41164,1.27628 -2.41164,-37.94303 0,-35.39705 0.002,-35.47278 0.79102,-36.47631 1.14169,-1.45141 2.68891,-2.12685 4.87199,-2.12685 h 1.91275 v 38.63637 38.63636 l -1.98864,-0.002 c -1.28887,-7.5e-4 -2.40626,-0.25607 -3.17548,-0.72512 z"
id="path1520" /><path
style="opacity:1;fill:#ff5f55;fill-opacity:0.956863;stroke:#4d4d4d;stroke-width:1"
d="m 592.87653,312.11027 c -0.50555,-0.0951 -1.32393,-0.43811 -1.8186,-0.76224 -2.07696,-1.36087 -1.99706,0.15175 -1.99706,-37.80487 0,-31.80626 0.058,-35.19116 0.61953,-36.14171 0.93372,-1.58066 2.4287,-2.28781 4.83664,-2.28781 h 2.11959 V 273.75 312.38636 l -1.42045,-0.0516 c -0.78125,-0.0284 -1.83409,-0.1294 -2.33965,-0.22451 z"
id="path1522" /><path
style="opacity:1;fill:#000000;fill-opacity:0.956863;stroke:#4d4d4d;stroke-width:1"
d="M 921.31509,126.45258 C 911.22775,105.90097 899.41123,89.210741 883.15837,72.558198 848.342,36.885643 804.48862,15.547979 753.51164,9.4762173 748.44895,8.8732107 740.43487,8.6841876 712.59008,8.5110262 L 677.96414,8.2956939 V 6.8885761 c 0,-0.9784616 0.48302,-1.8901352 1.58557,-2.9926826 l 1.58556,-1.5855648 h 30.73203 c 16.92783,0 33.54939,0.2176979 37.00428,0.4846569 50.75274,3.9216602 97.06468,24.5817024 133.31418,59.4722764 17.58138,16.922285 31.48259,35.738975 42.78184,57.909488 4.28368,8.40514 4.87972,10.05538 4.25358,11.77682 -0.41652,1.14511 -2.61821,3.7514 -3.13345,3.70927 -0.14438,-0.0118 -2.29207,-4.15642 -4.77264,-9.21026 z"
id="path1524" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 591.56604,904.17079 c -2.01964,-1.17632 -2.15587,-6.52992 -2.15587,-84.72244 v -83.46676 l 4.9277,-10.18986 4.92769,-10.18984 v -39.48272 -39.48272 l -4.92769,-9.84523 -4.9277,-9.84523 V 475.04429 333.1426 l 4.9277,-10.18986 4.92769,-10.18984 v -39.48272 -39.48272 l -4.93732,-9.86447 -4.93732,-9.86446 0.31761,-73.44555 0.31761,-73.44554 6.5676,-0.375829 c 3.78331,-0.216499 7.3086,0.239148 8.31548,1.074785 1.50292,1.24731 1.74788,59.776984 1.74788,417.620064 v 416.16945 l -2.73795,1.91775 c -3.10138,2.17229 -9.13889,2.45924 -12.35311,0.58713 z"
id="path1530" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="M 609.12095,465.08874 V 72.721096 h 4.31173 4.31173 V 465.08874 857.45638 h -4.31173 -4.31173 z"
id="path1532" /></svg>

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -1,120 +1,311 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg
<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" xmlns:dc="http://purl.org/dc/elements/1.1/"
viewBox="0 0 1000.8 1000" style="enable-background:new 0 0 1000.8 1000;" xml:space="preserve"> xmlns:cc="http://creativecommons.org/ns#"
<style type="text/css"> xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 1000.8 1000"
style="enable-background:new 0 0 1000.8 1000;"
xml:space="preserve"
sodipodi:docname="JoyConRight.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"><metadata
id="metadata85"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs83" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1003"
id="namedview81"
showgrid="false"
inkscape:zoom="0.715"
inkscape:cx="500.39999"
inkscape:cy="504.8442"
inkscape:window-x="1400"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<style
type="text/css"
id="style2">
.st0{opacity:0.1;} .st0{opacity:0.1;}
.st1{fill:#FF5F55;} .st1{fill:#FF5F55;}
.st2{fill:#FFFFFF;} .st2{fill:#FFFFFF;}
</style> </style>
<g class="st0">
<path class="st1" d="M597.9,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 class="st1" d="M597.9,636.6v79.5h-4.2c-3.3,0-6-2.7-6-6v-67.6c0-3.3,2.7-6,6-6L597.9,636.6L597.9,636.6z"/>
<path class="st1" d="M929,134.9l-3.4,3.4C892.4,60.3,815.8,9.6,730.9,9.6h-54.2V7c0-3.3,2.7-6,6-6l0,0h51.2
c84.8,0,161.7,49.8,196.4,127.2C931.3,130.5,930.8,133.1,929,134.9z"/>
<path class="st1" d="M679.5,94.5V82.8c0-1.6-1.3-3-3-3l0,0h-11.7c-1.6,0-3,1.3-3,3l0,0v11.7c0,1.6-1.3,3-3,3l0,0h-11.7
c-1.6,0-3,1.3-3,3l0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3,1.3,3,3l0,0v11.7c0,1.6,1.3,3,3,3l0,0h11.7c1.6,0,3-1.3,3-3l0,0
v-11.7c0-1.6,1.3-3,3-3l0,0h11.7c1.6,0,3-1.3,3-3l0,0v-11.7c0-1.6-1.3-3-3-3l0,0h-11.7C680.8,97.5,679.5,96.1,679.5,94.5
L679.5,94.5z"/>
<circle class="st1" cx="768.9" cy="333.9" r="37.5"/>
<circle class="st1" cx="768.9" cy="187.1" r="37.5"/>
<circle class="st1" cx="842.3" cy="260.5" r="37.5"/>
<circle class="st1" cx="695.5" cy="260.5" r="37.5"/>
<circle class="st1" cx="715" cy="721.3" r="27.9"/>
<path class="st1" d="M765.6,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.2h-12.3
C695.2,493.3,726.5,462,765.6,460.3z"/>
<path class="st1" d="M765.6,598.8v12.3c-39.1-1.7-70.3-33-72.1-72h12.3c3,0,5.5,2.2,5.9,5.2c3.7,25.2,23.5,45,48.7,48.7
C763.4,593.3,765.6,595.8,765.6,598.8z"/>
<path class="st1" d="M844.3,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.2L844.3,539z"/>
<path class="st1" d="M844.3,532.4H832c-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.9v-12.3
C811.3,462,842.6,493.3,844.3,532.4z"/>
<path class="st1" d="M844.4,535.7c0,1.1,0,2.2-0.1,3.3H832c-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 <style
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 type="text/css"
c0.4,2.9,2.9,5.1,5.9,5.2h12.3C844.3,533.5,844.4,534.6,844.4,535.7z"/> id="style2-6">
</g> .st0{opacity:0.1;}
<path class="st2" d="M601.6,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 .st1{fill:#02C5E5;}
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.5h7.9 .st2{fill:#FF5F55;}
c3.6,0,6.4,2.9,6.5,6.5v828.9C608,903.7,605.1,906.6,601.6,906.6z M593.7,65.7c-3,0-5.5,2.4-5.5,5.5V207c0,4.7,1.1,9.3,3.3,13.5 .st3{fill:#FFFFFF;}
l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-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.5 </style><g
l6.8,13.1c0,0.1,0.1,0.1,0.1,0.2v79.5c0,0.1,0,0.2-0.1,0.2l-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.9 id="g315"><g
c3,0,5.5-2.4,5.5-5.5V71.2c0-3-2.4-5.5-5.5-5.5H593.7z"/> class="st0"
<path class="st2" d="M618.8,858.9h-11.3c-0.3,0-0.5-0.2-0.5-0.5l0,0V72c0-0.3,0.2-0.5,0.5-0.5h11.3c0.3,0,0.5,0.2,0.5,0.5v786.4 id="g64">
C619.3,858.7,619.1,858.9,618.8,858.9L618.8,858.9z M608,857.9h10.3V72.5H608V857.9z"/> <path
<path class="st2" d="M730.9,1000H624.7c-3.6,0-6.5-2.9-6.5-6.5v-978c0-3.6,2.9-6.5,6.5-6.5h106.2c116.8,0,211.9,95.1,211.9,211.9 class="st2"
v567.2C942.8,905.1,848,1000,730.9,1000L730.9,1000z M624.7,10.1c-3,0-5.5,2.4-5.5,5.5v978c0,3,2.4,5.5,5.5,5.5h106.2 d="m 597.9,233.9 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z"
c116.3,0,210.9-94.6,210.9-210.9V220.9C941.8,104.6,847.2,10,730.9,10L624.7,10.1z"/> id="path36" />
<path class="st2" d="M715,763.2c-23.1,0-41.9-18.7-41.9-41.9s18.7-41.9,41.9-41.9s41.9,18.7,41.9,41.9l0,0 <path
C756.8,744.4,738.1,763.1,715,763.2z M715,680.4c-22.6,0-40.9,18.3-40.9,40.9c0,22.6,18.3,40.9,40.9,40.9 class="st2"
c22.6,0,40.9-18.3,40.9-40.9l0,0C755.8,698.7,737.6,680.4,715,680.4z"/> d="m 597.9,636.6 v 79.5 h -4.2 c -3.3,0 -6,-2.7 -6,-6 v -67.6 c 0,-3.3 2.7,-6 6,-6 h 4.2 z"
<path class="st1" d="M782.2,203.2h-5.5l-7.8-12.9l-7.8,12.9h-5.4l10.6-16.3l-9.8-15.6h5.2l7.3,12l7.4-12h5l-9.8,15.4L782.2,203.2z" id="path38" />
/> <path
<path class="st1" d="M709.2,244.5l-11.6,20.6v11.4h-4.4V265l-11.6-20.5h5.3l6.4,11.7l2.3,4.7l2.2-4.3l6.4-12.1L709.2,244.5z"/> class="st2"
<path class="st1" d="M855.9,276.5h-4.7l-2.2-7h-13.3l-2.3,7h-4.5l10.6-32h6L855.9,276.5z M847.7,265.6l-5.4-17.1l-5.4,17.1H847.7z" d="m 929,134.9 -3.4,3.4 C 892.4,60.3 815.8,9.6 730.9,9.6 H 676.7 V 7 c 0,-3.3 2.7,-6 6,-6 0,0 0,0 0,0 h 51.2 c 84.8,0 161.7,49.8 196.4,127.2 1,2.3 0.5,4.9 -1.3,6.7 z"
/> id="path40" />
<path class="st1" d="M779.4,340.4c0,1.4-0.3,2.8-0.9,4.1c-0.6,1.2-1.5,2.2-2.5,3c-1.2,0.9-2.6,1.5-4,1.9c-1.7,0.4-3.4,0.7-5.2,0.6 <path
h-8.4v-32h9.2c7.1,0,10.7,2.6,10.7,7.8c0,1.6-0.4,3.1-1.2,4.5c-1,1.4-2.4,2.3-4,2.8c0.9,0.2,1.7,0.4,2.5,0.8s1.5,0.9,2,1.5 class="st2"
c0.6,0.6,1.1,1.4,1.4,2.2C779.2,338.4,779.4,339.4,779.4,340.4z M773.7,326.3c0-0.6-0.1-1.3-0.3-1.8c-0.2-0.6-0.6-1.1-1-1.5 d="M 679.5,94.5 V 82.8 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 -1.3,3 -3,3 v 0 h -11.7 c -1.6,0 -3,1.3 -3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,1.3 3,3 0,0 0,0 0,0 v 11.7 c 0,1.6 1.3,3 3,3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 v 0 -11.7 c 0,-1.6 1.3,-3 3,-3 v 0 h 11.7 c 1.6,0 3,-1.3 3,-3 0,0 0,0 0,0 v -11.7 c 0,-1.6 -1.3,-3 -3,-3 v 0 h -11.7 c -1.7,0 -3,-1.4 -3,-3 0,0 0,0 0,0 z"
c-0.6-0.5-1.3-0.8-2-1c-1-0.3-2.1-0.4-3.2-0.4h-4.5v10h4.4c0.9,0,1.8-0.1,2.7-0.3c0.8-0.2,1.5-0.5,2.1-1c0.6-0.4,1-1,1.3-1.7 id="path42" />
C773.6,327.9,773.7,327.1,773.7,326.3L773.7,326.3z M774.8,340.5c0-0.8-0.2-1.5-0.5-2.2c-0.4-0.7-0.9-1.2-1.5-1.7 <circle
c-0.7-0.5-1.5-0.8-2.4-1c-1-0.3-2.1-0.4-3.2-0.4h-4.5v11h4.6c2.5,0,4.4-0.5,5.6-1.4C774.2,343.8,774.9,342.2,774.8,340.5 class="st2"
L774.8,340.5z"/> cx="768.90002"
<path class="st1" d="M715,701.3L695.4,721h5.6v16.8h28.2V721h5.3L715,701.3z M720.7,731.8h-11.1V721h11.1V731.8z"/> cy="333.89999"
<path class="st1" d="M597.9,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 r="37.5"
C598.9,313.9,598.4,314.3,597.9,314.3L597.9,314.3z M593.7,234.8c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5h3.2v-77.5L593.7,234.8 id="circle44" />
L593.7,234.8z"/> <circle
<path class="st1" d="M597.9,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 class="st2"
C598.9,716.6,598.4,717.1,597.9,717.1L597.9,717.1z M593.7,637.6c-2.7,0-5,2.2-5,5v67.6c0,2.7,2.2,5,5,5h3.2v-77.5L593.7,637.6 cx="768.90002"
L593.7,637.6z"/> cy="187.10001"
<path class="st1" d="M925.6,139.3c-0.1,0-0.1,0-0.2,0c-0.3-0.1-0.6-0.3-0.7-0.6C891.7,61,815.4,10.5,730.9,10.6h-54.2 r="37.5"
c-0.6,0-1-0.4-1-1l0,0V7c0-3.8,3.1-6.9,7-7h51.2c85.2,0.1,162.4,50.1,197.3,127.8c1.2,2.6,0.6,5.7-1.5,7.8l-3.4,3.4 id="circle46" />
C926.1,139.2,925.8,139.3,925.6,139.3z M677.7,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.5 <circle
C894.8,51.7,818.3,2.1,733.9,2h-51.2c-2.7,0-5,2.2-5,5V8.6z"/> class="st2"
<path class="st1" d="M676.5,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-4h11.7 cx="842.29999"
c1.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.7c0,2.2-1.8,4-4,4h-11.7 cy="260.5"
c-1.1,0-2,0.9-2,2v11.7C680.5,131.9,678.7,133.7,676.5,133.7z M647.2,98.5c-1.1,0-2,0.9-2,2v11.7c0,1.1,0.9,2,2,2h11.7 r="37.5"
c2.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-4h11.7c1.1,0,2-0.9,2-2v-11.7c0-1.1-0.9-2-2-2 id="circle48" />
h-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,4H647.2z"/> <circle
<path class="st1" d="M768.9,372.4c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 class="st2"
C807.3,355.2,790.1,372.4,768.9,372.4z M768.9,297.5c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 cx="695.5"
c20.1,0,36.5-16.3,36.5-36.5C805.3,313.8,789,297.5,768.9,297.5L768.9,297.5z"/> cy="260.5"
<path class="st1" d="M768.9,225.5c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 r="37.5"
C807.3,208.3,790.1,225.5,768.9,225.5z M768.9,150.6c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 id="circle50" />
c20.1,0,36.5-16.3,36.5-36.5C805.3,166.9,789,150.6,768.9,150.6L768.9,150.6z"/> <circle
<path class="st1" d="M842.3,299c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 class="st2"
C880.8,281.7,863.6,298.9,842.3,299z M842.3,224c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 cx="715"
c20.1,0,36.5-16.3,36.5-36.5C878.8,240.4,862.5,224,842.3,224L842.3,224z"/> cy="721.29999"
<path class="st1" d="M695.5,299c-21.2,0-38.5-17.2-38.5-38.5c0-21.2,17.2-38.5,38.5-38.5c21.2,0,38.5,17.2,38.5,38.5 r="27.9"
C733.9,281.7,716.7,298.9,695.5,299z M695.5,224c-20.1,0-36.5,16.3-36.5,36.5c0,20.1,16.3,36.5,36.5,36.5 id="circle52" />
c20.1,0,36.5-16.3,36.5-36.5C731.9,240.4,715.6,224,695.5,224L695.5,224z"/> <path
<path class="st1" d="M715,750.2c-16,0-28.9-13-28.9-28.9s13-28.9,28.9-28.9c16,0,28.9,13,28.9,28.9l0,0 class="st2"
C743.9,737.3,731,750.2,715,750.2z M715,694.3c-14.9,0-26.9,12.1-26.9,26.9s12.1,26.9,26.9,26.9c14.9,0,26.9-12.1,26.9-26.9 d="m 765.6,460.3 v 12.3 c 0,3 -2.2,5.5 -5.2,5.9 -25.2,3.7 -45,23.5 -48.7,48.7 -0.4,2.9 -2.9,5.1 -5.9,5.2 h -12.3 c 1.7,-39.1 33,-70.4 72.1,-72.1 z"
C741.9,706.4,729.9,694.4,715,694.3z"/> id="path54" />
<path class="st1" d="M705.8,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 <path
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.9C712.2,530.8,709.3,533.4,705.8,533.4z class="st2"
M694.6,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 d="m 765.6,598.8 v 12.3 c -39.1,-1.7 -70.3,-33 -72.1,-72 h 12.3 c 3,0 5.5,2.2 5.9,5.2 3.7,25.2 23.5,45 48.7,48.7 3,0.3 5.2,2.8 5.2,5.8 z"
C727.2,463.5,696.7,494,694.6,531.4z"/> id="path56" />
<path class="st1" d="M765.6,612.1C765.6,612.1,765.5,612.1,765.6,612.1c-39.6-1.7-71.3-33.4-73-73c0-0.6,0.4-1,1-1l0,0h12.3 <path
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.3C766.6,611.6,766.1,612.1,765.6,612.1L765.6,612.1 class="st2"
L765.6,612.1z M694.6,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 d="m 844.3,539 c -1.7,39.1 -33,70.3 -72.1,72 v -12.3 c 0,-3 2.2,-5.5 5.2,-5.9 25.2,-3.7 45,-23.5 48.7,-48.7 0.4,-2.9 2.9,-5.1 5.9,-5.2 z"
c-0.3-2.5-2.4-4.3-4.9-4.3H694.6z"/> id="path58" />
<path class="st1" d="M772.2,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 <path
c0.5-3.4,3.4-6,6.9-6h12.3c0.6,0,1,0.4,1,1l0,0C843.5,578.7,811.9,610.3,772.2,612.1C772.3,612.1,772.3,612.1,772.2,612.1z M832,540 class="st2"
c-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.9V610c37.4-2.2,67.8-32.6,70-70H832z"/> d="M 844.3,532.4 H 832 c -3,0 -5.5,-2.2 -5.9,-5.2 -3.7,-25.2 -23.5,-45 -48.7,-48.7 -2.9,-0.4 -5.1,-2.9 -5.2,-5.9 v -12.3 c 39.1,1.7 70.4,33 72.1,72.1 z"
<path class="st1" d="M844.3,533.4H832c-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 id="path60" />
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,73C845.3,532.9,844.9,533.3,844.3,533.4L844.3,533.4L844.3,533.4z <path
M773.2,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 class="st2"
C841.1,494,810.6,463.5,773.2,461.4z"/> d="m 844.4,535.7 c 0,1.1 0,2.2 -0.1,3.3 H 832 c -3,0 -5.5,2.2 -5.9,5.2 -3.7,25.2 -23.5,45 -48.7,48.7 -2.9,0.4 -5.1,2.9 -5.2,5.9 v 12.3 c -1.1,0.1 -2.2,0.1 -3.3,0.1 -1.1,0 -2.2,0 -3.3,-0.1 v -12.3 c 0,-3 -2.2,-5.5 -5.2,-5.9 -25.2,-3.7 -45,-23.5 -48.7,-48.7 -0.4,-2.9 -2.9,-5.1 -5.9,-5.2 h -12.3 c -0.1,-1.1 -0.1,-2.2 -0.1,-3.3 0,-1.1 0,-2.2 0.1,-3.3 h 12.3 c 3,0 5.5,-2.2 5.9,-5.2 3.7,-25.2 23.5,-45 48.7,-48.7 2.9,-0.4 5.1,-2.9 5.2,-5.9 v -12.3 c 1.1,-0.1 2.2,-0.1 3.3,-0.1 1.1,0 2.2,0 3.3,0.1 v 12.3 c 0,3 2.2,5.5 5.2,5.9 25.2,3.7 45,23.5 48.7,48.7 0.4,2.9 2.9,5.1 5.9,5.2 h 12.3 c 0,1.1 0.1,2.2 0.1,3.3 z"
<path class="st1" d="M768.9,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 id="path62" />
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 </g><path
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 class="st3"
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 d="m 601.6,906.6 h -7.9 c -3.6,0 -6.4,-2.9 -6.5,-6.5 V 742.9 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 v -79.2 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 340.1 c 0,-4.9 1.2,-9.6 3.4,-13.9 l 6.7,-13 V 234 l -6.7,-13 c -2.2,-4.3 -3.4,-9.1 -3.4,-14 V 71.2 c 0,-3.6 2.9,-6.4 6.5,-6.5 h 7.9 c 3.6,0 6.4,2.9 6.5,6.5 v 828.9 c -0.1,3.6 -3,6.5 -6.5,6.5 z M 593.7,65.7 c -3,0 -5.5,2.4 -5.5,5.5 V 207 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 269.7 c 0,4.7 1.1,9.3 3.3,13.5 l 6.8,13.1 c 0,0.1 0.1,0.1 0.1,0.2 v 79.5 c 0,0.1 0,0.2 -0.1,0.2 l -6.8,13.1 c -2.2,4.2 -3.3,8.8 -3.3,13.5 v 157.2 c 0,3 2.4,5.5 5.5,5.5 h 7.9 c 3,0 5.5,-2.4 5.5,-5.5 V 71.2 c 0,-3 -2.4,-5.5 -5.5,-5.5 z"
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.9H832c-2.5,0-4.6,1.8-4.9,4.3 id="path72"
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,1C771.2,612.1,770.1,612.2,768.9,612.2z M766.6,610.1 style="fill:#000000" /><path
c1.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.3c0-0.8,0-1.5,0-2.3 class="st3"
s0-1.6,0-2.3H832c-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 d="m 618.8,858.9 h -11.3 c -0.3,0 -0.5,-0.2 -0.5,-0.5 0,0 0,0 0,0 V 72 c 0,-0.3 0.2,-0.5 0.5,-0.5 h 11.3 c 0.3,0 0.5,0.2 0.5,0.5 v 786.4 c 0,0.3 -0.2,0.5 -0.5,0.5 0,0 0,0 0,0 z m -10.8,-1 h 10.3 V 72.5 H 608 Z"
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.3c0,0.8,0,1.5,0,2.3s0,1.6,0,2.3h11.3 id="path74"
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.3H766.6z"/> style="fill:#000000" /><path
</svg> class="st3"
d="M 730.9,1000 H 624.7 c -3.6,0 -6.5,-2.9 -6.5,-6.5 v -978 c 0,-3.6 2.9,-6.5 6.5,-6.5 h 106.2 c 116.8,0 211.9,95.1 211.9,211.9 v 567.2 c 0,117 -94.8,211.9 -211.9,211.9 0,0 0,0 0,0 z M 624.7,10.1 c -3,0 -5.5,2.4 -5.5,5.5 v 978 c 0,3 2.4,5.5 5.5,5.5 h 106.2 c 116.3,0 210.9,-94.6 210.9,-210.9 V 220.9 C 941.8,104.6 847.2,10 730.9,10 Z"
id="path76"
style="fill:#000000" /><path
class="st2"
d="m 597.9,314.3 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 v 79.5 c 0,0.7 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z"
id="path128"
style="fill:#000000" /><path
class="st2"
d="m 597.9,717.1 h -4.2 c -3.8,0 -6.9,-3.1 -7,-7 v -67.6 c 0,-3.8 3.1,-6.9 7,-7 h 4.2 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 V 716 c 0,0.6 -0.5,1.1 -1,1.1 0,0 0,0 0,0 z m -4.2,-79.5 c -2.7,0 -5,2.2 -5,5 v 67.6 c 0,2.7 2.2,5 5,5 h 3.2 v -77.5 h -3.2 z"
id="path130"
style="fill:#000000" /><path
style="fill:#ff5f55;fill-opacity:0.956863;stroke:#4d4d4d;stroke-width:1"
d="m 748.93436,998.67954 c 26.59545,-2.35471 50.45796,-9.1985 75.88056,-21.7626 65.98743,-32.61168 108.87577,-94.17749 116.99375,-167.94346 1.80381,-16.39057 1.80686,-591.16592 0.003,-608.68789 -2.68506,-26.08512 -9.29287,-49.0507 -20.75194,-72.12385 C 889.32253,64.257568 828.18558,20.735655 757.19631,11.511152 738.81239,9.1223039 622.08856,8.8130147 619.73408,11.146911 c -1.13928,1.129303 -1.47099,112.509439 -1.47099,493.898369 0,485.61761 0.0328,492.45765 2.37105,493.69808 2.83295,1.50294 111.21392,1.44894 128.30022,-0.0637 z"
id="path1240" /><path
class="st3"
d="m 715,763.2 c -23.1,0 -41.9,-18.7 -41.9,-41.9 0,-23.2 18.7,-41.9 41.9,-41.9 23.2,0 41.9,18.7 41.9,41.9 v 0 c -0.1,23.1 -18.8,41.8 -41.9,41.9 z m 0,-82.8 c -22.6,0 -40.9,18.3 -40.9,40.9 0,22.6 18.3,40.9 40.9,40.9 22.6,0 40.9,-18.3 40.9,-40.9 v 0 C 755.8,698.7 737.6,680.4 715,680.4 Z"
id="path78"
style="fill:#000000" /><path
class="st2"
d="m 782.2,203.2 h -5.5 l -7.8,-12.9 -7.8,12.9 h -5.4 l 10.6,-16.3 -9.8,-15.6 h 5.2 l 7.3,12 7.4,-12 h 5 l -9.8,15.4 z"
id="path88"
style="fill:#b3b3b3;fill-opacity:1" /><path
class="st2"
d="m 709.2,244.5 -11.6,20.6 v 11.4 h -4.4 V 265 l -11.6,-20.5 h 5.3 l 6.4,11.7 2.3,4.7 2.2,-4.3 6.4,-12.1 z"
id="path90"
style="fill:#b3b3b3" /><path
class="st2"
d="m 855.9,276.5 h -4.7 l -2.2,-7 h -13.3 l -2.3,7 h -4.5 l 10.6,-32 h 6 z m -8.2,-10.9 -5.4,-17.1 -5.4,17.1 z"
id="path92"
style="fill:#b3b3b3" /><path
class="st2"
d="m 779.4,340.4 c 0,1.4 -0.3,2.8 -0.9,4.1 -0.6,1.2 -1.5,2.2 -2.5,3 -1.2,0.9 -2.6,1.5 -4,1.9 -1.7,0.4 -3.4,0.7 -5.2,0.6 h -8.4 v -32 h 9.2 c 7.1,0 10.7,2.6 10.7,7.8 0,1.6 -0.4,3.1 -1.2,4.5 -1,1.4 -2.4,2.3 -4,2.8 0.9,0.2 1.7,0.4 2.5,0.8 0.8,0.4 1.5,0.9 2,1.5 0.6,0.6 1.1,1.4 1.4,2.2 0.2,0.8 0.4,1.8 0.4,2.8 z m -5.7,-14.1 c 0,-0.6 -0.1,-1.3 -0.3,-1.8 -0.2,-0.6 -0.6,-1.1 -1,-1.5 -0.6,-0.5 -1.3,-0.8 -2,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 10 h 4.4 c 0.9,0 1.8,-0.1 2.7,-0.3 0.8,-0.2 1.5,-0.5 2.1,-1 0.6,-0.4 1,-1 1.3,-1.7 0.4,-0.7 0.5,-1.5 0.5,-2.3 z m 1.1,14.2 c 0,-0.8 -0.2,-1.5 -0.5,-2.2 -0.4,-0.7 -0.9,-1.2 -1.5,-1.7 -0.7,-0.5 -1.5,-0.8 -2.4,-1 -1,-0.3 -2.1,-0.4 -3.2,-0.4 h -4.5 v 11 h 4.6 c 2.5,0 4.4,-0.5 5.6,-1.4 1.3,-1 2,-2.6 1.9,-4.3 z"
id="path94"
style="fill:#b3b3b3" /><path
class="st2"
d="M 715,701.3 695.4,721 h 5.6 v 16.8 h 28.2 V 721 h 5.3 z m 5.7,30.5 H 709.6 V 721 h 11.1 z"
id="path96"
style="fill:#333333" /><path
class="st2"
d="m 925.6,139.3 c -0.1,0 -0.1,0 -0.2,0 -0.3,-0.1 -0.6,-0.3 -0.7,-0.6 C 891.7,61 815.4,10.5 730.9,10.6 h -54.2 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 V 7 c 0,-3.8 3.1,-6.9 7,-7 h 51.2 c 85.2,0.1 162.4,50.1 197.3,127.8 1.2,2.6 0.6,5.7 -1.5,7.8 l -3.4,3.4 c -0.2,0.2 -0.5,0.3 -0.7,0.3 z M 677.7,8.6 h 53.2 c 84.7,-0.1 161.3,50.2 195,128 l 2.4,-2.4 v 0 c 1.5,-1.4 1.9,-3.6 1.1,-5.5 C 894.8,51.7 818.3,2.1 733.9,2 h -51.2 c -2.7,0 -5,2.2 -5,5 z"
id="path132"
style="fill:#000000" /><path
class="st2"
d="m 676.5,133.7 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 118 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 V 82.8 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,2.2 -1.8,4 -4,4 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2 -1.8,3.8 -4,3.8 z M 647.2,98.5 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 2.2,0 4,1.8 4,4 v 11.7 c 0,1.1 0.9,2 2,2 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-2.2 1.8,-4 4,-4 h 11.7 c 1.1,0 2,-0.9 2,-2 v -11.7 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -2.2,0 -4,-1.8 -4,-4 V 82.8 c 0,-1.1 -0.9,-2 -2,-2 h -11.7 c -1.1,0 -2,0.9 -2,2 v 11.7 c 0,2.2 -1.8,4 -4,4 z"
id="path134"
style="fill:#000000" /><path
class="st2"
d="m 768.9,372.4 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z"
id="path136"
style="fill:#000000" /><path
class="st2"
d="m 768.9,225.5 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.3 -17.3,38.5 -38.5,38.5 z m 0,-74.9 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 -0.1,-20.2 -16.4,-36.5 -36.5,-36.5 z"
id="path138"
style="fill:#000000" /><path
class="st2"
d="m 842.3,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 0,21.2 -17.2,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 0,-20.1 -16.3,-36.5 -36.5,-36.5 z"
id="path140"
style="fill:#000000" /><path
class="st2"
d="m 695.5,299 c -21.2,0 -38.5,-17.2 -38.5,-38.5 0,-21.2 17.2,-38.5 38.5,-38.5 21.2,0 38.5,17.2 38.5,38.5 -0.1,21.2 -17.3,38.4 -38.5,38.5 z m 0,-75 c -20.1,0 -36.5,16.3 -36.5,36.5 0,20.1 16.3,36.5 36.5,36.5 20.1,0 36.5,-16.3 36.5,-36.5 C 731.9,240.4 715.6,224 695.5,224 Z"
id="path142"
style="fill:#000000" /><path
class="st2"
d="m 715,750.2 c -16,0 -28.9,-13 -28.9,-28.9 0,-15.9 13,-28.9 28.9,-28.9 16,0 28.9,13 28.9,28.9 0,0 0,0 0,0 0,16 -12.9,28.9 -28.9,28.9 z m 0,-55.9 c -14.9,0 -26.9,12.1 -26.9,26.9 0,14.8 12.1,26.9 26.9,26.9 14.9,0 26.9,-12.1 26.9,-26.9 0,-14.8 -12,-26.8 -26.9,-26.9 z"
id="path144"
style="fill:#000000" /><path
class="st2"
d="m 705.8,533.4 h -12.3 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 1.7,-39.6 33.4,-71.3 73,-73 0.3,0 0.5,0.1 0.7,0.3 0.2,0.2 0.3,0.4 0.3,0.7 v 12.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.4,3.3 -3.3,5.9 -6.8,5.9 z m -11.2,-2 h 11.2 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -11.2 c -37.4,2.1 -67.9,32.6 -70,70 z"
id="path146"
style="fill:#000000" /><path
class="st2"
d="m 765.6,612.1 c 0,0 -0.1,0 0,0 -39.6,-1.7 -71.3,-33.4 -73,-73 0,-0.6 0.4,-1 1,-1 0,0 0,0 0,0 h 12.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 12.3 c -0.1,0.4 -0.6,0.9 -1.1,0.9 0,0 0,0 0,0 z m -71,-72.1 c 2.2,37.4 32.6,67.8 70,70 v -11.2 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 z"
id="path148"
style="fill:#000000" /><path
class="st2"
d="m 772.2,612.1 c -0.6,0 -1,-0.4 -1,-1 0,0 0,0 0,0 v -12.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 12.3 c 0.6,0 1,0.4 1,1 0,0 0,0 0,0 -1.8,39.7 -33.4,71.3 -73.1,73.1 0.1,0 0.1,0 0,0 z M 832,540 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 V 610 c 37.4,-2.2 67.8,-32.6 70,-70 z"
id="path150"
style="fill:#000000" /><path
class="st2"
d="M 844.3,533.4 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -12.3 c 0,-0.3 0.1,-0.5 0.3,-0.7 0.2,-0.2 0.5,-0.3 0.7,-0.3 39.6,1.7 71.3,33.4 73,73 0.1,0.6 -0.3,1 -0.9,1.1 0,0 0,0 0,0 z m -71.1,-72 v 11.2 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 11.2 c -2.1,-37.4 -32.6,-67.9 -70,-70 z"
id="path152"
style="fill:#000000" /><path
class="st2"
d="m 768.9,612.2 c -1.2,0 -2.3,0 -3.4,-0.1 -0.5,0 -0.9,-0.5 -0.9,-1 v -12.3 c 0,-2.5 -1.8,-4.6 -4.3,-4.9 -25.6,-3.9 -45.7,-24 -49.6,-49.6 -0.3,-2.5 -2.4,-4.3 -4.9,-4.3 h -12.3 c -0.5,0 -1,-0.4 -1,-0.9 -0.1,-1.1 -0.1,-2.2 -0.1,-3.4 0,-1.2 0,-2.3 0.1,-3.4 0,-0.5 0.5,-0.9 1,-0.9 h 12.3 c 2.5,0 4.6,-1.8 4.9,-4.3 3.9,-25.6 24,-45.7 49.6,-49.6 2.5,-0.3 4.3,-2.4 4.3,-4.9 v -12.3 c 0,-0.5 0.4,-1 0.9,-1 2.3,-0.1 4.5,-0.1 6.8,0 0.5,0 0.9,0.5 0.9,1 v 12.3 c 0,2.5 1.8,4.6 4.3,4.9 25.6,3.9 45.7,24 49.6,49.6 0.3,2.5 2.4,4.3 4.9,4.3 h 12.3 c 0.5,0 1,0.4 1,0.9 0.1,1.1 0.1,2.2 0.1,3.4 0,1.2 0,2.3 -0.1,3.4 0,0.5 -0.5,0.9 -1,0.9 H 832 c -2.5,0 -4.6,1.8 -4.9,4.3 -3.9,25.6 -24,45.7 -49.6,49.6 -2.5,0.3 -4.3,2.4 -4.3,4.9 v 12.3 c 0,0.5 -0.4,1 -0.9,1 -1.1,0 -2.2,0.1 -3.4,0.1 z m -2.3,-2.1 c 1.5,0.1 3.1,0.1 4.7,0 v -11.3 c 0,-3.5 2.6,-6.4 6,-6.9 24.7,-3.7 44.2,-23.1 47.9,-47.9 0.5,-3.4 3.4,-6 6.9,-6 h 11.3 c 0,-0.8 0,-1.5 0,-2.3 0,-0.8 0,-1.6 0,-2.3 H 832 c -3.5,0 -6.4,-2.6 -6.9,-6 -3.7,-24.7 -23.1,-44.2 -47.9,-47.9 -3.4,-0.5 -6,-3.4 -6,-6.9 v -11.3 c -1.5,-0.1 -3.1,-0.1 -4.7,0 v 11.3 c 0,3.5 -2.6,6.4 -6,6.9 -24.7,3.7 -44.2,23.1 -47.9,47.9 -0.5,3.4 -3.4,6 -6.9,6 h -11.3 c 0,0.8 0,1.5 0,2.3 0,0.8 0,1.6 0,2.3 h 11.3 c 3.5,0 6.4,2.6 6.9,6 3.7,24.7 23.1,44.2 47.9,47.9 3.4,0.5 6,3.4 6,6.9 v 11.3 z"
id="path154"
style="fill:#000000" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 686.27756,295.45757 c -6.3268,-1.65761 -11.02024,-4.44224 -16.19729,-9.60987 -7.7249,-7.71084 -11.00252,-16.02709 -10.55426,-26.7792 0.56274,-13.49806 7.94054,-24.90282 19.94518,-30.83167 10.51307,-5.1922 21.47279,-5.27638 31.58153,-0.24258 7.93543,3.95157 13.41304,9.50319 17.2109,17.44344 5.18792,10.84649 4.24806,24.40322 -2.39714,34.5766 -4.99743,7.65076 -13.48676,13.69608 -22.04004,15.69491 -4.81862,1.12607 -12.72306,1.01273 -17.54888,-0.25163 z m 11.6608,-24.5355 v -5.81067 l 5.62044,-9.96942 c 3.09124,-5.48319 5.62044,-10.21511 5.62044,-10.51538 0,-0.30027 -1.15454,-0.54595 -2.56564,-0.54595 h -2.56564 l -4.20029,8.09641 c -2.67942,5.1648 -4.33588,7.8298 -4.57474,7.3601 -0.20594,-0.40496 -2.13104,-4.04835 -4.27799,-8.0964 l -3.90356,-7.36011 h -2.87335 c -1.58035,0 -2.87336,0.12781 -2.87336,0.28402 0,0.1562 2.64964,4.96636 5.88808,10.68923 l 5.88809,10.40522 v 5.63681 5.63682 h 2.40876 2.40876 z"
id="path1462" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 762.70726,222.86949 c -4.07666,-0.78537 -10.17009,-3.29429 -13.6441,-5.61785 -6.91015,-4.6218 -11.71459,-10.88088 -14.5402,-18.94258 -1.34575,-3.83954 -1.49911,-4.98899 -1.49911,-11.23574 0,-6.24676 0.15336,-7.39621 1.49911,-11.23575 3.87774,-11.0635 11.80142,-19.0577 22.76847,-22.97107 4.25097,-1.51687 5.15889,-1.64602 11.57155,-1.64602 6.41266,0 7.32058,0.12915 11.57155,1.64602 14.51853,5.18065 23.77179,17.63258 24.42528,32.86862 0.45428,10.5913 -2.84072,19.07821 -10.28709,26.49636 -7.55957,7.53093 -14.1652,10.43737 -24.37154,10.72334 -3.38565,0.0949 -6.75791,0.0565 -7.49392,-0.0853 z m 2.38607,-25.68467 c 4.25443,-7.14961 3.37755,-7.25493 8.20926,0.98595 l 3.05431,5.20938 3.12152,0.01 3.12152,0.01 -1.22963,-2.0073 c -0.6763,-1.10401 -3.07664,-4.86619 -5.3341,-8.36039 l -4.10446,-6.35309 4.75516,-7.43514 c 2.61533,-4.08932 4.75516,-7.56602 4.75516,-7.72599 0,-0.15996 -1.24936,-0.21804 -2.77636,-0.12905 l -2.77635,0.16179 -3.10726,5.05393 c -1.70899,2.77966 -3.29562,5.24229 -3.52585,5.47251 -0.23022,0.23022 -1.93136,-2.10426 -3.78031,-5.18775 l -3.36174,-5.60633 h -2.95881 -2.95881 l 1.22685,2.0073 c 0.67476,1.10402 2.8714,4.62127 4.88142,7.81612 l 3.65457,5.80881 -4.85255,7.43415 c -2.66891,4.08878 -4.99211,7.79781 -5.16268,8.24229 -0.25287,0.65897 0.2216,0.80814 2.57051,0.80814 h 2.88063 z"
id="path1464" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 833.85476,295.72323 c -6.83119,-1.65863 -13.77734,-5.88165 -18.67395,-11.35311 -3.40208,-3.80148 -7.27107,-11.46438 -8.31543,-16.4695 -2.76322,-13.24277 2.63571,-27.85526 13.26894,-35.91309 19.99373,-15.15118 48.09433,-6.6877 56.44101,16.99918 1.86188,5.28381 2.27747,13.55775 0.97503,19.41195 -1.50813,6.77877 -4.55198,12.15816 -9.87968,17.46031 -5.26572,5.24048 -9.89475,7.95133 -16.43315,9.62357 -4.85615,1.24199 -12.80551,1.35206 -17.38277,0.24069 z m 0.90791,-22.33599 1.06927,-3.3455 6.50377,-0.1501 6.50377,-0.1501 0.98735,3.36178 0.98735,3.36179 2.51591,0.16314 c 1.8243,0.1183 2.51592,-0.0335 2.51592,-0.55237 0,-0.39353 -2.29576,-7.75345 -5.10169,-16.35537 l -5.10169,-15.63986 h -3.1506 -3.1506 l -5.20854,15.65695 c -2.86469,8.61132 -5.31927,15.95804 -5.45462,16.32605 -0.17576,0.47789 0.50564,0.6691 2.38452,0.6691 h 2.6306 z"
id="path1466" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 763.70798,369.86416 c -8.12397,-1.27622 -14.00129,-4.35733 -20.33165,-10.65861 -3.76197,-3.74468 -5.02094,-5.43974 -6.83916,-9.20812 -7.60051,-15.75262 -3.54817,-33.43875 10.18745,-44.46231 6.3567,-5.10159 13.61954,-7.5924 22.13836,-7.5924 29.9337,0 46.67981,33.83863 28.70945,58.01278 -7.44586,10.01634 -21.60997,15.83377 -33.86445,13.90866 z m 11.20335,-21.38348 c 3.07353,-1.75995 4.52918,-4.20847 4.57675,-7.69846 0.0443,-3.24643 -1.27165,-5.85301 -3.49954,-6.93201 l -1.49389,-0.72351 1.60877,-1.54129 c 1.87307,-1.79453 2.80455,-4.70189 2.3305,-7.27407 -0.92747,-5.03237 -3.68485,-6.33408 -13.45172,-6.35026 l -7.09246,-0.0118 v 16.10974 16.10973 l 7.3601,-0.18515 c 6.6513,-0.16732 7.58173,-0.31206 9.66149,-1.50296 z"
id="path1468" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 762.70726,326.44188 v -4.88945 l 3.72999,0.26688 c 4.16057,0.29769 6.24901,1.33706 6.7575,3.36306 0.94714,3.77369 -1.80659,6.14376 -7.14199,6.14695 l -3.3455,0.002 z"
id="path1470" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999998"
d="m 837.54718,264.82028 c 0,-0.76372 4.25204,-14.10124 4.62716,-14.51418 0.17889,-0.19692 1.32644,2.82483 2.55012,6.715 1.22368,3.89017 2.33144,7.35074 2.46168,7.69016 0.18748,0.48856 -0.7918,0.61711 -4.70107,0.61711 -3.25732,0 -4.93789,-0.17292 -4.93789,-0.50809 z"
id="path1496" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999998"
d="m 763.06218,340.74443 v -5.12084 h 3.61513 c 4.59667,0 6.58099,0.93645 7.49973,3.5393 0.55274,1.56594 0.54465,2.04231 -0.0591,3.47983 -0.97646,2.32493 -3.07062,3.22256 -7.51823,3.22256 h -3.53752 z"
id="path1498" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 766.92321,602.64753 c -0.29048,-8.92659 -0.85756,-9.59054 -10.1321,-11.86299 -21.45382,-5.25664 -37.29198,-20.85776 -42.70074,-42.06165 -0.55002,-2.15622 -1.00003,-4.47981 -1.00003,-5.16353 0,-0.68371 -1.0064,-2.24952 -2.23643,-3.47956 l -2.23643,-2.23643 h -6.9724 -6.97241 v -1.97332 -1.97332 h 5.94109 c 6.60342,0 9.93688,-1.00153 11.20212,-3.36564 0.44261,-0.82703 1.34271,-3.96544 2.00022,-6.97425 3.49259,-15.98235 14.91214,-30.68661 29.48362,-37.96428 4.71573,-2.35525 11.36654,-4.65443 15.50589,-5.36038 6.61875,-1.12879 8.22218,-3.61509 8.22218,-12.74947 v -5.94109 h 1.97332 1.97332 v 6.89625 c 0,6.61611 0.0735,6.97475 1.80888,8.82901 1.46262,1.5628 3.13096,2.25493 8.7155,3.61572 20.40883,4.97306 36.06052,19.9102 41.49254,39.59826 0.78813,2.85653 1.76467,6.36883 2.17007,7.80511 1.22789,4.35011 3.85392,5.61076 11.68766,5.61076 h 6.48046 v 1.97332 1.97332 h -6.6104 c -6.95598,0 -9.89025,0.84134 -10.81193,3.1001 -0.2638,0.64649 -1.18554,3.97814 -2.0483,7.40367 -5.38972,21.39923 -21.36363,37.35004 -42.22246,42.16138 -9.94989,2.29507 -10.66202,3.14671 -10.66202,12.75068 v 6.28151 h -1.91345 -1.91345 z"
id="path1500" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d=""
id="path1502" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 695.45795,526.49678 c 1.75282,-15.26781 9.42349,-30.89435 20.92126,-42.62035 11.95352,-12.1908 27.0212,-19.51188 45.22194,-21.97243 l 2.79554,-0.37793 v 6.18375 c 0,7.93282 -0.51936,8.65269 -7.23551,10.02904 -22.30129,4.57023 -40.70977,22.45408 -45.7072,44.40457 -2.01248,8.8395 -2.35691,9.12221 -11.11415,9.12221 h -5.42936 z"
id="path1504" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="M 754.53008,608.24817 C 722.31091,601.3332 698.78801,575.33696 695.1389,542.61223 l -0.23838,-2.13776 h 6.36187 c 5.30645,0 6.54081,0.19773 7.44049,1.19187 0.59325,0.65553 1.8242,4.13099 2.73545,7.72325 5.73315,22.60074 22.81787,39.26947 45.21411,44.1132 6.89875,1.49203 7.74425,2.60069 7.74425,10.15464 v 5.88328 l -2.13776,-0.0463 c -1.17577,-0.0255 -4.65375,-0.58628 -7.72885,-1.24626 z"
id="path1506" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 773.60552,603.37682 c 0,-7.26315 0.7124,-8.57514 5.06106,-9.32073 4.85038,-0.83162 11.1113,-2.92244 16.31659,-5.44891 15.80304,-7.67023 27.12455,-21.98721 31.55746,-39.907 0.97744,-3.95125 2.07685,-6.90365 2.75558,-7.39995 0.71733,-0.52453 3.39605,-0.82576 7.34299,-0.82576 h 6.21369 l -0.43161,3.7822 c -3.78834,33.19719 -31.7798,61.26383 -64.82878,65.00289 l -3.98698,0.45108 z"
id="path1508" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 829.28285,529.78565 c -1.17591,-1.07273 -1.92806,-2.90835 -2.7333,-6.67061 -4.37909,-20.45999 -18.95972,-36.61709 -39.28934,-43.53733 -2.43875,-0.83016 -5.8241,-1.71782 -7.52299,-1.97259 -1.88233,-0.28227 -3.68318,-1.05749 -4.6103,-1.9846 -1.37609,-1.3761 -1.5214,-2.11712 -1.5214,-7.7588 v -6.23739 l 2.46665,0.33127 c 18.99503,2.55107 32.67768,9.21103 45.44487,22.12006 10.43139,10.54728 17.44069,23.80984 20.16018,38.14583 0.547,2.88355 0.99455,6.09813 0.99455,7.14349 v 1.90066 h -5.88329 c -5.18197,0 -6.07667,-0.17643 -7.50563,-1.47999 z"
id="path1510" /><path
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.999999"
d="m 663.62068,131.03319 c -0.53326,-0.58925 -0.625,-1.69704 -0.625,-7.54707 v -6.85645 l -1.10115,-1.23333 -1.10115,-1.23332 -7.11278,-0.10646 c -9.08871,-0.13604 -8.43455,0.46843 -8.43455,-7.79389 0,-4.68262 0.12554,-6.289149 0.5353,-6.850301 0.49015,-0.671243 1.10329,-0.741434 7.26979,-0.832236 3.70397,-0.05454 7.12214,-0.18656 7.59593,-0.293374 0.47378,-0.106815 1.19541,-0.741963 1.60361,-1.411441 0.66219,-1.086052 0.74232,-1.921972 0.74358,-7.756551 8.2e-4,-3.782617 0.16622,-6.847257 0.39235,-7.269795 0.3648,-0.681634 0.8563,-0.730476 7.35092,-0.730476 6.49462,0 6.98613,0.04884 7.35092,0.730476 0.22614,0.422538 0.39154,3.487178 0.39236,7.269795 10e-4,5.834579 0.0814,6.670499 0.74358,7.756551 0.4082,0.669478 1.12983,1.304626 1.60361,1.411441 0.47379,0.106814 3.89196,0.238833 7.59593,0.293374 6.1665,0.0908 6.77964,0.160993 7.26979,0.832236 0.40976,0.561152 0.5353,2.167681 0.5353,6.850301 0,8.26232 0.65416,7.65785 -8.43455,7.79389 l -7.11278,0.10646 -1.10115,1.23332 -1.10115,1.23333 v 6.92207 c 0,6.22636 -0.0694,6.98488 -0.69062,7.54707 -0.58568,0.53003 -1.66715,0.62501 -7.11685,0.62501 -5.74601,0 -6.49238,-0.0731 -7.05124,-0.69063 z"
id="path1512" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 709.89826,726.4428 v -5.25775 h 5.25776 5.25775 v 5.25775 5.25776 h -5.25775 -5.25776 z"
id="path1514" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 708.88715,747.11324 c -7.7953,-1.94254 -14.19265,-7.02605 -17.61469,-13.99713 -2.11167,-4.3017 -2.80967,-7.2657 -2.80967,-11.93106 0,-4.6603 0.69677,-7.62382 2.80517,-11.93107 2.98868,-6.10556 8.92756,-11.23718 15.51022,-13.40195 4.61637,-1.51813 11.17625,-1.60821 15.65781,-0.215 15.04474,4.67704 23.00917,20.70184 17.43246,35.07495 -4.8049,12.38391 -18.34269,19.55071 -30.9813,16.40126 z m 20.42437,-17.43489 v -8.4933 h 2.62887 c 1.44589,0 2.62888,-0.13514 2.62888,-0.3003 0,-0.16516 -4.4121,-4.71516 -9.80467,-10.1111 l -9.80467,-9.8108 -9.81081,9.80467 c -5.39594,5.39257 -9.8108,9.94257 -9.8108,10.1111 0,0.16854 1.27399,0.30643 2.8311,0.30643 h 2.8311 v 8.4933 8.4933 h 14.1555 14.1555 z"
id="path1516" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 709.32587,761.61376 c -14.84534,-2.33618 -27.22151,-12.34303 -32.43644,-26.22673 -7.52289,-20.0282 2.33277,-43.0312 22.02756,-51.41208 6.07171,-2.58375 8.49788,-3.03235 16.23903,-3.00264 6.50926,0.025 7.37011,0.11595 10.71773,1.13248 14.44352,4.38591 24.64194,14.87492 28.58676,29.40132 0.78714,2.89856 0.92468,4.38074 0.9169,9.88116 -0.008,5.44704 -0.15534,7.01511 -0.93296,9.90885 -4.75273,17.68623 -20.04274,29.95104 -38.0751,30.54176 -2.55811,0.0838 -5.72767,-0.0171 -7.04348,-0.22412 z m 12.01917,-11.94961 c 11.93985,-2.6283 21.26602,-13.04595 22.49006,-25.12213 2.18282,-21.53536 -18.13115,-37.7028 -38.52104,-30.65805 -4.17709,1.44319 -6.99053,3.28712 -10.81791,7.09005 -2.821,2.80297 -3.81838,4.14269 -5.32568,7.15366 -2.55937,5.1126 -3.29841,8.68914 -3.02322,14.63061 0.31524,6.80606 2.15585,11.73401 6.30752,16.88741 6.75846,8.38917 18.22621,12.36591 28.89027,10.01845 z"
id="path1518" /><path
style="opacity:1;fill:#ff5f55;fill-opacity:0.956863;stroke:#4d4d4d;stroke-width:1"
d="m 591.47251,714.31134 c -2.59326,-1.58129 -2.41164,1.27628 -2.41164,-37.94303 0,-35.39705 0.002,-35.47278 0.79102,-36.47631 1.14169,-1.45141 2.68891,-2.12685 4.87199,-2.12685 h 1.91275 v 38.63637 38.63636 l -1.98864,-0.002 c -1.28887,-7.5e-4 -2.40626,-0.25607 -3.17548,-0.72512 z"
id="path1520" /><path
style="opacity:1;fill:#ff5f55;fill-opacity:0.956863;stroke:#4d4d4d;stroke-width:1"
d="m 592.87653,312.11027 c -0.50555,-0.0951 -1.32393,-0.43811 -1.8186,-0.76224 -2.07696,-1.36087 -1.99706,0.15175 -1.99706,-37.80487 0,-31.80626 0.058,-35.19116 0.61953,-36.14171 0.93372,-1.58066 2.4287,-2.28781 4.83664,-2.28781 h 2.11959 V 273.75 312.38636 l -1.42045,-0.0516 c -0.78125,-0.0284 -1.83409,-0.1294 -2.33965,-0.22451 z"
id="path1522" /><path
style="opacity:1;fill:#000000;fill-opacity:0.956863;stroke:#4d4d4d;stroke-width:1"
d="M 921.31509,126.45258 C 911.22775,105.90097 899.41123,89.210741 883.15837,72.558198 848.342,36.885643 804.48862,15.547979 753.51164,9.4762173 748.44895,8.8732107 740.43487,8.6841876 712.59008,8.5110262 L 677.96414,8.2956939 V 6.8885761 c 0,-0.9784616 0.48302,-1.8901352 1.58557,-2.9926826 l 1.58556,-1.5855648 h 30.73203 c 16.92783,0 33.54939,0.2176979 37.00428,0.4846569 50.75274,3.9216602 97.06468,24.5817024 133.31418,59.4722764 17.58138,16.922285 31.48259,35.738975 42.78184,57.909488 4.28368,8.40514 4.87972,10.05538 4.25358,11.77682 -0.41652,1.14511 -2.61821,3.7514 -3.13345,3.70927 -0.14438,-0.0118 -2.29207,-4.15642 -4.77264,-9.21026 z"
id="path1524" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="m 591.56604,904.17079 c -2.01964,-1.17632 -2.15587,-6.52992 -2.15587,-84.72244 v -83.46676 l 4.9277,-10.18986 4.92769,-10.18984 v -39.48272 -39.48272 l -4.92769,-9.84523 -4.9277,-9.84523 V 475.04429 333.1426 l 4.9277,-10.18986 4.92769,-10.18984 v -39.48272 -39.48272 l -4.93732,-9.86447 -4.93732,-9.86446 0.31761,-73.44555 0.31761,-73.44554 6.5676,-0.375829 c 3.78331,-0.216499 7.3086,0.239148 8.31548,1.074785 1.50292,1.24731 1.74788,59.776984 1.74788,417.620064 v 416.16945 l -2.73795,1.91775 c -3.10138,2.17229 -9.13889,2.45924 -12.35311,0.58713 z"
id="path1530" /><path
style="opacity:1;fill:#1a1a1a;fill-opacity:1;stroke:#4d4d4d;stroke-width:1"
d="M 609.12095,465.08874 V 72.721096 h 4.31173 4.31173 V 465.08874 857.45638 h -4.31173 -4.31173 z"
id="path1532" /></g></svg>

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 115 KiB

View file

@ -20,6 +20,7 @@ using System.Buffers;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Reflection;
using System.Threading; using System.Threading;
using static LibHac.Fs.ApplicationSaveDataManagement; using static LibHac.Fs.ApplicationSaveDataManagement;
@ -85,6 +86,7 @@ namespace Ryujinx.Ui.Widgets
using MessageDialog messageDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Question, ButtonsType.YesNo, null) using MessageDialog messageDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Question, ButtonsType.YesNo, null)
{ {
Title = "Ryujinx", Title = "Ryujinx",
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png"),
Text = $"There is no savedata for {titleName} [{titleId:x16}]", Text = $"There is no savedata for {titleName} [{titleId:x16}]",
SecondaryText = "Would you like to create savedata for this game?", SecondaryText = "Would you like to create savedata for this game?",
WindowPosition = WindowPosition.Center WindowPosition = WindowPosition.Center
@ -194,6 +196,7 @@ namespace Ryujinx.Ui.Widgets
_dialog = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Cancel, null) _dialog = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Cancel, null)
{ {
Title = "Ryujinx - NCA Section Extractor", Title = "Ryujinx - NCA Section Extractor",
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png"),
SecondaryText = $"Extracting {ncaSectionType} section from {System.IO.Path.GetFileName(_titleFilePath)}...", SecondaryText = $"Extracting {ncaSectionType} section from {System.IO.Path.GetFileName(_titleFilePath)}...",
WindowPosition = WindowPosition.Center WindowPosition = WindowPosition.Center
}; };
@ -310,6 +313,7 @@ namespace Ryujinx.Ui.Widgets
MessageDialog dialog = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null) MessageDialog dialog = new MessageDialog(null, DialogFlags.DestroyWithParent, MessageType.Info, ButtonsType.Ok, null)
{ {
Title = "Ryujinx - NCA Section Extractor", Title = "Ryujinx - NCA Section Extractor",
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png"),
SecondaryText = "Extraction has completed successfully.", SecondaryText = "Extraction has completed successfully.",
WindowPosition = WindowPosition.Center WindowPosition = WindowPosition.Center
}; };

View file

@ -1,4 +1,5 @@
using Gtk; using Gtk;
using System.Reflection;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
namespace Ryujinx.Ui.Widgets namespace Ryujinx.Ui.Widgets
@ -11,6 +12,7 @@ namespace Ryujinx.Ui.Widgets
: base(null, DialogFlags.Modal, messageType, buttonsType, null) : base(null, DialogFlags.Modal, messageType, buttonsType, null)
{ {
Title = title; Title = title;
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png");
Text = mainText; Text = mainText;
SecondaryText = secondaryText; SecondaryText = secondaryText;
WindowPosition = WindowPosition.Center; WindowPosition = WindowPosition.Center;

View file

@ -1,5 +1,6 @@
using Gtk; using Gtk;
using System; using System;
using System.Reflection;
using GUI = Gtk.Builder.ObjectAttribute; using GUI = Gtk.Builder.ObjectAttribute;
@ -19,6 +20,7 @@ namespace Ryujinx.Ui.Widgets
private ProfileDialog(Builder builder) : base(builder.GetObject("_profileDialog").Handle) private ProfileDialog(Builder builder) : base(builder.GetObject("_profileDialog").Handle)
{ {
builder.Autoconnect(this); builder.Autoconnect(this);
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png");
} }
private void OkToggle_Activated(object sender, EventArgs args) private void OkToggle_Activated(object sender, EventArgs args)

View file

@ -3,6 +3,7 @@ using Ryujinx.Common.Utilities;
using Ryujinx.Ui.Helper; using Ryujinx.Ui.Helper;
using System.Net.Http; using System.Net.Http;
using System.Net.NetworkInformation; using System.Net.NetworkInformation;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ui.Windows namespace Ryujinx.Ui.Windows
@ -11,6 +12,7 @@ namespace Ryujinx.Ui.Windows
{ {
public AboutWindow() : base($"Ryujinx {Program.Version} - About") public AboutWindow() : base($"Ryujinx {Program.Version} - About")
{ {
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png");
InitializeComponent(); InitializeComponent();
_ = DownloadPatronsJson(); _ = DownloadPatronsJson();

View file

@ -94,6 +94,8 @@ namespace Ryujinx.Ui.Windows
private ControllerWindow(Builder builder, PlayerIndex controllerId) : base(builder.GetObject("_controllerWin").Handle) private ControllerWindow(Builder builder, PlayerIndex controllerId) : base(builder.GetObject("_controllerWin").Handle)
{ {
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png");
builder.Autoconnect(this); builder.Autoconnect(this);
_playerIndex = controllerId; _playerIndex = controllerId;

View file

@ -48,8 +48,8 @@
<property name="title" translatable="yes">Ryujinx - Controller Settings</property> <property name="title" translatable="yes">Ryujinx - Controller Settings</property>
<property name="modal">True</property> <property name="modal">True</property>
<property name="window_position">center</property> <property name="window_position">center</property>
<property name="default_width">1100</property> <property name="default_width">1150</property>
<property name="default_height">600</property> <property name="default_height">690</property>
<child type="titlebar"> <child type="titlebar">
<placeholder/> <placeholder/>
</child> </child>

View file

@ -11,6 +11,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using GUI = Gtk.Builder.ObjectAttribute; using GUI = Gtk.Builder.ObjectAttribute;
@ -91,6 +92,8 @@ namespace Ryujinx.Ui.Windows
private SettingsWindow(MainWindow parent, Builder builder, VirtualFileSystem virtualFileSystem, HLE.FileSystem.Content.ContentManager contentManager) : base(builder.GetObject("_settingsWin").Handle) private SettingsWindow(MainWindow parent, Builder builder, VirtualFileSystem virtualFileSystem, HLE.FileSystem.Content.ContentManager contentManager) : base(builder.GetObject("_settingsWin").Handle)
{ {
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.Resources.Logo_Ryujinx.png");
_parent = parent; _parent = parent;
builder.Autoconnect(this); builder.Autoconnect(this);

View file

@ -1299,6 +1299,7 @@
<object class="GtkLabel"> <object class="GtkLabel">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Change System Time</property>
<property name="halign">end</property> <property name="halign">end</property>
<property name="label" translatable="yes">System Time:</property> <property name="label" translatable="yes">System Time:</property>
</object> </object>
@ -1509,7 +1510,7 @@
<object class="GtkLabel"> <object class="GtkLabel">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="tooltip-text" translatable="yes">Change System Region</property> <property name="tooltip-text" translatable="yes">Change Audio Backend</property>
<property name="halign">end</property> <property name="halign">end</property>
<property name="margin-right">5</property> <property name="margin-right">5</property>
<property name="label" translatable="yes">Audio Backend: </property> <property name="label" translatable="yes">Audio Backend: </property>