From b1c773495752890c3d009fe72a7bb972967fa1c6 Mon Sep 17 00:00:00 2001
From: Masusder <59669685+Masusder@users.noreply.github.com>
Date: Sat, 23 May 2026 21:44:47 +0200
Subject: [PATCH] Undawn lua, Fixed Criware/Rada bulk audio conversion
---
CUE4Parse | 2 +-
FModel/Resources/Lua.xshd | 312 +++++++++---------
FModel/ViewModels/AudioPlayerViewModel.cs | 173 +++++-----
FModel/ViewModels/CUE4ParseViewModel.cs | 8 +-
FModel/ViewModels/GameFileViewModel.cs | 4 +
FModel/Views/Resources/Colors.xaml | 3 +
.../Converters/FileToGeometryConverter.cs | 4 +
FModel/Views/Resources/Icons.xaml | 3 +
8 files changed, 265 insertions(+), 244 deletions(-)
diff --git a/CUE4Parse b/CUE4Parse
index ecc48789..cf74fc32 160000
--- a/CUE4Parse
+++ b/CUE4Parse
@@ -1 +1 @@
-Subproject commit ecc4878950336126f125af0747190edf474b2a21
+Subproject commit cf74fc32fe1b40e9fd3440032508c5e1d50cf58d
diff --git a/FModel/Resources/Lua.xshd b/FModel/Resources/Lua.xshd
index 148f5b97..88d749f2 100644
--- a/FModel/Resources/Lua.xshd
+++ b/FModel/Resources/Lua.xshd
@@ -1,58 +1,76 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ --\[\[(.|\n)*?\]\]
--.*$
+ \[\[(.|\n)*?\]\]
"([^"\\]|\\.)*"
'([^'\\]|\\.)*'
+ \b0[xX][0-9A-Fa-f]+\b
\b\d+\.\d+([eE][+-]?\d+)?\b
\b\d+[eE][+-]?\d+\b
\b\d+\b
- return
- function
- goto
- end
- if
+ and
+ break
+ do
else
elseif
- then
+ end
for
+ function
+ goto
+ if
in
+ or
+ repeat
+ return
+ then
until
while
- break
- or
- and
- repeat
- do
+ false
local
nil
not
true
- false
+
+
+
+ self
+ _G
+ _ENV
-
assert
collectgarbage
+ dofile
error
+ getmetatable
ipairs
+ load
+ loadfile
+ module
next
pairs
pcall
@@ -61,128 +79,24 @@
rawget
rawlen
rawset
+ require
select
setmetatable
tonumber
tostring
type
+ unpack
xpcall
- getmetatable
- require
- module
-
-
+ bit32
+ coroutine
+ debug
+ io
math
+ os
+ package
string
table
- coroutine
- os
- io
utf8
- bit32
- package
- debug
-
-
- arshift
- band
- bnot
- bor
- bxor
- btest
- extract
- lrotate
- lshift
- replace
- rrotate
- rshift
-
-
- create
- resume
- running
- status
- wrap
- yield
- isyieldable
-
-
- getuservalue
- gethook
- getinfo
- getlocal
- getregistry
- getupvalue
- upvaluejoin
- upvalueid
- setuservalue
- sethook
- setlocal
- setupvalue
- traceback
-
-
- close
- flush
- input
- lines
- open
- output
- popen
- read
- tmpfile
- seek
- setvbuf
- write
-
-
- byte
- char
- dump
- find
- format
- gmatch
- gsub
- len
- lower
- match
- rep
- reverse
- sub
- upper
- pack
- packsize
- unpack
- concat
- maxn
- insert
- move
- offset
- codepoint
- codes
- charpattern
-
-
- clock
- date
- difftime
- execute
- exit
- getenv
- remove
- rename
- setlocale
- time
- loadlib
- searchpath
- seeall
- preload
- cpath
- path
- searchers
- loaded
-
-
abs
acos
asin
@@ -195,36 +109,140 @@
exp
floor
fmod
- ult
+ frexp
+ huge
+ ldexp
log
log10
max
+ maxinteger
min
+ mininteger
modf
pi
+ pow
rad
random
randomseed
sin
+ sinh
sqrt
tan
- sinh
tanh
- pow
- frexp
- ldexp
- huge
- maxinteger
- mininteger
+ tointeger
+ ult
+ byte
+ char
+ dump
+ find
+ format
+ gmatch
+ gsub
+ len
+ lower
+ match
+ pack
+ packsize
+ rep
+ reverse
+ sub
+ upper
+ concat
+ insert
+ maxn
+ move
+ remove
+ sort
+ close
+ flush
+ input
+ lines
+ open
+ output
+ popen
+ read
+ seek
+ setvbuf
+ tmpfile
+ write
+ clock
+ date
+ difftime
+ execute
+ exit
+ getenv
+ rename
+ setlocale
+ time
+ create
+ isyieldable
+ resume
+ running
+ status
+ wrap
+ yield
+ arshift
+ band
+ bnot
+ bor
+ btest
+ bxor
+ extract
+ lrotate
+ lshift
+ replace
+ rrotate
+ rshift
+ charpattern
+ codepoint
+ codes
+ offset
+ gethook
+ getinfo
+ getlocal
+ getregistry
+ getupvalue
+ getuservalue
+ sethook
+ setlocal
+ setupvalue
+ setuservalue
+ traceback
+ upvalueid
+ upvaluejoin
+ cpath
+ loaded
+ loadlib
+ path
+ preload
+ searchers
+ searchpath
+ seeall
(\|)|(<<)|(>>)|(\/\/)|(==)|(~=)|(<=)|(>=)|(<)|(>)|(=)|(\()|(\))|(\{)|(\})|(\[)|(\])|(::)|(:)|(;)|(,)|(\.\.\.)|(\.\.)|(\.)|[+\-*%\^#&~]
- (?<=function\s)[A-Za-z0-9_]+(?=\.)
-
- (?<=\.)[A-Za-z0-9_]+(?=\()
- (?<=function\s)[A-Za-z0-9_]+(?=\s*\()
+ __[A-Za-z_][A-Za-z0-9_]*__
- \b[A-Z_][A-Z0-9_]*\b
+ (?<=::)[A-Za-z_][A-Za-z0-9_]*(?=::)
+
+ (?<![A-Za-z0-9_])_(?![A-Za-z0-9_])
+
+ (?<=function\s)[A-Za-z_][A-Za-z0-9_]*(?=\.)
+ (?<=function\s)[A-Za-z_][A-Za-z0-9_]*(?=:)
+
+ (?<=function\s)[A-Za-z_][A-Za-z0-9_]*(?=\s*\()
+
+ [A-Za-z_][A-Za-z0-9_]*(?=\.)
+ [A-Za-z_][A-Za-z0-9_]*(?=:)
+
+ (?<=:)[A-Za-z_][A-Za-z0-9_]*(?=\s*\()
+ (?<=\.)[A-Za-z_][A-Za-z0-9_]*(?=\s*\()
+ \b[A-Za-z_][A-Za-z0-9_]*(?=\s*\()
+
+ (?<=\.)[A-Za-z_][A-Za-z0-9_]*
+
+ \b[A-Z][A-Z0-9]*_[A-Z0-9_]*\b
+ \b[A-Z]{2}[A-Z0-9_]*\b
diff --git a/FModel/ViewModels/AudioPlayerViewModel.cs b/FModel/ViewModels/AudioPlayerViewModel.cs
index 81a52065..554d978a 100644
--- a/FModel/ViewModels/AudioPlayerViewModel.cs
+++ b/FModel/ViewModels/AudioPlayerViewModel.cs
@@ -570,139 +570,126 @@ public class AudioPlayerViewModel : ViewModel, ISource, IDisposable
{
if (SelectedAudioFile?.Data == null)
return false;
+ if (SelectedAudioFile.Extension == "wav")
+ return false;
- switch (SelectedAudioFile.Extension)
- {
- case "binka":
- case "adpcm":
- case "xvag":
- case "opus":
- case "wem":
- case "at9":
- case "raw":
- {
- if (TryConvert(out var wavFilePath))
- {
- var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(wavFilePath));
- Replace(newAudio);
- return true;
- }
+ if (!TryConvert(SelectedAudioFile.FilePath, SelectedAudioFile.Data, SelectedAudioFile.Extension, out var convertedFilePath, true))
+ return false;
- return false;
- }
- case "adx":
- case "hca":
- return TryConvertCriware();
- case "rada":
- {
- if (TryDecode(SelectedAudioFile.Extension, out var rawFilePath))
- {
- var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(rawFilePath));
- Replace(newAudio);
- return true;
- }
-
- return false;
- }
- }
+ var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(convertedFilePath));
+ Replace(newAudio);
return true;
}
- private bool TryConvertCriware()
+ public static bool TryConvert(string inputFilePath, byte[] inputFileData, string extension, out string wavFilePath, bool updateUi = false)
{
+ wavFilePath = string.Empty;
+
+ switch (extension.ToLowerInvariant())
+ {
+ case "hca":
+ case "adx":
+ return TryConvertCriware(inputFilePath, inputFileData, extension, out wavFilePath);
+ case "rada":
+ return TryConvertRada(inputFilePath, inputFileData, extension, out wavFilePath, updateUi);
+ default:
+ {
+ var vgmStreamPath = TryGetVgmstreamPath();
+ if (string.IsNullOrEmpty(vgmStreamPath))
+ return false;
+
+ var success = TryConvertToWav(inputFilePath, inputFileData, vgmStreamPath, true, out wavFilePath);
+
+ if (!success)
+ {
+ Log.Error("Failed to convert {InputFilePath} to .wav format", Path.GetFileName(inputFilePath));
+
+ if (updateUi)
+ {
+ FLogger.Append(ELog.Error, () =>
+ {
+ FLogger.Text("Failed to convert audio to .wav format. See: ", Constants.WHITE);
+ FLogger.Link("→ link ←", Constants.AUDIO_ISSUE_LINK, true);
+ });
+ }
+ }
+
+ return success;
+ }
+ }
+ }
+
+ private static bool TryConvertCriware(string inputFilePath, byte[] inputFileData, string extension, out string wavFilePath)
+ {
+ wavFilePath = string.Empty;
+
try
{
- byte[] wavData = SelectedAudioFile.Extension switch
+ byte[] wavData = extension switch
{
- "hca" => HcaWaveStream.ConvertHcaToWav(
- SelectedAudioFile.Data,
- UserSettings.Default.CurrentDir.CriwareDecryptionKey),
- "adx" => AdxDecoder.ConvertAdxToWav(
- SelectedAudioFile.Data,
- UserSettings.Default.CurrentDir.CriwareDecryptionKey),
+ "hca" => HcaWaveStream.ConvertHcaToWav(inputFileData, UserSettings.Default.CurrentDir.CriwareDecryptionKey),
+ "adx" => AdxDecoder.ConvertAdxToWav(inputFileData, UserSettings.Default.CurrentDir.CriwareDecryptionKey),
_ => throw new NotSupportedException()
};
- if (wavData.Length is 0)
+ // Fallback for ADX
+ if (wavData.Length == 0)
{
- if (TryConvert(out var wavFilePathFallback))
- {
- var newAudioFallback = new AudioFile(SelectedAudioFile.Id, new FileInfo(wavFilePathFallback));
- Replace(newAudioFallback);
- return true;
- }
+ var vgmStreamPath = TryGetVgmstreamPath();
+ if (string.IsNullOrEmpty(vgmStreamPath))
+ return false;
+
+ return TryConvertToWav(inputFilePath, inputFileData, vgmStreamPath, true, out wavFilePath);
}
- string wavFilePath = Path.Combine(
- UserSettings.Default.AudioDirectory,
- SelectedAudioFile.FilePath.TrimStart('/'));
- wavFilePath = Path.ChangeExtension(wavFilePath, ".wav");
+ wavFilePath = Path.ChangeExtension(inputFilePath, ".wav");
+
+ var directory = Path.GetDirectoryName(wavFilePath);
+ if (!string.IsNullOrEmpty(directory))
+ Directory.CreateDirectory(directory);
- Directory.CreateDirectory(Path.GetDirectoryName(wavFilePath)!);
File.WriteAllBytes(wavFilePath, wavData);
- var newAudio = new AudioFile(SelectedAudioFile.Id, new FileInfo(wavFilePath));
- Replace(newAudio);
-
return true;
}
catch (CriwareDecryptionException ex)
{
- FLogger.Append(ELog.Error, () => FLogger.Text($"Encrypted {SelectedAudioFile.Extension.ToUpper()}: {ex.Message}", Constants.WHITE, true));
- Log.Error($"Encrypted {SelectedAudioFile.Extension.ToUpper()}: {ex.Message}");
+ FLogger.Append(ELog.Error, () => FLogger.Text($"Encrypted {extension.ToUpper()}: {ex.Message}", Constants.WHITE, true));
+ Log.Error($"Encrypted {extension.ToUpper()}: {ex.Message}");
+
return false;
}
catch (Exception ex)
{
- FLogger.Append(ELog.Error, () => FLogger.Text($"Failed to convert {SelectedAudioFile.Extension.ToUpper()}: {ex.Message}", Constants.WHITE, true));
- Log.Error($"Failed to convert {SelectedAudioFile.Extension.ToUpper()}: {ex.Message}");
+ FLogger.Append(ELog.Error, () => FLogger.Text($"Failed to convert {extension.ToUpper()}: {ex.Message}", Constants.WHITE, true));
+ Log.Error($"Failed to convert {extension.ToUpper()}: {ex.Message}");
+
return false;
}
}
- private bool TryConvert(out string wavFilePath) => TryConvert(SelectedAudioFile.FilePath, SelectedAudioFile.Data, out wavFilePath, true);
- public static bool TryConvert(string inputFilePath, byte[] inputFileData, out string wavFilePath, bool updateUi = false)
- {
- wavFilePath = string.Empty;
- var vgmStreamPath = TryGetVgmstreamPath();
- if (string.IsNullOrEmpty(vgmStreamPath))
- return false;
-
- var success = TryConvertToWav(inputFilePath, inputFileData, vgmStreamPath, true, out wavFilePath);
-
- if (!success)
- {
- Log.Error("Failed to convert {InputFilePath} to .wav format", Path.GetFileName(inputFilePath));
- if (updateUi)
- {
- FLogger.Append(ELog.Error, () =>
- {
- FLogger.Text("Failed to convert audio to .wav format. See: ", Constants.WHITE);
- FLogger.Link("→ link ←", Constants.AUDIO_ISSUE_LINK, true);
- });
- }
- }
-
- return success;
- }
-
- private bool TryDecode(string extension, out string rawFilePath)
+ private static bool TryConvertRada(string inputFilePath, byte[] inputFileData, string extension, out string rawFilePath, bool updateUi = false)
{
rawFilePath = string.Empty;
var decoderPath = Path.Combine(UserSettings.Default.OutputDirectory, ".data", $"{extension}dec.exe");
if (!File.Exists(decoderPath))
{
- Log.Error("Failed to convert {FilePath}, rada decoder is missing", SelectedAudioFile.FilePath);
- FLogger.Append(ELog.Error, () =>
+ Log.Error("Failed to convert {FilePath}, {Extension} decoder is missing", inputFilePath, extension);
+
+ if (updateUi)
{
- FLogger.Text("Failed to convert audio because rada decoder is missing. See: ", Constants.WHITE);
- FLogger.Link("→ link ←", Constants.RADA_ISSUE_LINK, true);
- });
+ FLogger.Append(ELog.Error, () =>
+ {
+ FLogger.Text($"Failed to convert audio because {extension} decoder is missing. See: ", Constants.WHITE);
+ FLogger.Link("→ link ←", Constants.RADA_ISSUE_LINK, true);
+ });
+ }
+
return false;
}
- return TryConvertToWav(SelectedAudioFile.FilePath, SelectedAudioFile.Data, decoderPath, false, out rawFilePath);
+ return TryConvertToWav(inputFilePath, inputFileData, decoderPath, false, out rawFilePath);
}
private static bool TryConvertToWav(string inputFilePath, byte[] inputFileData, string converterPath, bool usevgmstream, out string wavFilePath)
diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs
index 5b97cc85..b30322cf 100644
--- a/FModel/ViewModels/CUE4ParseViewModel.cs
+++ b/FModel/ViewModels/CUE4ParseViewModel.cs
@@ -733,6 +733,7 @@ public class CUE4ParseViewModel : ViewModel
case "archive":
case "dnearchive": // Banishers: Ghosts of New Eden
case "gitignore":
+ case "gitattributes":
case "LICENSE":
case "playstats": // Dispatch
case "template":
@@ -791,6 +792,8 @@ public class CUE4ParseViewModel : ViewModel
case "bl":
case "bm":
case "br":
+ case "sql":
+ case "cs":
{
var data = Provider.SaveAsset(entry);
using var stream = new MemoryStream(data) { Position = 0 };
@@ -1321,8 +1324,7 @@ public class CUE4ParseViewModel : ViewModel
_ => []
};
- var directory = Path.GetDirectoryName(atomObject.Owner?.Name) ?? "/Criware/";
- directory = Path.GetDirectoryName(atomObject.Owner.Provider.FixPath(directory));
+ var directory = Path.GetDirectoryName(Provider.FixPath(atomObject.Owner?.Name ?? "/Criware/"));
foreach (var sound in extractedSounds)
{
SaveAndPlaySound(cancellationToken, Path.Combine(directory, sound.Name).Replace("\\", "/"), sound.Extension, sound.Data, saveAudio, updateUi);
@@ -1616,7 +1618,7 @@ public class CUE4ParseViewModel : ViewModel
bool conversionSuccess = true;
if (UserSettings.Default.ConvertAudioOnBulkExport && extLower is not "wav")
{
- if (AudioPlayerViewModel.TryConvert(savedAudioPath, data, out string wavFilePath))
+ if (AudioPlayerViewModel.TryConvert(savedAudioPath, data, extLower, out string wavFilePath))
savedAudioPath = wavFilePath;
else
{
diff --git a/FModel/ViewModels/GameFileViewModel.cs b/FModel/ViewModels/GameFileViewModel.cs
index 8f336ece..d5b90206 100644
--- a/FModel/ViewModels/GameFileViewModel.cs
+++ b/FModel/ViewModels/GameFileViewModel.cs
@@ -350,11 +350,15 @@ public class GameFileViewModel(GameFile asset) : ViewModel
case "pem":
case "xml":
case "gitignore":
+ case "gitattributes":
case "html":
case "css":
case "js":
case "data":
case "csv":
+ case "sql":
+ case "py":
+ case "cs":
AssetCategory = EAssetCategory.Data;
break;
case "stinfo":
diff --git a/FModel/Views/Resources/Colors.xaml b/FModel/Views/Resources/Colors.xaml
index eb034871..10e746c7 100644
--- a/FModel/Views/Resources/Colors.xaml
+++ b/FModel/Views/Resources/Colors.xaml
@@ -48,6 +48,9 @@
+
+
+
diff --git a/FModel/Views/Resources/Converters/FileToGeometryConverter.cs b/FModel/Views/Resources/Converters/FileToGeometryConverter.cs
index cd620def..3b75a145 100644
--- a/FModel/Views/Resources/Converters/FileToGeometryConverter.cs
+++ b/FModel/Views/Resources/Converters/FileToGeometryConverter.cs
@@ -80,10 +80,14 @@ public class FileToGeometryConverter : IMultiValueConverter
"bin" => ("DataTableIcon", "BinaryBrush"),
"xml" => ("XmlIcon", "JsonXmlBrush"),
"gitignore" => ("GitIcon", "GitBrush"),
+ "gitattributes" => ("GitIcon", "GitBrush"),
"html" => ("HtmlIcon", "HtmlBrush"),
"js" => ("JavaScriptIcon", "JavaScriptBrush"),
"css" => ("CssIcon", "CssBrush"),
"csv" => ("CsvIcon", "CsvBrush"),
+ "sql" => ("SQLIcon", "SQLBrush"),
+ "py" => ("PythonIcon", "PythonBrush"),
+ "cs" => ("CSharpIcon", "CSharpBrush"),
_ => ("DataTableIcon", "NeutralBrush")
},
diff --git a/FModel/Views/Resources/Icons.xaml b/FModel/Views/Resources/Icons.xaml
index 59505988..56b90f8e 100644
--- a/FModel/Views/Resources/Icons.xaml
+++ b/FModel/Views/Resources/Icons.xaml
@@ -99,6 +99,9 @@
M14 2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V8L14 2M15 16L13 20H10L12 16H9V11H15V16M13 9V3.5L18.5 9H13Z
M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V18A1,1 0 0,1 22,19H21V20A2,2 0 0,1 19,22H5A2,2 0 0,1 3,20V19H2A1,1 0 0,1 1,18V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z
M14,12L10,8V11H2V13H10V16M20,18V6C20,4.89 19.1,4 18,4H6A2,2 0 0,0 4,6V9H6V6H18V18H6V15H4V18A2,2 0 0,0 6,20H18A2,2 0 0,0 20,18Z
+ M231.822 132.778c1.2-5.152 6.352-8.357 11.505-7.158 5.153 1.2 8.357 6.352 7.158 11.505l-20.773 88.972c-1.199 5.153-6.352 8.358-11.504 7.158-5.153-1.199-8.358-6.352-7.158-11.505l20.772-88.972zM21.123 259.247h16.714V52.395C37.837 23.601 61.438 0 90.232 0h230.505a7.998 7.998 0 016.39 3.183l96.876 104.809a7.937 7.937 0 012.118 5.411h.041v145.844h16.714c11.618 0 21.124 9.525 21.124 21.124v163.863c0 11.599-9.526 21.124-21.124 21.124h-17.058c-3.001 25.877-25.473 46.505-52.051 46.505H90.232c-26.72 0-49.082-20.526-52.055-46.505H21.123C9.526 465.358 0 455.853 0 444.234V280.371c0-11.619 9.506-21.124 21.123-21.124zm32.731 0h356.292V136.525h-32.219v-.033h-.124c-19.111-.302-34.068-5.373-44.736-14.486-11.073-9.458-17.282-22.969-18.52-39.763l-.075-1.098V16.016H90.232c-20.032 0-36.378 16.346-36.378 36.379v206.852zm355.795 206.111H54.344c2.862 17.157 17.981 30.488 35.888 30.488h283.535c17.803 0 32.993-13.394 35.882-30.488zM330.467 30.272V81.11c.913 12.412 5.265 22.192 12.97 28.775 7.822 6.682 19.34 10.418 34.49 10.676v-.03h32.219v-4.052l-79.679-86.207zM199.303 204.095c3.972 3.477 4.377 9.521.9 13.493-3.478 3.973-9.521 4.377-13.494.9l-36.354-31.854c-3.972-3.477-4.377-9.521-.9-13.493.295-.336.606-.644.933-.927l36.321-31.826c3.973-3.478 10.016-3.073 13.494.899 3.477 3.973 3.072 10.016-.9 13.494l-28.14 24.656 28.14 24.658zm77.99 14.393c-3.972 3.477-10.016 3.073-13.493-.9-3.478-3.972-3.073-10.016.899-13.493l28.14-24.658-28.14-24.656c-3.972-3.478-4.377-9.521-.899-13.494 3.477-3.972 9.521-4.377 13.493-.899l36.318 31.826c.328.283.639.591.933.927 3.477 3.972 3.073 10.016-.899 13.493l-36.352 31.854zM120.405 400.89l3.805-19.455c8.333 2.083 15.827 3.123 22.484 3.123 6.66 0 12.024-.27 16.101-.815v-9.755l-12.228-1.086c-11.051-.999-18.635-3.648-22.759-7.951-4.121-4.302-6.181-10.665-6.181-19.089 0-11.592 2.514-19.565 7.54-23.911 5.029-4.35 13.565-6.523 25.612-6.523 12.047 0 22.915 1.134 32.61 3.398l-3.398 18.978c-8.423-1.358-15.171-2.038-20.244-2.038s-9.375.226-12.908.68v9.416l9.783.952c11.865 1.177 20.063 4.008 24.591 8.492 4.531 4.484 6.795 10.71 6.795 18.682 0 5.706-.77 10.528-2.311 14.47-1.541 3.94-3.373 6.927-5.502 8.966-2.129 2.038-5.141 3.601-9.037 4.687-3.892 1.087-7.312 1.745-10.255 1.97-2.944.228-6.864.341-11.755.341-11.775 0-22.688-1.177-32.743-3.532zm128.036-1.631l-11.548 3.125c-15.219 0-25.414-3.926-30.707-11.684-2.674-3.923-4.621-8.266-5.708-13.111-1.087-4.844-1.628-10.712-1.628-17.595 0-15.491 2.899-26.789 8.695-33.9 5.797-7.109 16.212-10.666 31.249-10.666 15.036 0 25.498 3.579 31.386 10.734 5.887 7.156 8.83 18.432 8.83 33.832 0 11.502-2.399 20.786-7.199 27.851l9.782 5.708-7.067 15.623-26.085-4.754v-5.163zm-20.382-18.072h11.279c3.714 0 6.407-.429 8.083-1.29 1.675-.861 2.514-2.83 2.514-5.909v-35.325h-11.414c-3.62 0-6.272.429-7.947 1.29-1.675.861-2.515 2.834-2.515 5.909v35.325zm115.536 21.197h-54.349v-84.917h27.175v63.179h27.174v21.738z
+ M19.14,7.5A2.86,2.86 0 0,1 22,10.36V14.14A2.86,2.86 0 0,1 19.14,17H12C12,17.39 12.32,17.96 12.71,17.96H17V19.64A2.86,2.86 0 0,1 14.14,22.5H9.86A2.86,2.86 0 0,1 7,19.64V15.89C7,14.31 8.28,13.04 9.86,13.04H15.11C16.69,13.04 17.96,11.76 17.96,10.18V7.5H19.14M14.86,19.29C14.46,19.29 14.14,19.59 14.14,20.18C14.14,20.77 14.46,20.89 14.86,20.89A0.71,0.71 0 0,0 15.57,20.18C15.57,19.59 15.25,19.29 14.86,19.29M4.86,17.5C3.28,17.5 2,16.22 2,14.64V10.86C2,9.28 3.28,8 4.86,8H12C12,7.61 11.68,7.04 11.29,7.04H7V5.36C7,3.78 8.28,2.5 9.86,2.5H14.14C15.72,2.5 17,3.78 17,5.36V9.11C17,10.69 15.72,11.96 14.14,11.96H8.89C7.31,11.96 6.04,13.24 6.04,14.82V17.5H4.86M9.14,5.71C9.54,5.71 9.86,5.41 9.86,4.82C9.86,4.23 9.54,4.11 9.14,4.11C8.75,4.11 8.43,4.23 8.43,4.82C8.43,5.41 8.75,5.71 9.14,5.71Z
+ M7878 15350 c-162 -15 -335 -63 -471 -131 -146 -74 -5492 -3082 -5567 -3133 -41 -28 -120 -96 -175 -151 -189 -189 -307 -411 -362 -682 -17 -84 -18 -245 -18 -3253 0 -3008 1 -3169 18 -3253 50 -249 159 -466 323 -645 64 -71 188 -173 269 -224 102 -64 5469 -3075 5535 -3106 367 -170 814 -166 1165 10 75 38 5370 3012 5482 3079 326 196 543 505 620 886 17 84 18 245 18 3253 0 3008 -1 3169 -18 3253 -55 271 -173 493 -362 682 -55 55 -134 123 -175 151 -75 51 -5421 3059 -5568 3133 -203 102 -479 152 -714 131z m591 -3534 c526 -70 1018 -235 1456 -489 298 -172 642 -446 866 -689 117 -126 259 -298 259 -312 -1 -6 -301 -184 -667 -396 -366 -212 -680 -393 -697 -403 l-31 -18 -85 82 c-583 568 -1404 778 -2184 559 -501 -141 -952 -471 -1245 -910 -249 -373 -374 -786 -374 -1240 0 -372 82 -709 250 -1030 337 -644 947 -1075 1678 -1185 133 -21 439 -23 570 -6 499 66 958 288 1304 631 l84 82 32 -18 c892 -514 1364 -791 1365 -800 1 -32 -300 -365 -462 -511 -583 -528 -1275 -856 -2043 -967 -200 -29 -382 -39 -638 -33 -277 6 -411 20 -672 72 -1512 301 -2719 1521 -3009 3040 -52 276 -61 378 -61 725 0 355 9 453 66 747 255 1307 1201 2410 2461 2867 312 113 669 190 1018 220 118 10 641 -2 759 -18z m3371 -2536 l0 -320 320 0 320 0 0 320 0 320 320 0 320 0 0 -320 0 -320 320 0 320 0 0 -320 0 -320 -320 0 -320 0 0 -320 0 -320 320 0 320 0 0 -320 0 -320 -320 0 -320 0 0 -320 0 -320 -320 0 -320 0 0 320 0 320 -320 0 -320 0 0 -320 0 -320 -320 0 -320 0 0 320 0 320 -320 0 -320 0 0 320 0 320 320 0 320 0 0 320 0 320 -320 0 -320 0 0 320 0 320 320 0 320 0 0 320 0 320 320 0 320 0 0 -320z M11840 8000 l0 -320 320 0 320 0 0 320 0 320 -320 0 -320 0 0 -320z
M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6 ZM12,11A3,3 0 1,0 12,17A3,3 0 0,0 12,11 ZM12,12.5L14,16H13L12,14.5L11,16H10L12,12.5Z