diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 00000000..1ff0c423
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..b06e864a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,212 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+
+# Visual Studio 2015 cache/options directory
+.vs/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUNIT
+*.VisualState.xml
+TestResult.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# DNX
+project.lock.json
+artifacts/
+
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# JustCode is a .NET coding add-in
+.JustCode
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+## TODO: Comment the next line if you want to checkin your
+## web deploy settings but do note that will include unencrypted
+## passwords
+#*.pubxml
+
+*.publishproj
+
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/packages/repositories.config
+
+# Windows Azure Build Output
+csx/
+*.build.csdef
+
+# Windows Store app package directory
+AppPackages/
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!*.[Cc]ache/
+
+# Others
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+orleans.codegen.cs
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+
+# SQL Server files
+*.mdf
+*.ldf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# LightSwitch generated files
+GeneratedArtifacts/
+_Pvt_Extensions/
+ModelManifest.xml
diff --git a/Unity Studio.sln b/Unity Studio.sln
new file mode 100644
index 00000000..71855626
--- /dev/null
+++ b/Unity Studio.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unity Studio", "Unity Studio\Unity Studio.csproj", "{24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.ActiveCfg = Debug|x86
+ {24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Debug|x86.Build.0 = Debug|x86
+ {24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.ActiveCfg = Release|x86
+ {24551E2D-E9B6-4CD6-8F2A-D9F4A13E7853}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Unity Studio/7zip/Common/CRC.cs b/Unity Studio/7zip/Common/CRC.cs
new file mode 100644
index 00000000..82cc857e
--- /dev/null
+++ b/Unity Studio/7zip/Common/CRC.cs
@@ -0,0 +1,55 @@
+// Common/CRC.cs
+
+namespace SevenZip
+{
+ class CRC
+ {
+ public static readonly uint[] Table;
+
+ static CRC()
+ {
+ Table = new uint[256];
+ const uint kPoly = 0xEDB88320;
+ for (uint i = 0; i < 256; i++)
+ {
+ uint r = i;
+ for (int j = 0; j < 8; j++)
+ if ((r & 1) != 0)
+ r = (r >> 1) ^ kPoly;
+ else
+ r >>= 1;
+ Table[i] = r;
+ }
+ }
+
+ uint _value = 0xFFFFFFFF;
+
+ public void Init() { _value = 0xFFFFFFFF; }
+
+ public void UpdateByte(byte b)
+ {
+ _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8);
+ }
+
+ public void Update(byte[] data, uint offset, uint size)
+ {
+ for (uint i = 0; i < size; i++)
+ _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8);
+ }
+
+ public uint GetDigest() { return _value ^ 0xFFFFFFFF; }
+
+ static uint CalculateDigest(byte[] data, uint offset, uint size)
+ {
+ CRC crc = new CRC();
+ // crc.Init();
+ crc.Update(data, offset, size);
+ return crc.GetDigest();
+ }
+
+ static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size)
+ {
+ return (CalculateDigest(data, offset, size) == digest);
+ }
+ }
+}
diff --git a/Unity Studio/7zip/Common/CommandLineParser.cs b/Unity Studio/7zip/Common/CommandLineParser.cs
new file mode 100644
index 00000000..8eabf59d
--- /dev/null
+++ b/Unity Studio/7zip/Common/CommandLineParser.cs
@@ -0,0 +1,274 @@
+// CommandLineParser.cs
+
+using System;
+using System.Collections;
+
+namespace SevenZip.CommandLineParser
+{
+ public enum SwitchType
+ {
+ Simple,
+ PostMinus,
+ LimitedPostString,
+ UnLimitedPostString,
+ PostChar
+ }
+
+ public class SwitchForm
+ {
+ public string IDString;
+ public SwitchType Type;
+ public bool Multi;
+ public int MinLen;
+ public int MaxLen;
+ public string PostCharSet;
+
+ public SwitchForm(string idString, SwitchType type, bool multi,
+ int minLen, int maxLen, string postCharSet)
+ {
+ IDString = idString;
+ Type = type;
+ Multi = multi;
+ MinLen = minLen;
+ MaxLen = maxLen;
+ PostCharSet = postCharSet;
+ }
+ public SwitchForm(string idString, SwitchType type, bool multi, int minLen):
+ this(idString, type, multi, minLen, 0, "")
+ {
+ }
+ public SwitchForm(string idString, SwitchType type, bool multi):
+ this(idString, type, multi, 0)
+ {
+ }
+ }
+
+ public class SwitchResult
+ {
+ public bool ThereIs;
+ public bool WithMinus;
+ public ArrayList PostStrings = new ArrayList();
+ public int PostCharIndex;
+ public SwitchResult()
+ {
+ ThereIs = false;
+ }
+ }
+
+ public class Parser
+ {
+ public ArrayList NonSwitchStrings = new ArrayList();
+ SwitchResult[] _switches;
+
+ public Parser(int numSwitches)
+ {
+ _switches = new SwitchResult[numSwitches];
+ for (int i = 0; i < numSwitches; i++)
+ _switches[i] = new SwitchResult();
+ }
+
+ bool ParseString(string srcString, SwitchForm[] switchForms)
+ {
+ int len = srcString.Length;
+ if (len == 0)
+ return false;
+ int pos = 0;
+ if (!IsItSwitchChar(srcString[pos]))
+ return false;
+ while (pos < len)
+ {
+ if (IsItSwitchChar(srcString[pos]))
+ pos++;
+ const int kNoLen = -1;
+ int matchedSwitchIndex = 0;
+ int maxLen = kNoLen;
+ for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++)
+ {
+ int switchLen = switchForms[switchIndex].IDString.Length;
+ if (switchLen <= maxLen || pos + switchLen > len)
+ continue;
+ if (String.Compare(switchForms[switchIndex].IDString, 0,
+ srcString, pos, switchLen, true) == 0)
+ {
+ matchedSwitchIndex = switchIndex;
+ maxLen = switchLen;
+ }
+ }
+ if (maxLen == kNoLen)
+ throw new Exception("maxLen == kNoLen");
+ SwitchResult matchedSwitch = _switches[matchedSwitchIndex];
+ SwitchForm switchForm = switchForms[matchedSwitchIndex];
+ if ((!switchForm.Multi) && matchedSwitch.ThereIs)
+ throw new Exception("switch must be single");
+ matchedSwitch.ThereIs = true;
+ pos += maxLen;
+ int tailSize = len - pos;
+ SwitchType type = switchForm.Type;
+ switch (type)
+ {
+ case SwitchType.PostMinus:
+ {
+ if (tailSize == 0)
+ matchedSwitch.WithMinus = false;
+ else
+ {
+ matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus);
+ if (matchedSwitch.WithMinus)
+ pos++;
+ }
+ break;
+ }
+ case SwitchType.PostChar:
+ {
+ if (tailSize < switchForm.MinLen)
+ throw new Exception("switch is not full");
+ string charSet = switchForm.PostCharSet;
+ const int kEmptyCharValue = -1;
+ if (tailSize == 0)
+ matchedSwitch.PostCharIndex = kEmptyCharValue;
+ else
+ {
+ int index = charSet.IndexOf(srcString[pos]);
+ if (index < 0)
+ matchedSwitch.PostCharIndex = kEmptyCharValue;
+ else
+ {
+ matchedSwitch.PostCharIndex = index;
+ pos++;
+ }
+ }
+ break;
+ }
+ case SwitchType.LimitedPostString:
+ case SwitchType.UnLimitedPostString:
+ {
+ int minLen = switchForm.MinLen;
+ if (tailSize < minLen)
+ throw new Exception("switch is not full");
+ if (type == SwitchType.UnLimitedPostString)
+ {
+ matchedSwitch.PostStrings.Add(srcString.Substring(pos));
+ return true;
+ }
+ String stringSwitch = srcString.Substring(pos, minLen);
+ pos += minLen;
+ for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++)
+ {
+ char c = srcString[pos];
+ if (IsItSwitchChar(c))
+ break;
+ stringSwitch += c;
+ }
+ matchedSwitch.PostStrings.Add(stringSwitch);
+ break;
+ }
+ }
+ }
+ return true;
+
+ }
+
+ public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings)
+ {
+ int numCommandStrings = commandStrings.Length;
+ bool stopSwitch = false;
+ for (int i = 0; i < numCommandStrings; i++)
+ {
+ string s = commandStrings[i];
+ if (stopSwitch)
+ NonSwitchStrings.Add(s);
+ else
+ if (s == kStopSwitchParsing)
+ stopSwitch = true;
+ else
+ if (!ParseString(s, switchForms))
+ NonSwitchStrings.Add(s);
+ }
+ }
+
+ public SwitchResult this[int index] { get { return _switches[index]; } }
+
+ public static int ParseCommand(CommandForm[] commandForms, string commandString,
+ out string postString)
+ {
+ for (int i = 0; i < commandForms.Length; i++)
+ {
+ string id = commandForms[i].IDString;
+ if (commandForms[i].PostStringMode)
+ {
+ if (commandString.IndexOf(id) == 0)
+ {
+ postString = commandString.Substring(id.Length);
+ return i;
+ }
+ }
+ else
+ if (commandString == id)
+ {
+ postString = "";
+ return i;
+ }
+ }
+ postString = "";
+ return -1;
+ }
+
+ static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms,
+ string commandString, ArrayList indices)
+ {
+ indices.Clear();
+ int numUsedChars = 0;
+ for (int i = 0; i < numForms; i++)
+ {
+ CommandSubCharsSet charsSet = forms[i];
+ int currentIndex = -1;
+ int len = charsSet.Chars.Length;
+ for (int j = 0; j < len; j++)
+ {
+ char c = charsSet.Chars[j];
+ int newIndex = commandString.IndexOf(c);
+ if (newIndex >= 0)
+ {
+ if (currentIndex >= 0)
+ return false;
+ if (commandString.IndexOf(c, newIndex + 1) >= 0)
+ return false;
+ currentIndex = j;
+ numUsedChars++;
+ }
+ }
+ if (currentIndex == -1 && !charsSet.EmptyAllowed)
+ return false;
+ indices.Add(currentIndex);
+ }
+ return (numUsedChars == commandString.Length);
+ }
+ const char kSwitchID1 = '-';
+ const char kSwitchID2 = '/';
+
+ const char kSwitchMinus = '-';
+ const string kStopSwitchParsing = "--";
+
+ static bool IsItSwitchChar(char c)
+ {
+ return (c == kSwitchID1 || c == kSwitchID2);
+ }
+ }
+
+ public class CommandForm
+ {
+ public string IDString = "";
+ public bool PostStringMode = false;
+ public CommandForm(string idString, bool postStringMode)
+ {
+ IDString = idString;
+ PostStringMode = postStringMode;
+ }
+ }
+
+ class CommandSubCharsSet
+ {
+ public string Chars = "";
+ public bool EmptyAllowed = false;
+ }
+}
diff --git a/Unity Studio/7zip/Common/InBuffer.cs b/Unity Studio/7zip/Common/InBuffer.cs
new file mode 100644
index 00000000..7c51f0bc
--- /dev/null
+++ b/Unity Studio/7zip/Common/InBuffer.cs
@@ -0,0 +1,72 @@
+// InBuffer.cs
+
+namespace SevenZip.Buffer
+{
+ public class InBuffer
+ {
+ byte[] m_Buffer;
+ uint m_Pos;
+ uint m_Limit;
+ uint m_BufferSize;
+ System.IO.Stream m_Stream;
+ bool m_StreamWasExhausted;
+ ulong m_ProcessedSize;
+
+ public InBuffer(uint bufferSize)
+ {
+ m_Buffer = new byte[bufferSize];
+ m_BufferSize = bufferSize;
+ }
+
+ public void Init(System.IO.Stream stream)
+ {
+ m_Stream = stream;
+ m_ProcessedSize = 0;
+ m_Limit = 0;
+ m_Pos = 0;
+ m_StreamWasExhausted = false;
+ }
+
+ public bool ReadBlock()
+ {
+ if (m_StreamWasExhausted)
+ return false;
+ m_ProcessedSize += m_Pos;
+ int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize);
+ m_Pos = 0;
+ m_Limit = (uint)aNumProcessedBytes;
+ m_StreamWasExhausted = (aNumProcessedBytes == 0);
+ return (!m_StreamWasExhausted);
+ }
+
+
+ public void ReleaseStream()
+ {
+ // m_Stream.Close();
+ m_Stream = null;
+ }
+
+ public bool ReadByte(byte b) // check it
+ {
+ if (m_Pos >= m_Limit)
+ if (!ReadBlock())
+ return false;
+ b = m_Buffer[m_Pos++];
+ return true;
+ }
+
+ public byte ReadByte()
+ {
+ // return (byte)m_Stream.ReadByte();
+ if (m_Pos >= m_Limit)
+ if (!ReadBlock())
+ return 0xFF;
+ return m_Buffer[m_Pos++];
+ }
+
+ public ulong GetProcessedSize()
+ {
+ return m_ProcessedSize + m_Pos;
+ }
+ }
+}
diff --git a/Unity Studio/7zip/Common/OutBuffer.cs b/Unity Studio/7zip/Common/OutBuffer.cs
new file mode 100644
index 00000000..2da16e16
--- /dev/null
+++ b/Unity Studio/7zip/Common/OutBuffer.cs
@@ -0,0 +1,47 @@
+// OutBuffer.cs
+
+namespace SevenZip.Buffer
+{
+ public class OutBuffer
+ {
+ byte[] m_Buffer;
+ uint m_Pos;
+ uint m_BufferSize;
+ System.IO.Stream m_Stream;
+ ulong m_ProcessedSize;
+
+ public OutBuffer(uint bufferSize)
+ {
+ m_Buffer = new byte[bufferSize];
+ m_BufferSize = bufferSize;
+ }
+
+ public void SetStream(System.IO.Stream stream) { m_Stream = stream; }
+ public void FlushStream() { m_Stream.Flush(); }
+ public void CloseStream() { m_Stream.Close(); }
+ public void ReleaseStream() { m_Stream = null; }
+
+ public void Init()
+ {
+ m_ProcessedSize = 0;
+ m_Pos = 0;
+ }
+
+ public void WriteByte(byte b)
+ {
+ m_Buffer[m_Pos++] = b;
+ if (m_Pos >= m_BufferSize)
+ FlushData();
+ }
+
+ public void FlushData()
+ {
+ if (m_Pos == 0)
+ return;
+ m_Stream.Write(m_Buffer, 0, (int)m_Pos);
+ m_Pos = 0;
+ }
+
+ public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; }
+ }
+}
diff --git a/Unity Studio/7zip/Compress/LZ/IMatchFinder.cs b/Unity Studio/7zip/Compress/LZ/IMatchFinder.cs
new file mode 100644
index 00000000..10ca2b37
--- /dev/null
+++ b/Unity Studio/7zip/Compress/LZ/IMatchFinder.cs
@@ -0,0 +1,24 @@
+// IMatchFinder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+ interface IInWindowStream
+ {
+ void SetStream(System.IO.Stream inStream);
+ void Init();
+ void ReleaseStream();
+ Byte GetIndexByte(Int32 index);
+ UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit);
+ UInt32 GetNumAvailableBytes();
+ }
+
+ interface IMatchFinder : IInWindowStream
+ {
+ void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter);
+ UInt32 GetMatches(UInt32[] distances);
+ void Skip(UInt32 num);
+ }
+}
diff --git a/Unity Studio/7zip/Compress/LZ/LzBinTree.cs b/Unity Studio/7zip/Compress/LZ/LzBinTree.cs
new file mode 100644
index 00000000..c1c006b6
--- /dev/null
+++ b/Unity Studio/7zip/Compress/LZ/LzBinTree.cs
@@ -0,0 +1,367 @@
+// LzBinTree.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+ public class BinTree : InWindow, IMatchFinder
+ {
+ UInt32 _cyclicBufferPos;
+ UInt32 _cyclicBufferSize = 0;
+ UInt32 _matchMaxLen;
+
+ UInt32[] _son;
+ UInt32[] _hash;
+
+ UInt32 _cutValue = 0xFF;
+ UInt32 _hashMask;
+ UInt32 _hashSizeSum = 0;
+
+ bool HASH_ARRAY = true;
+
+ const UInt32 kHash2Size = 1 << 10;
+ const UInt32 kHash3Size = 1 << 16;
+ const UInt32 kBT2HashSize = 1 << 16;
+ const UInt32 kStartMaxLen = 1;
+ const UInt32 kHash3Offset = kHash2Size;
+ const UInt32 kEmptyHashValue = 0;
+ const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1;
+
+ UInt32 kNumHashDirectBytes = 0;
+ UInt32 kMinMatchCheck = 4;
+ UInt32 kFixHashSize = kHash2Size + kHash3Size;
+
+ public void SetType(int numHashBytes)
+ {
+ HASH_ARRAY = (numHashBytes > 2);
+ if (HASH_ARRAY)
+ {
+ kNumHashDirectBytes = 0;
+ kMinMatchCheck = 4;
+ kFixHashSize = kHash2Size + kHash3Size;
+ }
+ else
+ {
+ kNumHashDirectBytes = 2;
+ kMinMatchCheck = 2 + 1;
+ kFixHashSize = 0;
+ }
+ }
+
+ public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); }
+ public new void ReleaseStream() { base.ReleaseStream(); }
+
+ public new void Init()
+ {
+ base.Init();
+ for (UInt32 i = 0; i < _hashSizeSum; i++)
+ _hash[i] = kEmptyHashValue;
+ _cyclicBufferPos = 0;
+ ReduceOffsets(-1);
+ }
+
+ public new void MovePos()
+ {
+ if (++_cyclicBufferPos >= _cyclicBufferSize)
+ _cyclicBufferPos = 0;
+ base.MovePos();
+ if (_pos == kMaxValForNormalize)
+ Normalize();
+ }
+
+ public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); }
+
+ public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
+ { return base.GetMatchLen(index, distance, limit); }
+
+ public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); }
+
+ public void Create(UInt32 historySize, UInt32 keepAddBufferBefore,
+ UInt32 matchMaxLen, UInt32 keepAddBufferAfter)
+ {
+ if (historySize > kMaxValForNormalize - 256)
+ throw new Exception();
+ _cutValue = 16 + (matchMaxLen >> 1);
+
+ UInt32 windowReservSize = (historySize + keepAddBufferBefore +
+ matchMaxLen + keepAddBufferAfter) / 2 + 256;
+
+ base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize);
+
+ _matchMaxLen = matchMaxLen;
+
+ UInt32 cyclicBufferSize = historySize + 1;
+ if (_cyclicBufferSize != cyclicBufferSize)
+ _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2];
+
+ UInt32 hs = kBT2HashSize;
+
+ if (HASH_ARRAY)
+ {
+ hs = historySize - 1;
+ hs |= (hs >> 1);
+ hs |= (hs >> 2);
+ hs |= (hs >> 4);
+ hs |= (hs >> 8);
+ hs >>= 1;
+ hs |= 0xFFFF;
+ if (hs > (1 << 24))
+ hs >>= 1;
+ _hashMask = hs;
+ hs++;
+ hs += kFixHashSize;
+ }
+ if (hs != _hashSizeSum)
+ _hash = new UInt32[_hashSizeSum = hs];
+ }
+
+ public UInt32 GetMatches(UInt32[] distances)
+ {
+ UInt32 lenLimit;
+ if (_pos + _matchMaxLen <= _streamPos)
+ lenLimit = _matchMaxLen;
+ else
+ {
+ lenLimit = _streamPos - _pos;
+ if (lenLimit < kMinMatchCheck)
+ {
+ MovePos();
+ return 0;
+ }
+ }
+
+ UInt32 offset = 0;
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+ UInt32 cur = _bufferOffset + _pos;
+ UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize;
+ UInt32 hashValue, hash2Value = 0, hash3Value = 0;
+
+ if (HASH_ARRAY)
+ {
+ UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
+ hash2Value = temp & (kHash2Size - 1);
+ temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
+ hash3Value = temp & (kHash3Size - 1);
+ hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
+ }
+ else
+ hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
+
+ UInt32 curMatch = _hash[kFixHashSize + hashValue];
+ if (HASH_ARRAY)
+ {
+ UInt32 curMatch2 = _hash[hash2Value];
+ UInt32 curMatch3 = _hash[kHash3Offset + hash3Value];
+ _hash[hash2Value] = _pos;
+ _hash[kHash3Offset + hash3Value] = _pos;
+ if (curMatch2 > matchMinPos)
+ if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur])
+ {
+ distances[offset++] = maxLen = 2;
+ distances[offset++] = _pos - curMatch2 - 1;
+ }
+ if (curMatch3 > matchMinPos)
+ if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur])
+ {
+ if (curMatch3 == curMatch2)
+ offset -= 2;
+ distances[offset++] = maxLen = 3;
+ distances[offset++] = _pos - curMatch3 - 1;
+ curMatch2 = curMatch3;
+ }
+ if (offset != 0 && curMatch2 == curMatch)
+ {
+ offset -= 2;
+ maxLen = kStartMaxLen;
+ }
+ }
+
+ _hash[kFixHashSize + hashValue] = _pos;
+
+ UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
+ UInt32 ptr1 = (_cyclicBufferPos << 1);
+
+ UInt32 len0, len1;
+ len0 = len1 = kNumHashDirectBytes;
+
+ if (kNumHashDirectBytes != 0)
+ {
+ if (curMatch > matchMinPos)
+ {
+ if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] !=
+ _bufferBase[cur + kNumHashDirectBytes])
+ {
+ distances[offset++] = maxLen = kNumHashDirectBytes;
+ distances[offset++] = _pos - curMatch - 1;
+ }
+ }
+ }
+
+ UInt32 count = _cutValue;
+
+ while(true)
+ {
+ if(curMatch <= matchMinPos || count-- == 0)
+ {
+ _son[ptr0] = _son[ptr1] = kEmptyHashValue;
+ break;
+ }
+ UInt32 delta = _pos - curMatch;
+ UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
+ (_cyclicBufferPos - delta) :
+ (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
+
+ UInt32 pby1 = _bufferOffset + curMatch;
+ UInt32 len = Math.Min(len0, len1);
+ if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
+ {
+ while(++len != lenLimit)
+ if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
+ break;
+ if (maxLen < len)
+ {
+ distances[offset++] = maxLen = len;
+ distances[offset++] = delta - 1;
+ if (len == lenLimit)
+ {
+ _son[ptr1] = _son[cyclicPos];
+ _son[ptr0] = _son[cyclicPos + 1];
+ break;
+ }
+ }
+ }
+ if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
+ {
+ _son[ptr1] = curMatch;
+ ptr1 = cyclicPos + 1;
+ curMatch = _son[ptr1];
+ len1 = len;
+ }
+ else
+ {
+ _son[ptr0] = curMatch;
+ ptr0 = cyclicPos;
+ curMatch = _son[ptr0];
+ len0 = len;
+ }
+ }
+ MovePos();
+ return offset;
+ }
+
+ public void Skip(UInt32 num)
+ {
+ do
+ {
+ UInt32 lenLimit;
+ if (_pos + _matchMaxLen <= _streamPos)
+ lenLimit = _matchMaxLen;
+ else
+ {
+ lenLimit = _streamPos - _pos;
+ if (lenLimit < kMinMatchCheck)
+ {
+ MovePos();
+ continue;
+ }
+ }
+
+ UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0;
+ UInt32 cur = _bufferOffset + _pos;
+
+ UInt32 hashValue;
+
+ if (HASH_ARRAY)
+ {
+ UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1];
+ UInt32 hash2Value = temp & (kHash2Size - 1);
+ _hash[hash2Value] = _pos;
+ temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8);
+ UInt32 hash3Value = temp & (kHash3Size - 1);
+ _hash[kHash3Offset + hash3Value] = _pos;
+ hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask;
+ }
+ else
+ hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8);
+
+ UInt32 curMatch = _hash[kFixHashSize + hashValue];
+ _hash[kFixHashSize + hashValue] = _pos;
+
+ UInt32 ptr0 = (_cyclicBufferPos << 1) + 1;
+ UInt32 ptr1 = (_cyclicBufferPos << 1);
+
+ UInt32 len0, len1;
+ len0 = len1 = kNumHashDirectBytes;
+
+ UInt32 count = _cutValue;
+ while (true)
+ {
+ if (curMatch <= matchMinPos || count-- == 0)
+ {
+ _son[ptr0] = _son[ptr1] = kEmptyHashValue;
+ break;
+ }
+
+ UInt32 delta = _pos - curMatch;
+ UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ?
+ (_cyclicBufferPos - delta) :
+ (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1;
+
+ UInt32 pby1 = _bufferOffset + curMatch;
+ UInt32 len = Math.Min(len0, len1);
+ if (_bufferBase[pby1 + len] == _bufferBase[cur + len])
+ {
+ while (++len != lenLimit)
+ if (_bufferBase[pby1 + len] != _bufferBase[cur + len])
+ break;
+ if (len == lenLimit)
+ {
+ _son[ptr1] = _son[cyclicPos];
+ _son[ptr0] = _son[cyclicPos + 1];
+ break;
+ }
+ }
+ if (_bufferBase[pby1 + len] < _bufferBase[cur + len])
+ {
+ _son[ptr1] = curMatch;
+ ptr1 = cyclicPos + 1;
+ curMatch = _son[ptr1];
+ len1 = len;
+ }
+ else
+ {
+ _son[ptr0] = curMatch;
+ ptr0 = cyclicPos;
+ curMatch = _son[ptr0];
+ len0 = len;
+ }
+ }
+ MovePos();
+ }
+ while (--num != 0);
+ }
+
+ void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue)
+ {
+ for (UInt32 i = 0; i < numItems; i++)
+ {
+ UInt32 value = items[i];
+ if (value <= subValue)
+ value = kEmptyHashValue;
+ else
+ value -= subValue;
+ items[i] = value;
+ }
+ }
+
+ void Normalize()
+ {
+ UInt32 subValue = _pos - _cyclicBufferSize;
+ NormalizeLinks(_son, _cyclicBufferSize * 2, subValue);
+ NormalizeLinks(_hash, _hashSizeSum, subValue);
+ ReduceOffsets((Int32)subValue);
+ }
+
+ public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; }
+ }
+}
diff --git a/Unity Studio/7zip/Compress/LZ/LzInWindow.cs b/Unity Studio/7zip/Compress/LZ/LzInWindow.cs
new file mode 100644
index 00000000..52d23ce3
--- /dev/null
+++ b/Unity Studio/7zip/Compress/LZ/LzInWindow.cs
@@ -0,0 +1,132 @@
+// LzInWindow.cs
+
+using System;
+
+namespace SevenZip.Compression.LZ
+{
+ public class InWindow
+ {
+ public Byte[] _bufferBase = null; // pointer to buffer with data
+ System.IO.Stream _stream;
+ UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done
+ bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream
+
+ UInt32 _pointerToLastSafePosition;
+
+ public UInt32 _bufferOffset;
+
+ public UInt32 _blockSize; // Size of Allocated memory block
+ public UInt32 _pos; // offset (from _buffer) of curent byte
+ UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos
+ UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos
+ public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream
+
+ public void MoveBlock()
+ {
+ UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore;
+ // we need one additional byte, since MovePos moves on 1 byte.
+ if (offset > 0)
+ offset--;
+
+ UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset;
+
+ // check negative offset ????
+ for (UInt32 i = 0; i < numBytes; i++)
+ _bufferBase[i] = _bufferBase[offset + i];
+ _bufferOffset -= offset;
+ }
+
+ public virtual void ReadBlock()
+ {
+ if (_streamEndWasReached)
+ return;
+ while (true)
+ {
+ int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos);
+ if (size == 0)
+ return;
+ int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size);
+ if (numReadBytes == 0)
+ {
+ _posLimit = _streamPos;
+ UInt32 pointerToPostion = _bufferOffset + _posLimit;
+ if (pointerToPostion > _pointerToLastSafePosition)
+ _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset);
+
+ _streamEndWasReached = true;
+ return;
+ }
+ _streamPos += (UInt32)numReadBytes;
+ if (_streamPos >= _pos + _keepSizeAfter)
+ _posLimit = _streamPos - _keepSizeAfter;
+ }
+ }
+
+ void Free() { _bufferBase = null; }
+
+ public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv)
+ {
+ _keepSizeBefore = keepSizeBefore;
+ _keepSizeAfter = keepSizeAfter;
+ UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv;
+ if (_bufferBase == null || _blockSize != blockSize)
+ {
+ Free();
+ _blockSize = blockSize;
+ _bufferBase = new Byte[_blockSize];
+ }
+ _pointerToLastSafePosition = _blockSize - keepSizeAfter;
+ }
+
+ public void SetStream(System.IO.Stream stream) { _stream = stream; }
+ public void ReleaseStream() { _stream = null; }
+
+ public void Init()
+ {
+ _bufferOffset = 0;
+ _pos = 0;
+ _streamPos = 0;
+ _streamEndWasReached = false;
+ ReadBlock();
+ }
+
+ public void MovePos()
+ {
+ _pos++;
+ if (_pos > _posLimit)
+ {
+ UInt32 pointerToPostion = _bufferOffset + _pos;
+ if (pointerToPostion > _pointerToLastSafePosition)
+ MoveBlock();
+ ReadBlock();
+ }
+ }
+
+ public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; }
+
+ // index + limit have not to exceed _keepSizeAfter;
+ public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit)
+ {
+ if (_streamEndWasReached)
+ if ((_pos + index) + limit > _streamPos)
+ limit = _streamPos - (UInt32)(_pos + index);
+ distance++;
+ // Byte *pby = _buffer + (size_t)_pos + index;
+ UInt32 pby = _bufferOffset + _pos + (UInt32)index;
+
+ UInt32 i;
+ for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++);
+ return i;
+ }
+
+ public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; }
+
+ public void ReduceOffsets(Int32 subValue)
+ {
+ _bufferOffset += (UInt32)subValue;
+ _posLimit -= (UInt32)subValue;
+ _pos -= (UInt32)subValue;
+ _streamPos -= (UInt32)subValue;
+ }
+ }
+}
diff --git a/Unity Studio/7zip/Compress/LZ/LzOutWindow.cs b/Unity Studio/7zip/Compress/LZ/LzOutWindow.cs
new file mode 100644
index 00000000..c998584a
--- /dev/null
+++ b/Unity Studio/7zip/Compress/LZ/LzOutWindow.cs
@@ -0,0 +1,110 @@
+// LzOutWindow.cs
+
+namespace SevenZip.Compression.LZ
+{
+ public class OutWindow
+ {
+ byte[] _buffer = null;
+ uint _pos;
+ uint _windowSize = 0;
+ uint _streamPos;
+ System.IO.Stream _stream;
+
+ public uint TrainSize = 0;
+
+ public void Create(uint windowSize)
+ {
+ if (_windowSize != windowSize)
+ {
+ // System.GC.Collect();
+ _buffer = new byte[windowSize];
+ }
+ _windowSize = windowSize;
+ _pos = 0;
+ _streamPos = 0;
+ }
+
+ public void Init(System.IO.Stream stream, bool solid)
+ {
+ ReleaseStream();
+ _stream = stream;
+ if (!solid)
+ {
+ _streamPos = 0;
+ _pos = 0;
+ TrainSize = 0;
+ }
+ }
+
+ public bool Train(System.IO.Stream stream)
+ {
+ long len = stream.Length;
+ uint size = (len < _windowSize) ? (uint)len : _windowSize;
+ TrainSize = size;
+ stream.Position = len - size;
+ _streamPos = _pos = 0;
+ while (size > 0)
+ {
+ uint curSize = _windowSize - _pos;
+ if (size < curSize)
+ curSize = size;
+ int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize);
+ if (numReadBytes == 0)
+ return false;
+ size -= (uint)numReadBytes;
+ _pos += (uint)numReadBytes;
+ _streamPos += (uint)numReadBytes;
+ if (_pos == _windowSize)
+ _streamPos = _pos = 0;
+ }
+ return true;
+ }
+
+ public void ReleaseStream()
+ {
+ Flush();
+ _stream = null;
+ }
+
+ public void Flush()
+ {
+ uint size = _pos - _streamPos;
+ if (size == 0)
+ return;
+ _stream.Write(_buffer, (int)_streamPos, (int)size);
+ if (_pos >= _windowSize)
+ _pos = 0;
+ _streamPos = _pos;
+ }
+
+ public void CopyBlock(uint distance, uint len)
+ {
+ uint pos = _pos - distance - 1;
+ if (pos >= _windowSize)
+ pos += _windowSize;
+ for (; len > 0; len--)
+ {
+ if (pos >= _windowSize)
+ pos = 0;
+ _buffer[_pos++] = _buffer[pos++];
+ if (_pos >= _windowSize)
+ Flush();
+ }
+ }
+
+ public void PutByte(byte b)
+ {
+ _buffer[_pos++] = b;
+ if (_pos >= _windowSize)
+ Flush();
+ }
+
+ public byte GetByte(uint distance)
+ {
+ uint pos = _pos - distance - 1;
+ if (pos >= _windowSize)
+ pos += _windowSize;
+ return _buffer[pos];
+ }
+ }
+}
diff --git a/Unity Studio/7zip/Compress/LZMA/LzmaBase.cs b/Unity Studio/7zip/Compress/LZMA/LzmaBase.cs
new file mode 100644
index 00000000..c7bca86f
--- /dev/null
+++ b/Unity Studio/7zip/Compress/LZMA/LzmaBase.cs
@@ -0,0 +1,76 @@
+// LzmaBase.cs
+
+namespace SevenZip.Compression.LZMA
+{
+ internal abstract class Base
+ {
+ public const uint kNumRepDistances = 4;
+ public const uint kNumStates = 12;
+
+ // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
+ // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
+ // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
+ // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
+
+ public struct State
+ {
+ public uint Index;
+ public void Init() { Index = 0; }
+ public void UpdateChar()
+ {
+ if (Index < 4) Index = 0;
+ else if (Index < 10) Index -= 3;
+ else Index -= 6;
+ }
+ public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); }
+ public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); }
+ public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); }
+ public bool IsCharState() { return Index < 7; }
+ }
+
+ public const int kNumPosSlotBits = 6;
+ public const int kDicLogSizeMin = 0;
+ // public const int kDicLogSizeMax = 30;
+ // public const uint kDistTableSizeMax = kDicLogSizeMax * 2;
+
+ public const int kNumLenToPosStatesBits = 2; // it's for speed optimization
+ public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits;
+
+ public const uint kMatchMinLen = 2;
+
+ public static uint GetLenToPosState(uint len)
+ {
+ len -= kMatchMinLen;
+ if (len < kNumLenToPosStates)
+ return len;
+ return (uint)(kNumLenToPosStates - 1);
+ }
+
+ public const int kNumAlignBits = 4;
+ public const uint kAlignTableSize = 1 << kNumAlignBits;
+ public const uint kAlignMask = (kAlignTableSize - 1);
+
+ public const uint kStartPosModelIndex = 4;
+ public const uint kEndPosModelIndex = 14;
+ public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
+
+ public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2);
+
+ public const uint kNumLitPosStatesBitsEncodingMax = 4;
+ public const uint kNumLitContextBitsMax = 8;
+
+ public const int kNumPosStatesBitsMax = 4;
+ public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
+ public const int kNumPosStatesBitsEncodingMax = 4;
+ public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
+
+ public const int kNumLowLenBits = 3;
+ public const int kNumMidLenBits = 3;
+ public const int kNumHighLenBits = 8;
+ public const uint kNumLowLenSymbols = 1 << kNumLowLenBits;
+ public const uint kNumMidLenSymbols = 1 << kNumMidLenBits;
+ public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols +
+ (1 << kNumHighLenBits);
+ public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1;
+ }
+}
diff --git a/Unity Studio/7zip/Compress/LZMA/LzmaDecoder.cs b/Unity Studio/7zip/Compress/LZMA/LzmaDecoder.cs
new file mode 100644
index 00000000..a9be39fc
--- /dev/null
+++ b/Unity Studio/7zip/Compress/LZMA/LzmaDecoder.cs
@@ -0,0 +1,398 @@
+// LzmaDecoder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZMA
+{
+ using RangeCoder;
+
+ public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream
+ {
+ class LenDecoder
+ {
+ BitDecoder m_Choice = new BitDecoder();
+ BitDecoder m_Choice2 = new BitDecoder();
+ BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
+ BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax];
+ BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits);
+ uint m_NumPosStates = 0;
+
+ public void Create(uint numPosStates)
+ {
+ for (uint posState = m_NumPosStates; posState < numPosStates; posState++)
+ {
+ m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits);
+ m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits);
+ }
+ m_NumPosStates = numPosStates;
+ }
+
+ public void Init()
+ {
+ m_Choice.Init();
+ for (uint posState = 0; posState < m_NumPosStates; posState++)
+ {
+ m_LowCoder[posState].Init();
+ m_MidCoder[posState].Init();
+ }
+ m_Choice2.Init();
+ m_HighCoder.Init();
+ }
+
+ public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState)
+ {
+ if (m_Choice.Decode(rangeDecoder) == 0)
+ return m_LowCoder[posState].Decode(rangeDecoder);
+ else
+ {
+ uint symbol = Base.kNumLowLenSymbols;
+ if (m_Choice2.Decode(rangeDecoder) == 0)
+ symbol += m_MidCoder[posState].Decode(rangeDecoder);
+ else
+ {
+ symbol += Base.kNumMidLenSymbols;
+ symbol += m_HighCoder.Decode(rangeDecoder);
+ }
+ return symbol;
+ }
+ }
+ }
+
+ class LiteralDecoder
+ {
+ struct Decoder2
+ {
+ BitDecoder[] m_Decoders;
+ public void Create() { m_Decoders = new BitDecoder[0x300]; }
+ public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); }
+
+ public byte DecodeNormal(RangeCoder.Decoder rangeDecoder)
+ {
+ uint symbol = 1;
+ do
+ symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
+ while (symbol < 0x100);
+ return (byte)symbol;
+ }
+
+ public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte)
+ {
+ uint symbol = 1;
+ do
+ {
+ uint matchBit = (uint)(matchByte >> 7) & 1;
+ matchByte <<= 1;
+ uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder);
+ symbol = (symbol << 1) | bit;
+ if (matchBit != bit)
+ {
+ while (symbol < 0x100)
+ symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder);
+ break;
+ }
+ }
+ while (symbol < 0x100);
+ return (byte)symbol;
+ }
+ }
+
+ Decoder2[] m_Coders;
+ int m_NumPrevBits;
+ int m_NumPosBits;
+ uint m_PosMask;
+
+ public void Create(int numPosBits, int numPrevBits)
+ {
+ if (m_Coders != null && m_NumPrevBits == numPrevBits &&
+ m_NumPosBits == numPosBits)
+ return;
+ m_NumPosBits = numPosBits;
+ m_PosMask = ((uint)1 << numPosBits) - 1;
+ m_NumPrevBits = numPrevBits;
+ uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+ m_Coders = new Decoder2[numStates];
+ for (uint i = 0; i < numStates; i++)
+ m_Coders[i].Create();
+ }
+
+ public void Init()
+ {
+ uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+ for (uint i = 0; i < numStates; i++)
+ m_Coders[i].Init();
+ }
+
+ uint GetState(uint pos, byte prevByte)
+ { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); }
+
+ public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte)
+ { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); }
+
+ public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte)
+ { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); }
+ };
+
+ LZ.OutWindow m_OutWindow = new LZ.OutWindow();
+ RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder();
+
+ BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+ BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates];
+ BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates];
+ BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates];
+ BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates];
+ BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+
+ BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates];
+ BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
+
+ BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits);
+
+ LenDecoder m_LenDecoder = new LenDecoder();
+ LenDecoder m_RepLenDecoder = new LenDecoder();
+
+ LiteralDecoder m_LiteralDecoder = new LiteralDecoder();
+
+ uint m_DictionarySize;
+ uint m_DictionarySizeCheck;
+
+ uint m_PosStateMask;
+
+ public Decoder()
+ {
+ m_DictionarySize = 0xFFFFFFFF;
+ for (int i = 0; i < Base.kNumLenToPosStates; i++)
+ m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits);
+ }
+
+ void SetDictionarySize(uint dictionarySize)
+ {
+ if (m_DictionarySize != dictionarySize)
+ {
+ m_DictionarySize = dictionarySize;
+ m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1);
+ uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12));
+ m_OutWindow.Create(blockSize);
+ }
+ }
+
+ void SetLiteralProperties(int lp, int lc)
+ {
+ if (lp > 8)
+ throw new InvalidParamException();
+ if (lc > 8)
+ throw new InvalidParamException();
+ m_LiteralDecoder.Create(lp, lc);
+ }
+
+ void SetPosBitsProperties(int pb)
+ {
+ if (pb > Base.kNumPosStatesBitsMax)
+ throw new InvalidParamException();
+ uint numPosStates = (uint)1 << pb;
+ m_LenDecoder.Create(numPosStates);
+ m_RepLenDecoder.Create(numPosStates);
+ m_PosStateMask = numPosStates - 1;
+ }
+
+ bool _solid = false;
+ void Init(System.IO.Stream inStream, System.IO.Stream outStream)
+ {
+ m_RangeDecoder.Init(inStream);
+ m_OutWindow.Init(outStream, _solid);
+
+ uint i;
+ for (i = 0; i < Base.kNumStates; i++)
+ {
+ for (uint j = 0; j <= m_PosStateMask; j++)
+ {
+ uint index = (i << Base.kNumPosStatesBitsMax) + j;
+ m_IsMatchDecoders[index].Init();
+ m_IsRep0LongDecoders[index].Init();
+ }
+ m_IsRepDecoders[i].Init();
+ m_IsRepG0Decoders[i].Init();
+ m_IsRepG1Decoders[i].Init();
+ m_IsRepG2Decoders[i].Init();
+ }
+
+ m_LiteralDecoder.Init();
+ for (i = 0; i < Base.kNumLenToPosStates; i++)
+ m_PosSlotDecoder[i].Init();
+ // m_PosSpecDecoder.Init();
+ for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
+ m_PosDecoders[i].Init();
+
+ m_LenDecoder.Init();
+ m_RepLenDecoder.Init();
+ m_PosAlignDecoder.Init();
+ }
+
+ public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+ Int64 inSize, Int64 outSize, ICodeProgress progress)
+ {
+ Init(inStream, outStream);
+
+ Base.State state = new Base.State();
+ state.Init();
+ uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
+
+ UInt64 nowPos64 = 0;
+ UInt64 outSize64 = (UInt64)outSize;
+ if (nowPos64 < outSize64)
+ {
+ if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0)
+ throw new DataErrorException();
+ state.UpdateChar();
+ byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0);
+ m_OutWindow.PutByte(b);
+ nowPos64++;
+ }
+ while (nowPos64 < outSize64)
+ {
+ // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64);
+ // while(nowPos64 < next)
+ {
+ uint posState = (uint)nowPos64 & m_PosStateMask;
+ if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
+ {
+ byte b;
+ byte prevByte = m_OutWindow.GetByte(0);
+ if (!state.IsCharState())
+ b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder,
+ (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0));
+ else
+ b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte);
+ m_OutWindow.PutByte(b);
+ state.UpdateChar();
+ nowPos64++;
+ }
+ else
+ {
+ uint len;
+ if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1)
+ {
+ if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+ {
+ if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0)
+ {
+ state.UpdateShortRep();
+ m_OutWindow.PutByte(m_OutWindow.GetByte(rep0));
+ nowPos64++;
+ continue;
+ }
+ }
+ else
+ {
+ UInt32 distance;
+ if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+ {
+ distance = rep1;
+ }
+ else
+ {
+ if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0)
+ distance = rep2;
+ else
+ {
+ distance = rep3;
+ rep3 = rep2;
+ }
+ rep2 = rep1;
+ }
+ rep1 = rep0;
+ rep0 = distance;
+ }
+ len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen;
+ state.UpdateRep();
+ }
+ else
+ {
+ rep3 = rep2;
+ rep2 = rep1;
+ rep1 = rep0;
+ len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState);
+ state.UpdateMatch();
+ uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder);
+ if (posSlot >= Base.kStartPosModelIndex)
+ {
+ int numDirectBits = (int)((posSlot >> 1) - 1);
+ rep0 = ((2 | (posSlot & 1)) << numDirectBits);
+ if (posSlot < Base.kEndPosModelIndex)
+ rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders,
+ rep0 - posSlot - 1, m_RangeDecoder, numDirectBits);
+ else
+ {
+ rep0 += (m_RangeDecoder.DecodeDirectBits(
+ numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits);
+ rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder);
+ }
+ }
+ else
+ rep0 = posSlot;
+ }
+ if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck)
+ {
+ if (rep0 == 0xFFFFFFFF)
+ break;
+ throw new DataErrorException();
+ }
+ m_OutWindow.CopyBlock(rep0, len);
+ nowPos64 += len;
+ }
+ }
+ }
+ m_OutWindow.Flush();
+ m_OutWindow.ReleaseStream();
+ m_RangeDecoder.ReleaseStream();
+ }
+
+ public void SetDecoderProperties(byte[] properties)
+ {
+ if (properties.Length < 5)
+ throw new InvalidParamException();
+ int lc = properties[0] % 9;
+ int remainder = properties[0] / 9;
+ int lp = remainder % 5;
+ int pb = remainder / 5;
+ if (pb > Base.kNumPosStatesBitsMax)
+ throw new InvalidParamException();
+ UInt32 dictionarySize = 0;
+ for (int i = 0; i < 4; i++)
+ dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8);
+ SetDictionarySize(dictionarySize);
+ SetLiteralProperties(lp, lc);
+ SetPosBitsProperties(pb);
+ }
+
+ public bool Train(System.IO.Stream stream)
+ {
+ _solid = true;
+ return m_OutWindow.Train(stream);
+ }
+
+ /*
+ public override bool CanRead { get { return true; }}
+ public override bool CanWrite { get { return true; }}
+ public override bool CanSeek { get { return true; }}
+ public override long Length { get { return 0; }}
+ public override long Position
+ {
+ get { return 0; }
+ set { }
+ }
+ public override void Flush() { }
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ return 0;
+ }
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ }
+ public override long Seek(long offset, System.IO.SeekOrigin origin)
+ {
+ return 0;
+ }
+ public override void SetLength(long value) {}
+ */
+ }
+}
diff --git a/Unity Studio/7zip/Compress/LZMA/LzmaEncoder.cs b/Unity Studio/7zip/Compress/LZMA/LzmaEncoder.cs
new file mode 100644
index 00000000..0237c51f
--- /dev/null
+++ b/Unity Studio/7zip/Compress/LZMA/LzmaEncoder.cs
@@ -0,0 +1,1480 @@
+// LzmaEncoder.cs
+
+using System;
+
+namespace SevenZip.Compression.LZMA
+{
+ using RangeCoder;
+
+ public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties
+ {
+ enum EMatchFinderType
+ {
+ BT2,
+ BT4,
+ };
+
+ const UInt32 kIfinityPrice = 0xFFFFFFF;
+
+ static Byte[] g_FastPos = new Byte[1 << 11];
+
+ static Encoder()
+ {
+ const Byte kFastSlots = 22;
+ int c = 2;
+ g_FastPos[0] = 0;
+ g_FastPos[1] = 1;
+ for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++)
+ {
+ UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1));
+ for (UInt32 j = 0; j < k; j++, c++)
+ g_FastPos[c] = slotFast;
+ }
+ }
+
+ static UInt32 GetPosSlot(UInt32 pos)
+ {
+ if (pos < (1 << 11))
+ return g_FastPos[pos];
+ if (pos < (1 << 21))
+ return (UInt32)(g_FastPos[pos >> 10] + 20);
+ return (UInt32)(g_FastPos[pos >> 20] + 40);
+ }
+
+ static UInt32 GetPosSlot2(UInt32 pos)
+ {
+ if (pos < (1 << 17))
+ return (UInt32)(g_FastPos[pos >> 6] + 12);
+ if (pos < (1 << 27))
+ return (UInt32)(g_FastPos[pos >> 16] + 32);
+ return (UInt32)(g_FastPos[pos >> 26] + 52);
+ }
+
+ Base.State _state = new Base.State();
+ Byte _previousByte;
+ UInt32[] _repDistances = new UInt32[Base.kNumRepDistances];
+
+ void BaseInit()
+ {
+ _state.Init();
+ _previousByte = 0;
+ for (UInt32 i = 0; i < Base.kNumRepDistances; i++)
+ _repDistances[i] = 0;
+ }
+
+ const int kDefaultDictionaryLogSize = 22;
+ const UInt32 kNumFastBytesDefault = 0x20;
+
+ class LiteralEncoder
+ {
+ public struct Encoder2
+ {
+ BitEncoder[] m_Encoders;
+
+ public void Create() { m_Encoders = new BitEncoder[0x300]; }
+
+ public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); }
+
+ public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol)
+ {
+ uint context = 1;
+ for (int i = 7; i >= 0; i--)
+ {
+ uint bit = (uint)((symbol >> i) & 1);
+ m_Encoders[context].Encode(rangeEncoder, bit);
+ context = (context << 1) | bit;
+ }
+ }
+
+ public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol)
+ {
+ uint context = 1;
+ bool same = true;
+ for (int i = 7; i >= 0; i--)
+ {
+ uint bit = (uint)((symbol >> i) & 1);
+ uint state = context;
+ if (same)
+ {
+ uint matchBit = (uint)((matchByte >> i) & 1);
+ state += ((1 + matchBit) << 8);
+ same = (matchBit == bit);
+ }
+ m_Encoders[state].Encode(rangeEncoder, bit);
+ context = (context << 1) | bit;
+ }
+ }
+
+ public uint GetPrice(bool matchMode, byte matchByte, byte symbol)
+ {
+ uint price = 0;
+ uint context = 1;
+ int i = 7;
+ if (matchMode)
+ {
+ for (; i >= 0; i--)
+ {
+ uint matchBit = (uint)(matchByte >> i) & 1;
+ uint bit = (uint)(symbol >> i) & 1;
+ price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit);
+ context = (context << 1) | bit;
+ if (matchBit != bit)
+ {
+ i--;
+ break;
+ }
+ }
+ }
+ for (; i >= 0; i--)
+ {
+ uint bit = (uint)(symbol >> i) & 1;
+ price += m_Encoders[context].GetPrice(bit);
+ context = (context << 1) | bit;
+ }
+ return price;
+ }
+ }
+
+ Encoder2[] m_Coders;
+ int m_NumPrevBits;
+ int m_NumPosBits;
+ uint m_PosMask;
+
+ public void Create(int numPosBits, int numPrevBits)
+ {
+ if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits)
+ return;
+ m_NumPosBits = numPosBits;
+ m_PosMask = ((uint)1 << numPosBits) - 1;
+ m_NumPrevBits = numPrevBits;
+ uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+ m_Coders = new Encoder2[numStates];
+ for (uint i = 0; i < numStates; i++)
+ m_Coders[i].Create();
+ }
+
+ public void Init()
+ {
+ uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits);
+ for (uint i = 0; i < numStates; i++)
+ m_Coders[i].Init();
+ }
+
+ public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte)
+ { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; }
+ }
+
+ class LenEncoder
+ {
+ RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder();
+ RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder();
+ RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];
+ RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax];
+ RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits);
+
+ public LenEncoder()
+ {
+ for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++)
+ {
+ _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits);
+ _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits);
+ }
+ }
+
+ public void Init(UInt32 numPosStates)
+ {
+ _choice.Init();
+ _choice2.Init();
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
+ {
+ _lowCoder[posState].Init();
+ _midCoder[posState].Init();
+ }
+ _highCoder.Init();
+ }
+
+ public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
+ {
+ if (symbol < Base.kNumLowLenSymbols)
+ {
+ _choice.Encode(rangeEncoder, 0);
+ _lowCoder[posState].Encode(rangeEncoder, symbol);
+ }
+ else
+ {
+ symbol -= Base.kNumLowLenSymbols;
+ _choice.Encode(rangeEncoder, 1);
+ if (symbol < Base.kNumMidLenSymbols)
+ {
+ _choice2.Encode(rangeEncoder, 0);
+ _midCoder[posState].Encode(rangeEncoder, symbol);
+ }
+ else
+ {
+ _choice2.Encode(rangeEncoder, 1);
+ _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols);
+ }
+ }
+ }
+
+ public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st)
+ {
+ UInt32 a0 = _choice.GetPrice0();
+ UInt32 a1 = _choice.GetPrice1();
+ UInt32 b0 = a1 + _choice2.GetPrice0();
+ UInt32 b1 = a1 + _choice2.GetPrice1();
+ UInt32 i = 0;
+ for (i = 0; i < Base.kNumLowLenSymbols; i++)
+ {
+ if (i >= numSymbols)
+ return;
+ prices[st + i] = a0 + _lowCoder[posState].GetPrice(i);
+ }
+ for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++)
+ {
+ if (i >= numSymbols)
+ return;
+ prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols);
+ }
+ for (; i < numSymbols; i++)
+ prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols);
+ }
+ };
+
+ const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols;
+
+ class LenPriceTableEncoder : LenEncoder
+ {
+ UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax];
+ UInt32 _tableSize;
+ UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax];
+
+ public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; }
+
+ public UInt32 GetPrice(UInt32 symbol, UInt32 posState)
+ {
+ return _prices[posState * Base.kNumLenSymbols + symbol];
+ }
+
+ void UpdateTable(UInt32 posState)
+ {
+ SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols);
+ _counters[posState] = _tableSize;
+ }
+
+ public void UpdateTables(UInt32 numPosStates)
+ {
+ for (UInt32 posState = 0; posState < numPosStates; posState++)
+ UpdateTable(posState);
+ }
+
+ public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState)
+ {
+ base.Encode(rangeEncoder, symbol, posState);
+ if (--_counters[posState] == 0)
+ UpdateTable(posState);
+ }
+ }
+
+ const UInt32 kNumOpts = 1 << 12;
+ class Optimal
+ {
+ public Base.State State;
+
+ public bool Prev1IsChar;
+ public bool Prev2;
+
+ public UInt32 PosPrev2;
+ public UInt32 BackPrev2;
+
+ public UInt32 Price;
+ public UInt32 PosPrev;
+ public UInt32 BackPrev;
+
+ public UInt32 Backs0;
+ public UInt32 Backs1;
+ public UInt32 Backs2;
+ public UInt32 Backs3;
+
+ public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; }
+ public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; }
+ public bool IsShortRep() { return (BackPrev == 0); }
+ };
+ Optimal[] _optimum = new Optimal[kNumOpts];
+ LZ.IMatchFinder _matchFinder = null;
+ RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder();
+
+ RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+ RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates];
+ RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates];
+ RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates];
+ RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates];
+ RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax];
+
+ RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates];
+
+ RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex];
+ RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits);
+
+ LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder();
+ LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder();
+
+ LiteralEncoder _literalEncoder = new LiteralEncoder();
+
+ UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2];
+
+ UInt32 _numFastBytes = kNumFastBytesDefault;
+ UInt32 _longestMatchLength;
+ UInt32 _numDistancePairs;
+
+ UInt32 _additionalOffset;
+
+ UInt32 _optimumEndIndex;
+ UInt32 _optimumCurrentIndex;
+
+ bool _longestMatchWasFound;
+
+ UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)];
+ UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits];
+ UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize];
+ UInt32 _alignPriceCount;
+
+ UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2);
+
+ int _posStateBits = 2;
+ UInt32 _posStateMask = (4 - 1);
+ int _numLiteralPosStateBits = 0;
+ int _numLiteralContextBits = 3;
+
+ UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize);
+ UInt32 _dictionarySizePrev = 0xFFFFFFFF;
+ UInt32 _numFastBytesPrev = 0xFFFFFFFF;
+
+ Int64 nowPos64;
+ bool _finished;
+ System.IO.Stream _inStream;
+
+ EMatchFinderType _matchFinderType = EMatchFinderType.BT4;
+ bool _writeEndMark = false;
+
+ bool _needReleaseMFStream;
+
+ void Create()
+ {
+ if (_matchFinder == null)
+ {
+ LZ.BinTree bt = new LZ.BinTree();
+ int numHashBytes = 4;
+ if (_matchFinderType == EMatchFinderType.BT2)
+ numHashBytes = 2;
+ bt.SetType(numHashBytes);
+ _matchFinder = bt;
+ }
+ _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits);
+
+ if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes)
+ return;
+ _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1);
+ _dictionarySizePrev = _dictionarySize;
+ _numFastBytesPrev = _numFastBytes;
+ }
+
+ public Encoder()
+ {
+ for (int i = 0; i < kNumOpts; i++)
+ _optimum[i] = new Optimal();
+ for (int i = 0; i < Base.kNumLenToPosStates; i++)
+ _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits);
+ }
+
+ void SetWriteEndMarkerMode(bool writeEndMarker)
+ {
+ _writeEndMark = writeEndMarker;
+ }
+
+ void Init()
+ {
+ BaseInit();
+ _rangeEncoder.Init();
+
+ uint i;
+ for (i = 0; i < Base.kNumStates; i++)
+ {
+ for (uint j = 0; j <= _posStateMask; j++)
+ {
+ uint complexState = (i << Base.kNumPosStatesBitsMax) + j;
+ _isMatch[complexState].Init();
+ _isRep0Long[complexState].Init();
+ }
+ _isRep[i].Init();
+ _isRepG0[i].Init();
+ _isRepG1[i].Init();
+ _isRepG2[i].Init();
+ }
+ _literalEncoder.Init();
+ for (i = 0; i < Base.kNumLenToPosStates; i++)
+ _posSlotEncoder[i].Init();
+ for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++)
+ _posEncoders[i].Init();
+
+ _lenEncoder.Init((UInt32)1 << _posStateBits);
+ _repMatchLenEncoder.Init((UInt32)1 << _posStateBits);
+
+ _posAlignEncoder.Init();
+
+ _longestMatchWasFound = false;
+ _optimumEndIndex = 0;
+ _optimumCurrentIndex = 0;
+ _additionalOffset = 0;
+ }
+
+ void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs)
+ {
+ lenRes = 0;
+ numDistancePairs = _matchFinder.GetMatches(_matchDistances);
+ if (numDistancePairs > 0)
+ {
+ lenRes = _matchDistances[numDistancePairs - 2];
+ if (lenRes == _numFastBytes)
+ lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1],
+ Base.kMatchMaxLen - lenRes);
+ }
+ _additionalOffset++;
+ }
+
+
+ void MovePos(UInt32 num)
+ {
+ if (num > 0)
+ {
+ _matchFinder.Skip(num);
+ _additionalOffset += num;
+ }
+ }
+
+ UInt32 GetRepLen1Price(Base.State state, UInt32 posState)
+ {
+ return _isRepG0[state.Index].GetPrice0() +
+ _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0();
+ }
+
+ UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState)
+ {
+ UInt32 price;
+ if (repIndex == 0)
+ {
+ price = _isRepG0[state.Index].GetPrice0();
+ price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+ }
+ else
+ {
+ price = _isRepG0[state.Index].GetPrice1();
+ if (repIndex == 1)
+ price += _isRepG1[state.Index].GetPrice0();
+ else
+ {
+ price += _isRepG1[state.Index].GetPrice1();
+ price += _isRepG2[state.Index].GetPrice(repIndex - 2);
+ }
+ }
+ return price;
+ }
+
+ UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState)
+ {
+ UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
+ return price + GetPureRepPrice(repIndex, state, posState);
+ }
+
+ UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState)
+ {
+ UInt32 price;
+ UInt32 lenToPosState = Base.GetLenToPosState(len);
+ if (pos < Base.kNumFullDistances)
+ price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos];
+ else
+ price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] +
+ _alignPrices[pos & Base.kAlignMask];
+ return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState);
+ }
+
+ UInt32 Backward(out UInt32 backRes, UInt32 cur)
+ {
+ _optimumEndIndex = cur;
+ UInt32 posMem = _optimum[cur].PosPrev;
+ UInt32 backMem = _optimum[cur].BackPrev;
+ do
+ {
+ if (_optimum[cur].Prev1IsChar)
+ {
+ _optimum[posMem].MakeAsChar();
+ _optimum[posMem].PosPrev = posMem - 1;
+ if (_optimum[cur].Prev2)
+ {
+ _optimum[posMem - 1].Prev1IsChar = false;
+ _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2;
+ _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2;
+ }
+ }
+ UInt32 posPrev = posMem;
+ UInt32 backCur = backMem;
+
+ backMem = _optimum[posPrev].BackPrev;
+ posMem = _optimum[posPrev].PosPrev;
+
+ _optimum[posPrev].BackPrev = backCur;
+ _optimum[posPrev].PosPrev = cur;
+ cur = posPrev;
+ }
+ while (cur > 0);
+ backRes = _optimum[0].BackPrev;
+ _optimumCurrentIndex = _optimum[0].PosPrev;
+ return _optimumCurrentIndex;
+ }
+
+ UInt32[] reps = new UInt32[Base.kNumRepDistances];
+ UInt32[] repLens = new UInt32[Base.kNumRepDistances];
+
+
+ UInt32 GetOptimum(UInt32 position, out UInt32 backRes)
+ {
+ if (_optimumEndIndex != _optimumCurrentIndex)
+ {
+ UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex;
+ backRes = _optimum[_optimumCurrentIndex].BackPrev;
+ _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev;
+ return lenRes;
+ }
+ _optimumCurrentIndex = _optimumEndIndex = 0;
+
+ UInt32 lenMain, numDistancePairs;
+ if (!_longestMatchWasFound)
+ {
+ ReadMatchDistances(out lenMain, out numDistancePairs);
+ }
+ else
+ {
+ lenMain = _longestMatchLength;
+ numDistancePairs = _numDistancePairs;
+ _longestMatchWasFound = false;
+ }
+
+ UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1;
+ if (numAvailableBytes < 2)
+ {
+ backRes = 0xFFFFFFFF;
+ return 1;
+ }
+ if (numAvailableBytes > Base.kMatchMaxLen)
+ numAvailableBytes = Base.kMatchMaxLen;
+
+ UInt32 repMaxIndex = 0;
+ UInt32 i;
+ for (i = 0; i < Base.kNumRepDistances; i++)
+ {
+ reps[i] = _repDistances[i];
+ repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen);
+ if (repLens[i] > repLens[repMaxIndex])
+ repMaxIndex = i;
+ }
+ if (repLens[repMaxIndex] >= _numFastBytes)
+ {
+ backRes = repMaxIndex;
+ UInt32 lenRes = repLens[repMaxIndex];
+ MovePos(lenRes - 1);
+ return lenRes;
+ }
+
+ if (lenMain >= _numFastBytes)
+ {
+ backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances;
+ MovePos(lenMain - 1);
+ return lenMain;
+ }
+
+ Byte currentByte = _matchFinder.GetIndexByte(0 - 1);
+ Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1));
+
+ if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
+ {
+ backRes = (UInt32)0xFFFFFFFF;
+ return 1;
+ }
+
+ _optimum[0].State = _state;
+
+ UInt32 posState = (position & _posStateMask);
+
+ _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
+ _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte);
+ _optimum[1].MakeAsChar();
+
+ UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+ UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1();
+
+ if (matchByte == currentByte)
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState);
+ if (shortRepPrice < _optimum[1].Price)
+ {
+ _optimum[1].Price = shortRepPrice;
+ _optimum[1].MakeAsShortRep();
+ }
+ }
+
+ UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
+
+ if(lenEnd < 2)
+ {
+ backRes = _optimum[1].BackPrev;
+ return 1;
+ }
+
+ _optimum[1].PosPrev = 0;
+
+ _optimum[0].Backs0 = reps[0];
+ _optimum[0].Backs1 = reps[1];
+ _optimum[0].Backs2 = reps[2];
+ _optimum[0].Backs3 = reps[3];
+
+ UInt32 len = lenEnd;
+ do
+ _optimum[len--].Price = kIfinityPrice;
+ while (len >= 2);
+
+ for (i = 0; i < Base.kNumRepDistances; i++)
+ {
+ UInt32 repLen = repLens[i];
+ if (repLen < 2)
+ continue;
+ UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState);
+ do
+ {
+ UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState);
+ Optimal optimum = _optimum[repLen];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = 0;
+ optimum.BackPrev = i;
+ optimum.Prev1IsChar = false;
+ }
+ }
+ while (--repLen >= 2);
+ }
+
+ UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0();
+
+ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+ if (len <= lenMain)
+ {
+ UInt32 offs = 0;
+ while (len > _matchDistances[offs])
+ offs += 2;
+ for (; ; len++)
+ {
+ UInt32 distance = _matchDistances[offs + 1];
+ UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState);
+ Optimal optimum = _optimum[len];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = 0;
+ optimum.BackPrev = distance + Base.kNumRepDistances;
+ optimum.Prev1IsChar = false;
+ }
+ if (len == _matchDistances[offs])
+ {
+ offs += 2;
+ if (offs == numDistancePairs)
+ break;
+ }
+ }
+ }
+
+ UInt32 cur = 0;
+
+ while (true)
+ {
+ cur++;
+ if (cur == lenEnd)
+ return Backward(out backRes, cur);
+ UInt32 newLen;
+ ReadMatchDistances(out newLen, out numDistancePairs);
+ if (newLen >= _numFastBytes)
+ {
+ _numDistancePairs = numDistancePairs;
+ _longestMatchLength = newLen;
+ _longestMatchWasFound = true;
+ return Backward(out backRes, cur);
+ }
+ position++;
+ UInt32 posPrev = _optimum[cur].PosPrev;
+ Base.State state;
+ if (_optimum[cur].Prev1IsChar)
+ {
+ posPrev--;
+ if (_optimum[cur].Prev2)
+ {
+ state = _optimum[_optimum[cur].PosPrev2].State;
+ if (_optimum[cur].BackPrev2 < Base.kNumRepDistances)
+ state.UpdateRep();
+ else
+ state.UpdateMatch();
+ }
+ else
+ state = _optimum[posPrev].State;
+ state.UpdateChar();
+ }
+ else
+ state = _optimum[posPrev].State;
+ if (posPrev == cur - 1)
+ {
+ if (_optimum[cur].IsShortRep())
+ state.UpdateShortRep();
+ else
+ state.UpdateChar();
+ }
+ else
+ {
+ UInt32 pos;
+ if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2)
+ {
+ posPrev = _optimum[cur].PosPrev2;
+ pos = _optimum[cur].BackPrev2;
+ state.UpdateRep();
+ }
+ else
+ {
+ pos = _optimum[cur].BackPrev;
+ if (pos < Base.kNumRepDistances)
+ state.UpdateRep();
+ else
+ state.UpdateMatch();
+ }
+ Optimal opt = _optimum[posPrev];
+ if (pos < Base.kNumRepDistances)
+ {
+ if (pos == 0)
+ {
+ reps[0] = opt.Backs0;
+ reps[1] = opt.Backs1;
+ reps[2] = opt.Backs2;
+ reps[3] = opt.Backs3;
+ }
+ else if (pos == 1)
+ {
+ reps[0] = opt.Backs1;
+ reps[1] = opt.Backs0;
+ reps[2] = opt.Backs2;
+ reps[3] = opt.Backs3;
+ }
+ else if (pos == 2)
+ {
+ reps[0] = opt.Backs2;
+ reps[1] = opt.Backs0;
+ reps[2] = opt.Backs1;
+ reps[3] = opt.Backs3;
+ }
+ else
+ {
+ reps[0] = opt.Backs3;
+ reps[1] = opt.Backs0;
+ reps[2] = opt.Backs1;
+ reps[3] = opt.Backs2;
+ }
+ }
+ else
+ {
+ reps[0] = (pos - Base.kNumRepDistances);
+ reps[1] = opt.Backs0;
+ reps[2] = opt.Backs1;
+ reps[3] = opt.Backs2;
+ }
+ }
+ _optimum[cur].State = state;
+ _optimum[cur].Backs0 = reps[0];
+ _optimum[cur].Backs1 = reps[1];
+ _optimum[cur].Backs2 = reps[2];
+ _optimum[cur].Backs3 = reps[3];
+ UInt32 curPrice = _optimum[cur].Price;
+
+ currentByte = _matchFinder.GetIndexByte(0 - 1);
+ matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1));
+
+ posState = (position & _posStateMask);
+
+ UInt32 curAnd1Price = curPrice +
+ _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() +
+ _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)).
+ GetPrice(!state.IsCharState(), matchByte, currentByte);
+
+ Optimal nextOptimum = _optimum[cur + 1];
+
+ bool nextIsChar = false;
+ if (curAnd1Price < nextOptimum.Price)
+ {
+ nextOptimum.Price = curAnd1Price;
+ nextOptimum.PosPrev = cur;
+ nextOptimum.MakeAsChar();
+ nextIsChar = true;
+ }
+
+ matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1();
+ repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1();
+
+ if (matchByte == currentByte &&
+ !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0))
+ {
+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState);
+ if (shortRepPrice <= nextOptimum.Price)
+ {
+ nextOptimum.Price = shortRepPrice;
+ nextOptimum.PosPrev = cur;
+ nextOptimum.MakeAsShortRep();
+ nextIsChar = true;
+ }
+ }
+
+ UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1;
+ numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull);
+ numAvailableBytes = numAvailableBytesFull;
+
+ if (numAvailableBytes < 2)
+ continue;
+ if (numAvailableBytes > _numFastBytes)
+ numAvailableBytes = _numFastBytes;
+ if (!nextIsChar && matchByte != currentByte)
+ {
+ // try Literal + rep0
+ UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes);
+ UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t);
+ if (lenTest2 >= 2)
+ {
+ Base.State state2 = state;
+ state2.UpdateChar();
+ UInt32 posStateNext = (position + 1) & _posStateMask;
+ UInt32 nextRepMatchPrice = curAnd1Price +
+ _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() +
+ _isRep[state2.Index].GetPrice1();
+ {
+ UInt32 offset = cur + 1 + lenTest2;
+ while (lenEnd < offset)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(
+ 0, lenTest2, state2, posStateNext);
+ Optimal optimum = _optimum[offset];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = false;
+ }
+ }
+ }
+ }
+
+ UInt32 startLen = 2; // speed optimization
+
+ for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++)
+ {
+ UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes);
+ if (lenTest < 2)
+ continue;
+ UInt32 lenTestTemp = lenTest;
+ do
+ {
+ while (lenEnd < cur + lenTest)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState);
+ Optimal optimum = _optimum[cur + lenTest];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur;
+ optimum.BackPrev = repIndex;
+ optimum.Prev1IsChar = false;
+ }
+ }
+ while(--lenTest >= 2);
+ lenTest = lenTestTemp;
+
+ if (repIndex == 0)
+ startLen = lenTest + 1;
+
+ // if (_maxMode)
+ if (lenTest < numAvailableBytesFull)
+ {
+ UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
+ UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t);
+ if (lenTest2 >= 2)
+ {
+ Base.State state2 = state;
+ state2.UpdateRep();
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;
+ UInt32 curAndLenCharPrice =
+ repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) +
+ _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
+ _literalEncoder.GetSubCoder(position + lenTest,
+ _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true,
+ _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))),
+ _matchFinder.GetIndexByte((Int32)lenTest - 1));
+ state2.UpdateChar();
+ posStateNext = (position + lenTest + 1) & _posStateMask;
+ UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
+ UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+
+ // for(; lenTest2 >= 2; lenTest2--)
+ {
+ UInt32 offset = lenTest + 1 + lenTest2;
+ while(lenEnd < cur + offset)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+ Optimal optimum = _optimum[cur + offset];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + lenTest + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = true;
+ optimum.PosPrev2 = cur;
+ optimum.BackPrev2 = repIndex;
+ }
+ }
+ }
+ }
+ }
+
+ if (newLen > numAvailableBytes)
+ {
+ newLen = numAvailableBytes;
+ for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ;
+ _matchDistances[numDistancePairs] = newLen;
+ numDistancePairs += 2;
+ }
+ if (newLen >= startLen)
+ {
+ normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0();
+ while (lenEnd < cur + newLen)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+
+ UInt32 offs = 0;
+ while (startLen > _matchDistances[offs])
+ offs += 2;
+
+ for (UInt32 lenTest = startLen; ; lenTest++)
+ {
+ UInt32 curBack = _matchDistances[offs + 1];
+ UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState);
+ Optimal optimum = _optimum[cur + lenTest];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur;
+ optimum.BackPrev = curBack + Base.kNumRepDistances;
+ optimum.Prev1IsChar = false;
+ }
+
+ if (lenTest == _matchDistances[offs])
+ {
+ if (lenTest < numAvailableBytesFull)
+ {
+ UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes);
+ UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t);
+ if (lenTest2 >= 2)
+ {
+ Base.State state2 = state;
+ state2.UpdateMatch();
+ UInt32 posStateNext = (position + lenTest) & _posStateMask;
+ UInt32 curAndLenCharPrice = curAndLenPrice +
+ _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() +
+ _literalEncoder.GetSubCoder(position + lenTest,
+ _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).
+ GetPrice(true,
+ _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1),
+ _matchFinder.GetIndexByte((Int32)lenTest - 1));
+ state2.UpdateChar();
+ posStateNext = (position + lenTest + 1) & _posStateMask;
+ UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1();
+ UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1();
+
+ UInt32 offset = lenTest + 1 + lenTest2;
+ while (lenEnd < cur + offset)
+ _optimum[++lenEnd].Price = kIfinityPrice;
+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext);
+ optimum = _optimum[cur + offset];
+ if (curAndLenPrice < optimum.Price)
+ {
+ optimum.Price = curAndLenPrice;
+ optimum.PosPrev = cur + lenTest + 1;
+ optimum.BackPrev = 0;
+ optimum.Prev1IsChar = true;
+ optimum.Prev2 = true;
+ optimum.PosPrev2 = cur;
+ optimum.BackPrev2 = curBack + Base.kNumRepDistances;
+ }
+ }
+ }
+ offs += 2;
+ if (offs == numDistancePairs)
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ bool ChangePair(UInt32 smallDist, UInt32 bigDist)
+ {
+ const int kDif = 7;
+ return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif));
+ }
+
+ void WriteEndMarker(UInt32 posState)
+ {
+ if (!_writeEndMark)
+ return;
+
+ _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1);
+ _isRep[_state.Index].Encode(_rangeEncoder, 0);
+ _state.UpdateMatch();
+ UInt32 len = Base.kMatchMinLen;
+ _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+ UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1;
+ UInt32 lenToPosState = Base.GetLenToPosState(len);
+ _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
+ int footerBits = 30;
+ UInt32 posReduced = (((UInt32)1) << footerBits) - 1;
+ _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
+ _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
+ }
+
+ void Flush(UInt32 nowPos)
+ {
+ ReleaseMFStream();
+ WriteEndMarker(nowPos & _posStateMask);
+ _rangeEncoder.FlushData();
+ _rangeEncoder.FlushStream();
+ }
+
+ public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished)
+ {
+ inSize = 0;
+ outSize = 0;
+ finished = true;
+
+ if (_inStream != null)
+ {
+ _matchFinder.SetStream(_inStream);
+ _matchFinder.Init();
+ _needReleaseMFStream = true;
+ _inStream = null;
+ if (_trainSize > 0)
+ _matchFinder.Skip(_trainSize);
+ }
+
+ if (_finished)
+ return;
+ _finished = true;
+
+
+ Int64 progressPosValuePrev = nowPos64;
+ if (nowPos64 == 0)
+ {
+ if (_matchFinder.GetNumAvailableBytes() == 0)
+ {
+ Flush((UInt32)nowPos64);
+ return;
+ }
+ UInt32 len, numDistancePairs; // it's not used
+ ReadMatchDistances(out len, out numDistancePairs);
+ UInt32 posState = (UInt32)(nowPos64) & _posStateMask;
+ _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0);
+ _state.UpdateChar();
+ Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
+ _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte);
+ _previousByte = curByte;
+ _additionalOffset--;
+ nowPos64++;
+ }
+ if (_matchFinder.GetNumAvailableBytes() == 0)
+ {
+ Flush((UInt32)nowPos64);
+ return;
+ }
+ while (true)
+ {
+ UInt32 pos;
+ UInt32 len = GetOptimum((UInt32)nowPos64, out pos);
+
+ UInt32 posState = ((UInt32)nowPos64) & _posStateMask;
+ UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState;
+ if (len == 1 && pos == 0xFFFFFFFF)
+ {
+ _isMatch[complexState].Encode(_rangeEncoder, 0);
+ Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset));
+ LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte);
+ if (!_state.IsCharState())
+ {
+ Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset));
+ subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte);
+ }
+ else
+ subCoder.Encode(_rangeEncoder, curByte);
+ _previousByte = curByte;
+ _state.UpdateChar();
+ }
+ else
+ {
+ _isMatch[complexState].Encode(_rangeEncoder, 1);
+ if (pos < Base.kNumRepDistances)
+ {
+ _isRep[_state.Index].Encode(_rangeEncoder, 1);
+ if (pos == 0)
+ {
+ _isRepG0[_state.Index].Encode(_rangeEncoder, 0);
+ if (len == 1)
+ _isRep0Long[complexState].Encode(_rangeEncoder, 0);
+ else
+ _isRep0Long[complexState].Encode(_rangeEncoder, 1);
+ }
+ else
+ {
+ _isRepG0[_state.Index].Encode(_rangeEncoder, 1);
+ if (pos == 1)
+ _isRepG1[_state.Index].Encode(_rangeEncoder, 0);
+ else
+ {
+ _isRepG1[_state.Index].Encode(_rangeEncoder, 1);
+ _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2);
+ }
+ }
+ if (len == 1)
+ _state.UpdateShortRep();
+ else
+ {
+ _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+ _state.UpdateRep();
+ }
+ UInt32 distance = _repDistances[pos];
+ if (pos != 0)
+ {
+ for (UInt32 i = pos; i >= 1; i--)
+ _repDistances[i] = _repDistances[i - 1];
+ _repDistances[0] = distance;
+ }
+ }
+ else
+ {
+ _isRep[_state.Index].Encode(_rangeEncoder, 0);
+ _state.UpdateMatch();
+ _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState);
+ pos -= Base.kNumRepDistances;
+ UInt32 posSlot = GetPosSlot(pos);
+ UInt32 lenToPosState = Base.GetLenToPosState(len);
+ _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot);
+
+ if (posSlot >= Base.kStartPosModelIndex)
+ {
+ int footerBits = (int)((posSlot >> 1) - 1);
+ UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
+ UInt32 posReduced = pos - baseVal;
+
+ if (posSlot < Base.kEndPosModelIndex)
+ RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders,
+ baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced);
+ else
+ {
+ _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits);
+ _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask);
+ _alignPriceCount++;
+ }
+ }
+ UInt32 distance = pos;
+ for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--)
+ _repDistances[i] = _repDistances[i - 1];
+ _repDistances[0] = distance;
+ _matchPriceCount++;
+ }
+ _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset));
+ }
+ _additionalOffset -= len;
+ nowPos64 += len;
+ if (_additionalOffset == 0)
+ {
+ // if (!_fastMode)
+ if (_matchPriceCount >= (1 << 7))
+ FillDistancesPrices();
+ if (_alignPriceCount >= Base.kAlignTableSize)
+ FillAlignPrices();
+ inSize = nowPos64;
+ outSize = _rangeEncoder.GetProcessedSizeAdd();
+ if (_matchFinder.GetNumAvailableBytes() == 0)
+ {
+ Flush((UInt32)nowPos64);
+ return;
+ }
+
+ if (nowPos64 - progressPosValuePrev >= (1 << 12))
+ {
+ _finished = false;
+ finished = false;
+ return;
+ }
+ }
+ }
+ }
+
+ void ReleaseMFStream()
+ {
+ if (_matchFinder != null && _needReleaseMFStream)
+ {
+ _matchFinder.ReleaseStream();
+ _needReleaseMFStream = false;
+ }
+ }
+
+ void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); }
+ void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); }
+
+ void ReleaseStreams()
+ {
+ ReleaseMFStream();
+ ReleaseOutStream();
+ }
+
+ void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream,
+ Int64 inSize, Int64 outSize)
+ {
+ _inStream = inStream;
+ _finished = false;
+ Create();
+ SetOutStream(outStream);
+ Init();
+
+ // if (!_fastMode)
+ {
+ FillDistancesPrices();
+ FillAlignPrices();
+ }
+
+ _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
+ _lenEncoder.UpdateTables((UInt32)1 << _posStateBits);
+ _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen);
+ _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits);
+
+ nowPos64 = 0;
+ }
+
+
+ public void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+ Int64 inSize, Int64 outSize, ICodeProgress progress)
+ {
+ _needReleaseMFStream = false;
+ try
+ {
+ SetStreams(inStream, outStream, inSize, outSize);
+ while (true)
+ {
+ Int64 processedInSize;
+ Int64 processedOutSize;
+ bool finished;
+ CodeOneBlock(out processedInSize, out processedOutSize, out finished);
+ if (finished)
+ return;
+ if (progress != null)
+ {
+ progress.SetProgress(processedInSize, processedOutSize);
+ }
+ }
+ }
+ finally
+ {
+ ReleaseStreams();
+ }
+ }
+
+ const int kPropSize = 5;
+ Byte[] properties = new Byte[kPropSize];
+
+ public void WriteCoderProperties(System.IO.Stream outStream)
+ {
+ properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits);
+ for (int i = 0; i < 4; i++)
+ properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF);
+ outStream.Write(properties, 0, kPropSize);
+ }
+
+ UInt32[] tempPrices = new UInt32[Base.kNumFullDistances];
+ UInt32 _matchPriceCount;
+
+ void FillDistancesPrices()
+ {
+ for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++)
+ {
+ UInt32 posSlot = GetPosSlot(i);
+ int footerBits = (int)((posSlot >> 1) - 1);
+ UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits);
+ tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders,
+ baseVal - posSlot - 1, footerBits, i - baseVal);
+ }
+
+ for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++)
+ {
+ UInt32 posSlot;
+ RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState];
+
+ UInt32 st = (lenToPosState << Base.kNumPosSlotBits);
+ for (posSlot = 0; posSlot < _distTableSize; posSlot++)
+ _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot);
+ for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++)
+ _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits);
+
+ UInt32 st2 = lenToPosState * Base.kNumFullDistances;
+ UInt32 i;
+ for (i = 0; i < Base.kStartPosModelIndex; i++)
+ _distancesPrices[st2 + i] = _posSlotPrices[st + i];
+ for (; i < Base.kNumFullDistances; i++)
+ _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i];
+ }
+ _matchPriceCount = 0;
+ }
+
+ void FillAlignPrices()
+ {
+ for (UInt32 i = 0; i < Base.kAlignTableSize; i++)
+ _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i);
+ _alignPriceCount = 0;
+ }
+
+
+ static string[] kMatchFinderIDs =
+ {
+ "BT2",
+ "BT4",
+ };
+
+ static int FindMatchFinder(string s)
+ {
+ for (int m = 0; m < kMatchFinderIDs.Length; m++)
+ if (s == kMatchFinderIDs[m])
+ return m;
+ return -1;
+ }
+
+ public void SetCoderProperties(CoderPropID[] propIDs, object[] properties)
+ {
+ for (UInt32 i = 0; i < properties.Length; i++)
+ {
+ object prop = properties[i];
+ switch (propIDs[i])
+ {
+ case CoderPropID.NumFastBytes:
+ {
+ if (!(prop is Int32))
+ throw new InvalidParamException();
+ Int32 numFastBytes = (Int32)prop;
+ if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen)
+ throw new InvalidParamException();
+ _numFastBytes = (UInt32)numFastBytes;
+ break;
+ }
+ case CoderPropID.Algorithm:
+ {
+ /*
+ if (!(prop is Int32))
+ throw new InvalidParamException();
+ Int32 maximize = (Int32)prop;
+ _fastMode = (maximize == 0);
+ _maxMode = (maximize >= 2);
+ */
+ break;
+ }
+ case CoderPropID.MatchFinder:
+ {
+ if (!(prop is String))
+ throw new InvalidParamException();
+ EMatchFinderType matchFinderIndexPrev = _matchFinderType;
+ int m = FindMatchFinder(((string)prop).ToUpper());
+ if (m < 0)
+ throw new InvalidParamException();
+ _matchFinderType = (EMatchFinderType)m;
+ if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType)
+ {
+ _dictionarySizePrev = 0xFFFFFFFF;
+ _matchFinder = null;
+ }
+ break;
+ }
+ case CoderPropID.DictionarySize:
+ {
+ const int kDicLogSizeMaxCompress = 30;
+ if (!(prop is Int32))
+ throw new InvalidParamException(); ;
+ Int32 dictionarySize = (Int32)prop;
+ if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) ||
+ dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress))
+ throw new InvalidParamException();
+ _dictionarySize = (UInt32)dictionarySize;
+ int dicLogSize;
+ for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++)
+ if (dictionarySize <= ((UInt32)(1) << dicLogSize))
+ break;
+ _distTableSize = (UInt32)dicLogSize * 2;
+ break;
+ }
+ case CoderPropID.PosStateBits:
+ {
+ if (!(prop is Int32))
+ throw new InvalidParamException();
+ Int32 v = (Int32)prop;
+ if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax)
+ throw new InvalidParamException();
+ _posStateBits = (int)v;
+ _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1;
+ break;
+ }
+ case CoderPropID.LitPosBits:
+ {
+ if (!(prop is Int32))
+ throw new InvalidParamException();
+ Int32 v = (Int32)prop;
+ if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax)
+ throw new InvalidParamException();
+ _numLiteralPosStateBits = (int)v;
+ break;
+ }
+ case CoderPropID.LitContextBits:
+ {
+ if (!(prop is Int32))
+ throw new InvalidParamException();
+ Int32 v = (Int32)prop;
+ if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax)
+ throw new InvalidParamException(); ;
+ _numLiteralContextBits = (int)v;
+ break;
+ }
+ case CoderPropID.EndMarker:
+ {
+ if (!(prop is Boolean))
+ throw new InvalidParamException();
+ SetWriteEndMarkerMode((Boolean)prop);
+ break;
+ }
+ default:
+ throw new InvalidParamException();
+ }
+ }
+ }
+
+ uint _trainSize = 0;
+ public void SetTrainSize(uint trainSize)
+ {
+ _trainSize = trainSize;
+ }
+
+ }
+}
diff --git a/Unity Studio/7zip/Compress/RangeCoder/RangeCoder.cs b/Unity Studio/7zip/Compress/RangeCoder/RangeCoder.cs
new file mode 100644
index 00000000..949c6bbe
--- /dev/null
+++ b/Unity Studio/7zip/Compress/RangeCoder/RangeCoder.cs
@@ -0,0 +1,234 @@
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+ class Encoder
+ {
+ public const uint kTopValue = (1 << 24);
+
+ System.IO.Stream Stream;
+
+ public UInt64 Low;
+ public uint Range;
+ uint _cacheSize;
+ byte _cache;
+
+ long StartPosition;
+
+ public void SetStream(System.IO.Stream stream)
+ {
+ Stream = stream;
+ }
+
+ public void ReleaseStream()
+ {
+ Stream = null;
+ }
+
+ public void Init()
+ {
+ StartPosition = Stream.Position;
+
+ Low = 0;
+ Range = 0xFFFFFFFF;
+ _cacheSize = 1;
+ _cache = 0;
+ }
+
+ public void FlushData()
+ {
+ for (int i = 0; i < 5; i++)
+ ShiftLow();
+ }
+
+ public void FlushStream()
+ {
+ Stream.Flush();
+ }
+
+ public void CloseStream()
+ {
+ Stream.Close();
+ }
+
+ public void Encode(uint start, uint size, uint total)
+ {
+ Low += start * (Range /= total);
+ Range *= size;
+ while (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+
+ public void ShiftLow()
+ {
+ if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1)
+ {
+ byte temp = _cache;
+ do
+ {
+ Stream.WriteByte((byte)(temp + (Low >> 32)));
+ temp = 0xFF;
+ }
+ while (--_cacheSize != 0);
+ _cache = (byte)(((uint)Low) >> 24);
+ }
+ _cacheSize++;
+ Low = ((uint)Low) << 8;
+ }
+
+ public void EncodeDirectBits(uint v, int numTotalBits)
+ {
+ for (int i = numTotalBits - 1; i >= 0; i--)
+ {
+ Range >>= 1;
+ if (((v >> i) & 1) == 1)
+ Low += Range;
+ if (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+ }
+
+ public void EncodeBit(uint size0, int numTotalBits, uint symbol)
+ {
+ uint newBound = (Range >> numTotalBits) * size0;
+ if (symbol == 0)
+ Range = newBound;
+ else
+ {
+ Low += newBound;
+ Range -= newBound;
+ }
+ while (Range < kTopValue)
+ {
+ Range <<= 8;
+ ShiftLow();
+ }
+ }
+
+ public long GetProcessedSizeAdd()
+ {
+ return _cacheSize +
+ Stream.Position - StartPosition + 4;
+ // (long)Stream.GetProcessedSize();
+ }
+ }
+
+ class Decoder
+ {
+ public const uint kTopValue = (1 << 24);
+ public uint Range;
+ public uint Code;
+ // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16);
+ public System.IO.Stream Stream;
+
+ public void Init(System.IO.Stream stream)
+ {
+ // Stream.Init(stream);
+ Stream = stream;
+
+ Code = 0;
+ Range = 0xFFFFFFFF;
+ for (int i = 0; i < 5; i++)
+ Code = (Code << 8) | (byte)Stream.ReadByte();
+ }
+
+ public void ReleaseStream()
+ {
+ // Stream.ReleaseStream();
+ Stream = null;
+ }
+
+ public void CloseStream()
+ {
+ Stream.Close();
+ }
+
+ public void Normalize()
+ {
+ while (Range < kTopValue)
+ {
+ Code = (Code << 8) | (byte)Stream.ReadByte();
+ Range <<= 8;
+ }
+ }
+
+ public void Normalize2()
+ {
+ if (Range < kTopValue)
+ {
+ Code = (Code << 8) | (byte)Stream.ReadByte();
+ Range <<= 8;
+ }
+ }
+
+ public uint GetThreshold(uint total)
+ {
+ return Code / (Range /= total);
+ }
+
+ public void Decode(uint start, uint size, uint total)
+ {
+ Code -= start * Range;
+ Range *= size;
+ Normalize();
+ }
+
+ public uint DecodeDirectBits(int numTotalBits)
+ {
+ uint range = Range;
+ uint code = Code;
+ uint result = 0;
+ for (int i = numTotalBits; i > 0; i--)
+ {
+ range >>= 1;
+ /*
+ result <<= 1;
+ if (code >= range)
+ {
+ code -= range;
+ result |= 1;
+ }
+ */
+ uint t = (code - range) >> 31;
+ code -= range & (t - 1);
+ result = (result << 1) | (1 - t);
+
+ if (range < kTopValue)
+ {
+ code = (code << 8) | (byte)Stream.ReadByte();
+ range <<= 8;
+ }
+ }
+ Range = range;
+ Code = code;
+ return result;
+ }
+
+ public uint DecodeBit(uint size0, int numTotalBits)
+ {
+ uint newBound = (Range >> numTotalBits) * size0;
+ uint symbol;
+ if (Code < newBound)
+ {
+ symbol = 0;
+ Range = newBound;
+ }
+ else
+ {
+ symbol = 1;
+ Code -= newBound;
+ Range -= newBound;
+ }
+ Normalize();
+ return symbol;
+ }
+
+ // ulong GetProcessedSize() {return Stream.GetProcessedSize(); }
+ }
+}
diff --git a/Unity Studio/7zip/Compress/RangeCoder/RangeCoderBit.cs b/Unity Studio/7zip/Compress/RangeCoder/RangeCoderBit.cs
new file mode 100644
index 00000000..4f0346d1
--- /dev/null
+++ b/Unity Studio/7zip/Compress/RangeCoder/RangeCoderBit.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+ struct BitEncoder
+ {
+ public const int kNumBitModelTotalBits = 11;
+ public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
+ const int kNumMoveBits = 5;
+ const int kNumMoveReducingBits = 2;
+ public const int kNumBitPriceShiftBits = 6;
+
+ uint Prob;
+
+ public void Init() { Prob = kBitModelTotal >> 1; }
+
+ public void UpdateModel(uint symbol)
+ {
+ if (symbol == 0)
+ Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+ else
+ Prob -= (Prob) >> kNumMoveBits;
+ }
+
+ public void Encode(Encoder encoder, uint symbol)
+ {
+ // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol);
+ // UpdateModel(symbol);
+ uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob;
+ if (symbol == 0)
+ {
+ encoder.Range = newBound;
+ Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+ }
+ else
+ {
+ encoder.Low += newBound;
+ encoder.Range -= newBound;
+ Prob -= (Prob) >> kNumMoveBits;
+ }
+ if (encoder.Range < Encoder.kTopValue)
+ {
+ encoder.Range <<= 8;
+ encoder.ShiftLow();
+ }
+ }
+
+ private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits];
+
+ static BitEncoder()
+ {
+ const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits);
+ for (int i = kNumBits - 1; i >= 0; i--)
+ {
+ UInt32 start = (UInt32)1 << (kNumBits - i - 1);
+ UInt32 end = (UInt32)1 << (kNumBits - i);
+ for (UInt32 j = start; j < end; j++)
+ ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) +
+ (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1));
+ }
+ }
+
+ public uint GetPrice(uint symbol)
+ {
+ return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits];
+ }
+ public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; }
+ public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; }
+ }
+
+ struct BitDecoder
+ {
+ public const int kNumBitModelTotalBits = 11;
+ public const uint kBitModelTotal = (1 << kNumBitModelTotalBits);
+ const int kNumMoveBits = 5;
+
+ uint Prob;
+
+ public void UpdateModel(int numMoveBits, uint symbol)
+ {
+ if (symbol == 0)
+ Prob += (kBitModelTotal - Prob) >> numMoveBits;
+ else
+ Prob -= (Prob) >> numMoveBits;
+ }
+
+ public void Init() { Prob = kBitModelTotal >> 1; }
+
+ public uint Decode(RangeCoder.Decoder rangeDecoder)
+ {
+ uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob;
+ if (rangeDecoder.Code < newBound)
+ {
+ rangeDecoder.Range = newBound;
+ Prob += (kBitModelTotal - Prob) >> kNumMoveBits;
+ if (rangeDecoder.Range < Decoder.kTopValue)
+ {
+ rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
+ rangeDecoder.Range <<= 8;
+ }
+ return 0;
+ }
+ else
+ {
+ rangeDecoder.Range -= newBound;
+ rangeDecoder.Code -= newBound;
+ Prob -= (Prob) >> kNumMoveBits;
+ if (rangeDecoder.Range < Decoder.kTopValue)
+ {
+ rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte();
+ rangeDecoder.Range <<= 8;
+ }
+ return 1;
+ }
+ }
+ }
+}
diff --git a/Unity Studio/7zip/Compress/RangeCoder/RangeCoderBitTree.cs b/Unity Studio/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
new file mode 100644
index 00000000..4b4506f9
--- /dev/null
+++ b/Unity Studio/7zip/Compress/RangeCoder/RangeCoderBitTree.cs
@@ -0,0 +1,157 @@
+using System;
+
+namespace SevenZip.Compression.RangeCoder
+{
+ struct BitTreeEncoder
+ {
+ BitEncoder[] Models;
+ int NumBitLevels;
+
+ public BitTreeEncoder(int numBitLevels)
+ {
+ NumBitLevels = numBitLevels;
+ Models = new BitEncoder[1 << numBitLevels];
+ }
+
+ public void Init()
+ {
+ for (uint i = 1; i < (1 << NumBitLevels); i++)
+ Models[i].Init();
+ }
+
+ public void Encode(Encoder rangeEncoder, UInt32 symbol)
+ {
+ UInt32 m = 1;
+ for (int bitIndex = NumBitLevels; bitIndex > 0; )
+ {
+ bitIndex--;
+ UInt32 bit = (symbol >> bitIndex) & 1;
+ Models[m].Encode(rangeEncoder, bit);
+ m = (m << 1) | bit;
+ }
+ }
+
+ public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol)
+ {
+ UInt32 m = 1;
+ for (UInt32 i = 0; i < NumBitLevels; i++)
+ {
+ UInt32 bit = symbol & 1;
+ Models[m].Encode(rangeEncoder, bit);
+ m = (m << 1) | bit;
+ symbol >>= 1;
+ }
+ }
+
+ public UInt32 GetPrice(UInt32 symbol)
+ {
+ UInt32 price = 0;
+ UInt32 m = 1;
+ for (int bitIndex = NumBitLevels; bitIndex > 0; )
+ {
+ bitIndex--;
+ UInt32 bit = (symbol >> bitIndex) & 1;
+ price += Models[m].GetPrice(bit);
+ m = (m << 1) + bit;
+ }
+ return price;
+ }
+
+ public UInt32 ReverseGetPrice(UInt32 symbol)
+ {
+ UInt32 price = 0;
+ UInt32 m = 1;
+ for (int i = NumBitLevels; i > 0; i--)
+ {
+ UInt32 bit = symbol & 1;
+ symbol >>= 1;
+ price += Models[m].GetPrice(bit);
+ m = (m << 1) | bit;
+ }
+ return price;
+ }
+
+ public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex,
+ int NumBitLevels, UInt32 symbol)
+ {
+ UInt32 price = 0;
+ UInt32 m = 1;
+ for (int i = NumBitLevels; i > 0; i--)
+ {
+ UInt32 bit = symbol & 1;
+ symbol >>= 1;
+ price += Models[startIndex + m].GetPrice(bit);
+ m = (m << 1) | bit;
+ }
+ return price;
+ }
+
+ public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex,
+ Encoder rangeEncoder, int NumBitLevels, UInt32 symbol)
+ {
+ UInt32 m = 1;
+ for (int i = 0; i < NumBitLevels; i++)
+ {
+ UInt32 bit = symbol & 1;
+ Models[startIndex + m].Encode(rangeEncoder, bit);
+ m = (m << 1) | bit;
+ symbol >>= 1;
+ }
+ }
+ }
+
+ struct BitTreeDecoder
+ {
+ BitDecoder[] Models;
+ int NumBitLevels;
+
+ public BitTreeDecoder(int numBitLevels)
+ {
+ NumBitLevels = numBitLevels;
+ Models = new BitDecoder[1 << numBitLevels];
+ }
+
+ public void Init()
+ {
+ for (uint i = 1; i < (1 << NumBitLevels); i++)
+ Models[i].Init();
+ }
+
+ public uint Decode(RangeCoder.Decoder rangeDecoder)
+ {
+ uint m = 1;
+ for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--)
+ m = (m << 1) + Models[m].Decode(rangeDecoder);
+ return m - ((uint)1 << NumBitLevels);
+ }
+
+ public uint ReverseDecode(RangeCoder.Decoder rangeDecoder)
+ {
+ uint m = 1;
+ uint symbol = 0;
+ for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+ {
+ uint bit = Models[m].Decode(rangeDecoder);
+ m <<= 1;
+ m += bit;
+ symbol |= (bit << bitIndex);
+ }
+ return symbol;
+ }
+
+ public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex,
+ RangeCoder.Decoder rangeDecoder, int NumBitLevels)
+ {
+ uint m = 1;
+ uint symbol = 0;
+ for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++)
+ {
+ uint bit = Models[startIndex + m].Decode(rangeDecoder);
+ m <<= 1;
+ m += bit;
+ symbol |= (bit << bitIndex);
+ }
+ return symbol;
+ }
+ }
+}
diff --git a/Unity Studio/7zip/ICoder.cs b/Unity Studio/7zip/ICoder.cs
new file mode 100644
index 00000000..c8b95c8d
--- /dev/null
+++ b/Unity Studio/7zip/ICoder.cs
@@ -0,0 +1,157 @@
+// ICoder.h
+
+using System;
+
+namespace SevenZip
+{
+ ///
+ /// The exception that is thrown when an error in input stream occurs during decoding.
+ ///
+ class DataErrorException : ApplicationException
+ {
+ public DataErrorException(): base("Data Error") { }
+ }
+
+ ///
+ /// The exception that is thrown when the value of an argument is outside the allowable range.
+ ///
+ class InvalidParamException : ApplicationException
+ {
+ public InvalidParamException(): base("Invalid Parameter") { }
+ }
+
+ public interface ICodeProgress
+ {
+ ///
+ /// Callback progress.
+ ///
+ ///
+ /// input size. -1 if unknown.
+ ///
+ ///
+ /// output size. -1 if unknown.
+ ///
+ void SetProgress(Int64 inSize, Int64 outSize);
+ };
+
+ public interface ICoder
+ {
+ ///
+ /// Codes streams.
+ ///
+ ///
+ /// input Stream.
+ ///
+ ///
+ /// output Stream.
+ ///
+ ///
+ /// input Size. -1 if unknown.
+ ///
+ ///
+ /// output Size. -1 if unknown.
+ ///
+ ///
+ /// callback progress reference.
+ ///
+ ///
+ /// if input stream is not valid
+ ///
+ void Code(System.IO.Stream inStream, System.IO.Stream outStream,
+ Int64 inSize, Int64 outSize, ICodeProgress progress);
+ };
+
+ /*
+ public interface ICoder2
+ {
+ void Code(ISequentialInStream []inStreams,
+ const UInt64 []inSizes,
+ ISequentialOutStream []outStreams,
+ UInt64 []outSizes,
+ ICodeProgress progress);
+ };
+ */
+
+ ///
+ /// Provides the fields that represent properties idenitifiers for compressing.
+ ///
+ public enum CoderPropID
+ {
+ ///
+ /// Specifies default property.
+ ///
+ DefaultProp = 0,
+ ///
+ /// Specifies size of dictionary.
+ ///
+ DictionarySize,
+ ///
+ /// Specifies size of memory for PPM*.
+ ///
+ UsedMemorySize,
+ ///
+ /// Specifies order for PPM methods.
+ ///
+ Order,
+ ///
+ /// Specifies Block Size.
+ ///
+ BlockSize,
+ ///
+ /// Specifies number of postion state bits for LZMA (0 <= x <= 4).
+ ///
+ PosStateBits,
+ ///
+ /// Specifies number of literal context bits for LZMA (0 <= x <= 8).
+ ///
+ LitContextBits,
+ ///
+ /// Specifies number of literal position bits for LZMA (0 <= x <= 4).
+ ///
+ LitPosBits,
+ ///
+ /// Specifies number of fast bytes for LZ*.
+ ///
+ NumFastBytes,
+ ///
+ /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B".
+ ///
+ MatchFinder,
+ ///
+ /// Specifies the number of match finder cyckes.
+ ///
+ MatchFinderCycles,
+ ///
+ /// Specifies number of passes.
+ ///
+ NumPasses,
+ ///
+ /// Specifies number of algorithm.
+ ///
+ Algorithm,
+ ///
+ /// Specifies the number of threads.
+ ///
+ NumThreads,
+ ///
+ /// Specifies mode with end marker.
+ ///
+ EndMarker
+ };
+
+
+ public interface ISetCoderProperties
+ {
+ void SetCoderProperties(CoderPropID[] propIDs, object[] properties);
+ };
+
+ public interface IWriteCoderProperties
+ {
+ void WriteCoderProperties(System.IO.Stream outStream);
+ }
+
+ public interface ISetDecoderProperties
+ {
+ void SetDecoderProperties(byte[] properties);
+ }
+}
diff --git a/Unity Studio/7zip/SevenZipHelper.cs b/Unity Studio/7zip/SevenZipHelper.cs
new file mode 100644
index 00000000..f70fe42a
--- /dev/null
+++ b/Unity Studio/7zip/SevenZipHelper.cs
@@ -0,0 +1,126 @@
+using System;
+using System.IO;
+
+
+namespace SevenZip.Compression.LZMA
+{
+ public static class SevenZipHelper
+ {
+
+ static int dictionary = 1 << 23;
+
+ // static Int32 posStateBits = 2;
+ // static Int32 litContextBits = 3; // for normal files
+ // UInt32 litContextBits = 0; // for 32-bit data
+ // static Int32 litPosBits = 0;
+ // UInt32 litPosBits = 2; // for 32-bit data
+ // static Int32 algorithm = 2;
+ // static Int32 numFastBytes = 128;
+
+ static bool eos = false;
+
+
+
+
+
+ static CoderPropID[] propIDs =
+ {
+ CoderPropID.DictionarySize,
+ CoderPropID.PosStateBits,
+ CoderPropID.LitContextBits,
+ CoderPropID.LitPosBits,
+ CoderPropID.Algorithm,
+ CoderPropID.NumFastBytes,
+ CoderPropID.MatchFinder,
+ CoderPropID.EndMarker
+ };
+
+ // these are the default properties, keeping it simple for now:
+ static object[] properties =
+ {
+ (Int32)(dictionary),
+ (Int32)(2),
+ (Int32)(3),
+ (Int32)(0),
+ (Int32)(2),
+ (Int32)(128),
+ "bt4",
+ eos
+ };
+
+
+ public static byte[] Compress(byte[] inputBytes)
+ {
+
+ MemoryStream inStream = new MemoryStream(inputBytes);
+ MemoryStream outStream = new MemoryStream();
+ SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
+ encoder.SetCoderProperties(propIDs, properties);
+ encoder.WriteCoderProperties(outStream);
+ long fileSize = inStream.Length;
+ for (int i = 0; i < 8; i++)
+ outStream.WriteByte((Byte)(fileSize >> (8 * i)));
+ encoder.Code(inStream, outStream, -1, -1, null);
+ return outStream.ToArray();
+ }
+
+ public static byte[] Decompress(byte[] inputBytes)
+ {
+ MemoryStream newInStream = new MemoryStream(inputBytes);
+
+ SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
+
+ newInStream.Seek(0, 0);
+ MemoryStream newOutStream = new MemoryStream();
+
+ byte[] properties2 = new byte[5];
+ if (newInStream.Read(properties2, 0, 5) != 5)
+ throw (new Exception("input .lzma is too short"));
+ long outSize = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ int v = newInStream.ReadByte();
+ if (v < 0)
+ throw (new Exception("Can't Read 1"));
+ outSize |= ((long)(byte)v) << (8 * i);
+ }
+ decoder.SetDecoderProperties(properties2);
+
+ long compressedSize = newInStream.Length - newInStream.Position;
+ decoder.Code(newInStream, newOutStream, compressedSize, outSize, null);
+
+ byte[] b = newOutStream.ToArray();
+
+ return b;
+ }
+
+
+ public static MemoryStream StreamDecompress(MemoryStream newInStream)
+ {
+ SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
+
+ newInStream.Seek(0, 0);
+ MemoryStream newOutStream = new MemoryStream();
+
+ byte[] properties2 = new byte[5];
+ if (newInStream.Read(properties2, 0, 5) != 5)
+ throw (new Exception("input .lzma is too short"));
+ long outSize = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ int v = newInStream.ReadByte();
+ if (v < 0)
+ throw (new Exception("Can't Read 1"));
+ outSize |= ((long)(byte)v) << (8 * i);
+ }
+ decoder.SetDecoderProperties(properties2);
+
+ long compressedSize = newInStream.Length - newInStream.Position;
+ decoder.Code(newInStream, newOutStream, compressedSize, outSize, null);
+
+ newOutStream.Position = 0;
+ return newOutStream;
+ }
+
+ }
+}
diff --git a/Unity Studio/AboutBox.Designer.cs b/Unity Studio/AboutBox.Designer.cs
new file mode 100644
index 00000000..66a2df47
--- /dev/null
+++ b/Unity Studio/AboutBox.Designer.cs
@@ -0,0 +1,188 @@
+namespace Unity_Studio
+{
+ partial class AboutBox
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox));
+ this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
+ this.logoPictureBox = new System.Windows.Forms.PictureBox();
+ this.labelProductName = new System.Windows.Forms.Label();
+ this.labelVersion = new System.Windows.Forms.Label();
+ this.labelCopyright = new System.Windows.Forms.Label();
+ this.labelCompanyName = new System.Windows.Forms.Label();
+ this.textBoxDescription = new System.Windows.Forms.TextBox();
+ this.okButton = new System.Windows.Forms.Button();
+ this.tableLayoutPanel.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // tableLayoutPanel
+ //
+ this.tableLayoutPanel.ColumnCount = 2;
+ this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 51.12107F));
+ this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 48.87893F));
+ this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0);
+ this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0);
+ this.tableLayoutPanel.Controls.Add(this.labelVersion, 1, 1);
+ this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 2);
+ this.tableLayoutPanel.Controls.Add(this.labelCompanyName, 1, 3);
+ this.tableLayoutPanel.Controls.Add(this.textBoxDescription, 1, 4);
+ this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5);
+ this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel.Location = new System.Drawing.Point(9, 9);
+ this.tableLayoutPanel.Name = "tableLayoutPanel";
+ this.tableLayoutPanel.RowCount = 6;
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.Size = new System.Drawing.Size(446, 264);
+ this.tableLayoutPanel.TabIndex = 0;
+ //
+ // logoPictureBox
+ //
+ this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image")));
+ this.logoPictureBox.Location = new System.Drawing.Point(3, 3);
+ this.logoPictureBox.Name = "logoPictureBox";
+ this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6);
+ this.logoPictureBox.Size = new System.Drawing.Size(221, 258);
+ this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.logoPictureBox.TabIndex = 12;
+ this.logoPictureBox.TabStop = false;
+ //
+ // labelProductName
+ //
+ this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelProductName.Location = new System.Drawing.Point(233, 0);
+ this.labelProductName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
+ this.labelProductName.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelProductName.Name = "labelProductName";
+ this.labelProductName.Size = new System.Drawing.Size(210, 17);
+ this.labelProductName.TabIndex = 19;
+ this.labelProductName.Text = "Product Name";
+ this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelVersion
+ //
+ this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelVersion.Location = new System.Drawing.Point(233, 26);
+ this.labelVersion.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
+ this.labelVersion.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelVersion.Name = "labelVersion";
+ this.labelVersion.Size = new System.Drawing.Size(210, 17);
+ this.labelVersion.TabIndex = 0;
+ this.labelVersion.Text = "Version";
+ this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelCopyright
+ //
+ this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelCopyright.Location = new System.Drawing.Point(233, 52);
+ this.labelCopyright.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
+ this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelCopyright.Name = "labelCopyright";
+ this.labelCopyright.Size = new System.Drawing.Size(210, 17);
+ this.labelCopyright.TabIndex = 21;
+ this.labelCopyright.Text = "Copyright";
+ this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelCompanyName
+ //
+ this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelCompanyName.Location = new System.Drawing.Point(233, 78);
+ this.labelCompanyName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
+ this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelCompanyName.Name = "labelCompanyName";
+ this.labelCompanyName.Size = new System.Drawing.Size(210, 17);
+ this.labelCompanyName.TabIndex = 22;
+ this.labelCompanyName.Text = "Company Name";
+ this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // textBoxDescription
+ //
+ this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.textBoxDescription.Location = new System.Drawing.Point(233, 107);
+ this.textBoxDescription.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
+ this.textBoxDescription.Multiline = true;
+ this.textBoxDescription.Name = "textBoxDescription";
+ this.textBoxDescription.ReadOnly = true;
+ this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.textBoxDescription.Size = new System.Drawing.Size(210, 126);
+ this.textBoxDescription.TabIndex = 23;
+ this.textBoxDescription.TabStop = false;
+ this.textBoxDescription.Text = "Description";
+ //
+ // okButton
+ //
+ this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.okButton.Location = new System.Drawing.Point(368, 239);
+ this.okButton.Name = "okButton";
+ this.okButton.Size = new System.Drawing.Size(75, 22);
+ this.okButton.TabIndex = 24;
+ this.okButton.Text = "&OK";
+ this.okButton.Click += new System.EventHandler(this.okButton_Click);
+ //
+ // AboutBox
+ //
+ this.AcceptButton = this.okButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(464, 282);
+ this.Controls.Add(this.tableLayoutPanel);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "AboutBox";
+ this.Padding = new System.Windows.Forms.Padding(9);
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "Unity Studio";
+ this.TopMost = true;
+ this.tableLayoutPanel.ResumeLayout(false);
+ this.tableLayoutPanel.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel;
+ private System.Windows.Forms.PictureBox logoPictureBox;
+ private System.Windows.Forms.Label labelProductName;
+ private System.Windows.Forms.Label labelVersion;
+ private System.Windows.Forms.Label labelCopyright;
+ private System.Windows.Forms.Label labelCompanyName;
+ private System.Windows.Forms.TextBox textBoxDescription;
+ private System.Windows.Forms.Button okButton;
+ }
+}
diff --git a/Unity Studio/AboutBox.cs b/Unity Studio/AboutBox.cs
new file mode 100644
index 00000000..4161b78b
--- /dev/null
+++ b/Unity Studio/AboutBox.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Windows.Forms;
+
+namespace Unity_Studio
+{
+ partial class AboutBox : Form
+ {
+ public AboutBox()
+ {
+ InitializeComponent();
+ this.Text = String.Format("About {0}", AssemblyTitle);
+ this.labelProductName.Text = AssemblyProduct;
+ this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion);
+ this.labelCopyright.Text = AssemblyCopyright;
+ this.labelCompanyName.Text = AssemblyCompany;
+ this.textBoxDescription.Text = AssemblyDescription;
+ }
+
+ #region Assembly Attribute Accessors
+
+ public string AssemblyTitle
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
+ if (attributes.Length > 0)
+ {
+ AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
+ if (titleAttribute.Title != "")
+ {
+ return titleAttribute.Title;
+ }
+ }
+ return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
+ }
+ }
+
+ public string AssemblyVersion
+ {
+ get
+ {
+ return Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ }
+ }
+
+ public string AssemblyDescription
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyDescriptionAttribute)attributes[0]).Description;
+ }
+ }
+
+ public string AssemblyProduct
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyProductAttribute)attributes[0]).Product;
+ }
+ }
+
+ public string AssemblyCopyright
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
+ }
+ }
+
+ public string AssemblyCompany
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyCompanyAttribute)attributes[0]).Company;
+ }
+ }
+ #endregion
+
+ private void okButton_Click(object sender, EventArgs e)
+ {
+ this.Close();
+ }
+ }
+}
diff --git a/Unity Studio/AboutBox.resx b/Unity Studio/AboutBox.resx
new file mode 100644
index 00000000..76cc9afc
--- /dev/null
+++ b/Unity Studio/AboutBox.resx
@@ -0,0 +1,603 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ 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
+
+
+
\ No newline at end of file
diff --git a/Unity Studio/AboutBox1.Designer.cs b/Unity Studio/AboutBox1.Designer.cs
new file mode 100644
index 00000000..a8a11b8e
--- /dev/null
+++ b/Unity Studio/AboutBox1.Designer.cs
@@ -0,0 +1,186 @@
+namespace Unity_Studio
+{
+ partial class AboutBox1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox1));
+ this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
+ this.logoPictureBox = new System.Windows.Forms.PictureBox();
+ this.labelProductName = new System.Windows.Forms.Label();
+ this.labelVersion = new System.Windows.Forms.Label();
+ this.labelCopyright = new System.Windows.Forms.Label();
+ this.labelCompanyName = new System.Windows.Forms.Label();
+ this.textBoxDescription = new System.Windows.Forms.TextBox();
+ this.okButton = new System.Windows.Forms.Button();
+ this.tableLayoutPanel.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // tableLayoutPanel
+ //
+ this.tableLayoutPanel.ColumnCount = 2;
+ this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 33F));
+ this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 67F));
+ this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0);
+ this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0);
+ this.tableLayoutPanel.Controls.Add(this.labelVersion, 1, 1);
+ this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 2);
+ this.tableLayoutPanel.Controls.Add(this.labelCompanyName, 1, 3);
+ this.tableLayoutPanel.Controls.Add(this.textBoxDescription, 1, 4);
+ this.tableLayoutPanel.Controls.Add(this.okButton, 1, 5);
+ this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.tableLayoutPanel.Location = new System.Drawing.Point(9, 9);
+ this.tableLayoutPanel.Name = "tableLayoutPanel";
+ this.tableLayoutPanel.RowCount = 6;
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
+ this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 10F));
+ this.tableLayoutPanel.Size = new System.Drawing.Size(417, 265);
+ this.tableLayoutPanel.TabIndex = 0;
+ //
+ // logoPictureBox
+ //
+ this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.logoPictureBox.Image = ((System.Drawing.Image)(resources.GetObject("logoPictureBox.Image")));
+ this.logoPictureBox.Location = new System.Drawing.Point(3, 3);
+ this.logoPictureBox.Name = "logoPictureBox";
+ this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 6);
+ this.logoPictureBox.Size = new System.Drawing.Size(131, 259);
+ this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
+ this.logoPictureBox.TabIndex = 12;
+ this.logoPictureBox.TabStop = false;
+ //
+ // labelProductName
+ //
+ this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelProductName.Location = new System.Drawing.Point(143, 0);
+ this.labelProductName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
+ this.labelProductName.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelProductName.Name = "labelProductName";
+ this.labelProductName.Size = new System.Drawing.Size(271, 17);
+ this.labelProductName.TabIndex = 19;
+ this.labelProductName.Text = "Product Name";
+ this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelVersion
+ //
+ this.labelVersion.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelVersion.Location = new System.Drawing.Point(143, 26);
+ this.labelVersion.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
+ this.labelVersion.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelVersion.Name = "labelVersion";
+ this.labelVersion.Size = new System.Drawing.Size(271, 17);
+ this.labelVersion.TabIndex = 0;
+ this.labelVersion.Text = "Version";
+ this.labelVersion.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelCopyright
+ //
+ this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelCopyright.Location = new System.Drawing.Point(143, 52);
+ this.labelCopyright.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
+ this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelCopyright.Name = "labelCopyright";
+ this.labelCopyright.Size = new System.Drawing.Size(271, 17);
+ this.labelCopyright.TabIndex = 21;
+ this.labelCopyright.Text = "Copyright";
+ this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // labelCompanyName
+ //
+ this.labelCompanyName.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.labelCompanyName.Location = new System.Drawing.Point(143, 78);
+ this.labelCompanyName.Margin = new System.Windows.Forms.Padding(6, 0, 3, 0);
+ this.labelCompanyName.MaximumSize = new System.Drawing.Size(0, 17);
+ this.labelCompanyName.Name = "labelCompanyName";
+ this.labelCompanyName.Size = new System.Drawing.Size(271, 17);
+ this.labelCompanyName.TabIndex = 22;
+ this.labelCompanyName.Text = "Company Name";
+ this.labelCompanyName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // textBoxDescription
+ //
+ this.textBoxDescription.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.textBoxDescription.Location = new System.Drawing.Point(143, 107);
+ this.textBoxDescription.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
+ this.textBoxDescription.Multiline = true;
+ this.textBoxDescription.Name = "textBoxDescription";
+ this.textBoxDescription.ReadOnly = true;
+ this.textBoxDescription.ScrollBars = System.Windows.Forms.ScrollBars.Both;
+ this.textBoxDescription.Size = new System.Drawing.Size(271, 126);
+ this.textBoxDescription.TabIndex = 23;
+ this.textBoxDescription.TabStop = false;
+ this.textBoxDescription.Text = "Description";
+ //
+ // okButton
+ //
+ this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this.okButton.Location = new System.Drawing.Point(339, 239);
+ this.okButton.Name = "okButton";
+ this.okButton.Size = new System.Drawing.Size(75, 23);
+ this.okButton.TabIndex = 24;
+ this.okButton.Text = "&OK";
+ //
+ // AboutBox1
+ //
+ this.AcceptButton = this.okButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(435, 283);
+ this.Controls.Add(this.tableLayoutPanel);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "AboutBox1";
+ this.Padding = new System.Windows.Forms.Padding(9);
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "AboutBox1";
+ this.tableLayoutPanel.ResumeLayout(false);
+ this.tableLayoutPanel.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TableLayoutPanel tableLayoutPanel;
+ private System.Windows.Forms.PictureBox logoPictureBox;
+ private System.Windows.Forms.Label labelProductName;
+ private System.Windows.Forms.Label labelVersion;
+ private System.Windows.Forms.Label labelCopyright;
+ private System.Windows.Forms.Label labelCompanyName;
+ private System.Windows.Forms.TextBox textBoxDescription;
+ private System.Windows.Forms.Button okButton;
+ }
+}
diff --git a/Unity Studio/AboutBox1.cs b/Unity Studio/AboutBox1.cs
new file mode 100644
index 00000000..e5b1cac9
--- /dev/null
+++ b/Unity Studio/AboutBox1.cs
@@ -0,0 +1,104 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Windows.Forms;
+
+namespace Unity_Studio
+{
+ partial class AboutBox1 : Form
+ {
+ public AboutBox1()
+ {
+ InitializeComponent();
+ this.Text = String.Format("About {0}", AssemblyTitle);
+ this.labelProductName.Text = AssemblyProduct;
+ this.labelVersion.Text = String.Format("Version {0}", AssemblyVersion);
+ this.labelCopyright.Text = AssemblyCopyright;
+ this.labelCompanyName.Text = AssemblyCompany;
+ this.textBoxDescription.Text = AssemblyDescription;
+ }
+
+ #region Assembly Attribute Accessors
+
+ public string AssemblyTitle
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
+ if (attributes.Length > 0)
+ {
+ AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
+ if (titleAttribute.Title != "")
+ {
+ return titleAttribute.Title;
+ }
+ }
+ return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
+ }
+ }
+
+ public string AssemblyVersion
+ {
+ get
+ {
+ return Assembly.GetExecutingAssembly().GetName().Version.ToString();
+ }
+ }
+
+ public string AssemblyDescription
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyDescriptionAttribute)attributes[0]).Description;
+ }
+ }
+
+ public string AssemblyProduct
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyProductAttribute)attributes[0]).Product;
+ }
+ }
+
+ public string AssemblyCopyright
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
+ }
+ }
+
+ public string AssemblyCompany
+ {
+ get
+ {
+ object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
+ if (attributes.Length == 0)
+ {
+ return "";
+ }
+ return ((AssemblyCompanyAttribute)attributes[0]).Company;
+ }
+ }
+ #endregion
+ }
+}
diff --git a/Unity Studio/AboutBox1.resx b/Unity Studio/AboutBox1.resx
new file mode 100644
index 00000000..09e0c929
--- /dev/null
+++ b/Unity Studio/AboutBox1.resx
@@ -0,0 +1,607 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ iVBORw0KGgoAAAANSUhEUgAAAHgAAAEGCAIAAAAhWcaAAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+ YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAcQNJREFUeF7tfQdc
+ lFfa/ez/K/tlExUVmN7ovQ1D74Kg2BWs2CvYEVEEG0VALHTpAip2xd57jzHGmF5MsokxdbPV/XY13//c
+ 9xleX2YAMTGJZnfy/PiNiATOnDn3POXe+xtZpew3v/mNCP/9v9/85j9+g4+i/xDhyf/7z//HnvzXb0T/
+ yf7InuOvfiNij/8TiR6KRN+L/u/h/7EnDwTPv2fP2Sf/T/T9599///r3D28/nDFsRp8+fezt7f8f98D/
+ zuiBb8l+hl/3A0DLK+WKKoWyWqmsUapqVeqNanW9WrNJo23SardptTu1VnusrA9YWx+2tj5qbXPCxuYU
+ Fydt8Nz6GPd5/G2ztdUuK6vtVlZbray2WFk1WllttLKqs9LkalSjVXJ3eW5u7htvvPHnP//5r3/96/37
+ 9//3f//3H//4xz//+c8HDx48fPjwe+7xf7/ehwgoy6sMQKtqVAzoWrWmTqOp12gbtNpGrdVmDrhtVlY7
+ raz3Wlvvs7Y+aG19xJpBzEcL1ta7ra12tMJaW6vV1mjV2WrlcKXMSVZSUvLJJ5/8C8LNgCY6M5RrWlCu
+ 02g3alnUa60aOHpusmKIN7UgvodDHEQ+xIGOANZ4AfDJvdZ4SYS8ZlhXa7VVWvVStXKQUmYl27x58x//
+ +Md/KbhFQFlRbQAaXFbXMTo/QrneyooPHnEQHPpAHOcRB8oIQE9YQ0bwBS0aYsC6Uqut0KrmqxSRiqSk
+ pBMnTvBw//3vf/91i4lIUalQVilV1RydazjR2GgA+hHERnAbIQ5d3sWpSjOHMgVhjb/CmwDvho1WBqwr
+ tNoNWm2JVjVFJfeRr1q16t133xXCDeE20u5fh26LFGUKRQXDmqFcq0Fo67QsNmrbBtqU4CQp4PgOK2i0
+ AXGADugh2bQ8GmFdrtWWaTWZGuUwpcxW1tTU9Ic//AFw/+Uvf/nb3/4Gdv/61kmRYo1CuV6pKlWpylXq
+ SrWmWqOpYVgzzyAMIakfS3BICiEOYeGXR7we9QJel2m1pRy156oUYYrFixffuHEDcP/pT39qz5Y819QW
+ KXIVijyFMk+pWqNSF6o1pRpNuUYLMa1ibgH+rFOIQ0xMFRz2A5ICoKEhvBVpaI11iVZbrNXkaZQjmSdp
+ bGz85ptvvvvuO4JbKNzPuwUUKbIVyhylapVKladSr1YjNGs12vWMa0xMgTgMA2xDbec4bgQ3RAPSAROC
+ ANb88lhnxb4t9Bq8xv+oSKsp1KjmqRThiiVLlty+ffvbb7/llcR0kXweqS1SZCqUWUpVjgpYq3PV6jy1
+ Jl+jKeACiBdyb3AB4p3iuBBukm/ATSFIZ1phXajVrNeoc9TKOKXMTrZ79+6vv/66TSV5TqktUq5QqjJV
+ qiwVcgr8nppVGuRyDGsebkK8iGMfONh5gpvCDUYT1rwVEfAapMb/SLNGo0pUyf3lq1ev/uyzz6Ak5Emw
+ SD7X1OaAXqlSZ6pZZKk1ORoWBHceB/fqFoKv0QALI0l5DMGNtJvYTcFjXdOiIRDr9Qas1UvUiliFVCa9
+ dOnSV199ZUrt5y5xFwFlHmhNlsYQ2QK4TQm+joMbBG9R8CeDm/Id0hDe9pFe81hz2oUiicxRtm3bti++
+ +OJ5pzYD+hGdeaDpCcHdHsGhJ8VPoidG7AbKIDVhTbYPLxuwxsIIXuPdQ1hDRvzk69evv3fvnpDapl77
+ GV8hRYqpClU6w/oRnY3gxh87hru1fD+e3aicUPEEKFOYYr3uEdbqRWpFFDPab7311pdffskbEr4E+FzI
+ iCggIEBqJ5UHyxXDFKqZqo7gFuqJkXzz7O6MmAipTaVBfDTFGgsjmZ8CDRYP5WClVCk9f/48qA1DAq9t
+ tEI+425E1NDQUFRUlJKSMmLECD8/P7mnXBmrVE1WaZa26LURwTtgN2k30mvAjSUO1tso32kvpQTKFJTO
+ 8BoiwNog2fayffv2ff7558+djIi2b9++c+fOXdwD7rWgoGD69OlRUVFyN7myjxKlH82KthA3hbuFfcyZ
+ kPXujBEkC0hKgsATI702wnoy6yEggYTzwwpJMkIp+zNeihLt37//wIEDBw8ePHToEJ7gAco0NzeD5jNn
+ zmSIe8lRRFbNMlEVXklMrfcaY9/dKWoT4o/FeiYr+5WVlX366aeQEXIjqEaZSvYztTyKUBQ+efLkKe6B
+ J8ePHz927NiRI0cId4AOjk+cOFGmkSlCFaqxJpLSgXCTkoDaXNnkMUk8L9yENZVVSUOQNLaYEIMVmaeS
+ B8rXrFmDZk3Hkv3sYC26zD2uXLmCj8gOLly4cO7cuTNnzgB3vAY86DCzqEIMGDCAEXyYUr1A4FKMXKAw
+ q/wB1CYxwccOsVYvVOOFz87O/vjjj4WSLUwgn6nlUfTaa6/dunULH2/evPnqq6++8sor169fv3r1KnAH
+ 6FjlATqYDsSPHj0Kmq9bt27s2LEyZ5myvxIVzlYJTnuOW0ht0/qUUQGWqE3BY13Kqk6teL1ao05TKyIU
+ K1as+Oijj+7evQvnxyeQvMt+drAWocHxXsvj7bfffvPNN9GrBvTAHQXil19+GaCD6UD87NmzoDm0BYhX
+ V1djzZTZy5hFmcPBDV53RrV5Q9JBvbs9rJHI8EsungDrdDW6YkuXLr1z5w6/PPIlVn55fBZa7KLftzyg
+ d3gb4if+8MMPgfw777zDgw6mg+bXrl0DzXnEwXGs/rNmzWJw91Oq56kfYd0etcmQtFSmOlohQXOCG0+I
+ 1/hX4LUQaxRh8jXqDJbOZGRk4Cen5ZG3IsLs8RfHWgSThDcdbCme4KeE3oEaAJ9A/+CDDwA6Mf3111/n
+ ESeOQ1Wg45s2bUKnVeYiUw5Rqhe3lKWMsOZrgbyMtGn+2uzjcNxnyymwLtFqkDTyvOaxjlQsW7YMFMFP
+ zlsRah08I7wWQdeQZcEh4SOewy0BdEDPgw6mQwSJ5oQ4hIUQxxJ68eJFLJ6QlNra2smTJ8u95aoxnJII
+ jbZRWYrSSOQ1cCOPlWyCnpvFeYQ1b645oBmvoSERiszMTDBDiDVs3zOCtQgvO/9AUguBMwKdmE40FyIO
+ KccSCh2HpBDBT58+XVxcHB8fj0aJaoaqI6x5N9KmZLfHa+rLcE10VrkmXvNYY20MVeTl5QFr3vaRxX4W
+ sBbRD4EHyup4DtsPhwTo8fPxoEP1UF4gmhPipCpYSIWSAoKTnqxcuZIJ9yAlysqstE0ZjUmBm7VvqNb6
+ WJdNpOZnFvBuQJGPN9c81ilqeYC8sLDw/ffff9awFqH0RQ+MweHRJuhgOtGcEOc5TjoOSUFdDY0+GBXS
+ E/hCpPUzZsxAo4SVTdrHGotbq+Wx49a7EGtKZHixJvOer4HjlOvlVVVVHWBNnu9nzmVEtBzTAz8BHm2C
+ TjQXIg4pB8FhYIng+MWg4KQnPNww3TJrmXKgEhraHq+fAOuWl4EpO/QdkyG8CWkhNcN6hgqFmq1btxph
+ LVwbf36sRUYvrBB0nulCmgNxXlWweBLB4VVgraDg0BMjuFFFgQVUBHKq3Y6GPDHWEGtK0GH4eBPCY52n
+ UU1UocN7+PBhHmsqifyCWBsDLcTdlOY84pByIcHxa5CCG8FNYgL3jYIJmlKqESqDWJs2JGH7hBa7PQ0R
+ kpo3fPzC2CIg6Hbi/4X6NXTsGcG6I6B50NtEnBZPnuCk4KQnQrih3fCCyDBRLUHuruijYF6bB1rY/O0M
+ 1oIXwDDMBxOCTiMtjAJS43+hHKCcO3culmve8+EnpLyRGup8a+Zn0OtOAW2KOOm4EcHJpeCX4dlN2o2l
+ EskOqihwgampqTAGqiSO2tSmEWLNr41GPkRo+EyxhgnhF0Ye61yNeoVa0UuRlZVlijVfe/rZsH4yoAlx
+ IcF5rwKOkJ4Q3CQm0G5aKskI0jqJ8qbMTaYap2JAt4c19NeoQcNjLVQVEmujhZFePHxnYL1AjeI1TAhe
+ bORceKthRaHaE2FNWw5+hgT9hwAtJLjQqJAZ5+GGmABu/GJwJjCC+D2xTkJJkOOgf8bcSJzyEdBCXqMk
+ Qv5aOIfWDqlZxkiVED6LEZCabeyYppI5yNDfwP+dak9U54OD4vsyP4MJ+VFAGxGc1xOCm8wJORPKdGBL
+ YLqJ2ugqjB8/HrVWvMENAiKYjTLkMlyObpiyNEoXOyPWHKkZ1lgYpVJoF2GNFx5rCXhAfRkqhvzUWD8F
+ oNuDm18qeeGGkiBhA7VRGgS1kdfMnj1b0VvBEkgjsaYcHeLL1Z4Y1qZ5ecdiTd+QMtJVGizC6enpWCog
+ Yni98ZPg5Rcavp9arJ8a0DzcJCb8Ugm4SbhJSYyoDf+HgQ3URtSpJlij9kSdMH56uAOsTZ01CUgLqfH9
+ 5b7yyspKvMB4V0HKhEW+n8GEPGWghXCbKgkYBCXB25anNt7LYBm6JIoghSpZ1cZwJbCG/rZH6pYaiKEM
+ wjtrcnutSa2aqsLuApTRkb7y5poMn9HC+FO4vZ8EaKEz4eEmJcESBGqTasMDkCHBb45diMz2zeew5scq
+ ARYMHxZGXqz5bkBbJsTgrKnkRGUQntRcvUU5VIk0Fb4e64TQhPwMC+NPBbSRcJOS8Iskr9pkSGiFRPbI
+ ilDAGkALRlgNE8PV3DiOsPPSHtbk9ig1JwFpUWr1crUiRAF/idWYNyH8wkiFzJ9IrH9aoNtUEl61hTKC
+ 5A1Wl2ENXkNDhKQmseYFRNhRNMVa2B/gBYSUmiM1pibh9jC4gvYF1mSjhZEX66de3vs5gBYqCU9tkhFK
+ bSAjlNeAZfn5+YpgBQYbW/VhKWMkZ82T2khGhGUQ6g/w6aKA1GhHYFwCnWWkTrQwUuXaSKyfutv7mYBu
+ k9qU2pCMIK+B0QbWYBmmNZgPQWWVLzfD7VGXAAICQPnZD+re8u0uozoqantUb+JXRY7U6mVqrL1r165F
+ 6kTZOVaLnzqL+VmBJmrzJW8IolBG8KtSUoPlERMEimgFGybmsebdHjkQfn6sTax5AUG9SbgqUgsih0sX
+ bWQYyIK/FGYx5Kx/CgH5uYFuT0Yoh8S6xC+PycnJKL8JSW0oW1dyqyI/HUljTSa8NjgQvjnAr4oc0ExA
+ +ivnz5+PsiJlMbyzFrq9pyggvwDQRjJCboR3fuSy8WuDa9OmTcOZCK1I3ZIuGkhNA6hCsTZKFyHrqIEI
+ V8UWUrMUxkteU1OD1JycNdYJKjn9FG7vFwPaSEaEzo9cNrBGqxe1J7RLDFgDL6yKcCC0KgJffti3Lawf
+ FazJVpuQGntkRo8ejeYAnDU8D5Wc8Er/FALySwJtKtlUisLvyWMNHyZzl7GpM37rI+3koFWRDrfged2m
+ gMBWC1dFWL0W9cBmdNhq5EoQELi9n1RAfmGgO4M15vzkQXKDCeFJTbYaukGbM4yw5gWEXxWFuSJ5aih1
+ tobl5RqWl8PtGQkIPxDyVFKYXx5ofnkUJutGvMYIErYdMlIDaH53KU9qfseRcGE0stVYFXmrJyR1tgb2
+ BoUtoYBgQeZre8LmwI+pgTwTQJtaEdg+IdZQT0yJQFJp47Rh9wZPauHurvYcCHUGeKsnJPUsFcZ9MIhi
+ 5EAohXlaBetnBeiOsYYPwdAwjj9QzVYxoGlJ5KrVTKlpyyICMtIxqakAQolii3pgUhDTsHPmzMEcIRwI
+ 1ZtoVUT9i59QoI7XDyb1MwS0Kdb82kj+ur6+nmXnyGLQL8eSyCflEGja/Ny+WBvmQIxITZOYWRrMHGO0
+ Hic9YRic6k1UA0F5gGz1j+/CPFtAt4c1mAWswTLMQaPUyYBGRs63BSAXRtueeQERrooogJS3DDeZknqg
+ MjExEU2fjlfFH0zqZw5o07URvEYGgTwCOTrKQMxZJ6kMQHOlaqYeEA06T4s/psIE61akJk8tUA91MiM1
+ Rusx7sPbatNV8Qfnis8i0EZYU95IOToyNwzVwe3h/W7Y+M8viXQqCLCmcxNMV0Wa+gWpTZWa27SKjB+k
+ RpZEqyJf2KNcka9W/zBSP6NAm+aNhDWcAJJGtFlV8SoGdMvOUcOSKDx7RYi10OpRUk6JIu/zOKCZUjvI
+ tmzZgkEfKuyZ5oo/uF/+7AItxJrqIVRTxQIFbwBE8GZnQHM7B1iZCchyJ5UZzl5p04EQqYWeGvaDy1xo
+ exn2PmGKDHsYMF0vzBWFBZAfZj+eaaCNsKaaKrDGwoh0EXuEHm09p9IHAY3zm/jz9tpTaiqfUkeRlJoD
+ GscO4KDJPXv2mFo9vgDyw0j9rAPNY02tGeHCiNoeysqM0ZBpjCSg0AHvwZ12yLDmD8oywtqU1AKggTXG
+ 9dLS0mDbyerxBZAfSernAGgjrHmxxqwTmrlgJe2nM3gPOlaSP2yvPaXGP6HqB+/zWtQDWxRwCDP2sMLq
+ GeUvP4bUzwfQhDUVQ3ixRjkC1FMlqOjEISbTSAuhHnR+Jx0iSYejtklqlPRQOTFZEkFqvH5oXT5dUj9P
+ QFMPjBpgqIQgi4HnlXvIkSsaJsdIpun4ZToclU7rbFOpN7ROXlpkmin1CNXIkSOfLqmfG6DbE2t0ctGF
+ eQQ0J9OG81GBNU/q1qVqw7Av+TwT9UAPHskLdk4SqU3txw/w1M8T0EKsKYuBaGK9QrFJvVJtmEQgoOmw
+ ZQQEpD1SY34MyQtfO229JCr7Mp8HUsN+8J6aTxSF1Y9OlpmeM6B5sRYKCPRUGa80AM3l4uwIWqC8nxOQ
+ DkgNcRcuiUL1mMYmfXG8AHlqPlGkpiL1BJ7I5z2XQPPTqnB7SBfx1sY7HV6YOTxKW7Ae0hH5wLo9UpPP
+ w5JIWSIVTlu8B1sSfdlpkth9TYkiNRWNSnqdT16eP6CNBIRSGCg12gKGdi0BjQOs6ZB23PJApDapfjCl
+ xpLIlz5aA40y4bhx49DlouoH6lnUKUdti+rU1HzpZJnpuQTaVEBQ24T90K7lrn4g40FA0y0PROo2fR5a
+ t3yWSOl4y6lo2ISLdiI6L9jjDntDozaoU/PzY9R86SSpn2OgeQGhFIZ56ikqQ2GaHB7drgGs93Gkxmtg
+ SmosiSh98OohAJpliYHsxAScBQNSU52ab74YJS+PXRKfV6BNSY2TQzCJypZE3koD6KPcHSZ4AlKjfMod
+ QSac1aONRoatzlShFsg0aoSjRo3C5BhOEjDNyJ9oSXy+gTZaFXFgiCpFZQz0cY7XUGpUP0yTF1oSeUPd
+ 2uSxwqlGhqMBTX2esMvVGfV4joE2XRXR9EOblc5gZ9IBdT7GrkKyBtYHudth2lsSST0oc2mtHkjHoR5Y
+ EuHz+CWRpk+fSD2eb6CBNZ+XY2nC749GF7yaodxBQOOqqVM2TEPgqWlJbFM9KHOhqqnglFB4D+ysxv59
+ 4ZJIE5HoQnS+8/LcA01zwHyxCexD+c1wZwakGUDjWq8z3LVeB7gl0bTLRerBZy5GMj2TZS7YD4olkVq3
+ 1HkxyhIfqx7PPdDCVRGkBu8wZG69jbt9hwf6HMOaKTWWxDbVA96DMpc21cNTjoNHkCWi9MFniW0a6g68
+ x68EaCGpUXjD9OIjoE/b2JznAqSGz2tPPZC5UNXURKZxGC6OacXhipQlokcuNNS8enScufwagDYiNY6v
+ RZGaJd+4MA3ScdrG9ryt/Xl7RupDLephtLMc6lHJHRbZlkzjfIB+/fqhz8Aban6aiUb0qMbUsXqwo34e
+ a7af/S8QKjXe3ShTMOOBVAVAn7GxO2/ndMEJcDNP3Z56GJk8gZvGyLpMy7rjP0Y9fiVAE6mprwh+IcuA
+ S2OifJwBDTq7XnQF1mB3R+rBm7zW6yEVmHJyckg9aMLmSdVDBGV59gnbmZ+QSE3lU6xd2CdAJtrmnA0g
+ 9rjk4X7RnZGa1ENo8gSncrYr0/2U6AWTeph6D34+rwP1YED/OtSDPDX5PJQmMA7JLm6FieaA9rzk6X3Z
+ 2/mCs0E92qx7VAlkunXaoprAOrbYfiBUDxTzTDOX9sBk5979aoCmBi5NJfTt2xclUGgF/AZ0Ayj7XfED
+ 3GxJRDrenskT5uKCtEWdopaqpDgWijIXTK2js4MtkZS5UCuAr5q2+f4TUUW1M+/NZ/9rhEsiinlAh1ZC
+ t4tuvld8g64GAWvoNUvHjUwerx5CmW59iwSumcAOaqgHqldQD9NWAFVN21MIUQd/9+wja/oT8qQG+5A9
+ QzeALATa/6p/2MthoddCATrUgw00mcg0OzUIbprSFpP1EIM18+bNw1n81AowrZp2bPIY0L8y9aAlEe9r
+ tAJsDjOB9rrkBTr3ut4r8nokqM28xx5rVp42OaeJuWkUPdpKW1RxKtygApnmq6ZooWHi1DRFbFOKRU/U
+ j3kuOM4viUOGDLEtt4VA6y/rweU+1/v0e6UfnjDvgRSxTZmGm6at+ib5IcbPwsLCMJbHmzz0XIxkmu/Y
+ mgIleqJ+zHMBNK8emO61WWRDugE6D7gxYMirQ6KvRwN6ZvIg08KGCy/TtB6ijNfaeOBcRKyHuB6XN3k0
+ MCbs2HYg0+z86I6Xy+cCXOEPyRtqgKIdoYXfgG4AX6A8/LXhg24MgnowmW7PTXewHrqx69F+mEyLOlkT
+ eb7gJvWAMVD5qwAr5KLvK33jbsYl3EoA1vgjZJoNjD12PWxtPODNYWaEMk3zHiTTwj6AqUyL+JoIfrJf
+ maHGG1kql/ru9o14OQK6MfrW6Em3J417fRzEGp6P9QG4m9CM+wBYD1HGI+PRGmi0b9At27t3Ly/TnXfT
+ Ijpn71e2JPIyjeaIvkQPZIfdHDbh9oTENxOnvzl96KtDmclDHwDrocm5hWgCMONBhWlBaYkNP45WDR48
+ GDeKkZumaTHTokebqYmImoy/viWR1GP58uVeaV6g86hbo6a9OW3+2/MRY18fy2T6cDvrIZoAMB7k8IyA
+ nq4KCQnB7W1ouPBumm+4CJE0TVtEP2zu5tmXbCrm4RBUt3FuoPP418fPfmv24ncXp72XBlKHvxyOehPr
+ i3dgPEwcHu6NcnV13bFjB2Sab9di2AOHBfHnT7SXtoh+2NzNcwE0EjG0rh16O4DOU96YkvJOyor3V2R+
+ kJn8djIMNbJzlh+2CTS1tUwcHho3aP7iLJX20hZ+PTTNAUWoPwmPAun8MNkzjjWZPBR9tG7acTfHzXxz
+ Jric+2FuwZ2CjPcy4ECwHrZtPHA3Bjk8U6BRmHZjt84ZrYfY54KjxvhBU1rwjJyFqM1hsl9HmYlkGteO
+ JhxPAIvB5fUfrS/9uDT3Tu7E2xNZ2gLjYeTwKG3hKx6tcxbadYGDtbAe4u4CmqqhJgBfxiO7bLoeivjD
+ yH7MTphnk90k04MGDUrYlpD+Xjq4XPn7ytrPaks+Lpn15izk5SwRN3J4BDSGxPjSkpGVjlBgQB3roTA/
+ 5Cd66eQJ2g9gRFYR706Ei+avQ0DI5OEswZFlI3M+zCn7pGzT3U3b722v+6wu7d00pC0sEW/T4cFKtwM0
+ WWmMmArzQ+GkB2/hjIGmRZM6BeSpf8AGjWeW0QAa7/S47Lh1H60Dvrvu7Trw5YEd93YAdyTlaMG0a6Xb
+ y1nilMOHDyfjQd0WzIl1xniI+BP2nu7xFM8I9KBVSUnJwAUDK35fsfXzrYe/Onzym5MHvzxY+FHh4FcH
+ M4eH0lIHOYtJcohBBoweYOyRNx40UkNtLd5WmBafRXREp/DUt18TqQE0Skt9J/et/6x+35f7Tn97+vJ3
+ l/Gx5tMaZOSs4tEm0LXcIG9bWTjmzXr16gWgYTz4tlZnCtPsztmf4niKZ4TRkGnU6SPiIyAXx78+DpQp
+ wO7Jtyej/8JyFpOD1jE0zYZp2gQ6SYUr69G+ERamaSdzxw5PhD7YT3po0y+LOIBGIzWwTyDk4uIfLvJA
+ g90wHuhysWJpW0CzmUdk4SbSoZ6r9vLywpkhvMOjIbE2G7VCKy1Sqdzw+gg3Pf+aVkX8qrAE3kHeJBp8
+ QKlT30nF9AFLDk2vDkDzsD2gF6pdXFwIaGGj9rGlJZGr63SUuPCyGB3aROXTZ62qB+Ae+zBqAiCVcPVy
+ FaKM52D38veXY6SGTae3CTT6LFRXau2jcXWznZ0dgG7TSguHpo1yFlFQUKODQxxuVjI6uPonOgtViALe
+ OlhGMPuDsTZMJuLSWNwWglcdKQYWHH9/f3d3d3t7e41Go1QqZdwDT/BHfBJ/hS+IiIgYOHAg/glO7oeN
+ Q/sDF+Ci3AMrhd8ZKyEe+L/YOdpd+sMlYQBrpOMY82BZeFuXYbDNFm0BrVmq0Wq1WGDbrOHxzo3vafG/
+ L4De5OdXaGPTCyk87cUVnvr2tI6NxPeBB4IlwvWZOEw4Li4OMLk5OfYODUoYMmD+5HE5C+ZsyFq6rajg
+ aF355R2Ntw/tunP64L3LJ//4yvn7r1/9x5vXH779CgJP8Ed8En+FL7jd3HS5ofxoce62zEUbkqdnTx41
+ L67fmMjg3t4ebnbWSL7xP8LEbY+ePfI25TVcaDjxyYmL31xk8e3FNR+u0V/UM0bzJ4kJdgK0C/QKjUql
+ AtDt5SxGxdJWQANrnW65Wu2FoiK1DExPvufvlOrk4oZWJN4i4BcOUIPDt7HSRoUETRsVvypl7ua1ueea
+ agHTP958+ft3bvzYuH3p+1dOPbx08OHpnQ+PbX64v+bhzpKHm1f/vXr5B7mzz6aMbZwwYG6A0/hgt1AX
+ rUohjhgUMW7BuKUblqY0p+hP6bXbufMnEEZXcGHzYZuMztTI5XIAbVosBUFpG0CbySEYvZmLTR4e8xQK
+ Wwh8myffd+aEPbyYGJcCZ6dMmWKt1faLjFgwZUJl9vIzm2s/u3DsxwLawUvy1svf3zz3/bVjD883Pzy+
+ 9eHB2oe7GNYPalc+qEh7UJx8d1H8/VXj72eO/nDBgKMTwksG6mcFO0Y4y83Ev+0S2aXnqJ7ShVJVsYqu
+ dGYb6Gqt2C5PsneZXAiUGgoGrTNNDoVbEPmqtJDRTUFBWwhuF5fJuL8K8078NSWPPfkeSxPc4YYNGzBs
+ 6exgP3JAP3B2X2Xxh6cO/oTImoL+9vXvb138/vqJhxcPMGofrn+4p/zh1rUP6nMeVC29u2zc/TXTOKxH
+ 3V867G9LBv4tNfZP8yOujnOtitXM9RNH2He1sPzvLmFdzMeayzJkOA0LPlqdp1ZnqzUrW7AmxFGS5oCm
+ 5JCfeQQ72yz/PwI6OHhrUNAjrB0dR2FFavPke+E1JVgq8f/Azhz8X/tHRiyfk7i3fP1HZw7/rOAawf3m
+ te9fO9+C9Q6GdXPFwx1FDzfl381Nul82//66xPt5k+5nj7m/LP5v6YP/lNL73hzfuzM8705xvTvJ6XK8
+ bWmUYqrOXG/14n+a/Uf3vt3FE8XKJezONBYrWTDQVzLpgCTCE1MWThtb2gOat9IiAC3Aeou/f5W9/WAc
+ 88uffE8rKRVRQXB8d7TcHexsxw0bVLpiybXdm39JcAlrQAw6v3oWKH9/5cjDC/sNen2g9mHzhgfbCz9f
+ l3K/Jv3+hpT7hbPvF0xl1F458i/pA+8lh9yd5XN3Oof1RMdPJjjcGe/w/lj7plj1Qj/LSNuu3Xv+d7eQ
+ bpajLZWLlLgshyG+VI3FEAc+Amg+C8emWqNyh2lDC0BvE2DNqO3nV2JnF4v7q1CUotMMgTXakVjW7Gxt
+ xg8bUpm97PWDux68xZzAT44yFkzG05MGBM/ueXh6x8MTWx8e28Li6KaHRxsfHmlg/EUc2vjwYN1Dhm/V
+ w70bHu4qfbij+J9Na+6tT7m/cfn9qsX3y5PvF81mMpI74S8rR3yRFnUXWM/2vztDd3eKG3jNsB7n8G6C
+ /dtj7N8cZbc7VrPYTxxl07V79/82CzcTjxfDR8Nf4jharIfIWfi5Ayp3dFBXEqGra4J1k4/PWhubKJzJ
+ jj4CblMXi8WDo6NWL06G8frra5f/fht+6+V/tliup4D1q2fZOgbUgE5TwYO6TLaIlSQ/WDvrwerpD3In
+ P8ie8CBz7IOVCQ9WjGaxfBT3ZMyDzIQHWeMe5ExgX5M39UFBIvsn6+c8KJrH/nnpwgfli/5RmnovawqD
+ uHT+/eK59wtn3V834/7qKX/JSfhiWb/PFwPrMIZ1kv7uNI+7k5w/neAIXr+XYP/WKLvbI+1ujbB9dbjt
+ 5hjVHG8Lf+1L//nSf1haWq5atQq7dOHwKDmkdI8vd9AhE0YFPFFY2P42sXZzy7K01Fur1bPGjd66Pv/T
+ c0e/uHzy25fP/OnVC3+7deV/fwTWzIqBdI25D0pTHuROebBsxD8XDfzn3N7/nBXxv4mhf5ke8sdpwd9M
+ DfpqatC9KUH3JgfenRT42aTATycF/n4iCzzBHxGfTw7E3345JejrqUF/mBaMf/XXGSF/Twz5Z1LoP2dH
+ sG+4IBbf+f7CQV8kRd5fFnd/xYj7WWPu5yTczxmL+EvWyHvLYj9Pi/48NfJucujdOQF3Z/owrKe4fDbR
+ 8aOxDh+MMWD92gjbG8NtX463vRZnWxQmG2PT01NhiWIp3uJ8+Z8f8MC7n59LF7ZoRRERxzisdxOvAwO3
+ eHvXubiUuziXujhlaJSBq1PnvXVkN1wEsP7yyqk/XD/755sXeaxJQDrWEMbW7YWMX1njOEwjAQdwAUbA
+ 6+OJAXfGB7w/zv/dsf5vj/V/c6z/Gwn+txP8X0/wuzXG77UxfjfbCnwef4uvQeCL8a8Q+OfvjfP/YLz/
+ nQkB+Lb45nglPh/v+0Gc03fT/f6a6P+3pKC/zQn/W3LU3xb2/VNqn88Xht5dEMYYPT/k7twgxmtgzSTb
+ 7e4Ep0/GMazfHW1PvAbWAPrKEJsrsbbHBriuDLDpaycLDw9PSUnBukXlf3J4lLPwDS1aDwH0SQ7rA4GB
+ O3S6OgeHYne3Ch/vmiC/BoTeM8taHZKfMvfto3vunD702XmG9XfXzz0Ga6B/bPODmmUPciYyZGeG/3l6
+ CMEKCIApAQqAhFC+Otrvxwf/qtDLgNfs5nCvKwMc3hzr/e54/QcT9B9P9Lk72ffLKX5fT9PfneIE/jIW
+ Q6MhHRR4znjNsP79WMc7CQ7AGnptwHqozbX+dreGe96M97gR71ka7pDgprKRWi5YsADlaagH5vDoKHWs
+ h8JzlwD06dDQoz4+u11cNuo8N/rp64P9N7VEY7B/o94zx1Ybnj1v5jtH93505tDdC8e+unqasEY2TBpC
+ vH5wZjeT1+wJeM/+IzEUb2e864XI4jfnGfrjMe3kd7gy1P1Mf/vro7wQN0brbo7RvZ6ge2Os9xtjPV4Z
+ Y3trjN2bY+zfG2sPXYZiYD28O9mFoTzZ7e5El7vjnT4bx7B+fzSTkddH2r06zPbVQQ5vDPd8nWHt+epw
+ r1fiPRuinWforD3UMpSM0BpHmQX5Id2aw9/FIPLzO+TpsdNXvyckcH9Y0N7QwB3B/puNsPbV5dtZRWck
+ TXn3WDOw/vzicSHWf99T8fd1s/938eB/zAwDuJBOgIu38FucCPDgdhKXp/5lFwe5nhngeG2kF8XLo1gA
+ 9CujXE8Ptz4XZ30x3ubKcJvrI21vjrJ7A1qRYP/hOAfoxqfjHIEygnj9wWj7tyEjcXa3Bzu9M9LrzRFe
+ r4/wwtvlRjyw9ro+XLc91m2ur63eSgHtxvLIV+Xo5i2Rn8+BsOBjvcKOR4QeDQ85FB7cHBq4MyRgS2u4
+ N/npC+1tBiRPTHi1eSth/WVjwbdZk7+b1+eP04IYuOMBrh8Dd+wvD67w1To/wPncIGceaP7JhREux+Ot
+ jg21OjHU6uRQqzPDrM9zoF8bYXt9hO2tkbZvjLKDaABfoIz4cAzD+p14+3fjXO6M9npvlO7tUbrbI3S3
+ Rni9Olz3ynDdy8O9rw333tnfY66fvY+1EudpwfNBrOFAQG1Rr7BTXJzsFXYiIvRYeMjh8OB9YUG7QwKa
+ jLAO8K10shs+pW/EmdlxH86I+ni8/7vjfN9I8Hl9tM/N0b43mcL63mDhh3jqxPzB3/BsP8cLQ1xMgT43
+ 3PnYMKtjQ1piqNVxDvHTQ63PDrO+MNTmSpwNnAa8HRQDugHQWcTZ3xnu+kmC7s4Y3fujvYH1W6N0r4/U
+ 3RzhfWOEN8N6hP7KCP22fh4zfe3ctYri4mIkIpARHmjC+iSwjgg9Eh4MGQHW2zisOSXxawjWVQd7bHBR
+ DZN16VnTy/F8nO5CnPfFeO9Lw70vj9BfG+lzbaTv9VG+r7B4hrA+1df+4jA3U6DPDndqBTSP+BCr40Os
+ Tg62OjXY+uxg6wuwGcNs4DeAONbD20Ps7gx3+zRB9/sE748T9B+O8X5vjPfbo73fGKW/NUp/Y6T+5RH6
+ qyP0l4frL43Qb+zjPlFnZ6uSw3QLgeapDRk5Eh5ykJPsnSG+DcFeVcHuZUFupYFupQGupS6aCXIzzQp/
+ qyODvU4O052J051ncON/AKx9TLEmjvPBvRIs8JUvj2RxdaTvlRE+l0f4XBzO4jwiXo84F68/G6c/Iwj8
+ EYHP0xfgK/H1l7h/i++AVxrfDd+25Wdgb6/j0TaX4z2ujvRCCOE+M9yhbaAHWx0dxOLYIKvjgxjip4WI
+ D7B5O97tzmjdR2O8P0nQf5zgfSdB/0GC/t0xPm+N5t7co3yuj9RfYz+Snn6XwkjXoW7WAPo0Jx30USgj
+ R8P994Z5bwn13BjkXhXgVh7gWubvWkrhbjNXbe6Z5K48MNDz+BDd6WG6c/Fgt/7KcIY1Ufv6KL9XRvsJ
+ McXnAQf97wHW6Tj9iTjvY8O8Dw/VHRis28/FvsFewmge5GUURl9A/wr//NAQ3dGh7LudjPPGa4OXgb1s
+ 8boDUVYXh3teGuF5eYTnFS4I9JPx9keHCqSjhdFHCeiBhgDcPOJnBluf62uFMXashO+M8oJ03Bnj/VGC
+ /qOxPh+O9Xl/rO/bCb63x/i+NtoHvzVwwMt/gSMNfk0CunWEnuoVcKiXT3OE984w3fYQz81BHhsD3asD
+ 3Db4uZb7uZZxUertsMJG0iveTlId6XR0iO4UqB3vfSFefwlwM51iFLs8whd0I1hPxemFmAIvQnBvS+wZ
+ 6LWbi12dCPpK/BME/x3oG9IrQejv7efWFGF1ZKj7sWHuJ+Pcz8R7nBvucXEEw/14nM2RIdojg7VHh1hR
+ kF4bAS1EHAQ/Ea29OsTtRpzHa/Geb4wE3N7vj/H+MMHnzljfO+N8Pxjn926C31sJvrfG+N5gWPsS1vj1
+ WwMNiP0P9/LZF6FvDvcGnfeEee8K0e0I9moK8mwI9Kjzd6v0bw23o2qErKt8hb81ZOTEUC/AfWoowhsf
+ jw9lVD04xGvfIF0z98sTrAQooblzgOeOAZ7bBbGtvyfFVpPg/wpPhP8E3wGBb0Xfk14AQn9rtFNDhNWu
+ ga6IPQPdmge7HRzifnSo+4k49+YhVvsGaQ4M0h4arD08WID4YKsjAkbzQLMn/a2OR1tfHup+daj7y3Es
+ YXlthNcbI73fGe39XoLPh+N8Pxzn9+E4ZKdwX36vj2HuAFIGrEG1Fo02hhgoI5pDdXtDdbtDvHaEeG0P
+ 8twU6FEf4F4jgJsR3M16jtpcN9FZ3hDjuneAx66BHrA47NfGc/bL4wnCaycHKwFkwLGf59anGNzLw78A
+ BH19L7uNkbbbBrhuH8hiB4c4YsdA54b+qi2xqu391Lv6q5sHavYN1BwcxCE+SHtkIMKKohXQ/axOxNhe
+ GuIOrK8M87g2zON6vOdNOLyR3m+O0r+bAPVgQH843h/Z7zssjWD1A6gosOaAJqHQ7+VYzCIUoWNAU/Bw
+ c9RuBLUfwe0GrMu9nXJtZP0tXuqxUK9t6OPaGOu2ua/75lj3LbHum/t5NPXzYB9jPZv6sXia4Hbw3bg3
+ RGWIVV1v+839XZoQA1wRWznQN/W3r+6rrIlR1sYo6/ooN/VVbY1liO8doNk3QHNwgPbQAO0RCiHisVan
+ +tgxoBnWHleGelyN83w53uvGCN1rI/W3R+nfGuP77li/98f5od7yPuwvV2lAMgysRb18m3sxiKESLAhi
+ PhjKLRGi2xOi2xXMqN0U6NEQ4F7n51bj51bl61rp41qBcNYmKXp6xNlJ80MdqqJda2LcNsa4NfRxb+zr
+ vqmvx+ZYjy2xBrh/Hqzxohb6yOtiHBtiXRr7uWzq5wLEt3Cg18XabIhRVvRWVkYrq6JbI95XvStWvaef
+ Zl8/zcH+2sNCuPtYnY51aAX0MM+rcV4vI2EZ4X2TOTyfN8ZgSfR7lwmIgdfAGoUXUbj3rjDv3YhQoKyj
+ aIV1C9D7Qr0RzYA7WLczyGtbgOcWf48GP8DtXuvrVu0LxN2qdE4F1rLBFi9JprmpKnu7Vke71sW41ce4
+ NzK4GdaIn43ajTGuJQEqoCwMQryyr7Y0WlEWpSjvrdzQ24B4NRCPVtT0Vm6MVqIAvb2PGoX/5n6aA/0N
+ BD8crT3T3+niEHdOPTygHleHeV6L87oWz9LCV0bqXx2ph+WA8Xgzwe/tsX5gNOCGhgBrUahue6j3Tggx
+ F62wDtHtRTxiNFD23hesQ+wN8tod6Lkj0HObv8dmP/dGX7eNvm6A2xCuNgvVlkGRavNUH2tQuzYa1HZv
+ k9o/qZLURTqWh2iNgKY/lkari3srSiIV6BMieMQreyuqohTVXNRGKRujVU0xql191XtiGcEPRGnODnC+
+ MNgNQF8a6nF5mOcVDuiX43XXh3tfH6G/Mcrn1VEsT4bruD3Gj4OblSoRomCvLSHwcLodobpdPNacSjCU
+ DeHdDHCDdfgIlPcHGaI50Gt3gOeOAAb3Fj/3TX7uDb5u9RzoG31caxzUU2TdXQbbSDID7Wqi3UypDSXZ
+ HOtZHOWWFeacEuAwTW8/ysNmgItVLweNv63K00rlpFbYKOVquUyBHrBUisAT/BGfxF/hC/Bl+GL8E/xD
+ /HN8E3yrkii3LZx2V4XZVobbmAJdH+tcHK0silQU9WJRHPkI8XJwPFJREamojFRUI6IUNVHK+mjllhjV
+ jhj1nnD1qQEu5wa5XRhiwPpKHJMOMJqAfmWkz42RPjAbwPq10b5UpwWdUQISYWWDnQj22gZrAaxD4DEY
+ yoZg5NXtCfJiwT1vDtLtA9DB3gcQHOIM7kCvnRzcTRzBgXgjhbdzka1ipKSbdoSDLC/EAdReHea80N9h
+ ks5ugIs20FbloFI4OztjaikmJgZTRRMnTsRw16JFi9A/w7HvGBHBIANua6qrq8NwDx5o1uEyicrKSoyX
+ Yw42KysLnWJsKsEkCcZ0cLxPYGAghhAdVYogO3WoovsYN+XCQNuCXg5CuGv62hf1VvBAE9wIEJxFL3lZ
+ L3l5L8WGXgzuqha463opt4ZrD/dzOTHA9cwgt/OD3S8SqQE0V1HigYaDfnUUwxqWgy+Li+CLA9xr4SWC
+ PbdioQvR7eSw3h1swHc3oRzIRRDDGsFjfTDYG0GI7w302tVCcCAOBd/McPfY4uaQp5IO6fI7qaKnmaWF
+ OTaf4iSNqVOnoteOOTRs2wN2GzduBIiAEp18PFAcwAPjE+iB0gNzhaYPtKLxMP18eXl5cnKyhcQCc0k+
+ 4T4WEnN3rSTGSTlRp80ItlsfZdUm0AzuCEVxhBxYl0TIyyJawx2maAiz2tnHaV+s85H+ricHuZ1lWHte
+ jvO6Gq8D1gD6+kgfRmoOaPAahTBgTc0gEXI8+LMA92p45CDPLaB2kNeOIK9dUGEKjrAGoNvB+lCwN4IQ
+ J4Lv8vXY7u2+1dOtyc21yd19u5fXThcXbAsZZWFhN3ToUOwcrqioqKqqAsRgKyBGA59HFsABPkyoYBoI
+ D/RAMVGIB7rO9MAQeJsP/gvwxajB+/fyz67PRmTVZc3JmTN69ujecb09AjwU8hf1Ni8Nde0+39eysIXO
+ Bl5HKIrC5YhiLgB3aQvcFSGKhnCbbTGOO2Kcd/d1PtDP9dhAt9ODPc4zrHVXh7PSHQN6FAOaYc0BTVgj
+ CGgEsupKf/daf49NAZ5bsdAFee0EXlwQ1o/gbuE1ZIQ05FCI/jAi2Puwv+6Q3nO/p3uzp2ezTrdfrz/g
+ 53cwIOCQvz+LgIDDXl4bbG0nisUumALFwSUgMlhM/AW+ABewEpSYmkAvDt1PPDDsgH4zHujK0wN9fqMH
+ /1f0lTihNG5q3Oqtq1c3rc7fkp+3OQ9zjrmNuasaVmlSNWZDzV4MePF/bP7HRvFCpH3Xad7m+WEyjtEM
+ ZRZhLAhrA7sDFQ297JqiHZFtbu/jtLOvy95+LocHup0c7HF2qNeleO8rwJqRGksiAxoVY2FpV+TrUuzr
+ WuLrUuqDcC33davxd28M8NgCzYUOtId1C7UZ1kHeB/y8Dvh4HfLyPKzTnfD1PR0QcCY4+GxQ0GlEYODJ
+ wMDjiIAA9hERFHTCx2eTg8MchSIgMjISJ0JBPQAxcRb4EqxowWEOCPNQeGASF9O9aOzjgV4RHjhR0ehB
+ n6evwRf7+vqmrEkp3FO4fvf6dbvWrdu5bu2OtQXbC+bWz5XlysSpYvFcsXi2uOeInl0jur7g/IJK9j8R
+ dl2neZkXhD4C+hHcQNxP3hDpsKm34+Zop60xwNoZWO+OdT0wwP3YYM8zQ71QMb4ynJWLoR6M11xpHs9h
+ BFETF/m4FOudi31cSvSGKOMc8UbIaztYP6K2v9devcceT/e9XgDa5yiH74Xg4EshIZe5uBQcfDE4+Hxw
+ 8LngYPwVC0IfT0JCzgQGHnZ3z7KyGmxhocJFHHTYGXgKZAlWQInD9TFzhS3dOJgLQ4HYqYouET2w+4Z/
+ 8J/EF+DLsH56+XuVHypHlB0sKz1QiijZX1LcXDy0dqg0VypNk0oWSCTzuZgrYYiP6tk1tOsLdi/YSl/o
+ Z2+W7GNJKBsiRF4eqK6PcmiIIqydt8Y4b+vrsjPWdXc/t+b+HkcGe6K8g3IxKtGokV4f5QNDcn6gy9He
+ 1qdiHS8MchfpnYsQ3s7FCD1AZ3CX6l0qYIrhH2AkADdMhZDaAV67fTx2e7nvdnPdBX3w8zsSGHgiMPAU
+ ByLQPA+IQ0KuhGLLJIurXDDcEaGhF1riYmgo4lJY2BVf33onp3kqVQgRnC6pAl6EJgau0MzHEDAeGJ/A
+ hhGMBmJgxeiBT+KBv8XXwLcMmzSs7kxd3em62lO1NSdrqk9WV5+orjxWGVATIM+XY5JRtlgmXSSVpkql
+ KVJJMgf3DLHlRMsesT1e0r3Upft/+ahfGufWIz9EBqwLA+Ubgq3qIh02Rjo29HZsjHbaEuO8tY/L9ljX
+ nf3c9vR3R5Hn4GDPE0N1UJITA5yP9rE/GmN7pr/zxSEwf74IAF3ozQJYs2jBGnCX+bgi36sXUtvfc5e3
+ xy4Pt12QYOivvz9YfAxBmsCpBOAGWxnWwDcMZ82FvRIefoP7iLiOwCfDcYyDICIiXunV60Z4+BW9foOj
+ 4wyl0h9GDasZ5BuoAT403zDchsEJjLliPzAeGOLGA+19/kGfwV4SPLBnIL04velq05YrW7Zc3rL58ubG
+ i40YRK86W2VfZ69Yo5CvlMuXyuUZclk6Q1y2SCZNlkoSJeLJYsx9iceKLUZYmIWaveDwgq3shcGO3dO9
+ xJWhNrW9HDZGOdZHMaAbo50Z1n1dd8S67ezvDiVpirLfFG7dFKZtjnY41t/9/FDvS3E+V+J9rsb7MKBt
+ FcO8nddzYQr3I2r7uDfp3La6uW7T6Zp9fbG+AWIKBjRhDfHlgikD5AJYh4VdBbIREa9GRLwWEXGrVy8+
+ XouMvBkZiY+PIirqVlTU6717v9mr13U/v1onp8kaTTBOQEtKSoJrxuQ1htswGosH5lRwNhceGJjHFhWj
+ BwRdF6ADvrtf273r5q6dN3fufHXnjhs7tl3ftvDkQnWDWrlWqVilUGQpFJkKxQqFfDlH8FSZdKZUmiiV
+ TJZIJkrEEwyI9+jb4yWXl2Qv/vcwB1mmvw2yTWDd0JsBDWpv7GVXG25TFaypCdY0hNtu7e20K9Zz3wCv
+ o4N0p4Z4nxumvxjnc5nDWtT9f16wksZ4OqxqC24m3F7OZe7Olc5OtZ6e23x9m/39mYsICDjCBQM6MJBn
+ NEh9Ijj4ZHDwKU6Fz0EcoAyEda9er0dGvhEV9VZU1NsUvXtTvMUFnrwTHf1uTAzivZiYDyIjryECAzd5
+ ei61sxuhVHrGxsZCWOALId/oeGKiEGNBeGDOHoNY9BEP3FGWMCvhwDsH9r+zf9/b+1i8tW/vG3v33t47
+ 6OggVb1KWaRUrlYq85XKPKVylVKZo1SsVMjT5LJ5MtlMmXS6VDpVKp3CIT5JIpkgsYyyRFaFoSRrcc9B
+ ttIMb9WGYG1ZgKrET7khSFMTZtsQ6dTUx2NbH4/tsZ47Yz139/Pc28/r0EDvE4O9zw7VX4jzAbVFWUF2
+ fa0sVRYBrjapLVgb2O3pVOTqWORgX+TqWqnT1ev1W319d/r5AWuIBsM6MPAohzLRmWf0yZCQU1ycDgk5
+ GxZ2Pjz8UkTENYgD+AvCEqDR0e8DTUSfPh9ycYeLj7j4uE+fT3r3vt279xsxMW/FxLzTp8970dE3Q0K2
+ +/hku7pOsLYOlkhkMHDQYqSOWD8hLJgPwgOTK0gR8xrzjn549Oido/h45IMjiEPvHTr47kHvQ97qjWpV
+ qUpVqFKtU6nWqhjiq5WKHIV8iVy+QC6fK5fPkgNuWaJMNl0mmSKxmGDRzbMbdmIh4XzxxRe7d+8p7fJi
+ fyvLlb5Wdb2c6qNcGqNdG6PdtsS4M6z7eu4wYO21p7/uwADv44O9zwDrYXpRYbjzmjDH4fYyqZmjo2Yq
+ Ye3ltN7VYZ2D/ToXlzJPzypM43GxUa/f7Ou7zc9vj7///oCAg4GBwPpYUBCCoRwcTHQ2AB0aihmo02Fh
+ hPXFiIgr0ISoqFeBYHT02zEx73PIftK37+/79v20b9+7sbF3+/VDfN6v3z0Eod+378f9+n3cv//HAwf+
+ fvDg38fFfTpixKejRn02dOjF2NimiIhVfn7T3dxira3d9Xo9Bg8HDBjghSzr9u6D7x089MGhIx8eYXAj
+ PjqadytPc1ADoNXlanWJWlWkUhYqFesUstUyaZbUcpGlxTyLnjN7dp/Wvdvkbi+Nf+nFhBd/N/p3L45+
+ 6X/kv/Pw8O/TZ/jIkYnTp6ePHTs3LKyfg1Q8xkVTGAoNcd0U47Ypxn1LH/etfT2B9XbA3c9rd3+G9b4B
+ uqODvCEjotJeLoURDOupbirLLlIb+TBXh7WO9mtdXIo9PDbodOBylU5Xg2iBu8HHZ6uf305//2YO68NB
+ QUeDg49zAYgpThHKBHR4OOJcePiFiIhLkZFXo6Je6d37tejoNyERQLNv3084iO/17/9l//5fDxjw9cCB
+ Xw8ahI+fDRp0d8iQz4cO/Twu7t7w4fdGjvxizJgvxo37YsKELyZP/nLGjC9nzfpq/vyvUlO/Sku7t2DB
+ zVmzjvj4jBiXPHnfOweb3zmw9619e95s3nV7987Xd+64tSPqYNRL1S+9uPrFF3NefDGTxUsrX+qyskuX
+ ZV26LurWdW7XrrPMzBJ7dE/s2WOmhXmSpUWSRDxTZjFc2r27eVJSRmLisqSk5bNmZc6dmz1/fu7kyQsj
+ Ivrr1fIkL9v6aAb05j7A2gNYb4313B7rBax3cXA399cdHugtquztUhbJsF4b5jTaRfXb//xPS8tejo4r
+ vbwqEC1AM6y9vWv1+jq9Hryu9/Fp9PPb5u+/OzBwf1DQ4eDgoyEhx0NCToSGngwNBcqnwsIA8RkKDuiz
+ ERHnIiLOR0Rc7NXrclTUNcAdHf1aTMybkIXY2DuxsZ9yWDOIhwz5Ji7um/j4L4YP/2LUKID7ZULCl+PH
+ fzVp0tdTpnw9Y8bXSUlfz579TXLyN4sWfZOR8c2KFd+uWvWHgoI/5Od/IldZlx2qOfHp+RO/P3fi03Mn
+ Pzt38u65U1x4ndartmmV1VplhVZZzkJRqlGUaOTr1PJstWypSpamlC1USlOU0gVK6XwFQjJPYREpCQqK
+ Abhz5uTMm5ezYMHqhQsLFi1au2RJ8bJlZSjYhIT0jbZTLwtw3NzHA8GwjvVC8Fhvi/Fs6uUlQm0eWOeG
+ Og1z1drIxBC4/v37S6V6e/s5Xl6VFCC1tzfCgLWPz0Yfn3pfX2C9JSBgZ2Bgc3DwwZCQI8AaQIeFEcqn
+ w8MBsRBlAH2uV6/zXFyMjLzcwu6bMTFv9Onzbt++d/r1+7R//y8GDvwGWMfHfzV69FcJCd9MmPDN5Mnf
+ Tp36bVLSt3Pnfpec/F1q6ndpad8tW/bHrKw/5uX9ae3aP5WU/Lmy8i9z5mwZMCbu1N0Lpz6/cPrehTP3
+ Lp794uJZfLx3ceVbOepjVqrNLUAD6w0c1iUaxTqNPEstX66Spatki1WyRSpZqopHvKeHOC5u6oIFeSkp
+ q1NT1y5eXJieXrJsWXlmZlVOzsa8vMaCgi0TJiTbymQJ7jblka5b+no0QUBivTZFe9ZHeG4M86wL9agP
+ dRehTDzfzz7YRgnviZIjrgzAFiDszerZU21lNdzDYz1HagPWen2NXl/r41MHrDmgEZv8/bHdCOPVGLI+
+ HBqKCeAT4eGnwsMZ0BERIDIFQ5kHOjLyAhcM7qioK717v9y7942YmNf79Hm7b98PYmM/6d//cwjIsGHf
+ jBz57dixf5g8+Q/Tpn03e/Yfk5P/uGjRH9PT/7hixZ9WrfrTmjV/Li7+S0XFX2pr/7ply99iYqZl1uSd
+ /eLS2S8vnfvq8nkuzuH5l5cGXBui3melarRS1Vqpqrio1CIYqdcQ0Gr5kpZIMyAunarsKRODzosWrU9L
+ K8rIAIvLV6yozsmpy8/ftGbN1vXrdxYV7Sktbc7Orhk2bFKItTrZ27E23KM6hEVViHt1sFttCMJVNNrD
+ 2kYhw04sXECwdu1aeKO8vDxsHcCCHh0drVCEOjkt9Pau5BhdpddXA2sfn1pf3zqkc35+Df7+AHpzQMAW
+ jFcHB+8NCTkQiimn8OPh4Ri7Ph0RQViDyBRE50fRgji0G4hf7d37enT0q4R4bOwH/fr9HgQfNAjs/jYh
+ gcGdlPTdvHkMa9A5O5sBXVr6l6qqvzY0/DU7+2xgVMSh908wlL80oExY7/v8oPM5d/VOK1U9B3Q1Fwxr
+ K2WpVpGvUWSpFSvU8gwu0rngQJcMUISGxi5ZUgQWL11atnx5ZXZ2bW5uQ0FBU2HhzpKSZlieysojWVmH
+ Z8w4MGTIAU/PTPOXJIOstPm+zpVBrlXBhqgB0Dh8GiX20tJSJAXYkI1aOxDHA5UHfH7ChAmWljY2NqO9
+ vAr1egBd5eMDoGt8fWv9/Db6+dX7+zOsOaAR2Gu0IySkOTT0YFjY0fDwExERp3r1OtOr11ku2oUb0Lfm
+ OEO8heNvgeP9+oHj9yApcXGM4FOmfDdz5ncLFjBqA+61a/9cVvaXwYPT5+Sknrl36UxrRgPoWbfnqY9Z
+ q5qsVHVWqhouOKyZWBdpFasAtEaxQqNYSvEIcUu9bPToWRyLKzIzQeSN+fmNa9ZsKyjYnZ6+b/r0g3Fx
+ h2NioJmHoZ/+/jvw/gZQKtVwvUQ+39WuMsilKtilMph9FKFbgQeyABhSPFAyx6OMewB9PNDsgGdSqUJd
+ XFJ8fKp9fYEyCz+/OmAdEFAfENAQEACssSUUG0OBNfbTEdwHwsOPcjsKTOE2prYJzaEql6AqLTSHjt8W
+ 0Pwe0RygT53KJGXKlFccPfT1F3ee/OzSqbuXTn1+6TSP+JeXAy+FqputVJtMgMaSuE6ryOWAXq5RLBPE
+ Uo1shspCLsW6l55ekZxcPWNG7ZgxdYMHN8bEbAsN3QUXEBCwJyAAT2DA4As2A2UoKvemr7C1naXoJh5l
+ qwXKFCIUuvCgNgdq8PQRZWL+I30SO+UlEitb23idLh/5McLfv44LhnVgYENgYGNg4GbwugXrbSEhO0JD
+ 92LTRlgYExMO8dMt1O4IaB50Ac0fgd7C9Df79mV2pV+/zyAvrq7ZCfNmHv7o0pGPLh39+NLRTy4d+/2l
+ 459eOvHppZVvrJYfsZFuspJWa2WVWlkFCzk+lmtkRRrpKo00SyNdrpFmqCXpLMRL1JZpaovFarMouZ3d
+ wJCQ4oCAUhRhdDoKJqEQT2CKJYpk09/fEPgMFBV/i7e+i8tKqTSmt0qVo3dkQBOg1EZC9Z36RsIGB3oc
+ KBbjgYYIenoqlY+z83Q/vyp//9qAAKDMB4Mbh1JgWzlH7S20fTE4eDt2IoWF7QsPP4zNMq3hbkO1TXW8
+ TdxbNB2r6CuhoYfVNi4lBxoOfnj+4IcXDrG4aIg7F0NPDejRpO1RoelRrOlRqOlRpOlZyKLHGk33HI1Z
+ htosTW2WojZboO6WrBKE8gVbsZXVNDe3bDe3HC7yPDxWe3mt9/Yu9fau4MQTQAPibQEB2wMCdnAfEU2g
+ tq8vsg2YtA1q9WhvsSzFzU4EiNGjQ3cODQ7qbqCvgdI7dTGo+o6PeOCPqBdjwUQvytq6t4dHakBAHRcb
+ AwOBMgWjNoe1QUla4CaCN4Pg4eFHIiJ+CMHbW0sdHOYPT5x88IOzBz84Z4gPzx3kovB2rXy/Q/dalVmJ
+ ymy9ymydymwti25rlN1ylV2XKbqmKbouVHSdTyHn46U46W9/a+7ktMTZOd3FZamr6wp39xwPj3xPz3Xe
+ 3uV6faWv70Z//ybgC+kICtoTFLQXXoB7Ar+7HX/FsRtpR5WtbaKVmVjEQ4zuEZpGQBPVL7QqUHHHA0Vh
+ VNxRTafSOz6DKhr+Fvtq5XIre/shOt1KgjswEHC3hziEu0mA+C4O8YOcgrMF80klRYg4fk+VtXNhcy0H
+ tHHEnI4z26o026AwK1SYrVeYrVOYrWXRbbW8W5a8a5qsa6qs6wJZ1/nG8TtfsUzW18lpcQvQmW5uqzw9
+ C3S6IkgwpxubAgO3cb52H9IILpM4wHnc/cHBe+DBOGoj26jGO8DRcb4ImkAsBmfR10BTA4Ci3I6N5Ci0
+ 46wlqrLjI0rD+CPK8KjH4wUA5RcuXKhUOmOfvl6f28JuHnQjgpOe8HBDUsBxJikCxJ9YxIG4nd2cUbOm
+ tolyzVvb1QeczTYqzUo5oFtQNluj6JYr77aMA3phGyh3mSL9rdTc2nqak1Oas3OGi8tyV9csd3fQGbpR
+ BpLC1+KosMBAbDreFxICiJFAHOHiMAc02A1eY7M3pLxcp1vn5ZUnQo8OgoDuEXgK2gJi4AtYsV0f9XUU
+ 0VFZRyEYDzzBZ/B54A7QCXEoODy4SuXu5DRGr88LCIBwUzwR4jsFqsLrOHxh2+6bZzRoZePiWXa4sU2g
+ B59N6L5dZVapMCsyoXO2vOsSjs4pbQD9Ym+JuXmQk9MiSAd0w8VlBejMCXQhZBdrHdZAQd5wGF4WEHNx
+ ICQEAgLVRipX7eeHL4agF+p0a0QgJrQCmgB9QMcIrSBACXxx5CDK6lT2xQP7FPEcJXaU2wlxVCZBcBAf
+ /xCraGJiokrl4eg4xtt7lQDuxyMuVBWsnKGhewQ0N5Jy48XT2nrqpEVz2kR549s7tQddzeqVZmVt0Xl5
+ u3SGjPyPnYVaPapFN5a5upJurNHpijl1RuoAMdwJC0sulsN3D+0+RgGd87vQFphgiAwcC4AuEEEu0KAj
+ IgM7QIwWBiAGuCii49wIqvPSA1sVUWgH4oAbHOfhBrshJpjN4OB2cXCAC1zRGm4DzVtLeXsrJxOW1qBj
+ /RQynaU/eBd7BYfUX9zVLp13tEPnHHnXdFnXRW3T+aXBUjMzL6KzszPoDN3IdnfP45ZBoMb8BvIGZGdc
+ ggaZRgWCFn/QHJ9vxLsZlszPDy9JuY9PCYDW69eJoMiACVKAjhyoCgQJYsCKQ3qx1RYndWCzHB54gk2K
+ 2OgM9PEF4DixG308iAleJ7xa+G5YXTGjhVOD7O0HeHgsbAtuIeimUm5kV8gjQtAhL3DlpOkMd6Vy2PzV
+ S9tEufLNJqbObdI5T95tRQudk9vQjRc8LeXygRyd01xcYDkA9EpYDk/PfJ1urbc3FsNSIAgcIQ6cu6Uc
+ gn4R/BHCUu3vj7+tQLRgXSTCex+KDLDAUCgDGkLAERADVuyOw2ZE7GmmB3Yl4o+EOODGAeD4YvwTdPDw
+ PsDrBNmB+EC4ofXwMChR4Q5Aa+twHK3n67uufcSZvAgcC35uY6a3XkUZ7o6OyVHDBu175+SBD87wcfCD
+ M1ycjTk9rPt2ZbeKttS5YzqPlPy2W08YMvgE/C8cHVOcnFKdnRe7uqa7uy/z8MjR6VaDoRAEDmusijX+
+ /jWCXw3PWXBY428Z3L6+G3x9y0QgIxQAckEHoIDIoC3t98Secdpeiwee0IOHG1+GvhGJCaQGmk5KgjcH
+ CTcUCQssqlToOUG+cbqep2dah3C3Ky8t3txgz/F7yjW2OZvWH/jgtGmsfq1Uvs/OrE7erUzWbb2s21pD
+ dC2Qdc2VdV0h65Im7ZIq7ZIs7TKfQtJlniF+52cuFofa2U23s0u0t5+JKR/A7ey80NV1iZvbcg+PLPgH
+ b+81Pj7AuoTDugLkBawcvrwR4LE2UBtYs4O6oQDQAUBGR/qAyHSGI38yGN0mjwdd6oq/whfgKDt8MbiP
+ 14ZXErwt8ObAdAAZQQg3wY0kHnqCyVsrqxBn5wne3tmdQLxN98JyIo1mxNj50w98cKrNCD4ebbZF1q1C
+ 2q1I2m2dtNtaabc1LLqulnbNknZZIumySNJlwSNweZRfGiv+rUV3fHNb26nA2t4eWM92dJzr7LzA1XWx
+ m9tSd3f0Q1ZhZdPr13NAb+CAJpSFQOMnN6a2CCiDktABkgvauEwQA1n+PhE6qJJOzSeswXdSEug4ryS0
+ TvLCbQQ3TCQqghhKQrJjYxPp4jLVxKLwpGj3ibNzil9kRMPlnQfeP2UaC64tNd+rMquVdSuRdlsvRFnS
+ dZWk63JJl8XiLgvFXeaLu8wzjhcCe1pY+NvYTLK1nUxYOzgkcUCnuLgwoMFonQ6MXtuiHgDalM7Cn9xA
+ bZ0uWwSU6cw1Xi5MUebPFCOshdRuU0lIuI3gpvQSCRHcJHJ9tBdw1zEQt7aOAMdxwmFnOI7f0EKqzqhY
+ 1SbK+KTrYV+zTdJu5dJuha3pnCfpminpkibukirusqANlF8ab/lbiZlKNdTGZqKNDYCeBkY7OMzCCJWL
+ C6QDGr3C05M0GnQuhuxydEbNx0g3HgGNXwq/GlYp/JoiXpSN5IIo3OYVmEZwg9q8kuAF412gEG6ICWk3
+ lko4E+TxsJWooiAvBeI4XBSqotH4Qcfd3ef5+KxpD3S8r0fPndIeysPPT+i+S2ZWzYmGkM75HJ2XdUjn
+ oJ7m5n7W1kB5oq3tFE46QOc50A0Xl0UcnTO9vHIh0BydSTd4Oj/SDfzw+BXwi+DXwS+F6XocUYNaP7sr
+ SyjKQrno4HRMI6zpkmgoCb4VucA24aalEs6EjCCyJMg3CI7sH2UsdBtwjihGBhQKG0i5o+NID4/5Pj4F
+ POggV3Cf6PZEY/2tCtV+B7MGabey1nQukHbNlXRd2YJym3Qea0TnqRydZ3J0TsFK6O6+nKNzPhyxXs/T
+ 2QA0fkj8qPiB8WPjh+/duzfKnJgB52vOqNyJsKYJD0rp/O3VvGoLlaQDuPkcB5knDCV8N1ZL0hMiOBSc
+ CoRw4mhd4mhIuEO5XKXR+MKS29kNV9vYZTesaY/OgcejzLZKu1WarIGgc7akS4a4yyJxl5Q2RANi/YI/
+ 1DlAQGfoBug828kpmaNzBkfnVd7ehmXQ2zvf3X2hs/Mke/v++PHwQ2I8E+9LOFq0SoSVZyRxVBw13NBp
+ tPR18qRXfFmbcJNwG7EbppuWShhB8t1UMyGCkz+BggsRR6kLlXE01ebMmePk5JS4IrH5nebmd/fve/fg
+ vvcO73/v6P73ju1//8SB909OvJTUfY/crEbarZQTDZgNg9OQMDrza2ByG0C/OMrit+ZmGk18izpjGZxB
+ dKZl0MVlnqPjNEfHBBubQVptuFLpLpOpgoKCsEEEd4+gA4VKPV/TJ2QJXNoRQsV9drnvD0ZZuEi2t07y
+ cMN0w9uQEYTv5ldLnuC8ggsRh6qA48jsR88aferzU4gTn5049vtjRz46cujOoQMfHNj33r7Cm0WafVZd
+ Npp1KTXrsq5HlzU9u64x71pggeiSa9El07LLEssuqZZdUixbOw38kcX/6MzMzfVqNdp1fVWqKKUSa1eg
+ TKaXSt0lEjtLSyV6pjqdDpzFLAYmLqEJoK1wUwi/74bfbkPg8rsXwBh2Lzgdz9bm0td5aneS3ZTBU5pD
+ JSoiONw3FBy5JSQFiPMch6pg61X00OhtL28788WZM/dYnL53+lF8fjrqYpS0WWpZb2m+wbxnSc8ehT3M
+ 1pmZrTXrmt+1S3aXlzJeejH1xd8t+N3v5v7ud7Nbx5zfvTDwhf966b9w/re1tTXeNJ6enjh1GvOMWCpg
+ iiBfmAbAQYt4V6FzjT4q7bvhd4RQNV+46Ybft0D7Qmi0Hsu+iET5x6PcMbt5Z0K+m9IcwA09QWmFEEey
+ Y4o49M470LtkX8nZL84iGNZ8cKBPvTlVcVwh3y6XbZTJqmWySpmsQibbIJOWSaXFUmmBVJIlkayQSJZK
+ JOksxOniR5Em7qnviZ132CIGTGfMmIHVGDKFHV3AF2dQwRFh+AKrNE7sQQsbnVVADP6SJhBnhchSc4oH
+ l3aE0L4F0dNFuQO4yZnACPIFE75ERYjzksIjjp/Sxt4mszrz3Ffnzn3J4uyXZ1lwoCPWvrvW6bSTYrdC
+ 3iiX18rlVfJHQJdKpeukkhwJA3q5AWXCmg+LIRbQBOgspAkQo7COsWC4MezLw0H2QBn1A6AMoQCR8ZIT
+ xLTdBnV8PIiz1PYDbYEsHvymENoOQpsWGNBPpA9P9MVGSyWfVdJqCcNDJSoQHArOSwohDu0GBMn5yee/
+ Ps/iq/MMbgoO9MOfHw68GKg8oFQ0KRR1CkWNAkDLK+XyCrmsXCYrkrEx0WypFM3oZVJphnFIZkl6OveE
+ 7GILKVgMiHFIILYZYK8YGnWwPfyOUhAZSxz1VAlcIIvFg9/FRJuXQFtq+MFKEbh8iwpphOiJgPthX8zD
+ bZRV8gSnBZMkhUd8yZIl09OmX/jmAouvWRgQ50BHDH55sPqYWrVDpWxQKmuVimqFokqhqFTIN8jlpXL5
+ WrksRybDAdfLZbKlMulSqSFaEMd4OW2ZgVDggbYc/o+40AFLAkSZJzKGA+hEf0AMfEFbUgMsHli0+S1M
+ wr02sFIwVPxeEGz4wHv05wC6PT0Rlk1IUnjEwSZM7WO62XD3wTcXDYi3gJ50O8nqjJV6t1q1WaWqU6lq
+ VcpqpbJKqaxUKsoVikKFPE8uz5Fjr4psmYzF0lYhGS8xV5lDLkBhyDH8LxQZRg2zcNjMi3UPs0TQCnSO
+ 0KujnjXhC84SYbFi0xYm1HOwhgNZ0JZ22WClIXBpCwhWILxHf1agCfE2Cc4XqoA4fsm4yXF7X9976dtL
+ CNwwYQi6cOKbiznv57icc9Hs06ib1NiTQkCrqlkAaGWJUrlGqchVKLINW1Tky+TCwNYgsa8YxVuoBPAF
+ iwExzgPEq4sLRmAtMFEEraDD5QExNBfkBb6kBgSrcPMS31lFtZnfWQNw4axgZ7ECQRV/AaDbJDifXuI3
+ HDhmIMzco2tTOLh50Os/rfe97Ks9qNVs12gauQn+WrW6hoWqUqUqV6nWq9jmlBylMlOJvUAslrcKyUAJ
+ 5jcBLpY74AsWA2LSClgLpMuQY7oKixrWuAQK+AJcLBsgLLEVrpRgJc4iFyNksaoDWQIXzgp2Fms+VPGX
+ BNoUcahhvxH9Nl3YdPkPlxFGt9Tgj7hYrNe1XlbHrbQ7tZotOJpco9mo0dSyUFer1RVqdbFatVqlylUp
+ s5XKFW2EfIpcbCuGYkCIYSogFOTe8DaCQabjt2HRqJUKiCG4IC/wRTES4PJSQFuVaIcSYEUuxiOLlQbg
+ YtWhLiDWfKjiMwE0IQ4excbHNpxrIJSNgkAfdGOQ9Slrqz1W2iattlGrrddqN2q1dVqGdaVGXapWrVGp
+ 8lWqVSpVlkq10jhwOYI0UIorNoEvHhAK1NUw1AmtICLzt/ZCKIjFaBsBX9JZkgIeU9qbRLAKkcVKQ+BS
+ /48aVc8K0EixwOWG8w1Gl1oJ4R5za4z1WWurfVbaba1QZrfiVWs05RpcQqherVbnsms91JmtQpXJQJcP
+ lOOqeowm40EQQytAZBhk/i5ImgmgsQtIBA0EkBTwsFLPmm9bt4ks3wXEmo/HMwE0ftVBCYOYYgguaDN6
+ PvWNqbhg2nq/NbsYDzfy0n3e3HVAWtxNj3uPizS4KJZdnpJjjDKBrpyklFpLYZChxQQxEZncG13WC0WG
+ naDrleAZwGLwl6QW4JIOEFuFhCXOGiHLV5Ao9/7lgcavHT8lHttaO0B5zltzHC84Wh/kUMZ1vHTHNI9y
+ pZZdBNTOdbx0KZB6gVrmI8PwMSDGMDidaoOFl64X41GGY4NLo0usoL901TfwpZI91ZOFmFLnmjhLbVW6
+ CY0vbDy6h+WH5SBP5V/hF8CKNHbO2OY3mjtAGTfUszu8ceMxLhAzRblKq8XF9Dh0ha62yja+GI+AlkfL
+ sTEHEFPJgmZo6aJNpCEwcMiV+Qs0aSAAQkG3HRPEPKAdw9pepv2LMRrLCzKFxIzEYx8d6wDlRe8uMkYZ
+ okFcxr1W1Vp2K/1aJhptXkxPKCvjlVKplI5nosIQncNCt2wCZSR4dEcvz2WgTK1quhNBWEmmPOBJa0S/
+ DNBY0B1cHFLXpHYAMf4KKLtddLM+LOCyKcq4hZdEw+RWekJZNUUlc5DBLPMVZEKZv5BQqMvCa++e7r2Z
+ vwDQcKn+4f659bkdo2xQDKCMux2bOF1uWQANXC7nruDtWJrnqeV6OeoY/BFZUAxCGYk1qkKoBMEs89cb
+ w8DxV07T4ia8S+XHCObPCjTegFiL+o/qX3mksmOUsfo9UozWKOPuQaYYG7TawsctgBlqRYQCtWYeZVr9
+ 6IY8lN9Qu4BfRrECNQrhhd104URnbhbsPPQ/H9DIrFDnnZQyae+tvR2jPO2NacxjCFc/3swBZc7Msct3
+ icsm18Lydw8q+7Fb6fl9UKjD0fV4VIcjaTa6QZruqnm6okEvxs8ENOoGOn9dRkkGsruOUU64lYBbpJmT
+ 4z3GD0JZFa+SKqXIrYXSDJtBtx+jPI/EBEWiNi8UfLqi8TMBDclDsot8ZMOhDR1DfOKbE4NfHYxL0Q1Z
+ CTm59lBu857Slns0VWNVMjvDAgigycwJpRnVZKR/dMcuakPI/R57RWbnVaLNr/xpGY23J9zFnMw5OJSk
+ Y5Qb7zZGXo+0OW1jvU+QlbR4DKbLQsXo0DKrpqnkrnKUQIULoJE0wzUb3RqNksVPJBoGRm8oXfFTRG52
+ 8tDBvcP7h+Y0ZJ387HjHsex2uvspV9k+sXSzWFJnKam0lFRYSsotJWUsxCUW4kIL8VoL8SoLy5XmlsvN
+ LZeaWy4xt0xrI8wn9uju1DUyMiBh9MCxYwaOGzt4wrghkycOmzIpfsa0EbOSxsydPT5l/qRFC6dlLElc
+ sXR2Tub8/FULCvJT169JK1qfXlKYUVq0tKx4WXnJ8qcLy0/CaJQO3HRu87LnPZbIoDkMBi5Ctz5ibb3b
+ 2mqrSR2DshJ+9euQy2qYOX85+iY8l/kFEBkgSTNcM6SZbpunSVq6Q+xpXczdnsKIhK9bRdlKisryzJbI
+ qtqAyEZUVyByqitzaipXIWqrcg1RnVfHIn9jTX56WlJ0dPDAhP7rd609dfeEcXx+4pQgDn66v//lWOVx
+ uWynVNYokdVJZFUSWaVEViGRbWAhLRNLi8XSdWJpnliSJZasFEuWiyUZYkm6WEqR8SgksyzNfXr2iek1
+ d87UeXOnzZ83IyU5KXXhrCVpc5dmLMhcsSg3J31NwcriotyK8jV1NUWbN23YvrV6z676/c1bDh/cfuzo
+ rhPH95w+2Xzm9IFzZw5cOHfowrnDF88fuXjhyKULRy9dPHb50vEriMsnrl4+ee3KqWtXT7189fTL185c
+ f/nsKy+fe+X6uRuvnH/1lQuv3rh488bF11699NrNy7duXrn12pXXb119/da1p8Zo1G3RrYgcGJlVm4VG
+ aseKjL8t/bgUJ9+1Icp8tYjPsPmspH0np16kVoQrMFrImzksgHyeTbkJFkDMsvKuGQUNFD+NpPlppSem
+ vH4KjF6dt3jUiP6u3s4zVyRuv7G1DSLz1G6h85QbkxxO2smaJbImiXSjRFrTQmSey6ViaZFYulYsybWU
+ ZFkauJzOuEwhZLRknqV5YM+IiOC5s6fMnQ06T0+en7hwQVLaojnpS5JXLFuYk52Wn7e8cH1WWUl+deW6
+ ho2lTZsrdu2o27u74eD+piOHth/n6Xxq/9kzB86fPfhsMRqVARQ5PXw8Zi6fufXa1seyGF+w9fOtA24M
+ sDlvw5wycmsTUWYGA1xG5RM1OaoW0UXogivQhc/Vi9WKXoqEhAQUjHjLTGYOSwWfAZLNoKuhhQUNvmzU
+ yXnlH2zyfiCjczKTRw7vZ+9iO37+2MpjGzpisUCpZ91Mcj3tLN8vlW2VSOvF0hqxtFIirZBIOUVmUS6R
+ loilhWLparEkm+PyCkvJMkueyEaMlsxlXA4PC5g9a/Kc2VOhzkyaFyQuSoU0z1uWkZKVuTgvd+m6NStL
+ inIrNxTUQpoby7cxad64b++mQwe2Hj28A3Q+eXzPqVPNZ07tgzqfO3vwmWA0SjDoH/sE+cxeOXvLpS2d
+ YTG+BjYZRLY9b4vE2uAuNrfOR/iyJwwGVfE7rHyyWn4K02VMJROXhYkJVTNoUoBKoEKb8VPnJm0nLJ10
+ HUXrMhKnjw4P8/Pv5Ts7a2bjpfpTd4+3hIm7aO03JrwyjinyPk6RDUQWSyvE0g1iKSiMgMGAKMNgrBVL
+ c2EwIMqWkuWWkqXgMsUjdTY8T7Q01/eIjAyZPXMy0Xn+3OkLkmcsTJkJaV4Gm7EydVV2+prVKwrXZ28o
+ y6+pWt9YX9K0uXLndibNB/ZtPnJo29HD208cY3SG2Th9qvns6f2/JKPhOtGWt7W3RcMpf1P+yd+f7CSL
+ 8WWrPlzFrMXZ1oosTKxRwheK8roWUW6/V8JKzDNV8MuY/xR6DJpAJC6jZkQNQPzwKIFSnk1b/IQ2g6qg
+ nd/k8IMFmhWV2mP0soyZSK78fT38wn2mp08pP1J68u5xYXTM6JL3iqIvRqmOKWS7JbItsBZiaTUUuYXI
+ jMssJLxTNhZlnsvGjBaPs+jp0j02NnJm0iTQmbMZUxfMn56aMnPxotkZ6fNXLIfNWLI6f+n6tbAZeVWV
+ a+s3FsM179hWvXvnxv3Nmzmnse3YkZ2g86kTe06d2At1PnN638/KaJQNYSQgfAERAdMWTSveW3z23tnO
+ UxhfuevertG3RrPOyDFr6+aWwgX1rQWtawOR0fEra6ksI+vLa7dRYmiXjGV1DMwkGnEZHsOIy1TOB5dR
+ aCbLTNtVhd2pn4fLj2od2ZnzUAeI7Rvm5mrvG+o9bl5C3uZV+99pNhQoWhOZJ7Upo7d93DTq2gjIMfMV
+ 2yTSRrG0ViytEhCZYzEjcqmlpMRSsl4sKWjtLh6JchuMthxg3kNlFh/Xf2bSxFkzJ0Ga586Zkjxv+sKU
+ RMblJfNWLk/Jzlycn7d03drM0uJVlVwGuKmhbFtT1c4ddc17IM1IArfCOB87suPk8d2I0yf3smzwZ2A0
+ NsJ5+HrETYpLK0zbeGbjY+vFbbJ77xd7J92epLussznJFTlRSoZBFvqKlnzvUVO1vKV4/zinzAxGhhpV
+ fNSX0foT1jEo9yO/TAOfNCpnxGXTTuvPyWUDo1GUaH5rT0fVtQ4ZXfF++ZArgxxO2Mn2S2TbxYzFda1Z
+ 3CLHBiIXg8iWkgJLsdAmZxjxt9UfxTMszf17BAbop0waxXF54pxZk+cxLk9buCBxcSq4PHfFMuJyxlpY
+ 5uKcivKC2ur1jSwDrIQ0t7hmRmc4jeNHeXWG3/i5GP1E+iv84oI7BZiEY509aDGKyB2yuJUiUxeqE0Sm
+ Hja6q3zfjzbqoPWHphS1Syj3w9gnHTzSJpf5ytxT3Bn1pA5E9NhisZHZ2PHRtmmvTPE56y0/KpXuFku3
+ iKX1ltJaS6bFZI0pWuSYERlyDCKvs5SsBpEtxJkW4hWWYuR7HRIZ9tkCoqwxGzQwOmnG+KTE8QYuz52S
+ PH86ShmLU2cxLi9Nyc5q4XJRzoay1bXVqGaUbNm8YXtT1a6dTJoP7t986ACchoHOYDTUmfMbzySj8+7k
+ DX11qMclD5tTzBezBG8bNzoER8FbY4EWG+QYnREqXNAABqxFh7ULwwQXsr5oBaZeeFGmm5747TqoL2Ns
+ ATU5dLJpyIg/eER4JMazwGWDRj+W0flv5Q7DxcGnXGRHJIzCTWJJvSX6INIqS2mFpXQDF+WI1iwmX1Fo
+ KVljKcmzZCxeCSJbiJdZiDMsxEssERKEIfFr9cRytHlPt+4RYQHTpiYkzRhn4PLsSfPAZYPHmJWRPo/p
+ ctai/NwMrpSRXVEOLq+tryvewgrNVbt21DbvbtjfvAl0PnyQjDMzG/DOXDb4bDD6zLdnVt9ZDTvsf8Wf
+ VdqOClTYlMKtWfxIjuErULXAVBw/F9DOMBFfjWPuYrBSZivDoDjvlIWijMEXMhjUxkZ9mT9zi06DotzP
+ dJrrSSe4nlSCH/v1rTS69L3i6TemRpwPtT9hKzvcwt8GS0mtpaS6pZW3gevmMQpzUdbyBIwu4+S4iJPj
+ fF6OLcTLLcRLwWJhtMFoy/HmPb17BAR4j00YNmN6QuL0sTOZLk+YM3vy/DlTFyQj90tasnj20vR5K1cs
+ XJW9eHUecr8VJUWrKjasrmG6DC7DMleCy3t31+/b23CA0RlOo+noYVbWOH4UhTrmN34ZRpd9Ujb3rbnw
+ D75XfNkA8nFrpr97uYwOXrhN/oLC7bEYtbeSljoyZXooJbcz4dmKyEOVmJDDcUBEZOE2YMr6+IMQ6axJ
+ MhiYMKJZcTpzy/R4l6e+L/ixzG23Zyg7LJbuEUthgdGBJvJWCcjbwl9isSG45jTjMp6UWhi0eC2nxQZT
+ 0cLidCMi8398xGjLBPOeuu5+vl6jRw6ePm0MuAxdnpk0fs6siVziNy1lwYzFqTOXpM1ZvjQ5c+XCVTlp
+ BfnLCtdxud+G/NoqA5e3bqnYuZ1Z5uY9aANuOrBv0+EDTVweuJXU+RdmdBvMpYqEaXDDsnywPgg5ChQr
+ YI1JizvNYiooI9+T2cjopj1TItO5qej4wSnTHjQ6CBGz4uhhYyKfihg0yGx65tZPuin4SaktkoCzbdLW
+ hMI0ZcGVKSwkRRaSdRaSAjZrwRwFAkJMjqJdFgvYnWZpMbhnD0ez4CCfcQnDGJGnjeFEedxsiPIsZjAW
+ zJ+WujAxbREzGCuXL8jOhMFIX1uwvGh9ZlkJ2iXMLzfWF29phC6jAQguo9BMBQ20TrYgjjA6Q50NfuOX
+ ZnSb5DVVYeqAEIVhJ3gh5h1F+209o3Yfkj1FiALnNGAzpZG14O/p5ImM8gV/bip/ECJEuTMnmz0p6X7S
+ rxe1El9iMTG3JdigULGFuIibFVptIc4xF2dyAVNMdqIzFOYsh+Vk854h3buLu8VEh06dMmra1NHgciJE
+ OXHcrMTxs2dOnDdncvL8qakpMxalzkyHKC9LzlqxMJeJcgZnMJD45VZXFtTVol1CHqNiJ6sy13BchjQz
+ OpNxZt75GWW0qQTTZEUFy+vYMDKvwjQs2wk78chXzOPk2F6GPX7Yd8bLsfA8dlgLOiycTrIWHgAsPDe1
+ Y1F+pnRZ+BYRteJvqaWBvDTrlm9hucrcMtOcTbytMBcvNxcvMxdnmIvTzcVp5q19cXvuwsIy0dy8d4/u
+ Vt0CA71HjhwwdTKIPGr61NEzpo9J4pwyRHnunEnJ86YsTJ6+aGFSetrs5UvhlBesyl6Un7dkbcEyTpRz
+ KpjBQOJXuKmhuGlz+fat8BhI/2ogzc170DdBEth4YF8jV9Zg3vnZYzSJL09eWAjoL/Xu+NIE2eHH5XVG
+ WoxJOOUApcxZhjNzsLuPWCy8nJo/ZATJHgbjcEIDv72dTrLmiUzlC6NzU5/KaVA/qS63YrR4nYUY5iHP
+ wjKHYy5HXjaxSUObGeaW6YahTcZiYbTK9Fox2mJiz57h3buru/n7ecUN6ztl0oipk0dOmzJqBog8LSFx
+ BucuZk2YByLPn7pwwfRFqSDyrGUZczOXp+Rkpebnpq0pWFq4bmVpcVZFWW5V5eqNNej7FW5uQBubcXnH
+ tiroMknzvj1IAuvBZU6dmUA/o4w2MJfMAy++IO/j0rk2R4dUk1WYG5JZyXAAKXrnbbIYdWT0RIR3N/AX
+ C9D2a9rhzh9NKyQybakUdq+fWVE2eq+IGG155raQt83R4w4YbTnb3HxAj+7u3RwcrCPC/MeMHDR50nCe
+ yFDkRCjyjLGzZ46bM3vivLmTFoDIKTPSQOQls5dlcIqctTAvJ23t6qXr1y0vKcoqL82pgihXr9lYC7Nc
+ tKWxdOuW8u1N4DJKGQabwei8t37/XqgzzMazz+gfxFyezhivV/ZlQoxrnnDsE09hOrCMv+GFDtQiFtOt
+ AuiJ0GkjGCOioxroHAHyyGQt+NoFT2S0SJ6d8sUT6buoTfI+ltEWU3v27NO9u2u3bt26BAV6DxvaZ9L4
+ +MkT4idPHDFl8ohpU0bCWsyYNjpxxphZSePmzBo/b/ak+XOnLFwwbdHCGUsWJ2UsYdYia0XyqmxekZcX
+ F2aWl6J8kVdTVVBXs7YRotxY0rSJuIypjMpd25k079lFrhk1DczPPUeMbmdKs00JhpHAbidFoEKmYefI
+ 4igiYWpHFKZ7oCDE8MX8PUX8PTp0szpqb5hTFsoxqha0yZ0/R0B4JPvzS2Se9Z1itMXEHoy/7t3MLLt6
+ eTpHRwWPGTVw4vi4iRPiJk2IY3I8eThYPGMaY3FSYsKspLGzZ42fO3vi/LmTU5KnpKZMX7KIM8gZc1cu
+ n5+dmZKbvWh13pJ1azIK1yHfA5FzKjesqq5YXVe9pmHj+s0NRVs2FYPL25qIyxXg8q4dVXsYnVFrRvyK
+ GK1OVavGqZR9lHJPOXp3dA4ynckJ/SUJ5o+SpTMjicL8yXB0chnm7FE+RiuEtBiFNzIVqL1h3z3JMfkK
+ tEXoKIE297k/kSA+g1/citEWST3Nh3fvGWEG8TUTd3VysgkM0PXvFzF+7JAJ44ZOHD904oRhkybGTWmh
+ 8PSpjMUQ4pkzwGJOi+dMTJ43KSV56qKF09NSEzl3PHvl8nlZK5Hppa7OXbxmdfq6NUuL168oLc6sKAOR
+ c2sqV9fVrKmv40SZ4/LWzdDlsu1N5eDyTtB5R9Vu5jSqn29Gwzao4pj5ZcxVSR97DjJ/LCfPX8rroMLo
+ SROF6XA4OryMvw0KrRA6+cmIxXQJCX9DhtGBDc8gN3/YjySytVZ7ejiFhuj79wtPGDVwPLcxz0Be8HcC
+ +BsPCZ46efj0qSOmc14iCRROTIApxp69eXMmcBRmjmJxKuco0mcuXzoHLM5mLF64OndRQX4aJ8fLS4tW
+ lpdkbSjDHi9Yi3yOyOsaN8IpF25phFkuAZe3NTEub99aDi7v3A6nAeP8q2A06md0ayR/wjR/fSR/Wq/w
+ HGQ69pRO5qTDDenkSFJhnsK8EMMXo1JBh2uRNeav0hG6Y35O+XnJ9J6U16KJE4ZOmjAMe0snM/GNnzqJ
+ kXfaFJCX09/p4O9ojr9j58waN2/O+OR5ExfMIy8xLS11evriRFAYQrxi2dyslfNzshbk5izMz11csDpt
+ XUFG0bplJUWQ45UbSjF3AV+RV1sFRS6or2WivKl+/SaIcmNR02ZwmdGZuLxjK5zGhl8bo5GzQW07fw4y
+ HXuKiU3iL2psdP4emni8CmO+gg405C/covO1yFHwV+n86lncqno3Y9rIxOmIUTNxunsSErmEObPGzp09
+ bh7pL6tLTF64APydmrZo+pLFM9KXJC1Ln7Vi6ZxM5iXm5WQlrwKFV6UW5IHCS9avzShav7S4cHlpCViM
+ 2hvkGNts2b7auurVIHJD3dqGjevA5c2NnC4zj1GydUvpNhYGdf51Mhpu94nOQUaNGEUJHPJE50eSBJOR
+ 4I/gEx4VKRTiX6uj6Ixei+bPhW2YsGD+xJTkSakLJi9aOGXxwhbypiUuTZ+1fOmsFctmZy6fmw3+ZoK/
+ KXmrmJdYw1Q4bf2a9MJ18MXLSgpXlBGLyxmLq9l+cShy3sYaVJMLGurWwF1sqmdc3tSwnuNyURPSP1Ln
+ fwVGP+k5yMKjeukISTo/kr+TT6jC/8oUNq5HL12SuCwjaXnGzBVLZ61chiwO4suRF+KbvSA3OyU/d+Hq
+ vNQ1+YvWrl7MqfAS7DksXr+0tGh5WTF88coNZVmV5YgcdvZBRW4NTj2AItfk19fCXTAuI4jLmxsQqMmR
+ Ov+LMfpJz0EW6q/QRfAdvH8pL9EZdTbMR+OomLyc5LxVC3AQy+rchQV58A+pHHmhv0yCib/FhcvKikHh
+ FeXsxBqc6YEDPcBi7hwPw/EdhlM7DFyuM3C5cSOKGLDM//KMplt7O38OstGxp8IDTzv/8v4LfqVoHaNt
+ WuHaJYiidenF6zOKuXOFuGAsxulCTIhL6ViarMoNWZwWG86hYUfRCE6gYR6jFn65oP7fjDY6geZJz0H+
+ xUfnn9N3g6ikcCmCKMyRlwU2iLecr0SHKzFf0Zkzlf7N6HbPVGrveOlfaxXtl3pDiHgKC1j8w08J+zej
+ f/JTwn4ppjwv/98feKZSe+fe/ZvR/2b0L0z9fzP65zrd4Bd+of9l/vf/ZvS/Gf3rIvu/Gf1vRv+6GP3/
+ AZ+4Ui+mkTlKAAAAAElFTkSuQmCC
+
+
+
\ No newline at end of file
diff --git a/Unity Studio/AssetPreloadData.cs b/Unity Studio/AssetPreloadData.cs
new file mode 100644
index 00000000..2e0978cd
--- /dev/null
+++ b/Unity Studio/AssetPreloadData.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Unity_Studio
+{
+ public class AssetPreloadData : ListViewItem
+ {
+ public long m_PathID;
+ public int Offset;
+ public int Size;
+ public int Type1;
+ public ushort Type2;
+
+ //public string m_Name = "";
+ public string TypeString;
+ public int exportSize;
+ public string InfoText;
+
+ public AssetsFile sourceFile;
+ public int specificIndex = -1; //index in specific asset list
+ public string uniqueID;
+ }
+}
diff --git a/Unity Studio/AssetsFile.cs b/Unity Studio/AssetsFile.cs
new file mode 100644
index 00000000..a594a11c
--- /dev/null
+++ b/Unity Studio/AssetsFile.cs
@@ -0,0 +1,319 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Diagnostics; //remove this later
+
+namespace Unity_Studio
+{
+ public class AssetsFile
+ {
+ public EndianStream a_Stream;
+ public string filePath;
+ public int fileGen;
+ public string m_Version = "2.5.0f5";
+ public int[] version = new int[4] { 0, 0, 0, 0 };
+ public string[] buildType;
+ public int platform = 100663296;
+ //public EndianType endianType = EndianType.BigEndian;
+ //public List preloadTable = new List();
+ public Dictionary preloadTable = new Dictionary();
+ public List GameObjectList = new List();
+ public List TransformList = new List();
+ //public List RectTransformList = new List();
+ //public List MeshFilterList = new List();
+ //public List SkinnedMeshList = new List();
+ public List exportableAssets = new List();
+ public List sharedAssetsList = new List() {new UnityShared()};
+ private ClassIDReference UnityClassID = new ClassIDReference();
+
+ private bool baseDefinitions = false;
+
+ public class UnityShared
+ {
+ public int Index = -1; //actual index in main list
+ public string aName = "";
+ public string fileName = "";
+ }
+
+ public AssetsFile(string fileName, EndianStream fileStream)
+ {
+ //if (memFile != null) { Stream = new EndianStream(memFile, endianType); }
+ //else { Stream = new EndianStream(File.OpenRead(fileName), endianType); }
+ a_Stream = fileStream;
+
+ filePath = fileName;
+ int tableSize = a_Stream.ReadInt32();
+ int dataEnd = a_Stream.ReadInt32();
+ fileGen = a_Stream.ReadInt32();
+ int dataOffset = a_Stream.ReadInt32();
+ sharedAssetsList[0].fileName = Path.GetFileName(fileName); //reference itself because sharedFileIDs start from 1
+
+ switch (fileGen)
+ {
+ case 6:
+ {
+ a_Stream.Position = (dataEnd - tableSize);
+ a_Stream.Position += 1;
+ break;
+ }
+ case 7://beta
+ {
+ a_Stream.Position = (dataEnd - tableSize);
+ a_Stream.Position += 1;
+ m_Version = a_Stream.ReadStringToNull();
+ break;
+ }
+ case 8:
+ {
+ a_Stream.Position = (dataEnd - tableSize);
+ a_Stream.Position += 1;
+ m_Version = a_Stream.ReadStringToNull();
+ platform = a_Stream.ReadInt32();
+ break;
+ }
+ case 9:
+ {
+ a_Stream.Position += 4;//azero
+ m_Version = a_Stream.ReadStringToNull();
+ platform = a_Stream.ReadInt32();
+ break;
+ }
+ case 14:
+ case 15://not fully tested!s
+ {
+ a_Stream.Position += 4;//azero
+ m_Version = a_Stream.ReadStringToNull();
+ platform = a_Stream.ReadInt32();
+ baseDefinitions = a_Stream.ReadBoolean();
+ break;
+ }
+ default:
+ {
+ //MessageBox.Show("Unsupported Unity version!", "Unity Studio Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ }
+
+ if (platform > 255 || platform < 0)
+ {
+ byte[] b32 = BitConverter.GetBytes(platform);
+ Array.Reverse(b32);
+ platform = BitConverter.ToInt32(b32, 0);
+ //endianType = EndianType.LittleEndian;
+ a_Stream.endian = EndianType.LittleEndian;
+ }
+
+ /*Platform list:
+ -2: unitypackage
+ 4: OSX
+ 5: PC
+ 6: Web
+ 7: Web_streamed
+ 9: iOS
+ 10: PS3(big)
+ 11: Xbox360(big)
+ 13: Android
+ 16: Google_NaCl
+ 21: WP8
+ 25: Linux
+ */
+
+ int baseCount = a_Stream.ReadInt32();
+ for (int i = 0; i < baseCount; i++)
+ {
+ if (fileGen < 14)
+ {
+ int baseType = a_Stream.ReadInt32();
+ readBase();
+ }
+ else { readBase5(); }
+ }
+
+ if (fileGen >= 7 && fileGen < 14) {a_Stream.Position += 4;}//azero
+
+ int assetCount = a_Stream.ReadInt32();
+ if (fileGen >= 14) { a_Stream.AlignStream(4); }
+
+ string assetIDfmt = "D" + assetCount.ToString().Length.ToString(); //format for unique ID
+
+ for (int i = 0; i < assetCount; i++)
+ {
+ AssetPreloadData asset = new AssetPreloadData();
+ if (fileGen < 14) { asset.m_PathID = a_Stream.ReadInt32(); }
+ else { asset.m_PathID = a_Stream.ReadInt64(); }
+ asset.Offset = a_Stream.ReadInt32();
+ asset.Offset += dataOffset;
+ asset.Size = a_Stream.ReadInt32();
+ asset.Type1 = a_Stream.ReadInt32();
+ asset.Type2 = a_Stream.ReadUInt16();
+ a_Stream.Position += 2;
+ if (fileGen >= 15) { int azero = a_Stream.ReadInt32(); }
+
+ asset.TypeString = asset.Type2.ToString();
+ if (UnityClassID.Names[asset.Type2] != null)
+ {
+ asset.TypeString = UnityClassID.Names[asset.Type2];
+ }
+
+ asset.uniqueID = i.ToString(assetIDfmt);
+
+ asset.exportSize = asset.Size;
+ asset.sourceFile = this;
+
+ preloadTable.Add(asset.m_PathID, asset);
+
+ //this should be among the first nodes in mainData and it contains the version - useful for unity 2.x files
+ if (asset.Type2 == 141 && fileGen == 6)
+ {
+ long nextAsset = a_Stream.Position;
+
+ BuildSettings BSettings = new BuildSettings(asset);
+ m_Version = BSettings.m_Version;
+
+ a_Stream.Position = nextAsset;
+ }
+ }
+
+ buildType = m_Version.Split(new string[] { ".", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }, StringSplitOptions.RemoveEmptyEntries);
+ string[] strver = (m_Version.Split(new string[] { ".", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "\n" }, StringSplitOptions.RemoveEmptyEntries));
+ version = Array.ConvertAll(strver, int.Parse);
+
+ if (fileGen >= 14)
+ {
+ int someCount = a_Stream.ReadInt32();
+ a_Stream.Position += someCount * 12;
+ }
+
+ int sharedFileCount = a_Stream.ReadInt32();
+ for (int i = 0; i < sharedFileCount; i++)
+ {
+ UnityShared shared = new UnityShared();
+ shared.aName = a_Stream.ReadStringToNull();
+ a_Stream.Position += 20;
+ string sharedFileName = a_Stream.ReadStringToNull(); //relative path
+ shared.fileName = sharedFileName.Replace("/", "\\");
+ sharedAssetsList.Add(shared);
+ }
+ }
+
+ private void readBase()
+ {
+ string baseFormat = a_Stream.ReadStringToNull();
+ string baseName = a_Stream.ReadStringToNull();
+ a_Stream.Position += 20;
+ int childrenCount = a_Stream.ReadInt32();
+ //Debug.WriteLine(baseFormat + " " + baseName + " " + childrenCount);
+ for (int i = 0; i < childrenCount; i++) { readBase(); }
+ }
+
+ private void readBase5()
+ {
+ int baseType = a_Stream.ReadInt32();
+ if (baseType < 0) { a_Stream.Position += 16; }
+ a_Stream.Position += 16;
+
+ if (baseDefinitions)
+ {
+ #region cmmon string array
+ string[] baseStrings = new string[1007];
+ baseStrings[0] = "AABB";
+ baseStrings[5] = "AnimationClip";
+ baseStrings[19] = "AnimationCurve";
+ baseStrings[49] = "Array";
+ baseStrings[55] = "Base";
+ baseStrings[60] = "BitField";
+ baseStrings[76] = "bool";
+ baseStrings[81] = "char";
+ baseStrings[86] = "ColorRGBA";
+ baseStrings[106] = "data";
+ baseStrings[138] = "FastPropertyName";
+ baseStrings[155] = "first";
+ baseStrings[161] = "float";
+ baseStrings[167] = "Font";
+ baseStrings[172] = "GameObject";
+ baseStrings[183] = "Generic Mono";
+ baseStrings[208] = "GUID";
+ baseStrings[222] = "int";
+ baseStrings[241] = "map";
+ baseStrings[245] = "Matrix4x4f";
+ baseStrings[262] = "NavMeshSettings";
+ baseStrings[263] = "MonoBehaviour";
+ baseStrings[277] = "MonoScript";
+ baseStrings[299] = "m_Curve";
+ baseStrings[349] = "m_Enabled";
+ baseStrings[374] = "m_GameObject";
+ baseStrings[427] = "m_Name";
+ baseStrings[490] = "m_Script";
+ baseStrings[519] = "m_Type";
+ baseStrings[526] = "m_Version";
+ baseStrings[543] = "pair";
+ baseStrings[548] = "PPtr";
+ baseStrings[564] = "PPtr";
+ baseStrings[581] = "PPtr";
+ baseStrings[616] = "PPtr";
+ baseStrings[633] = "PPtr